home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l430 / 1.ddi / SOURCE.ZIP / WMHANDLR.C < prev   
Encoding:
C/C++ Source or Header  |  1992-06-09  |  8.9 KB  |  278 lines

  1. /*
  2.     WMHANDLR.C -- Windows message handling without switch statements
  3.     Part of the WINIO Library
  4.     
  5.     Copyright (c) Dave Maxey & Andrew Schulman, 1990-1992.
  6.     All Rights Reserved.
  7.     
  8.     Contact:  Andrew Schulman (CompuServe 76320,302)
  9.     
  10.     From Chapter 4 of "Undocumented Windows" (Addison-Wesley 1992)
  11.     by Andrew Schulman, Dave Maxey and Matt Pietrek
  12. */
  13.  
  14. #include <windows.h>
  15. #include <string.h>
  16. #include "wmhandlr.h"
  17.  
  18. long  defwmhandler(HWND, unsigned, WORD, LONG);
  19.  
  20.  
  21. /* -----------------------------------------------------------------------    */
  22. /* Sees if this is one of the 16 allowable extra message handlers handling    */
  23. /* messages above WM_USER. If so, returns TRUE, and puts the index of the    */
  24. /* handler in the wmhandlrtable into pwExtraMsg. Otherwise returns FALSE    */
  25. /* -----------------------------------------------------------------------  */
  26. BOOL wmhandler_isextramsg(WMTAB wmTab, WORD wMsg, WORD *pwExtraMsg)
  27.     {
  28.     WORD i;
  29.     
  30.     for (i = 0; i < MAX_EXTRA_WMS; i++)
  31.         if (wmTab->wExtraMsg[i] == wMsg)
  32.             {
  33.             *pwExtraMsg = i + WM_USER;
  34.             return TRUE;
  35.             }
  36.     return FALSE;
  37.     }
  38.  
  39.  
  40. /* -----------------------------------------------------------------------    */
  41. /* Gets the current handler for the supplied message above WM_USER if one    */
  42. /* is registered. If none is registered, returns NULL.                        */
  43. /* -----------------------------------------------------------------------  */
  44. WMHANDLER wmhandler_getextratab(WMTAB wmTab, WORD wMsg)
  45.     {
  46.     WORD i;
  47.     
  48.     for (i = 0; i < MAX_EXTRA_WMS; i++)
  49.         if (wmTab->wExtraMsg[i] == wMsg)
  50.             return wmTab->wmhandlertable[WM_USER+i];
  51.     return NULL;
  52.     }
  53.  
  54.  
  55. /* -----------------------------------------------------------------------    */
  56. /* Sets the current handler for the supplied message above WM_USER to the    */
  57. /* specified function. If the message was already registered, updates the    */
  58. /* handler and returns the previous. Otherwise, registers the message at    */
  59. /* the first free entry in the table, and returns defwmhandler as the        */
  60. /* previous handler. If none available, returns NULL.                        */
  61. /* -----------------------------------------------------------------------  */
  62. WMHANDLER wmhandler_setextratab(WMTAB wmTab, WORD wMsg, WMHANDLER f)
  63.     {
  64.     WORD i, iUse = 0xffff;
  65.     WMHANDLER old = defwmhandler;
  66.     
  67.     // Is it in the table of extra wmhandlers
  68.     for (i = 0; i < MAX_EXTRA_WMS; i++)
  69.         if (wmTab->wExtraMsg[i] == wMsg)
  70.             break;
  71.         else
  72.         // while we're going through, identify a free entry
  73.         if ((wmTab->wExtraMsg[i] == 0) && (iUse == 0xffff)) 
  74.             iUse = i;
  75.  
  76.     if ( i < MAX_EXTRA_WMS)
  77.         iUse = i;
  78.     
  79.     if (iUse == 0xffff)
  80.         return NULL;
  81.     
  82.     // Out with the old, in with the new
  83.     old = wmTab->wmhandlertable[WM_USER+iUse];
  84.     wmTab->wmhandlertable[WM_USER+iUse] = f ? f : defwmhandler;
  85.     
  86.     // If the entry is being NULLed, remove it
  87.     if ((! f) || (f == defwmhandler))
  88.         wmTab->wExtraMsg[iUse] = 0;
  89.     else
  90.         wmTab->wExtraMsg[iUse] = wMsg;
  91.     
  92.     return old;
  93.     }
  94.  
  95.  
  96. /* -----------------------------------------------------------------------  */
  97. /* This is our event processor. It is the dispatcher for the handlers set   */
  98. /* using SetHandler. An Application plugs this function into its            */
  99. /* window, sets handlers for messages, and wndproc handles the rest.        */
  100. /* This window procecedure should never need to be changed!                 */
  101. /* -----------------------------------------------------------------------  */
  102. long FAR PASCAL _export wmhandler_wndproc(HWND hWnd, WORD wMsg,
  103.         WORD wParam, LONG lParam)
  104.     {
  105.     LPCREATEPARAMS lpcp;
  106.     WMTAB wmTab;
  107.     WORD wExtraMsg;
  108.     
  109.     // On a CREATE, the message table needs to be installed
  110.     // and a WM_GETMINMAXINFO is the first message received
  111.  
  112.     if (wMsg == WM_CREATE)
  113.         {
  114.         lpcp = (LPCREATEPARAMS) ((LPCREATESTRUCT) lParam)->lpCreateParams;
  115.         SetWindowLong(hWnd, 0, (DWORD) (lpcp->wmTab));
  116.         SetWindowLong(hWnd, 4, (DWORD) (lpcp->lpData));
  117.         }
  118.  
  119.     if ((! hWnd) || ((wmTab = (WMTAB) GetWindowLong(hWnd, 0)) == NULL))
  120.         return DefWindowProc(hWnd, wMsg, wParam, lParam);
  121.     
  122.     if (wMsg < WM_USER)
  123.         return (*(wmTab->wmhandlertable[wMsg]))(hWnd, wMsg, wParam, lParam);
  124.     else
  125.     if (wmhandler_isextramsg(wmTab, wMsg, &wExtraMsg))
  126.         return (*(wmTab->wmhandlertable[wExtraMsg]))
  127.             (hWnd, wMsg, wParam, lParam);
  128.     else
  129.         return DefWindowProc(hWnd, wMsg, wParam, lParam);
  130.     }
  131.  
  132. /* ---------------------------------------------------------------- */
  133. /* Routines to get and set the message handlers. Setting to NULL    */
  134. /* uninstalls a handler, by setting the handler to the default      */
  135. /* which calls Windows own DefWndProc.                              */
  136. /* ---------------------------------------------------------------- */
  137. WMHANDLER wmhandler_get(HWND hWnd, WORD wMsg)
  138.     {
  139.     WMTAB wmTab = (WMTAB) GetWindowLong(hWnd, 0);
  140.     return (wMsg < WM_USER) ?
  141.         wmTab->wmhandlertable[wMsg] :
  142.         wmhandler_getextratab(wmTab, wMsg);
  143.     }
  144.  
  145. WMHANDLER wmhandler_settab(WMTAB wmTab, WORD wMsg, WMHANDLER f)
  146.     {
  147.     WMHANDLER oldf;
  148.  
  149.     if (wMsg < WM_USER)
  150.         {
  151.         oldf = wmTab->wmhandlertable[wMsg];
  152.         wmTab->wmhandlertable[wMsg] = f ? f : defwmhandler;
  153.         return (oldf ? oldf : defwmhandler);
  154.         }
  155.     else
  156.         return wmhandler_setextratab(wmTab, wMsg, f);
  157.     }
  158.  
  159. WMHANDLER wmhandler_set(HWND hWnd, WORD wMsg, WMHANDLER f)
  160.     {
  161.     WMTAB wmTab = (WMTAB) GetWindowLong(hWnd, 0);
  162.     return wmhandler_settab(wmTab, wMsg, f);
  163.     }
  164.  
  165. /* ----------------------------------------------------------------------- */
  166. /* This is a default handler so that an application chain on to a previous */
  167. /* handler from their current one without having to worry what was there   */
  168. /* before. All this default handler does is to call DefWindowProc.         */
  169. /* ----------------------------------------------------------------------- */
  170. long defwmhandler(HWND hwnd, unsigned wMsg, WORD wParam, LONG lParam)
  171.     {   
  172.     return DefWindowProc(hwnd, wMsg, wParam, lParam);
  173.     }
  174.  
  175. /* -------------------------------------------------------------------  */
  176. /* Create a new wm handler function disatch table.                        */
  177. /* -------------------------------------------------------------------  */
  178. WMTAB wmhandler_create(void)
  179.     {
  180.     int i;
  181.     WMTAB wmTab;
  182.     
  183.     if (! (wmTab = (WMTAB) GlobalLock(
  184.                         GlobalAlloc(GMEM_MOVEABLE, sizeof(WMHANDLERDATA)))))
  185.         return NULL;
  186.     
  187.     for (i = 0; i < WM_USER + MAX_EXTRA_WMS; i++) 
  188.         wmTab->wmhandlertable[i] = defwmhandler;
  189.     
  190.     for (i = 0; i < MAX_EXTRA_WMS; i++)
  191.         wmTab->wExtraMsg[i] = 0;
  192.     
  193.     return wmTab;
  194.     }
  195.  
  196.  
  197. /* -------------------------------------------------------------------  */
  198. /* Destroy a wm handler function disatch table.                            */
  199. /* -------------------------------------------------------------------  */
  200. void wmhandler_destroy(HWND hwnd)
  201.     {
  202.     GlobalFree(LOWORD(GlobalHandle(HIWORD(GetWindowLong(hwnd, 0)))));
  203.     SetWindowLong(hwnd, 0, NULL);
  204.     }
  205.  
  206.  
  207. /* -------------------------------------------------------------------  */
  208. /* Returns an HWND that can be used as a message recicipent. The         */
  209. /* window is invisible.  Somewhat like "object windows" in PM.            */
  210. /* -------------------------------------------------------------------  */
  211. HWND wmhandler_hwnd(char *name)
  212. {
  213.     extern HANDLE __hPrevInst;    // in ARGCARGV
  214.     extern HANDLE __hInst;
  215.     HWND hWnd;
  216.     CREATEPARAMS cp;
  217.         
  218.     if (! __hPrevInst) // NOT VALID! ASSUMES LAST APP DID WMHANDLER_HWND()
  219.         {
  220.         WNDCLASS wndclass;
  221.         memset(&wndclass, 0, sizeof(wndclass));
  222.         wndclass.lpfnWndProc = wmhandler_wndproc;
  223.         wndclass.hInstance = __hInst;
  224.         wndclass.lpszClassName = "OBJECTWND";
  225.         wndclass.cbWndExtra = 8;
  226.         RegisterClass(&wndclass);
  227.         }
  228.     
  229.     if (! (cp.wmTab = wmhandler_create()))
  230.         return NULL;
  231.     
  232.     /* MAYBE SHOULD HAVE ICON, WITH EXIT/ABOUT... */
  233.  
  234.     if (! (hWnd = CreateWindow("OBJECTWND", name, WS_DISABLED,
  235.         0, 0, 0, 0, NULL, NULL, __hInst, (LPSTR) &cp)))
  236.         return NULL;
  237.     
  238.     return hWnd;
  239.     }
  240.  
  241. /* -------------------------------------------------------------------  */
  242. /* This is where messages get received and dispatched. In cooperative   */
  243. /* multitasking of Windows, this function MUST be called periodically.  */
  244. /* Same as winio_yield(); probably ought to have been here instead.     */
  245. /* -------------------------------------------------------------------  */
  246. void wmhandler_yield(void)
  247.     {
  248.     MSG msg;
  249. #ifdef POWER_UNFRIENDLY
  250.     while (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
  251.         {
  252.         TranslateMessage(&msg);
  253.         DispatchMessage(&msg);
  254.         }
  255. #else
  256. #ifdef PRE_APP_TIMER
  257.     if (InSendMessage())
  258.         return;
  259.     for (;;)
  260.         {
  261.         if (! GetMessage(&msg, NULL, 0, 0))
  262.             break;
  263.         TranslateMessage(&msg);
  264.         DispatchMessage(&msg);
  265.         if (! PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE))
  266.             break;
  267.         }
  268. #else
  269.     if (GetMessage(&msg, NULL, 0, 0))
  270.         {
  271.         TranslateMessage(&msg);
  272.         DispatchMessage(&msg);
  273.         }
  274. #endif
  275. #endif
  276.     }
  277.         
  278.