Hello again everyone,
How are you all doing? I am an fairly familiar with C/C++. I have five books on my shelf about programming in C/C++ but none could provide me with a satisfactory solution to this one problem. I would like to graduate from the Hello World project in Window application and move on to a more intermediate level. For a while I have steered away from class creations because I don't quite have a full grasp on the concept. However, I would have to face them eventually so I took the liberty to go at it. Below are the code of my entire Hello World Advance project, My Project 5.

Under the

void c_AppSys::CreateMyWindow()

method definition

cm_wcx.lpfnWndProc = WinProc;

.

When I compile the code I get an undeclared error.

49 MyProject5\project5main.cpp 'WinProc' undeclared (first use this function)

These code are my own but I based the class off of the sample given in one of my books SAMS Teach yourself GAME PROGRAMMING in 24 hours by Michael Morrison. I don't understand how the class would work for him. I even copy his code exactly onto My Project 3 but it also showed me the same error. I'm only assuming that the code somehow works for him. And thats what I want to know, how does he solve this error to get the class to recognise his WndProc from outside the class? Thanks in advance everyone. Oh and there are some opengl codes in there I figured I'd kill two birds with one stone and incorporate some gl in the mix.

These are his:

BOOL GameEngine::Initialize(int iCmdShow)
{
WNDCLASSEX wndclass;

wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbWndExtra = 0;
wndclass.cbClsExtra = 0;
wndclass.hInstance = m_hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
wndclass.lpszClassName = m_szWindowClass;
wndclass.lpszMenuName = NULL;

m_hWindow = CreateWindow(m_szWindowClass,m_szTitle,WS_POPUPWINDOW|WS_CAPTION|WS_MINIMIZEBOX, 0,0,640,480,NULL,NULL,m_hInstance,NULL);

His WinProc is

LRESULT CALLBACK WndProc(HWND hWindow,UINT msg,WPARAM wParam,LPARAM lParam)
{
return GameEngine::GetEngine()->HandleEvent(hWindow,msg,wParam,lParam);
}

And here are my codes:

#include <windows.h>
#include <windowsx.h>
#include <glut.h>

//my very own class used to handle the application system
class c_AppSys
{private://private members
         bool       cm_bRun;//flags to die or live
         HINSTANCE  cm_hInstance;//application instance
         HWND       cm_hWnd;//application window handle
         int        cm_iwidth;//window width
         int        cm_iheight;//window height
         WNDCLASSEX cm_wcx;//application class
 public:
        c_AppSys();//the constructor automatically executes the instant this class's
        //object is declared
        ~c_AppSys();//the destructor automatically executes the instance this class's
        //object is destroyed
        //some of the methods - functions that has access to the private data
        bool CreateMyWindow();
        bool LeakFlag(){return cm_bRun;}
        HWND LeakhWnd(){return cm_hWnd;}
        LRESULT CALLBACK MyWinProc(HWND,UINT,WPARAM,LPARAM);
        
        void ClearOut();//use this to clear out any allocated memory
        void IDoKeys();//handles any keys as they are pressed       
        void InitSys();//i will use this to initiate glut api
        void MyResizing(int,int);//in event the window is changed in dimension
};

//the definitions of all of my methods
c_AppSys::c_AppSys()//the constructor
{
    cm_bRun = TRUE;//initiated to be set as true
    cm_iwidth = 640;//default width of my window
    cm_iheight = 480;//default height of my window
}

c_AppSys::~c_AppSys()//the destructor
{
}

bool c_AppSys::CreateMyWindow()
{
     HINSTANCE hInstance;
     HWND hWnd;

     cm_wcx.style = CS_HREDRAW|CS_VREDRAW;
     cm_wcx.cbSize = sizeof(WNDCLASSEX);
     cm_wcx.lpfnWndProc = WinProc;
     cm_wcx.cbClsExtra = 0;
     cm_wcx.cbWndExtra = 0;
     cm_wcx.hIcon = LoadIcon(NULL,IDI_APPLICATION);
     cm_wcx.hIconSm = NULL;
     cm_wcx.hCursor = LoadCursor(NULL,IDC_ARROW);
     cm_wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
     cm_wcx.lpszClassName = "MYPROJECT5";
     cm_wcx.lpszMenuName = NULL;

     if(!(RegisterClassEx(&cm_wcx)))
     {return FALSE;}
     
     if(!(hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,"MYPROJECT5",
     "My Project 5",WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
     60,60,cm_iwidth,cm_iheight,NULL,NULL,hInstance,NULL)))
     {return FALSE;}
     
     cm_hWnd = hWnd;//store the handle in the class member
     cm_hInstance = hInstance;//store the instance in the class member
     
     ShowWindow(cm_hWnd,SW_SHOW);
     UpdateWindow(cm_hWnd);
     return TRUE;
}

