Archived

This topic is now archived and is closed to further replies.

Processing messages in Win32

This topic is 4940 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, in my OpenGL project I have some problems with handling window''s messages. Actually I spent some time serching the internet and hoping that someone somewhere had answered similar question, but without success . My aim is to build a C++ class with a method capable of handling OpenGL window''s messages, since within such member function I have a full access to private components of a class, whereas in global window procedure it''s imposible (althogh it can make a friend function) here is the code:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string>

using namespace std;

class wSystem
{
        private:  // --- The Section Of Private Data Related To The Applicatin''s Window ---

    
                  WNDCLASSEX    windowClass;
                  HWND          windowHandle;
                  MSG           windowMessage;
                  WNDPROC       windowProcedure;
              
                  const string  windowClassName;
                        string  windowCaption;
              
        public:
                  wSystem(void);
                  wSystem(WNDPROC wndProcedure);
              
              int wInitSystem(WNDPROC wndProcedure);
             void wRun(void);
             
                 ~wSystem(void);
};

wSystem :: wSystem(void) : windowClassName("wSystemWindowClassName")
{
    this->windowCaption.assign("windowCaption");
}

wSystem :: wSystem(WNDPROC wndProcedure) : windowClassName("wSystemWindowClassName")
{
    this->windowCaption.assign("windowCaption");
    this->wInitSystem(wndProcedure);
}

int wSystem :: wInitSystem(WNDPROC wndProcedure)
{
    // --- Init The Structure That Stores The Window''s Data ---


       this->windowClass.cbSize        = sizeof(WNDCLASSEX);
       this->windowClass.style         = 0;
       this->windowClass.lpfnWndProc   = wndProcedure;
       this->windowClass.cbClsExtra    = 0;
       this->windowClass.cbWndExtra    = 0;
       this->windowClass.hInstance     = GetModuleHandle(NULL);
       this->windowClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
       this->windowClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
       this->windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
       this->windowClass.lpszMenuName  = NULL;
       this->windowClass.lpszClassName = this->windowClassName.c_str();
       this->windowClass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // --- Register Thw windowClass ---


       if(!RegisterClassEx(&this->windowClass)) return 0;

    // --- Create The Window ---

    
       this->windowHandle = CreateWindowEx(WS_EX_CLIENTEDGE, this->windowClassName.c_str(), this->windowCaption.c_str(), WS_OVERLAPPEDWINDOW,
                                           50, 50, 640, 480, NULL, NULL, this->windowClass.hInstance, NULL);

       if(this->windowHandle == NULL)
       {
           return 0;
       }

    // --- Show The Window ---


       ShowWindow(this->windowHandle, SW_SHOW);
       UpdateWindow(this->windowHandle);
       return 1;
}


void wSystem :: wRun(void)
{
    while(GetMessage(&this->windowMessage, NULL, 0, 0) > 0)
    {
        if(this->windowMessage.message == WM_CLOSE)
        {
            DestroyWindow(this->windowHandle);
            continue;
        }
        else
        {
            if(this->windowMessage.message == WM_DESTROY)
            {
                PostQuitMessage(0);
                continue;
            }
        }

        TranslateMessage(&this->windowMessage);
        DispatchMessage(&this->windowMessage);
    }
}


wSystem :: ~wSystem(void)
{}

//----------------------------------------------


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

//----------------------------------------------


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
    wSystem window;
    if(!window.wInitSystem(WndProc))
    {
        MessageBox(NULL,"Initialization failed !","Error !",MB_OK);
        return 1;
    }
    window.wRun();
    MessageBox(NULL,"Program has just finished its work !","Success !",MB_OK);
    return 0;
}
It looks like a simple windows program that seem to be free form bugs, compiler and linker do not complain. When i run it it simply shows a window which I can close. Clicking ''x'' at the upper right corner of a window I send a WM_CLOSE message to the main thread''s queue, then GetMessage() wakes up, gets that message from the queue leaving it empty and returns integer value greater than zero. Program''s flow enters while-loop''s scope and calls DestroyWindow() function which sends WM_DESTRROY to the queue. WM_DESTROY is precessed in the same way as WM_CLOSE, and PostQuitMessage(0) sets process''s exit code to zero and sends WM_QUIT message which makes GetMessage(..) return zero. This should be the end of the idle-loop - but it is NOT, although window is closed but the only thread of the process is still handled by the OS. Do I do something wrong ? Thanks in advance for any help, Rafal Pielech

