3

Windowsアプリケーションの場合、最初に作成されたシングルトンクラスの一部として取得しようとしていますがCreateWindow()、関数をにシフトしようとしてから、「未解決の外部シンボル_WinMain@」を取得し続けています。 16"。それらは元々グローバル関数であり、すべてが正常にコンパイルされていたので、それらをGameHandlerに移動することにしました。それ以来、それらをに戻そうとしても、未解決の外部関数しか得られません。WndProc()_tWinMain()GameHandler.hGameHandler.cppmain.cppmain.cpp

私はVS2010でこれを行っていますが、プロジェクトはWindowsアプリケーションとして作成されており、プロパティに特定のエントリポイントが設定されていません(これまでに見つけたすべてのソリューションは、コンソールアプリであるためだと言っているので、再確認しました。これはそうではありません。 t)。

私が現在持っているコードを以下に示します。実際のプロジェクトには、関連性がないと思うので省略した数千行の他のコードがあります(ただし、幸いにも間違っていることがわかります。実際のウィンドウ作成コードは関連していますが、コード自体はないと思います。問題は(私が残したものは別として)、GameWindowProc()および/またはCreateGameWindow()の場所、またはそれらの呼び出し方法です。実際のウィンドウ作成コードは、NeHeのチュートリアルから取得されます。次のコードのみをコンパイルしようとしています。前述の未解決の外部を与えます。

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内またはその一部としての厄介な関数を切り替えるために、いくつかのプリプロセッサ条件を設定しました。のグローバル関数としてそれらを持っている#define USEGMGR最初にコメントアウトします。GameManager.hmain.cpp

誰かが私が間違っていることを教えてもらえますか?

編集:実行すると終了できないというコメントを削除しました。

4

2 に答える 2

5

このWinMain関数は、「シングルトン」クラスであっても、クラスのメンバー関数にすることはできません。

これはプログラムの「エントリポイント」として機能し、基本的にmain従来のC ++アプリケーションにある関数を置き換えるため、無料のグローバル関数である必要があります。

このメッセージは、名前が付けられた(および名前マングリングが含まれている)Unresolved external _WinMain@16予期されたエントリポイントが見つからないことを示す、コンパイラの不可解な方法にすぎません。WinMain

于 2012-05-04T08:27:48.387 に答える
2

追加

#include <tchar.h>

マクロが適切に定義される main.cppように、上部に移動します。_tWinMain

マクロ定義がない場合は、オブジェクトファイルに名前付きの関数_tWinMain()(またはのような名前のマ​​ングルバージョン)が含まれることになりますが、リンカーとランタイム初期化コードはまたは?_tWinMain@@YGHPAUHINSTANCE__@@0PADH@Z()を探します。彼らはそれを見つけません。WinMain()wWinMain()

<tchar.h>_tWinMain() 名前を他のすべてが探している2つの名前の1つに変換するマクロを定義します。リファクタリングを開始する前に(おそらく間接的に)そのヘッダーを含む何かがあり、何らかの理由でそれを失ったに違いありません。

または、マクロバージョンを省略して、関数に名前を付けることもできますWinMainwWinMainUNICODE用にビルドしているかどうかに関係なく、どちらかが機能するはずです)。LPTSTRその場合は、選択したものと一致するようにパラメーター宣言を変更することを忘れないでください。

于 2012-05-04T08:31:40.563 に答える