home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / SAMPLES / MAKEAPP / APP.C_ / APP.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  7.5 KB  |  265 lines

  1. #include "makeapp.h"
  2.  
  3. // Globals
  4.  
  5. APP    g_app;
  6. UINT   WM_MSGFILTER = 0;      // Private message
  7.  
  8. int PASCAL WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int cmdShow)
  9. {
  10.     // Initialize the APP structure
  11.     //
  12.     g_app.hinst       = hinst;
  13.     g_app.hinstPrev   = hinstPrev;
  14.     g_app.lpszCmdLine = lpszCmdLine;
  15.     g_app.cmdShow     = cmdShow;
  16.     g_app.hwndMain    = NULL;
  17.     g_app.codeExit    = 1;      // Assume failure
  18.     g_app.fQuit       = FALSE;
  19.  
  20.     // Initialize, run, and terminate the application
  21.     //
  22.     if (App_Initialize(&g_app))
  23.         App_Run(&g_app);
  24.  
  25.     App_Terminate(&g_app, (g_app.codeExit == 0 ? TERM_QUIT : TERM_ERROR));
  26.  
  27.     return g_app.codeExit;
  28. }
  29.  
  30. // Process messages until it's time to quit.
  31. //
  32. void App_Run(APP* papp)
  33. {
  34.     while (App_ProcessNextMessage(papp))
  35.         ;
  36. }
  37.  
  38. // Process the next incoming message, or, if none are available,
  39. // perform a slice of idle processing.
  40. //
  41. // Returns TRUE to continue processing messages, FALSE to quit the app.
  42. //
  43. BOOL App_ProcessNextMessage(APP* papp)
  44. {
  45.     // If we've already processed a WM_QUIT message, just return TRUE.
  46.     //
  47.     if (papp->fQuit)
  48.         return FALSE;
  49.  
  50.     // If a message exists in the queue, translate and dispatch it.
  51.     //
  52.     if (PeekMessage(&papp->msg, NULL, 0, 0, PM_REMOVE))
  53.     {
  54.         // See if it's time to quit...
  55.         //
  56.         if (papp->msg.message == WM_QUIT)
  57.         {
  58.             papp->codeExit = (int)papp->msg.wParam;
  59.             papp->fQuit = TRUE;
  60.             return FALSE;
  61.         }
  62.  
  63.         // Call the message filter hook to handle
  64.         // accelerators, modal dialog messages, and the like
  65.         //
  66.         if (!CallMsgFilter(&papp->msg, MSGF_MAINLOOP))
  67.         {
  68.             TranslateMessage(&papp->msg);
  69.             DispatchMessage(&papp->msg);
  70.         }
  71.     }
  72.     else
  73.     {
  74.         // No messages: do idle processing.
  75.         // If the idle proc need not be called any longer,
  76.         // call WaitMessage() to suspend the application.
  77.         //
  78.         if (!App_Idle(papp))
  79.             WaitMessage();
  80.     }
  81.     return TRUE;
  82. }
  83.  
  84. static HHOOK hhook = NULL;
  85.  
  86. // Register the "WM_MSGFILTER" window message, and install our
  87. // message filter hook procedure.
  88. //
  89. BOOL App_InitializeHook(APP* papp)
  90. {
  91.     WM_MSGFILTER = RegisterWindowMessage("WM_MSGFILTER");
  92.     if (WM_MSGFILTER == NULL)
  93.         return FALSE;
  94.  
  95.     hhook = SetWindowsHookEx(WH_MSGFILTER, (FARPROC)App_MsgFilterHook, g_app.hinst, GetWindowTask(g_app.hwndMain));
  96.     if (hhook == NULL)
  97.         return FALSE;
  98.  
  99.     return TRUE;
  100. }
  101.  
  102. // If necessary, uninstall our message filter hook.
  103. //
  104. void App_TerminateHook(APP* papp)
  105. {
  106.     UnhookWindowsHookEx(hhook);
  107. }
  108.  
  109. // Message filter hook proc.  Calls App_MsgFilter to do the work,
  110. // after guarding against infinite recursion.
  111. //
  112. LRESULT __export CALLBACK App_MsgFilterHook(int code, WPARAM wParam, LPARAM lParam)
  113. {
  114.     BOOL fProcessed = FALSE;
  115.     static LPARAM lParamPrev = NULL;
  116.  
  117.     if (code < 0)
  118.         return CallNextHookEx(hhook, code, wParam, lParam);
  119.  
  120.     // Prevent infinite recursion if CallMsgFilter is called recursively,
  121.     // such as from a call to IsDialogMessage(), which calls CallMsgFilter.
  122.     //
  123.     if (lParam == lParamPrev)
  124.         return (LRESULT)FALSE;
  125.  
  126.     lParamPrev = lParam;
  127.  
  128.     // Call App_MsgFilter to filter the message.
  129.     //
  130.     fProcessed = App_MsgFilter(&g_app, (MSG FAR*)lParam, code);
  131.  
  132.     lParamPrev = NULL;
  133.  
  134.     return (LRESULT)fProcessed;
  135. }
  136.  
  137. // All posted (queued) messages are routed here via the WH_MSGFILTER hook.
  138. //
  139. BOOL App_MsgFilter(APP* papp, MSG FAR* lpmsg, int context)
  140. {
  141.     HWND hwnd;
  142.     HWND hwndNext;
  143.     BOOL fSentToMain = FALSE;
  144.  
  145.     // Don't filter WM_PAINT messages, to make repainting
  146.     // as efficient as possible.  It's not useful or possible
  147.     // to filter WM_PAINT messages here anyhow since many are
  148.     // sent directly to destination window via UpdateWindow().
  149.     //
  150.     if (lpmsg->message == WM_PAINT)
  151.         return FALSE;
  152.  
  153.     // This loop enumerates the destination window and all its parents,
  154.     // until a top-level window is reached.  Then, GetParent() enumerates
  155.     // owner windows: in this way, an app's main window can filter messages
  156.     // destined for its owned dialogs or dialog controls.
  157.     //
  158.     for (hwnd = lpmsg->hwnd; hwnd != NULL; hwnd = hwndNext)
  159.     {
  160.         // Get the "next" window before we send the message,
  161.         // in case hwnd is destroyed while handling the message.
  162.         //
  163.         hwndNext = GetParent(hwnd);
  164.  
  165.         if (hwnd == papp->hwndMain)
  166.             fSentToMain = TRUE;
  167.  
  168.         if (FORWARD_WM_MSGFILTER(hwnd, lpmsg, context, SendMessage))
  169.             return TRUE;
  170.     }
  171.  
  172.     // If we haven't already sent the message to the main window,
  173.     // do so now.  This ensures that the main window has a chance
  174.     // to filter any unfiltered messages for any window in this app.
  175.     //
  176.     if (!fSentToMain)
  177.         return FORWARD_WM_MSGFILTER(papp->hwndMain, lpmsg, context, SendMessage);
  178.  
  179.     return FALSE;
  180. }
  181.  
  182. // This function is called when there are no messages available in the
  183. // queue, and can be used to perform "background" processing tasks.
  184. //
  185. // As with the processing of messages, you should not spend too much
  186. // time in this call, or the application will not seem responsive to
  187. // user actions.
  188. //
  189. // App_Idle() will continue to be called as long as the function returns
  190. // TRUE.
  191. //
  192. BOOL App_Idle(APP* papp)
  193. {
  194.     // Return TRUE to get called again (i.e., there is more work to do),
  195.     // FALSE if there is no more idle processing to do.
  196.     //
  197.     return FALSE;
  198. }
  199.  
  200. // Initialize the application
  201. //
  202. // Startup information is provided in *papp.
  203. //
  204. BOOL App_Initialize(APP* papp)
  205. {
  206.     if (!App_InitializeHook(papp))
  207.         return FALSE;
  208.  
  209.     if (!Frame_Initialize(papp))
  210.         return FALSE;
  211.  
  212.     if (!Client_Initialize(papp))
  213.         return FALSE;
  214.  
  215.     papp->hwndMain = Frame_CreateWindow(
  216.             "MakeApp Application",
  217.             CW_USEDEFAULT, CW_USEDEFAULT,
  218.             CW_USEDEFAULT, CW_USEDEFAULT,
  219.             papp->hinst);
  220.  
  221.     if (papp->hwndMain == NULL)
  222.     return FALSE;
  223.  
  224.     ShowWindow(papp->hwndMain, papp->cmdShow);
  225.  
  226.     return TRUE;
  227. }
  228.  
  229. void App_Terminate(APP* papp, int codeTerm)
  230. {
  231.     // Called on app termination.  codeTerm indicates the
  232.     // reason for the termination:
  233.     //
  234.     // TERM_QUIT: The application main loop terminated normally
  235.     // due to recieving a WM_QUIT message.  You should destroy all
  236.     // created windows, GDI objects, and any other resources that
  237.     // may have been allocated.
  238.     //
  239.     // TERM_ENDSESSION: The application is being terminated because
  240.     // the windows session is being ended by the user.  The application
  241.     // need NOT destroy windows, GDI objects, or memory, but simply
  242.     // flush disk caches, close files, etc.
  243.     //
  244.     // TERM_ERROR: An error occured while initializing the app,
  245.     // or the application main loop was terminated abnormally with
  246.     // a WM_QUIT message with a non-zero value in wParam.
  247.     // The application should destroy all allocated windows, GDI
  248.     // objects, and other allocated resources, as well as flush
  249.     // caches and such to disk.
  250.     //
  251.     if (codeTerm != TERM_ENDSESSION)
  252.     {
  253.         if (papp->hwndMain)
  254.         {
  255.             DestroyWindow(papp->hwndMain);
  256.             papp->hwndMain = NULL;
  257.         }
  258.     }
  259.  
  260.     Client_Terminate(papp, codeTerm);
  261.     Frame_Terminate(papp, codeTerm);
  262.  
  263.     App_TerminateHook(papp);
  264. }
  265.