• Advertisement
Sign in to follow this  

PeekMessage and CALLBACK messages....

This topic is 4042 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

Does anyone know how to get the WM_MOVE/WM_MOVING message with either GetMessage or PeekMessage? I tried putting this in my Window Process but it doesn't work like it did for WM_KILLFOCUS. case WM_MOVE: PostMessage(NULL, Msg, wParam, lParam); break; Same goes for WM_SIZE/SIZING. I need them to be able to be recieved within WinMain or I'll have to use global variables which I wish to stay away from. Thanks.

Share this post


Link to post
Share on other sites
Advertisement
Not sure, but have you tried just getting the message from Get/PeekMessage? ie..

MSG msg;
if (PeekMessage (&msg, hWnd, 0,0,PM_REMOVE)) {

// Catch message before call to wnd proc
if (msg.message==WM_MOVE)
PostMessage (NULL, Msg, msg.wParam, msg.lParam);

TranslateMessage (&msg);
DispatchMessage (&msg);
}

Share this post


Link to post
Share on other sites
Yep, I've tried, it seems that those messages are never put into the queue, but rather are sent directly to the callback function of the window. Even when I PostMessage it happens which makes no sense given I've gotten around it with WM_KILLFOCUS and WM_ACTIVATE. I'm not sure why MOVE/SIZE doesn't work that way too.

Share this post


Link to post
Share on other sites
Hmm, I might be understanding it wrong but the problem with that is not only are messages not being put into any sort of thread queue (going straight to the callback instead), but my application isn't MFC either.

Basically my callback is:


LRESULT CALLBACK WndProcess(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;

case WM_KILLFOCUS:
PostMessage(NULL, Msg, wParam, lParam);
break;
case WM_MOVE:
PostMessage(NULL, Msg, wParam, lParam);
break;

}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}


And then in my WinMain I have my PeekMessage loop:

