- Messages in Windows
- Using Registered Messages
- Tips for Using Messages Well
- Summary
Using Registered Messages
Programmers often forget that they can use messages to pass data between two applications, between an application and a Dynamic Link Library (DLL), or even within an application. The registered message paradigm is even more overlooked. If your application already has 16,384 messages statically defined, you can use RegisterWindowMessage to go beyond that limitand these new message types are guaranteed unique.
It starts off with you registering a message with the RegisterWindowMessage function; the parameter should be a string containing the registered message, and the return value should be an ordinal of the message (or a zero, if the function failed):
static UINT WM_MYWINDOWSMESSAGE; .... WM_MYWINDOWSMESSAGE = RegisterWindowMessage("MyMessageString"); ....
Once you have that message, you can use it in a message-processing loop with the standard message case statement or in Microsoft Foundation Classes (MFC) with the ON_REGISTERED_MESSAGE macro:
ON_REGISTERED_MESSAGE(WM_MYWINDOWSMESSAGE,MyMessageFunction)
Here's another example (C/C++):
switch (iMsg) { case WM_MYWINDOWSMESSAGE: MyMessageFunction(); break; }
Since this is now a standard message, you can use the LPARAM and WPARAM of the function to pass data, and use typecasting to convert the parameters to data you can use:
UNIT CMyFunction::MyMessageFunction(WPARAM wParam, LPARAM lParam) { bool xmit,rec; xmit=(bool) wParam; rec = (bool) lParam; ..... return 0; }
This is a great way to pass data to and from a DLL that you can release, without having to give another programmer a header file. Just give him the strings of the messages you plan to send and let him call RegisterWindowMessage in his own header fileeven if the other programmer is writing in VB, Delphi, or some other programming language for Windows.
Since it's a Windows message, this lowers the overhead of your application, and even with the gigs of ram that we have in our systems now, a few cycles here and there still make a difference.
Remember, you need an hWnd (window handle) to send messages to the other application, and it needs your hWnd.
The other app will need to have an init function; this can be done either by exporting a function and calling it with the parameter of your hwnd, or by doing a FindWindow and looking for its Windows class defined lpszClassName. We'll deal with the message method, since that's what this article is all about.
Let's set up the lpszClassName first (this is using MFC):
WNDCLASS wndcls={0}; wndcls.lpfnWndProc = ::DefWindowProc; wndcls.hInstance = AfxGetInstanceHandle(); wndcls.hIcon = LoadIcon(IDR_MAINFRAME); // or load a // different icon wndcls.hCursor = LoadCursor( IDC_ARROW ); wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wndcls.lpszMenuName = NULL; // Specify your own class name for using FindWindow later // Register the new class and exit if it fails wndcls.lpszClassName = _T("MY OWN PROGRAM"); if(!AfxRegisterClass(&wndcls)) { TRACE("Class Registration Failed\n"); return FALSE; }
In C/C++ with the Windows API, you'd do the following:
if(!RegisterClass(&wndcls)) { TRACE("Class Registration Failed\n"); return FALSE; }
The lpszClassName for this app is set to MY OWN PROGRAM.
Next, we use the FindWindow function to get the hWnd of the app:
HWND theapp_hWnd = ::FindWindow(NULL, "MY OWN PROGRAM");
Now that we have the window handle of the other application, we can do a PostMessage to it with our hWnd:
::PostMessage(theapp_hWnd,WM_MYWINDOWMESSAGEINIT, (WPARAM) m_hwnd, NULL);
where the m_hWnd is your program's window handles. On the other app's end, there's code that takes your hWnd. Now you can both post messages to each other with the registered messages you've created in your init code.
I also recommend setting up a "bye" message, which you call to tell the other app that you're exiting and to stop sending messages to you. This can be done by adding another registered message in the function that passes and receives this message, setting the hWnds to NULL.