INFO: Message Retrieval in a DLL
ID: Q96479
|
The information in this article applies to:
-
Microsoft Windows Software Development Kit (SDK)
-
Microsoft Win32 Software Development Kit (SDK)
-
Microsoft Windows 2000
SUMMARY
When a function in a dynamic-link library (DLL) retrieves messages on
behalf of a calling application, the following must be addressed:
- The application and the DLL may be re-entered.
- The application can terminate while in the DLL's message retrieval
loop.
- The DLL must allow the application to preprocess any messages that
may be retrieved.
MORE INFORMATION
The following concerns arise when a function in a DLL retrieves
messages by calling GetMessage or PeekMessage:
- When the DLL function retrieves, translates, and dispatches
messages, the calling application and the DLL function may be re-
entered. This is because message retrieval can cause the calling
application to respond to user input while waiting for the DLL
function to return. The DLL function can return a reentrancy error
code if this happens. To prevent reentrancy, disable windows and
menu-items, or use a filter in the GetMessage or PeekMessage call
to retrieve specific messages.
- The application can terminate while execution is in the DLL
function's message retrieval loop. The WM_QUIT message retrieved by
the DLL must be re-posted and the DLL function must return to the
calling application. This allows the calling application's message
retrieval loop to retrieve WM_QUIT and terminate.
- When the DLL retrieves messages, it must allow the calling
application to preprocess the messages (to call
TranslateAccelerator, IsDialogMessage, and so forth) if required.
This is be done by using CallMsgFilter to call any WH_MSGFILTER
hook that the application may have installed.
The following code shows a message retrieval loop in a DLL function
that waits for a PM_COMPLETE message to signal the end of processing:
while (notDone)
{
GetMessage(&msg, NULL, 0, 0);
// PM_COMPLETE is a WM_USER message that is posted when
// the DLL function has completed.
if (msg.message == PM_COMPLETE)
{
Clean up and set result variables;
return COMPLETED_CODE;
}
else if (msg.message == WM_QUIT) // If application has terminated...
{
// Repost WM_QUIT message and return so that calling
// application's message retrieval loop can exit.
PostQuitMessage(msg.wParam);
return APP_QUIT_CODE;
}
// The calling application can install a WH_MSGFILTER hook and
// preprocess messages when the nCode parameter of the hook
// callback function is MSGF_MYHOOK. This allows the calling
// application to call TranslateAccelerator, IsDialogMessage, etc.
if (!CallMsgFilter(&msg, MSGF_MYHOOK))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
:
:
}
Define MSGF_HOOK to a value greater than or equal to MSGF_USER defined
in WINDOWS.H to prevent collision with values used by Windows.
Preprocessing Messages in the Calling Application
The calling application can install a WH_MSGFILTER hook to preprocess
messages retrieved by the DLL. It is not required for the calling
application to install such a hook if it does not want to preprocess
messages.
lpfnMsgFilterProc = MakeProcInstance((FARPROC)MsgFilterHookFunc,
ghInst);
hookprocOld = SetWindowsHook(WH_MSGFILTER, lpfnMsgFilterProc);
// Call the function in the DLL.
DLLfunction();
UnhookWindowsHook(WH_MSGFILTER, lpfnMsgFilterProc);
FreeProcInstance(lpfnMsgFilterProc);
MsgFilterHookFunc is the hook callback function:
LRESULT CALLBACK MsgFilterHookFunc(int nCode, WPARAM wParam,
LPARAM lParam)
{
if (nCode < 0)
return DefHookProc(nCode, wParam, lParam, &hookprocOld);
// If CallMsgFilter is being called by the DLL.
if (nCode == MSGF_MYHOOK)
{
Preprocess message (call TranslateAccelerator,
IsDialogMessage etc.);
return 0L if the DLL is to call TranslateMessage and
DispatchMessage. Return 1L if TranslateMessage and
DispatchMessage are not to be called.
}
else return 0L;
}
Additional query words:
yield
Keywords : kbNTOS kbWinOS2000 kbSDKWin32 kbGrpUser kbWinOS kbWndw kbWndwMsg
Version : WINDOWS:
Platform : WINDOWS
Issue type : kbinfo