Windowsアプリケーションの場合、CreateWindow()
とWndProc()
(または私のバージョン)を作成するシングルトンクラスの一部として取得しようとしています。 _tWinMain()
の先頭にありますが、機能をGameHandler.h
とGameHandler.cpp
にシフトしようとしているので、「未解決の外部シンボル_WinMain @ 16」が続きます。彼らはもともとmain.cpp
のグローバル関数であり、すべてがうまくコンパイルされていましたが、私はそれらをGameHandlerに移動することにしました。それはmain.cpp
に戻そうとしても未解決の外部です。WndProcを別のcppファイルに移動すると「未解決の外部_WinMain @ 16」
私はVS2010でこれをやっていますが、プロジェクトはWindowsアプリケーションとして作成されており、プロパティには特定のエントリポイントが設定されていません(これまでコンソールのapp - これはそうではありません)。
私が現在持っているコードを以下に示します。実際のプロジェクトには、数千行のコードがありますが、私はそれが適切ではないと思っています。しかし、実際にはウィンドウの作成コードは関連していますが、コードそのもの実際のウィンドウ作成コードはNeHe's tutorialから取られています。次のコードをコンパイルしようとすると、次のコードだけが表示されます。 。前述の未解決の外部
main.cppに:GameManager.hで
#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.cppで#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
:
#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.h
の先頭にコメントアウトして、グローバル機能としてmain.cpp
に設定します。
私が間違っていることを教えてもらえますか?
編集:は、実行すると終了できないというコメントを削除しました。
私はこれについて知りませんでしたが、嫌なことに何かになるのではないかと心配しました(私はWinAPIを学ぼうとしています)ので、何か新しいことを学びました。明確な説明をありがとう。 '_tWinMain'を' WinMain'に変更すると動作します。何らかの理由で一方通行かもう一方通貨が望ましいですか? – Malorion
@Malorion:自分の好みでは、 '_tWinMain()'ではなく、 'WinMain()'(または 'unWindow ')という名前の関数を単純に持つことになります。しかし、ちょうどあなたが逃げ出した混乱以外の強力な技術的理由はありません。 –