ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – 如果我将WndProc移动到另一个cpp文件,则“未解析的外部_WinMain @ 16”

2019-07-29 17:06:43  阅读:203  来源: 互联网

标签:c winapi unresolved-external


对于Windows应用程序,我试图让CreateWindow()和WndProc()(或我的版本)成为在_tWinMain()开头创建的单例类的一部分但是因为尝试将函数转移到GameHandler .h和GameHandler.cpp我一直得到“未解析的外部符号_WinMain @ 16”.它们最初是main.cpp中的全局函数,一切都编译得很好然后我决定将它们移动到GameHandler,因为我得到的是未解析的外部,即使我试图将它们移回main.cpp.

我在VS2010中这样做,该项目是作为Windows应用程序创建的,并且在属性中没有设置特定的入口点(我仔细检查过,因为我发现的每个解决方案都说是因为它是一个控制台应用程序 – 这不是’ T).

我目前拥有的代码如下所示.实际项目有几千行其他代码我遗漏了,因为我认为它不相关(但很高兴证明是错误的.虽然实际的窗口创建代码是相关的,但我不认为代码本身是问题(除了我留下的),它是GameWindowProc()& /或CreateGameWindow()的位置或它们的调用方式.实际的窗口创建代码取自NeHe’s tutorial.尝试仅编译以下代码给出上述未解决的外部因素.

main.cpp中:

#include <Windows.h>
#include "GameManager.h"

#ifndef USEGMGR
bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
LRESULT CALLBACK GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif

int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, 
                        LPTSTR lpCmdLine, int nCmdShow)
{
    GameManager::Startup();
    GameManager* GMgr = GameManager::GetInstance();

    GMgr->SetProgramState(GAME_MODE);
    while(GMgr->GetProgramState() != GAME_MODE) // Normally this would be if (State != GAME_QUIT)
    { /* do game related stuff */ }

    GameManager::Shutdown();
    return 0;
}

#ifndef USEGMGR
bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag)
{
    // Fairly complex but flexible creation code, taken from NeHe's tutorials. Of relevant interest is:
    WNDCLASS        wc;                             // Windows Class Structure
    wc.lpfnWndProc  = (WNDPROC) GameWindowProc;  // WndProc Handles Messages
    if (!RegisterClass(&wc))                         // Attempt To Register The Window Class
    {
        MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return false;
    }
    return true;
}

LRESULT CALLBACK GameWindowProc(HWND    hWnd,            // Handle For This Window
    UINT    uMsg,            // Message For This Window
    WPARAM    wParam,            // Additional Message Information
    LPARAM    lParam)            // Additional Message Information
{
    // various custom message handling, if not processed:
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
#endif

在GameManager.h中:

#ifndef GAMEMANAGER_H
#define GAMEMANAGER_H
#define USEGMGR // makes CreateGameWindow() and GameWindowProc() methods in GameManager instead of global

#include <Windows.h>

enum ProgramState
{
    GAME_MODE,
    GAME_QUIT,
};

class GameManager
{
public:
    static void             Startup();
    static void             Shutdown();
    static GameManager*     GetInstance();
    void                    Update(); // code not shown, check quit key etc
#ifdef USEGMGR
    const bool              CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
    static LRESULT CALLBACK GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
    void                    KillGameWindow(void);
    const int                GetProgramState() const;
    void                    SetProgramState(const int& newMode);
private:
    GameManager();
    ~GameManager();
    GameManager(const GameManager&);
    GameManager& operator=(const GameManager&);
    HINSTANCE                m_hInstance;
    HWND                    m_hWnd;        
    HDC                        m_hDC;        
    static GameManager*        s_instance;
    int                        m_programState; // uses ProgramState enum
};
#endif

在GameManager.cpp中:

#include "GameManager.h"
#include <Windows.h>
#include <assert.h>

#ifndef USEGMGR
extern bool CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag);
#endif
GameManager*        GameManager::s_instance    = NULL;
GameManager::GameManager(){}
GameManager::~GameManager(){}


void GameManager::Startup()
{
    assert(s_instance == NULL);
    s_instance = new GameManager;
#ifdef USEGMGR
    if (! (s_instance->CreateGameWindow("Game Window", 800, 600, 32, true )) )
#else
    if (! (CreateGameWindow("Game Window", 800, 600, 32, true )) )
#endif
        assert("CreateGameWindow failed! Need an error here"); // Quit If Window Was Not Created - clean this up later    
}

void GameManager::Shutdown()
{
    assert(s_instance != NULL);
    delete s_instance;
    s_instance = NULL;
}

GameManager* GameManager::GetInstance(){return s_instance;}

void GameManager::Update(){/* msg handling, watch for quit key, etc */}
const int GameManager::GetProgramState() const{return s_instance->m_programState;}
void GameManager::SetProgramState(const int& newState){s_instance->m_programState = newState;}

#ifdef USEGMGR
const bool GameManager::CreateGameWindow(char* title, int width, int height, int bits, bool fullScreenFlag)
{
    // Fairly complex but flexible creation code, taken from NeHe's tutorials. Of relevant interest is:
    WNDCLASS        wc;                             // Windows Class Structure
    wc.lpfnWndProc  = (WNDPROC) GameManager::GameWindowProc;  // WndProc Handles Messages
    if (!RegisterClass(&wc))                         // Attempt To Register The Window Class
    {
        MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
        return false;
    }
    return true;
}

LRESULT CALLBACK GameManager::GameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // various custom message handling, if not processed:
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
#endif    

正如您所看到的,我已经设置了一些预处理器条件,以便在main.cpp中或作为GameManager的一部分之间切换麻烦的函数.在GameManager.h的开头注释#define USEGMGR,将它们作为main.cpp中的全局函数.

有人可以告诉我我做错了什么吗?

编辑:删除评论,如果你让它运行不能退出.

解决方法:

#include <tchar.h>

到main.cpp的顶部,以便正确定义_tWinMain宏.

如果你没有宏定义会发生什么,你最终会在目标文件中找到一个名为_tWinMain()的函数(或者名称的某个错位版本,如?_tWinMain @@ YGHPAUHINSTANCE __ @@ 0PADH @ Z()),但链接器和运行时初始化代码正在寻找WinMain()或wWinMain().他们找不到.

&LT TCHAR.H&GT定义一个宏,将名称_tWinMain()转换为其他所有要查找的名称之一.在开始重构之前(很可能是间接的),你必须拥有包含那个标题的东西,并以某种方式丢失它.

或者您可以免除宏版本并将函数命名为WinMain或wWinMain(无论您是否正在为UNICODE构建,都应该可以使用它).如果这样做,只需记住更改LPTSTR参数声明以匹配您选择的声明.

标签:c,winapi,unresolved-external
来源: https://codeday.me/bug/20190729/1573354.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有