how to use a class method as a WIN32 application callback method (WINPROC)... Error static struct HINSTANCE__
I am receiving errors and at the same time trying to make this work so please read what I got to say. Thanks....
I am creating a c++ application and majority of the application is encapsulated into a class. That means that my WinProc function is a static class method that I use as my call back method for my win32 application. The problem is that since I created that as a win32 application, every class member I use inside that method has to be static as well. Including my HINSTANCE class which I use inside of it. Now I receive this error
error LNK2001: unresolved external symbol "public: static struct HINSTANCE__
I need to figure out how to make this all work and below is my class declaration. My static member static HINSTANCE m_hInst is causing the error I believe.
#pragma once
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
class RenderEngine {
protected:
int m_width;
int m_height;
ATOM RegisterEngineClass();
public:
static HINSTANCE m_hInst; //<------ This is causing the error
HWND m_hWnd;
int m_nCmdShow;
TCHAR m_szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR m_szWindowClass[MAX_LOADSTRING]; // the main window class name
bool InitWindow();
bool InitDirectX();
bool InitInstance();
//static functions
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
int Run();
};
Below is the implementation
#include "stdafx.h"
#include "RenderEngine.h"
bool RenderEngine::InitWindow()
{
RenderEngine::m_hInst = NULL;
// Initialize global strings
LoadString(m_hInst, IDS_APP_TITLE, m_szTitle, MAX_LOADSTRING);
LoadString(m_hInst, IDC_RENDERENGINE, m_szWindowClass, MAX_LOADSTRING);
if(!RegisterEngineClass())
{
return false;
}
if(!InitInstance())
{
retu开发者_JAVA技巧rn false;
}
return true;
}
ATOM RenderEngine::RegisterEngineClass()
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = RenderEngine::WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = m_hInst;
wcex.hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_RENDERENGINE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_RENDERENGINE);
wcex.lpszClassName = m_szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
LRESULT CALLBACK RenderEngine::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool RenderEngine::InitInstance()
{
m_hWnd = NULL;
m_hWnd = CreateWindow(m_szWindowClass, m_szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, m_hInst, NULL);
if (!m_hWnd)
{
return FALSE;
}
if(!ShowWindow(m_hWnd, m_nCmdShow))
{
return false;
}
UpdateWindow(m_hWnd);
return true;
}
// Message handler for about box.
INT_PTR CALLBACK RenderEngine::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
int RenderEngine::Run()
{
MSG msg;
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(m_hInst, MAKEINTRESOURCE(IDC_RENDERENGINE));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
and below is the code being used within the WinMain
RenderEngine go;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
RenderEngine::m_hInst = hInstance;
go.m_nCmdShow = nCmdShow;
if(!go.InitWindow())
{
return 0;
}
go.Run();
return 0;
}
If anything does not make any sense, then I apologize, I am a newb. Thanks for the help!!
You've got a declaration of a static variable in a header file, but there is no definition anywhere!
Somewhere in a object (cpp) file you need to "assign" memory to the variable at global scope:
HINSTANCE RenderEngine::m_hInst = NULL;
Try putting it before the InitWindow
implementation.
Static variables, contrary to normal ones, can exist from the beginning of the program even if no class of their holder type has been allocated. Hence you need to point to the compiler a place for them, just as you need to point a space for global variables when using extern.
精彩评论