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


Last Reviewed: January 26, 2000
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.