INTELLIGENT WORK FORUMS FOR COMPUTER PROFESSIONALS
Come Join Us!
- Talk With Other Members
- Be Notified Of Responses
To Your Posts
- Keyword Search
- Turn Off Ad Banners
- One-Click Access To Your
Favorite Forums
- Automated Signatures
On Your Posts
- Best Of All, It's Free!
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.
Partner With Us!
"Best Of Breed" Forums Add Stickiness To Your Site

(Download This Button Today!)
Member Feedback
"...Keep up the good work - excellent site - i'd been looking for something like this for ages !..."
Geography
Where in the world do Tek-Tips members come from?
|
Microsoft: Visual C++ FAQ
|
Programming
|
Sending and receiving messages between windows
Posted: 17 Oct 02
|
This FAQ is the result of particulary long thread on the subject of posting and receiving messages between windows in a program. The main reason, I have seen many requests for help on this subject before in this forum BUT there are some very powerful features which VC++ users should be aware of in addition to simple message routines - such as the ability to not only send a 'message' but actually attach objects to the message for retrieval in a different window. In any VC++ program, messages are bouncing around everywhere all the time between the different parts of the program. For example, when a user clicks the 'close box' of a window, a WM_CLOSE message is sent to different parts of the program which, in turn, enables those different parts to process the closing window accordingly.
However, you can actually post your own 'custom' messages between windows when the need arises. This helps with the OOP model ofeffectively 'doing-away' with global variables.
Suppose, for example, you have an MDI project. Your project will have a Main Frame window plus any number of document windows open at any time. Now, suppose also you have a dialog in the program which displays a list (database if you like) of all available documents. The database contains a ListCtrl item which displays the doc name and creation date. When the user creates a new document the database obviously needs updating to reflect the new doc. This works fine with only one drawback: if the database dialog is open when the new document is created, the changes are not reflected in the database dialog until you close the dialog and open it back up (effectively re-loading all DB entries). What we need is some way of knowing that a new document has been created PLUS we also need to know the title and creation date of the document. Many new programmers will immediately think of using some kind of global variable - but this defeats the whole point of OOP (Object Orientated Programming) where each class looks after itself and is not dependent on global objects flying around.
In cometh the messaging system and the CWnd::PostMessage() function.
Here's how it works: In your document class you can override the OnNewDocument() function and post a message to your CMainFrame code.
BOOL CMyDoc::OnNewDocument() { // Get a pointer to the main frame window CWnd* pMainFrame = ::AfxGetMainWnd(); // Now post a message to the main frame pMainFrame->PostMessage(WM_USER,NULL,NULL); }
Now in your CMainFrame code you can use class wizard to create a message handler for the PreTranslateMessage() function. In there you will be looking to intercept messages of type WM_USER. If you catch one, you know a new document had just been created:
BOOL MainFrame::PreTranslateMessage(MSG* pMsg) { // catch any WM_USER messages if (pMsg->message == WM_USER) { // we know a new doc has been created! } }
Now, this is a message in it's simplest form. There are two extra parameters in the PostMessage() function which we can take advantage of: wParam and lParam. These two parameters are effectively of type integer. Therefore you can further enhance your message processing capabilities at the catching end end by passing in numerical codes:
// Defines go in the header file! #define kMsg_Open 1234 #define kMsg_Save 1235 #define kMsg_New 1236
// An example would be to send this message from the // document's OnSaveDocument() override pMainFrame->PostMessage(WM_USER,kMsg_Save,NULL);
When it comes to catching the message in your Main Frame code, you can test each part of the message:
BOOL MainFrame::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_USER && pMsg->wParam == kMsg_Save && pMsg->lParam == NULL) { // We know a doc has been saved } }
Now for the most POWERFUL part of the message: You can actually pass a pointer to any object along with message. Recall that a pointer is just a numerical address in memory for the object. Both the wParam and lParam fields of a message are numercial integers so we can store some object in there and pass it around in a message!
Assume you have created a class called MyClass which stores the document's creation date and title. Your document's OnSaveDocument() could look like this:
BOOL CMyDoc::OnSaveDocument() { MyClass anObject; pMainFrame->PostMessage(WM_USER,kMsg_Save,(int)&anObject); }
Notice how we typecast the object to type (int) and pass in the address of the object (hence the '&' ampersand symbol). Now, in your MainFrame code, you can catch both the message and a pointer to anObject in the code:
BOOL MainFrame::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_USER && pMsg->wParam == kMsg_Save) { MyClass* pAnObject = (MyClass*)pMsg->lParam; } }
Notice we typecast the lParam parameter back to type MyClass* so now we have a pointer to the original object.
Going back to the original plan, we have caught the message and a pointer to the object. We now need to relay this to our database dialog for updating. If you've followed me so far you should know how to do this:
Assume the dialog is a child of the main frame, therefore let's assume our dialog is called m_DBDialog and is a member of the MainFrame class. You would simply relay the message on to the dialog:
BOOL MainFrame::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_USER && pMsg->wParam == kMsg_Save) { MyClass* pAnObject = (MyClass*)pMsg->lParam; // relay the message and pointer to database dialog m_DBDialog->PostMessage(WM_USER,kMsg_Save,(int)pAnObject); } }
You would then catch the message in your dialog's PreTranslateMessage() function in the same manner as you did in the MainFrame code!
Cool no???? |
Back to Microsoft: Visual C++ FAQ Index
Back to Microsoft: Visual C++ Forum
My FAQ Archive
Email This FAQ To A Friend |
|
 |
|