Solved

Passing Sent Messages to Child and Popup Windows

Posted on 2004-04-21
5
339 Views
Last Modified: 2013-11-20
I have a windows messenging delimma.

I perform several functions for my applications in worker threads and need to send messages back to the GUI to update itself and its child windows.  I need to be able to send a parameter with the message to say which object number to update.  I have come to understand that that means I cannot use a WM_COMMAND message, since wParam must be used to say what to do (for example ID_UPDATE_FORM) and lParam must be 0 so I cannot use it for telling which object to update.  Someone please tell me if there is a good way around this.

As a result of this I went to the idea of using a WM_APP message instead.  Then I could use the message itself to say what to do and the wParam to say which object it is and have lParam at my dispense for future needs.  I implemented this and it works fine, except that I need to be able to SendMessage instead of PostMessage or it causes problems.  I can catch the Posted Messages in my MainWnd's PreTranslateMessage() and then pass them from there to my child and popup windows.  I just don't know how to do this with Sent messages.  Anybody tell me how to do this?

StringsandBeyond
0
Comment
Question by:stringsandbeyond
  • 3
  • 2
5 Comments
 
LVL 14

Accepted Solution

by:
wayside earned 250 total points
Comment Utility
You could try using SendNotifyMessage instead of SendMessage, that will prevent the thread from blocking until the message is handled, and avoid message deadlocks.

If your worker thread has to wait until the main app has processed the event, you could use some other means of synchronizing, such as an event (the kind created by the CreateEvent() function).

In your thread you create the event, pass its handle in your PostMessage call, and WaitForSingleObject() on the event.

In your main app, in your event handler, after you are done processing, signal the event (using SetEvent() for example).

I am surprised that you can't catch the event in PreTranslateMessage() though. MSDN says it directly calls the windows proc of the window the message is sent to, although you can wind up with a deadlock doing this:

"If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code."

and

"A thread that calls the SendMessage function to send a message to another thread cannot continue executing until the window procedure that receives the message returns. If the receiving thread yields control while processing the message, the sending thread cannot continue executing, because it is waiting for SendMessage to return. If the receiving thread is attached to the same queue as the sender, it can cause an application deadlock to occur."
0
 

Author Comment

by:stringsandbeyond
Comment Utility
Wayside,

Thanks for the good info.  Your thoughts spawned an idea that lead me to the answer.  I just needed to Overload the WindowProc() function and transmit the messages from there.  I wondered, however, what the deal is about this application deadlock.  I guess I don't think my application could get it, but perhaps I am just not understanding what it takes for it to occur.  My application is using worker threads to download xml objects from a website.  Once it downloads and adds the object to a global db object it sends a message to the gui with the index number of the new object to have it add it to the CListCtrl on one of its child windows.  After adding it, the OnUpdateList() function that I use simply returns, which ultimately would give control back to the worker thread.  Do you see danger that my app will end up in deadlock?
0
 
LVL 14

Expert Comment

by:wayside
Comment Utility
Your app looks like it should be OK as far as deadlock goes.

Given your description, it's not obvious to me why PostMessage() wouldn't work for you though. After thinking about it further, I'm wondering if you created an ON_MESSAGE entry in your message map to handle the WM_APP messages. You shouldn't have to handle these in PreTranslateMessage() (unless of course you want to), the better way is to add a handler in the message map. A message sent via SendMessage() would also be handled by the message handler. If I get a chance I'll build a small app and try this myself.

Anyway, here's the section from MSDN on message deadlocks:

"Message Deadlocks

A thread that calls the SendMessage function to send a message to another thread cannot continue executing until the window procedure that receives the message returns. If the receiving thread yields control while processing the message, the sending thread cannot continue executing, because it is waiting for SendMessage to return. If the receiving thread is attached to the same queue as the sender, it can cause an application deadlock to occur. (Note that journal hooks attach threads to the same queue.)

Note that the receiving thread need not yield control explicitly; calling any of the following functions can cause a thread to yield control implicitly.

DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam
GetMessage
MessageBox
PeekMessage
SendMessage

To avoid potential deadlocks in your application, consider using the SendNotifyMessage or SendMessageTimeout functions. Otherwise, a window procedure can determine whether a message it has received was sent by another thread by calling the InSendMessage or InSendMessageEx function. Before calling any of the functions in the preceding list while processing a message, the window procedure should first call InSendMessage or InSendMessageEx. If this function returns TRUE, the window procedure must call the ReplyMessage function before any function that causes the thread to yield control. "
0
 

Author Comment

by:stringsandbeyond
Comment Utility
Thanks for the further clarification.  I don't ever explicitly give up control, but at times I may call a MessageBox or something else which might.  Perhaps I should try posting them.  Initially I tried posting them and was getting problems.  I thought it was because of having two threads accessing my global db object.  After looking into it more I discovered it was actually my function declarations for my message handlers.  I hate MFC on that!!!  The debug libraries put up with it, but the release libraries throw an access violation.  I had my message handlers defined like this:

ON_MESSAGE(WM_APP_UPDATE_FORM, OnUpdateForm)
afx_msg void OnUpdateForm();

However, they must be like this:

afx_msg LRESULT OnUpdateForm(WPARAM wParam, LPARAM lParam);

This is the third time this has burned me.  I should have learned by now.

Acutally I think I lost you on the WindowProc() stuff.  What I meant is that I send the message to my main window and then relay them to my child and popup windows in WindowProc().  I do not actually handle them there.  The problem before was that I tried to handle them in PreTranslateMessage, but messages that are Sent and not Posted do not ever pass through there so I could not relay them via that override.  Thanks for your help!
0
 
LVL 14

Expert Comment

by:wayside
Comment Utility
Using PostMessage() is the best, it avoids all chances of deadlock.

I just built a small app which creates a thread which alternately does a PostMessage and a SendMessage. The ON_MESSAGE handler I set up gets both of them. So I think you should be able to use either one.

> After looking into it more I discovered it was actually my function declarations for my message handlers.

Hehe, been there done that. :)

> What I meant is that I send the message to my main window and then
> relay them to my child and popup windows in WindowProc().

It's rare in my experience to need to override WindowProc(), in fact I'm not sure I've ever done it. If you need to have the message handled somewhere else you could either post it to that window to begin with, have the message handler in your main window post it again to the window that needs to get it, or directly call the appropriate handler in the child window class.

0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Suggested Solutions

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now