Message Retrieval in a DLL

Last reviewed: November 2, 1995
Article ID: Q96479
The information in this article applies to:
  • Microsoft Windows Software Development Kit (SDK) versions 3.1
  • Microsoft Win32 Application Programming Interface (API) included with:

        - Microsoft Windows NT versions 3.5 and 3.51
        - Microsoft Windows 95 version 4.0
    

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 reference words: 3.10 3.50 3.51 4.00 95 yield
KBCategory: kbui
KBSubcategory: UsrMsg


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 2, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.