Share this post


Link to post
Share on other sites
It looks fine, except:

this->windowClass.lpfnWndProc = wndProcedure;

This statement allows you to set a callback function to handle all of the messages that are sent to your application. In this case, wndProcedure is initialized to a random value because you never initialize it. You have, however, already defined the function WndProc, so replace wndProcedure with WndProc and that might solve your problem.





h20, member of WFG
0 A.D.

Share this post


Link to post
Share on other sites
Hi,
I must admit I misunderstood you.
Do you mean that windowProcedure is not initialized properly ?

If so, replace old WndProc() with this one:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN: MessageBox(NULL,"WM_BUTTONDOWN","Info",MB_OK);
break;

default: return DefWindowProc(hwnd, msg, wParam, lParam);
}

return 0;
}


after such replacement, if you click on a window you''ll see message box. In other words private attribute windowProcedure is initialized in good way.

Sincerely,
Rafal Pielech

Share this post


Link to post
Share on other sites
well I would do this somewhere in my program but such method has nothing to do with a good programming style. The problem concerns processing thread''s messages within idle-loop, and that program which I''ve listed never reaches the point where MessageBox() is called.

I mean MessageBox(NULL,"Program has just finished its work !","Success !",MB_OK);

so, the solution:

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
wSystem window;
if(!window.wInitSystem(WndProc))
{
MessageBox(NULL,"Initialization failed !","Error !",MB_OK);
return 1;
}
window.wRun();
MessageBox(NULL,"Program has just finished its work !","Success !",MB_OK);
TerminateProcess(GetCurrentProcess(), 0);
return 0;
}

doesn''t make sense.

Sincerely,
Rafal Pielech

Share this post


Link to post
Share on other sites
Well, placing that isn''t the best way but anyway it can be placed there only for temporary. I had the same situation as rafalp some time ago, I placed that ''TerminateProcess'' in my program, but after some further developping of my app I removed it and I noticed that I don''t need it (strangly program repaired themselves), so placing it in app only for temporary isn''t the worst idea.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You''re not the first guy with this problem, maybe a look at this thread might help:

[url=http://www.gamedev.net/community/forums/topic.asp?topic_id=222474]Closing a Win32 app[/url]

Share this post


Link to post
Share on other sites
Sorry about that anonymous post (I'm used to some other forums), here's the link:

Closing a win32 app

Maybe you can try some of the things they mention there.

I think the problem is your message loop never receives a WM_QUIT after DestroyWindow()
(though I'm still quite confused about this stuff)

[edited by - ThomasB on June 4, 2004 10:07:07 AM]

Share this post


Link to post
Share on other sites
Ok, I think I found your problem:

Try moving the PostQuitMessage(0) into the window procedure, otherwise the WM_QUIT doesn't end up in your window's message queue. Something like this:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
if(msg == WM_DESTROY) PostQuitMessage(0);
return DefWindowProc(hwnd, msg, wParam, lParam);
}





[edited by - ThomasB on June 5, 2004 10:12:19 AM]

Share this post


Link to post
Share on other sites
Huge thanks !
Now I know much more, but I am also still confused about this problem, sice it is not trivial. If I solve it I will explain you the solution.

Sincerely,
Rafal Pielech

Share this post


Link to post
Share on other sites
You''re welcome!

It seems if you post a message in the window procedure, it ends up back in the right window procedure. If you want to post a message outside the window procedure you have to specify the handle of the window (by using PostMessage(...)) you want to send it to.
If you don''t, DispatchMessage() doesn''t know which window procedure it was meant for.

Here''s a link to an article in MSDN about the subject:
Messages and message queues

Share this post


Link to post
Share on other sites