LRESULT CALLBACK c_AppSys::MyWinProc(HWND hWnd,UINT umsg,WPARAM wParam,LPARAM lParam)
{
        switch(umsg)
        {
            case WM_DESTROY:
                 ClearOut();
                 PostQuitMessage(0);
                 break;
        }
        
        return DefWindowProc(hWnd,umsg,wParam,lParam);
}

//this is where i initialize any glut api
void c_AppSys::InitSys()
{
     int*   argc;
     char** argv;
     
     glInit(&argc,argv);
     glInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
     //Undo comments to have glut handle window creation
     //glutInitWindowSize(640,480);
     //glutCreateWindow("MYPROJECTX");
     glutKeyboardFunc(IDoKeys);//i will handle the keys not glut
     glutReshapeFunc(MyResizing);//i will handle the resizing not glut
}

void c_AppSys::IDoKeys()
{
}

void c_AppSys::ClearOut()
{
//this is probably the wrong way to clear allocated space
     UnregisterClass("MYPROJECT5",cm_hInstance);
     cm_bRun = FALSE;//flag set to kill
     cm_hInstance = NULL;
     cm_hWnd = NULL;
}

void c_AppSys::MyResizing(int iwidth,int iheight)
{
     glViewPort(0,0,iwidth,iheight);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluPerspective(45.0,(double)iwidth/(double)iheight,1.0,200.0);
}

//a redering class system
class c_RenderSys
{public:
        void IDoDraw();
        void InitRenderSys();
        void InitRenderAccel(); 
};

void c_RenderSys::IDoDraw()
{
     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
     glMatrxMode(GL_MODELVIEW);
     glLoadIdentity();
     glBegin(GL_TRIANGLES);
     glVertex3f(-1.0f,0.0f,0.0f);
     glVertex3f(0.0f,-1.0f,0.0f);
     glVertex3f(1.0f,0.0f,0.0f);
     glEnd();
     glutSwapBuffers();
}

void c_RenderSys::InitRenderSys()
{
     glutDisplayFunc(IDoDraw);
}

void c_RenderSys::InitRenderAccel()
{
     glEnable(GL_DEPTH_TEST);
}

//i declare my application object
c_AppSys MyApp;
c_RenderSys MyRender;

LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM);//the real winproc

int TheLoop()//handles the eternal loop here
{
    HWND hWnd;
    MSG msg;

    hWnd = pMyApp.LeakhWnd();

    do
    {
        if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE))
        {
            if(msg.message == WM_QUIT)
            {
                //MyApp.ClearOut();
                PostQuitMessage(0);
                break;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        MyRender.IDoDraw();
        MyApp.IDoKeys();
    }
    while(MyApp.LeakFlag() != FALSE);
    pMyApp.ClearOut();
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hprevInstance,LPSTR lpszCmdLine,int iCmdShow)
{
    MyApp.CreateMyWindow();
    MyApp.InitSys();
    MyRender.InitRenderSys();
    TheLoop();
    return 0;
}

LRESULT CALLBACK WinProc(HWND hWnd,UINT umsg,WPARAM wParam,LPARAM lParam)
{
        return pMyApp.MyWinProc(hWnd,umsg,wParam,lParam);
}

Just move this line 160:

LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM);//the real winproc

To the start of the code (after the includes) and all will be fine. The compiler has to know that there is a function (defined later) that is called WinProc and has the given prototype, before it gets to the line 50. Also, I'm pretty sure that you should take the address of the function as so:

cm_wcx.lpfnWndProc = &WinProc; //note the additional & before WinProc.

thank you mike for your assistance. i have modified the code as you have suggested and add the ampersand where needed. Alas with great regret the error remains although your suggestion is plausible. perhaps maybe i should create a pointer to my class object and have it point to the address of WinProc? or should i just leave the window creation outside of the class, which would defeat the purpose of my class? what would you suggest i do as i am still puzzled by this dilemma? Any alternative suggestions would be highly appreciated as well. thank you.

Thank you mike 2000 17 without your post i wouldn't have come onto an epiphany. As you mentioned in your post "To the start of the code (after the includes) and all will be fine." I realized that the line of code is a prototype for the WinProc and when I called it within my class WinProc was out of scope since I placed WinProc prototype several blocks after the class definition. It was so obvious and I feel absolutely embarrassed that I missed such a minor detail. To correct this error had simply to move the prototype for WinProc to before it will be referenced to by my class method. Thanks again so very much for your assistance couldn't have done it without and would have to steer clear of class creation again.

This question has already been answered. Start a new discussion instead.