while(PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
{
switch(Msg.message)
{

...


case WM_MOVE:
Other.Update();
break;

...



The current status of my CALLBACK was my attempt at fixing it because that's how I fixed WM_KILLFOCUS. No matter what though, WM_MOVE is never seen by PeekMessage.

Share this post


Link to post
Share on other sites
As you found WM_MOVE and similar messages (quite a lot actually) are not directly seen by the PeekMessage loop. They are sent directly (the window moving is done during a WM_NCLBUTTONDOWN message in a seperate Windows internal message loop).

Now since this is a seperate loop you won't see posted messages until the window move is finished. And SendMessage will bypass the queue.

In short: You won't be able to do that without ugly trickery. And you're not supposed to. You ought to process messages in the callback function. Period.

What are you trying to achieve?

Share this post


Link to post
Share on other sites
Basically I have an application that initializes the "engine" object in WinMain, and all the data is processed/rendered/updated inside this engine. So I have my WinMain process messages which are sent to this engine. If I were to use the callback to update the engine I would have to have a global so the object can be seen by both WinMain and the callback, but I want a global-less application.

Share this post


Link to post
Share on other sites
Hmm, the problem persists however.

You can make a window wrapper class inside your engine which encapsulates the window proc. For this to work however you need to make that method static. Use the windows user value to pass a pointer to your class and pass on messages it.

There's a nice wrapper sample by the almighty Oluseyi: Clicky

Basically you will enter a world of pain if you try to process all messages inside WinMain for no benefit.
Try to incorporate the WindowProc inside your engine or abstract it away; however do handle the messages inside a proper callback proc.

Share this post


Link to post
Share on other sites
Interesting, that link you provided is a way to go about it I've never seen, I'll have to give it a try. Thanks for the help. What is your preferred way to handle it?

Share this post


Link to post
Share on other sites
I appear to have run into a problem with that solution. This is a good day indeed.

It's all fine and functional, but the problem is that I don't want my messages handled in my Window class, but rather in my Engine class. So I've put the callback into the engine class, but my problem now is how to get it to communicate with that class since there's no 'This' in the callback. That tutorial shows how to do it via getting a handle to the window object, but what if I want to send my messages to my engine class? Any ideas?

Share this post


Link to post
Share on other sites
You could derive your engine from the window handler class making the classes proc virtual.

You could also keep both seperate and pass the messages from the window handler class via event handling to a handler method in your engine.

Since i work on Windows only i derived my engine/app class from the window handler class.

Share this post


Link to post
Share on other sites
Unless I'm understanding wrong, the problem with the second method is that it would require a global so both WinMain can talk to the Engine as well as the Callback talking to the Engine's message handler.

Also, with the first, then I would have to have WinMain -> Message Handler -> Engine which would also complicate things.

Right now it basically is structured as:

WinMain -> Engine

Engine -> Application (Sets up application instance, nothing else)
Engine -> Window (Sets up parent window)
Engine -> ChildWindow(Sets up various child windows depending on what is needed)
Engine -> Render (OpenGL class)

The Engine handles all input/events, so I would want the Engine to obtain messages as opposed to the Window class.

Share this post


Link to post
Share on other sites
You don't need globals for message handling.

I've got a templated IEventGenerator and IEventListener interface in my codebase.

The IEventGenerator interface is able to keep a list of IEventListeners and send or post them messages.
The IEventListener has a virtual method calles ProcessEvent which takes the templated event type as parameter.
If you use an approach like this neither the engine and the window need to know about each other.

The window class, derived from IEventGenerator passes all messages on to its listeners. The engine class, derived from IEventListener, registers itself as listener to the window class.

This way you could use the window class for other things as well.

Share this post


Link to post
Share on other sites
Hmm, so that would make it seem that the engine and the window classes are separate, as opposed to the window class being within the engine class as I have it. I basically want the engine to be the lower-most class that all other classes reside within, so it would seem I'm going to have to go about this a different way than I'm understanding you unless I want to rewrite how most all of it is structured as my engine classes uses the window class in many different ways at the moment.

There has to be a logical way to going about having the engine handle messages while the window class resides inside it, I must be going about this wrong. Before this project I was doing multithreaded work and it seems to have interfered with the way I'm thinking about things.

Share this post


Link to post
Share on other sites
The event handler and listener method works as well if the window is a member of the engine. The interfaces just provide a connection point for the messages.

Share this post


Link to post
Share on other sites
I still don't understand how it should be structured in my application then.

Engine class = Is created in WinMain. Handles all input, checks to see if keys are pressed, gets mouse cursor locations, clicks, etc.

Window class = created inside Engine to create a window and return various things such as the window dimensions, etc.


So I would have my CALLBACK declared inside the Engine, and passed to my Window::Create?

Well if that's the case, then how can I let my CALLBACK communicate with the engine? I don't need it to communicate with the window class. I don't understand from previous links and my own research how I can let the CALLBACK communicate with the the Engine. I do not understand how to create this bridge, could you please elaborate? Thanks.

Share this post


Link to post
Share on other sites
The window class has the callback function handler.

On creating the window class inside your engine you add the engine as listener to the window class. Now every message will be forwarded to the engine's callback function.

Some sample code:


class IWindowMessageHandler
{

public:

virtual ~IWindowMessageHandler()
{
}

virtual LRESULT HandleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) = 0;

}


Your Engine class derives from IWindowMessageHandler and implements the HandleMessage method:


class Engine : public IWindowMessageHandler
{

class IWindowMessageHandler
{

public:

virtual LRESULT HandleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{

switch ( uMsg )
{
case ...
}

return ::DefWindowProc( hWnd, uMsg, wParam, lParam );

}

}



Your Window class looks quite similar to the one in the linked article. You add a pointer to a IWindowMessageHandler as member, initialize it to NULL:


class Window
{
protected:

IWindowMessageHandler* m_pHandler;

public:

Window() :
m_pHandler( NULL )
{
// do original stuff from the article
}

void SetHandler( IWindowMessageHandler* pHandler )
{
m_pHandler = pHandler;
}

LRESULT CALLBACK MsgRouter( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{

Window *wnd = 0;

if(message == WM_NCCREATE)
{
// retrieve Window instance from window creation data and associate
wnd = reinterpret_cast<Window *>((LPCREATESTRUCT)lparam)->lpCreateParams;
::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(wnd));

// save window handle
wnd->SetHWND(hwnd);
}
else
{
// retrieve associated Window instance
wnd = reinterpret_cast<Window *>(::GetWindowLong(hwnd, GWL_USERDATA));
}
if ( wnd )
{
// we've got a handler
if ( m_pHandler )
{
return m_pHandler->HandleMessage( hwnd, message, wparam, lparam );
}

tyMessageIterator it;
it = wnd->GetMessageHandler(message);
if(it != NULL)
return (it->second)((*wnd), hwnd, wparam, lparam);
}
return DefWindowProc(hwnd, message, wparam, lparam);
}

};


You can call the SetHandler function during Create or afterwards to set the handler.

Share this post


Link to post
Share on other sites
Okay, I really hope I'm understanding this right.....

The way the engine handler can be seen by the 'real' handler is because I provide the real handler with a pointer to the engine handler? If that's the case I'm not sure why I need most of the other stuff, but it is starting to make sense. If that's not true then I'm just not following how to 'connect' the Engine handler to the CALLBACK.

Share this post


Link to post
Share on other sites
You could of course have the window class carry a pointer to the engine class and call it directly.

With the interfaces you create a connection point that makes the window class independant of the engine class.

Share this post


Link to post
Share on other sites
The way I have things though, my window class is inside the engine class, and it needs to be because I call multiple window class functions from within the engine on each update. So this solution won't work that way then? I've been working with some of the ideas presented so far and the problem I've run into is in fact getting the Window object to see the Engine message handler. I assume none of this will work with the Window object inside the Engine? Is there any other solution with it working this way? I really can't move the Window object outside of the engine, it would complicate things far too much.

Share this post


Link to post
Share on other sites
Of course the window class can have a pointer to the engine class. You just have to use forward declaration in the window class header file:


class Engine;

class Window
{

...

Engine* m_pEngine;
};


You do have to include "Engine.h" in "Window.cpp" though. This way you're able to call the engine's methods from the window class once you set the pointer:


Engine::Engine()
{
m_Window.m_pEngine = this;
}

Share this post


Link to post
Share on other sites
The problem with that however, is I already have the Window header included in my Engine header, so I get a redefinition error at the start of my Window header if I try and include my engine header.

Share this post


Link to post
Share on other sites
That's what the forward declaration is for. If you write class Engine; before the Window definition and only use a pointer or reference you don't have to include "engine.h".

Share this post


Link to post
Share on other sites
Oh, pardon that. Interesting, I've never seen it done like that before (Referencing the parent header), though it seems logical. I'm used to Perl includes/requires where redefinitions are required in some situations (use Vars, fun stuff). I should be good to go now, hopefully I don't run into any other problems, thanks for the help.

Share this post


Link to post
Share on other sites
And yet a new problem has arisen. you said to declare my Engine class before the Window class... but now that means that the Engine is declared for the Window class, but it's not defined, so I can't use any methods from my Engine class in my Window class, I get the errors:

error C2027: use of undefined type 'Engine'
see declaration of 'Engine'
error C2227: left of '->HandleMessage' must point to class/struct/union

On line:


&MessageHandler->HandleMessage(hWnd, Msg, wParam, lParam);

Which is in my MessageRouter in my WindowClass

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement