how to use a class method as a WIN32 application callback method (WINPROC)... Error static struct HI
        Posted  
        
            by numerical25
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by numerical25
        
        
        
        Published on 2010-05-23T12:59:40Z
        Indexed on 
            2010/05/23
            13:00 UTC
        
        
        Read the original article
        Hit count: 314
        
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())
    {
        return 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!!
© Stack Overflow or respective owner