message q's and message mapping

I have already asked this question ...but could not get convincing reply..
In traditional way of windows programming... when a windows messages is generated say WM_LBUTTONDOWN this message is put in 'system message queue'
then OS(windows nt) will remove this message from 'system message queue' and puts in 'window message queue'(each window is having separte mess.queue)'.
Then the window removes the message and asks the 'windows'(OS) to call the wndproc call back function to handle the message.
1. So there are one system message queue
and message queues for all the windows in an application. Further every window is having it's own wndproc. Is it correct ?

2. Can u explain in detail how messages are handled by the MFC.(wanted a brief explanation). will the message map macros call again win32 sdk function.
where does these 'getmessage', dispath message' function comes and called in mfc way of message mapping process ?

3. Which class is providing a message loop eithere CWinApp::Run or CWinthread::Run

Adv. thanks
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Hi Sunraj !!!
   Yes u are right. There are 2 queues one for windows and another for windows window.
1)If u register u r class then u can have u r own windproc. Else the default window procedure will be called.
2)The dispatch message and translate message are there in CWinThread class. U r CWinApp class is derived from CWinThread. They are in implemented in the CWinThread::Run() function. U can also override this function to know the details. U can see the source files where CWinThread class is implemented.
3) Its CWinThread::Run()
This article contains all answers on your questions.
1) Windows has a system message queue, but it's not exposed to applications. Devices put events in the queue, and Windows reads them and translates them into real application messages.  This system queue exists once for the system, and Windows carefully prioritizes the way it decides to dispatch messages.

An application may have zero, one, or many message queues. If a thread within an application--even the primary thread--never calls a message-queue related function (like PeekMessage() or GetMessage()) it will never have a queue. If it does call such a function, it gets a queue. Since an app can have multiple threads, it might have multiple queues. A thread can process only messages in its own queue.

Your #2 and #3 questions are too intertwined:

MFC's CWinThread::Run() function has a message pump. There, MFC looks for messages that should be processed by the given thread. If it finds one, it looks in a map to see if the window handle for the message. If it finds a hit, it'll have the this pointer of the C++ CWnd-derived object that will be handling the message.

With that pointer, MFC gets the first message map. It looks through the map to see if there's a handler. If it finds no handler, it starts looking in related classes. It might also consider other windows--if the message is a command message, it might be reflected or routed. That's just a matter of picking another set of windows, using a few simple rules, to try to find a handler.

If a match is eventually found, MFC unpacks the parameters to the message (from wParam and lPAram) and makes them in to real C++ types. Then, it throws 'em on the stack and makes the call.

It's CWinThread::Run() that actually has the message pump. It calls PeekMessage(), and if a message is pending, it will call CWinThread::PumpMessage() to initiate the process I describe above.

Any good book on Windows or MFC should answer your questions. I explain all of these things in great detail in my own book. Jeff Richter's book explains it very well from a Win32 perspective, and Jeff Prosise's book is another good explanation from the MFC point of view.

..B ekiM
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

sunrajAuthor Commented:
dear mr.mikeblas could you start with a simple example say WM_LBUTTONDOWN. Now this message will go where...does it goes to system mess. queue...then will the operating system will notify the application that there is a message for it. Now cwinthread::run get's the message and dispatches the message to where....? when the message map macros comes into picture....
the CWinThread::Run() function makes a call to a member function called
PumpMessage(). This function implementation looks something like this:

DispatchMessage will route the messages to a Window Procedure. MFC's standard Window procedure is AfxWndProc(). This then calls the appropriate window object, where the message is received by the corresponding CWnd::WindowProc() function. This function parses the wParam and lParam values and calls member functions in CWnd derived classes.

hope this helps.
> dear mr.mikeblas could you start with a simple
 > example say WM_LBUTTONDOWN.

When you have the mouse in your hand, you press the left-button. The mouse driver notices this action and creates a system message about it.

The system decides to go looking at the system message queue. It finds a record of the mouse press, as well as information about where the mouse cursor was at the time the button was pressed. The system figures out which window was under the mouse when it was pressed and checks to see if some application had captured the mouse. It needs to do that in order to decide which window should receive the WM_LBUTTONDOWN message.

The exercise of finding the recipient window in the system is called targeting. All messages in Windows are really destined for only one window. If you were following a keyboard message, for instance, it would be targeted to the window that had input focus.

Windows will then remove the low-level hardware event message from the system queue and make a WM_LBUTTONDOWN message and place it in the thread queue for the thread which owns the targeted window.

Assuming that's an MFC window, the message is picked up as MFC pumps messages from the loop in CWinThread::Run(). Run() realizes it has messages to process, so it calls CWinThread::PumpMessage().  (Like I said in my previous answer.)

CWinThread::PumpMessage() actually calls ::GetMessage(), which retrieves a MSG structure--which completely defines a Windows message. Part of that information is the window handle that is targeted to be the recipient of the message; the rest of the structure includes the message ID, the wParam and lParam for the message, and the tickcount when the message was posted.

CWinThread::PumpMessage() then [normally] calls ::TranslateMessage(), which decides if the message was really a keyboard input message that should be translated into a WM_COMMAND message--as if activating a menu by keyboard.  That just modifies the MSG structure, in-place.

Finally, CWinThread::PumpMessage() calls ::DispatchMessage().  DispatchMessage() looks up the window proc for the window which was targeted to receive the message, and calls that WindowProc with the appropriate parameters.  For a popup window in an MFC application, the window proc is AfxWindowProc().  There, the mapping lookup I mentioned in the previous post is done. MFC calls the AfxCallWndPRoc() helper function, passing a pointer to the CWnd object which will handle the message--along with the rest of the message parameters.

AfxCallWndProc() turns around and calls CWnd::WindowProc(). There, MFC sets up a backstop exception handler so that any exceptions your application throws, but doesn't catch, are handled without trying to return them through Windows. (Which won't work!)  From there, we go to CWnd::OnWndMsg().

It's in OnWndMsg() that we first try to find a message map. First, we look in a cache which holds references to maps for the most recently received messages. If we don't get a cache hit, a linear search happens to find the message proc. The comparison is done simply on the message id.

If a match is found, MFC will call the function identified in the message map. If no match is found, MFC ends up calling CWnd::DefWindowProc(), which turns around and calls the default window procedure for the window--that's what you're supposed to do with window (non-dialog) messages you don't handle yourself.

That's how it works.  There are some special cases I skipped; most notably, dialog messages and messages sent as a window is first created and MFC is just learning about its existance.

..B ekiM


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
wow mikeblas, that was really a comprehensive explanation. since you have started the explanation, there are a few queries here.
Regarding the message map maintained by MFC, is a single message map maintained for all windows objects (more specifically CCmdTarget derived object). what exactly is the structure of this message map?
Can you give us an idea of how the special cases skipped by you are handled - i.e. dialog messages and window creation messages.
> that was really a comprehensive explanation

It sure is.  And all for only seventy points!

 > Regarding the message map maintained by MFC, is a
 > single message map maintained for all windows objects
 > (more specifically CCmdTarget derived object).
 > what exactly is the structure of this message map?

This is described and answered in great detail in my book.

..B ekiM
Please remember to grade your question.

..B ekiM
mikeblas, i appreciated your answer, but i did not ask it. only sunraj, who actually asked it can do so.
> only sunraj, who actually asked it can do so.

Of course. It was him whom I was addresing.

..B ekiM

It's been nearly a month.  Please grade your answer before the autograder cheats me.

..B ekiM
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.