home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / PVIEW95.PAK / PVIEW95.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  22.1 KB  |  792 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   pview95.c
  9. //
  10. //  PURPOSE:   Implement the windows procedure for the main application
  11. //    windows.  Also implement the basic message and command dispatchers.
  12. //
  13. //  FUNCTIONS:
  14. //    WndProc            - Processes messages for the main window.
  15. //    MsgCommand         - Handle WM_COMMAND messages for the main window.
  16. //    MsgCreate          - Handles the WM_CREATE message.
  17. //    MsgPaint           - Redraws divider bar
  18. //    MsgSize            - Resizes app and all child controls
  19. //    MsgLButtonDown     - Starts redrawing divider bar
  20. //    MsgLButtonUp       - Ends redrawing divider bar
  21. //    MsgMouseMove       - Helps redraw divider bar
  22. //    MsgNotify          - Handles notification messages from child controls
  23. //    MsgActivateApp     - Refreshes the process list when app is activated
  24. //    MsgDisplayChange   - Resizes application if display dimensions change
  25. //    MsgDestroy         - Handles the WM_DESTROY message by calling
  26. //                         PostQuitMessage().
  27. //    CmdRefreshDisplay  - Refreshes the process list
  28. //    CmdKillProcess     - Handles the menu/toolbar item that allows the
  29. //                         user to kill a process
  30. //    CmdExit            - Handles the file exit command by calling destory
  31. //                         window on the main window.
  32. //
  33. //  COMMENTS:
  34. //
  35.  
  36. #include <windows.h>            // required for all Windows applications
  37. #include <windowsx.h>
  38. #include <commctrl.h>
  39. #include "globals.h"            // prototypes specific to this application
  40. #include "resource.h"
  41. #include "listview.h"
  42. #include "toolbar.h"
  43. #include "procthrd.h"
  44.  
  45.  
  46. //-------------------------------------------------------------------------
  47. // Manifest constants
  48.  
  49. #define DIVIDER_HEIGHT  7  // height of the resizing divider (height - 1)
  50. #define TOP_HEIGHT      27 // height at the top to reserve for controls
  51. #define BOTTOM_HEIGHT   0  // height at the bottom to reserve for controls
  52.  
  53.  
  54. //-------------------------------------------------------------------------
  55. // Useful application-global variables defined here!
  56. HWND g_hwndMain    = NULL;
  57. HWND g_hwndProcess = NULL;
  58. HWND g_hwndThread  = NULL;
  59.  
  60.  
  61. //-------------------------------------------------------------------------
  62. // Useful static global variables defined here!
  63. static RECT g_rcClient;             // Save the client area so the controls
  64.                               //   can remain proportionally sized
  65. static RECT g_rcDivider;            // Position of the divider between
  66.                                       //   the controls
  67. static LONG g_lPrevPos;             // Previous mouse position for resizing
  68. static LONG g_lToolbarHeight;       // Height of the toolbar
  69. static double g_dDividerProportion;   // Proportion of the screen that the
  70.                              //   is at divider
  71. static HCURSOR g_hcurResize;        // Resizing cursor handle
  72.  
  73.  
  74. // Main window message table definition.
  75. MSD rgmsd[] =
  76. {
  77.     {WM_COMMAND,        MsgCommand},
  78.     {WM_PAINT,          MsgPaint},
  79.     {WM_SIZE,           MsgSize},
  80.     {WM_LBUTTONDOWN,    MsgLButtonDown},
  81.     {WM_LBUTTONUP,      MsgLButtonUp},
  82.     {WM_MOUSEMOVE,      MsgMouseMove},
  83.     {WM_NOTIFY,         MsgNotify},
  84.     {WM_ACTIVATEAPP,    MsgActivateApp},
  85.     {WM_DISPLAYCHANGE,  MsgDisplayChange},
  86.     {WM_CREATE,         MsgCreate},
  87.     {WM_DESTROY,        MsgDestroy}
  88. };
  89.  
  90. MSDI msdiMain =
  91. {
  92.     sizeof(rgmsd) / sizeof(MSD),
  93.     rgmsd,
  94.     edwpWindow
  95. };
  96.  
  97.  
  98. // Main window command table definition.
  99. CMD rgcmd[] =
  100. {
  101.     {ID_FILE_EXIT,       CmdExit},
  102.     {ID_PROCESS_REFRESH, CmdRefreshDisplay},
  103.     {ID_PROCESS_KILL,    CmdKillProcess},
  104.     {ID_HELP_ABOUT,      CmdAbout}
  105. };
  106.  
  107. CMDI cmdiMain =
  108. {
  109.     sizeof(rgcmd) / sizeof(CMD),
  110.     rgcmd,
  111.     edwpWindow
  112. };
  113.  
  114.  
  115. //
  116. //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
  117. //
  118. //  PURPOSE:  Processes messages for the main window.
  119. //
  120. //  PARAMETERS:
  121. //    hwnd     - window handle
  122. //    uMessage - message number
  123. //    wparam   - additional information (dependant on message number)
  124. //    lparam   - additional information (dependant on message number)
  125. //
  126. //  RETURN VALUE:
  127. //    The return value depends on the message number.  If the message
  128. //    is implemented in the message dispatch table, the return value is
  129. //    the value returned by the message handling function.  Otherwise,
  130. //    the return value is the value returned by the default window procedure.
  131. //
  132. //  COMMENTS:
  133. //    Call the DispMessage() function with the main window's message dispatch
  134. //    information (msdiMain) and the message specific information.
  135. //
  136.  
  137. LRESULT CALLBACK WndProc(HWND   hwnd,
  138.                          UINT   uMessage,
  139.                          WPARAM wparam,
  140.                          LPARAM lparam)
  141. {
  142.     return DispMessage(&msdiMain, hwnd, uMessage, wparam, lparam);
  143. }
  144.  
  145.  
  146. //
  147. //  FUNCTION: MsgCommand(HWND, UINT, WPARAM, LPARAM)
  148. //
  149. //  PURPOSE: Handle the WM_COMMAND messages for the main window.
  150. //
  151. //  PARAMETERS:
  152. //    hwnd                                - window handle
  153. //    uMessage                            - WM_COMMAND (Unused)
  154. //    GET_WM_COMMAND_ID(wparam, lparam)   - Command identifier
  155. //    GET_WM_COMMAND_HWND(wparam, lparam) - Control handle
  156. //
  157. //  RETURN VALUE:
  158. //    The return value depends on the message number.  If the message
  159. //    is implemented in the message dispatch table, the return value is
  160. //    the value returned by the message handling function.  Otherwise,
  161. //    the return value is the value returned by the default window procedure.
  162. //
  163. //  COMMENTS:
  164. //    Call the DispCommand() function with the main window's command dispatch
  165. //    information (cmdiMain) and the command specific information.
  166. //
  167.  
  168. #pragma argsused
  169. LRESULT MsgCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  170. {
  171.     return DispCommand(&cmdiMain, hwnd, wparam, lparam);
  172. }
  173.  
  174.  
  175. //
  176. //  FUNCTION: MsgCreate(HWND, UINT, WPARAM, LPARAM)
  177. //
  178. //  PURPOSE:  Performs initialization needed at window creation time
  179. //
  180. //  PARAMETERS:
  181. //
  182. //    hwnd      - Window handle
  183. //    uMessage  - WM_CREATE      (Unused)
  184. //    wparam    - Extra data     (Unused)
  185. //    lparam    - Extra data     (Unused)
  186. //
  187. //  RETURN VALUE:
  188. //
  189. //    Returns 0 if all initialization was successful, or -1 if any part
  190. //    of the initialization failed.
  191. //
  192. //  COMMENTS:
  193. //    Returning 0 allows the window to continue being created while -1
  194. //    forces the creation to fail.
  195. //
  196.  
  197. #pragma argsused
  198. LRESULT MsgCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  199. {
  200.     HWND  hwndToolbar;
  201.     RECT  rcToolbar   = {0};
  202.  
  203.    // Save the main window handle for accelerators
  204.    g_hwndMain = hwnd;
  205.  
  206.    // Create the toolbar control
  207.    hwndToolbar = CreateAppToolbar(hwnd, IDC_TOOLBAR);
  208.    if (!hwndToolbar)
  209.       return (-1);
  210.  
  211.    // Find the height of the toolbar and save it so we can properly place
  212.    // the other controls
  213.     GetWindowRect(hwndToolbar, &rcToolbar);
  214.    g_lToolbarHeight = (rcToolbar.bottom - rcToolbar.top);
  215.  
  216.    // Create the listview controls for the process list and thread list.
  217.    // If the windows were not created, show the error and exit the program.
  218.    g_hwndProcess = CreateListView(hwnd,
  219.                                      WS_CHILD|LVS_REPORT|LVS_SINGLESEL|
  220.                                      LVS_SHOWSELALWAYS|WS_TABSTOP,
  221.                                   acdProcess,
  222.                                   CPROCESSCOLUMNS,
  223.                                   IDC_PROCESS);
  224.     if (!g_hwndProcess)
  225.          return (-1);
  226.  
  227.    g_hwndThread = CreateListView(hwnd,
  228.                                     WS_CHILD|LVS_REPORT|LVS_SINGLESEL|WS_TABSTOP,
  229.                                  acdThread,
  230.                                  CTHREADCOLUMNS,
  231.                                  IDC_THREAD);
  232.    if (!g_hwndThread)
  233.        return (-1);
  234.  
  235.     // Subclass the thread list view so that we can set the focus back to
  236.     // the process list view if the user should select anything in the
  237.      // thread list view.
  238.     g_lpfnThreadListView = (FARPROC)SetWindowLong(g_hwndThread,
  239.                                                   GWL_WNDPROC,
  240.                                                   (LONG)LV_Subclass);
  241.  
  242.    // Load the resizing cursor from the resources, if a problem occurs,
  243.    // default to the system defined arrow cursor
  244.    g_hcurResize = LoadCursor(hInst, MAKEINTRESOURCE(IDC_RESIZE));
  245.    if (!g_hcurResize)
  246.        g_hcurResize = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
  247.  
  248.    // The listview controls were created correctly, so show them
  249.     ShowWindow(g_hwndProcess, SW_SHOW);
  250.    ShowWindow(g_hwndThread, SW_SHOW);
  251.  
  252.    // Set the initial size of the client area and divider position
  253.    GetClientRect(hwnd, &g_rcClient);
  254.  
  255.    // make room at the top and bottom for any controls
  256.    g_rcClient.top += g_lToolbarHeight - 1;
  257.    g_rcClient.bottom -= (BOTTOM_HEIGHT + g_rcClient.top);
  258.  
  259.    // The initial divider proportion is 50%
  260.    g_dDividerProportion = 0.50;
  261.  
  262.    // The initial divider position is mid way down the client area
  263.     g_rcDivider.top = (LONG) ((g_rcClient.bottom - g_rcClient.top)
  264.                           * g_dDividerProportion) + g_rcClient.top;
  265.    g_rcDivider.bottom = g_rcDivider.top + DIVIDER_HEIGHT;
  266.    g_rcDivider.left = 0;
  267.    g_rcDivider.right = g_rcClient.right;
  268.  
  269.  
  270.    // Update the information in the process list
  271.    RefreshProcessList(g_hwndProcess);
  272.  
  273.      return 0;
  274. }
  275.  
  276.  
  277. //
  278. //  FUNCTION: MsgPaint(HWND, UINT, WPARAM, LPARAM)
  279. //
  280. //  PURPOSE:  Repaints the divider bar between the process and thread lists.
  281. //
  282. //  PARAMETERS:
  283. //
  284. //    hwnd      - Window handle
  285. //    uMessage  - WM_PAINT       (Unused)
  286. //    wparam    - Extra data     (Unused)
  287. //    lparam    - Extra data     (Unused)
  288. //
  289. //  RETURN VALUE:
  290. //
  291. //    Always returns 0 - Message handled
  292. //
  293. //  COMMENTS:
  294. //
  295. //
  296.  
  297. #pragma argsused
  298. LRESULT MsgPaint(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  299. {
  300.    PAINTSTRUCT ps;
  301.    HDC      hdc;
  302.  
  303.    hdc = BeginPaint(hwnd, &ps);
  304.  
  305.    DrawEdge(hdc, &g_rcDivider, EDGE_RAISED, BF_TOP | BF_BOTTOM | BF_MIDDLE);
  306.  
  307.    EndPaint(hwnd, &ps);
  308.  
  309.     return 0;
  310. }
  311.  
  312.  
  313. //
  314. //  FUNCTION: MsgSize(HWND, UINT, WPARAM, LPARAM)
  315. //
  316. //  PURPOSE:  Resizes all controls proportionally within the main window
  317. //            when the main window is resized.
  318. //
  319. //  PARAMETERS:
  320. //
  321. //    hwnd      - Window handle
  322. //    uMessage  - WM_SIZE
  323. //    wparam    - Resizing type
  324. //    lparam    - New Width & Height of the window
  325. //
  326. //  RETURN VALUE:
  327. //
  328. //    Always returns 0 - Message handled
  329. //
  330. //  COMMENTS:
  331. //
  332. //
  333.  
  334. #pragma argsused
  335. LRESULT MsgSize(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  336. {
  337.     int cx = LOWORD(lparam);
  338.     int cy = HIWORD(lparam);
  339.  
  340.  
  341.     // store the client area size for the next time we have to do this
  342.     g_rcClient.right = cx;
  343.     g_rcClient.bottom = cy - BOTTOM_HEIGHT - g_rcClient.top;
  344.  
  345.     // set the new divider position to a proportional position
  346.      g_rcDivider.top = (LONG) ((g_rcClient.bottom + g_rcClient.top)
  347.                               * g_dDividerProportion);
  348.     g_rcDivider.bottom = g_rcDivider.top + DIVIDER_HEIGHT;
  349.     g_rcDivider.right = cx;
  350.  
  351.     // Update the positions of the controls
  352.     MoveWindow(g_hwndProcess, 0, g_rcClient.top, cx,
  353.                (g_rcDivider.top - g_rcClient.top), TRUE);
  354.     MoveWindow(g_hwndThread, 0, g_rcDivider.bottom + 1, cx,
  355.                (g_rcClient.bottom - g_rcDivider.bottom + g_rcClient.top),
  356.                TRUE);
  357.     MoveWindow(GetDlgItem(hwnd, IDC_TOOLBAR), 0, 0, g_rcClient.right,
  358.                     g_lToolbarHeight, TRUE);
  359.  
  360.     return 0;
  361. }
  362.  
  363.  
  364. //
  365. //  FUNCTION: MsgLButtonDown(HWND, UINT, WPARAM, LPARAM)
  366. //
  367. //  PURPOSE:  Start moving the divider bar within the main window's
  368. //            client area.
  369. //
  370. //  PARAMETERS:
  371. //
  372. //    hwnd      - Window handle
  373. //    uMessage  - WM_LBUTTONDOWN (Unused)
  374. //    wparam    - Extra data     (Unused)
  375. //    lparam    - X, Y coordinates where mouse event occurred
  376. //
  377. //  RETURN VALUE:
  378. //
  379. //    Always returns 0 - Message handled
  380. //
  381. //  COMMENTS:
  382. //    Works in conjunction with MsgLButtonUp and MsgMouseMove
  383. //
  384.  
  385. #pragma argsused
  386. LRESULT MsgLButtonDown(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  387. {
  388.     POINT pt;
  389.  
  390.     pt.x = LOWORD(lparam);
  391.     pt.y = HIWORD(lparam);
  392.  
  393.    // Check to see if the mouse is in the divider
  394.    if (PtInRect(&g_rcDivider, pt))
  395.    {
  396.       SetCursor(g_hcurResize);
  397.       SetCapture(hwnd);       // keep track of the mouse until the
  398.                            // ..button is released;
  399.       DrawResizeLine(hwnd, pt.y);   // draw the resizing rectangle
  400.       g_lPrevPos = pt.y;         // save the position so the resize
  401.                                     // ..rectangle can be moved
  402.    }
  403.  
  404.     return 0;
  405. }
  406.  
  407.  
  408. //
  409. //  FUNCTION: MsgLButtonUp(HWND, UINT, WPARAM, LPARAM)
  410. //
  411. //  PURPOSE:  Stop moving divider bar and resize process and thread
  412. //            list views
  413. //
  414. //  PARAMETERS:
  415. //
  416. //    hwnd      - Window handle
  417. //    uMessage  - WM_LBUTTONUP   (Unused)
  418. //    wparam    - Extra data     (Unused)
  419. //    lparam    - X, Y coordinates where mouse event occurred
  420. //
  421. //  RETURN VALUE:
  422. //
  423. //    Always returns 0 - Message handled
  424. //
  425. //  COMMENTS:
  426. //
  427. //
  428.  
  429. #pragma argsused
  430. LRESULT MsgLButtonUp(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  431. {
  432.     WORD y = HIWORD(lparam);
  433.  
  434.    if (GetCapture() != NULL)
  435.    {
  436.       SetCursor(g_hcurResize);
  437.         // clean up from resize operation, release the capture and
  438.       // remove the resizing line from the window
  439.       ReleaseCapture();
  440.       DrawResizeLine(hwnd, g_lPrevPos);
  441.  
  442.       // update the divider position
  443.       g_rcDivider.top = y;
  444.       g_rcDivider.bottom = g_rcDivider.top + DIVIDER_HEIGHT;
  445.  
  446.       // move the listivew controls
  447.       MoveWindow(g_hwndProcess, 0, g_rcClient.top, g_rcClient.right,
  448.             g_rcDivider.top - g_rcClient.top, TRUE);
  449.         MoveWindow(g_hwndThread, 0, g_rcDivider.bottom + 1, g_rcClient.right,
  450.             (g_rcClient.bottom - g_rcDivider.bottom + g_rcClient.top), TRUE);
  451.  
  452.       // find out where the divider was in proportion to the window size
  453.       g_dDividerProportion = (double)(g_rcDivider.top) /
  454.             (double)(g_rcClient.bottom + g_rcClient.top);
  455.  
  456.         // update the window
  457.       InvalidateRect(hwnd, NULL, TRUE);
  458.       UpdateWindow(hwnd);
  459.    }
  460.     return 0;
  461. }
  462.  
  463.  
  464. //
  465. //  FUNCTION: MsgMouseMove(HWND, UINT, WPARAM, LPARAM)
  466. //
  467. //  PURPOSE:  Move divider bar in client area.
  468. //
  469. //  PARAMETERS:
  470. //
  471. //    hwnd      - Window handle  (Unused)
  472. //    uMessage  - WM_MOUSEMOVE   (Unused)
  473. //    wparam    - Extra data     (Unused)
  474. //    lparam    - Extra data     X, Y coordinates where mouse event occurred
  475. //
  476. //  RETURN VALUE:
  477. //
  478. //    Always returns 0 - Message handled
  479. //
  480. //  COMMENTS:
  481. //
  482. //
  483.  
  484. #pragma argsused
  485. LRESULT MsgMouseMove(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  486. {
  487.     WORD x = LOWORD(lparam);
  488.     WORD y = HIWORD(lparam);
  489.  
  490.  
  491.    if (GetCapture() != NULL)
  492.    {
  493.       DrawResizeLine(hwnd, g_lPrevPos);   // remove the previous line
  494.       DrawResizeLine(hwnd, y);         // draw the new resizing line in
  495.                                  // .. the current position
  496.         g_lPrevPos = y;                  // save this position for next
  497.    }                             // .. time
  498.    else
  499.    {
  500.       // if the mouse is over the resizing line, change the cursor
  501.       POINT pt;
  502.  
  503.       pt.x = x; pt.y = y;
  504.       if (PtInRect(&g_rcDivider, pt))
  505.          SetCursor(g_hcurResize);
  506.    }
  507.  
  508.      return 0;
  509. }
  510.  
  511.  
  512. //
  513. //  FUNCTION: MsgNotify(HWND, UINT, WPARAM, LPARAM)
  514. //
  515. //  PURPOSE:  Handles notification messages from controls
  516. //
  517. //  PARAMETERS:
  518. //
  519. //    hwnd      - Window handle  (Unused)
  520. //    uMessage  - WM_NOTIFY      (Unused)
  521. //    wparam    - Child control ID
  522. //    lparam    - Child control-specific information
  523. //
  524. //  RETURN VALUE:
  525. //
  526. //    Always returns 0 - Message handled
  527. //
  528. //  COMMENTS:
  529. //
  530. //
  531.  
  532. #pragma argsused
  533. LRESULT MsgNotify(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  534. {
  535.     int    idFrom  = (int)wparam;
  536.     NMHDR *pnmhdr  = (NMHDR *)lparam;
  537.  
  538.    switch (pnmhdr->code)
  539.    {
  540.       case NM_CLICK:
  541.          return ListView_OnClick(idFrom, (NM_LISTVIEW *) pnmhdr);
  542.  
  543.         case LVN_GETDISPINFO:
  544.          return ListView_OnGetDispInfo(idFrom, (LV_DISPINFO *) pnmhdr);
  545.  
  546.       case LVN_DELETEITEM:
  547.          return ListView_OnDeleteItem(idFrom, (NM_LISTVIEW *) pnmhdr);
  548.  
  549.       case LVN_COLUMNCLICK:
  550.          return ListView_OnColumnClick(idFrom, (NM_LISTVIEW *) pnmhdr);
  551.  
  552.       case TTN_NEEDTEXT:
  553.          return Toolbar_OnNeedText(idFrom, (LPTOOLTIPTEXT) pnmhdr);
  554.    }
  555.  
  556.     return 0;
  557. }
  558.  
  559.  
  560. //
  561. //  FUNCTION: MsgActivateApp(HWND, UINT, WPARAM, LPARAM)
  562. //
  563. //  PURPOSE:  To refresh the process list when application is made active.
  564. //
  565. //  PARAMETERS:
  566. //
  567. //    hwnd      - Window handle  (Unused)
  568. //    uMessage  - WM_ACTIVATEAPP (Unused)
  569. //    wparam    - Whether app is being activated or deactivated
  570. //    lparam    - Extra data     (Unused)
  571. //
  572. //  RETURN VALUE:
  573. //
  574. //    Always returns 0 - Message handled
  575. //
  576. //  COMMENTS:
  577. //
  578. //
  579.  
  580. #pragma argsused
  581. LRESULT MsgActivateApp(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  582. {
  583.     BOOL bActivating = (BOOL)wparam;
  584.  
  585.     if (bActivating)
  586.     {
  587.       ListView_DeleteAllItems(g_hwndThread);
  588.         RefreshProcessList(g_hwndProcess);
  589.      }
  590.  
  591.     return 0;
  592. }
  593.  
  594. //
  595. //  FUNCTION: MsgDisplayChange(HWND, UINT, WPARAM, LPARAM)
  596. //
  597. //  PURPOSE:  Resizes the application if the display's dimensions change.
  598. //
  599. //  PARAMETERS:
  600. //
  601. //    hwnd      - Window handle    (Unused)
  602. //    uMessage  - WM_DISPLAYCHANGE (Unused)
  603. //    wparam    - Extra data       (Unused)
  604. //    lparam    - Extra data       (Unused)
  605. //
  606. //  RETURN VALUE:
  607. //
  608. //    Always returns 0 - Message handled
  609. //
  610. //  COMMENTS:
  611. //
  612. //
  613.  
  614. #pragma argsused
  615. LRESULT MsgDisplayChange(HWND hwnd,
  616.                                  UINT uMessage,
  617.                                  WPARAM wparam,
  618.                                  LPARAM lparam)
  619. {
  620.    static WORD cxOld, cyOld;  // Used to store old screen resolution
  621.                                // when wparam == FALSE
  622.    WORD cxNew, cyNew;
  623.    RECT rcWindow;
  624.    RECT rcNewWindow;
  625.    float cxChange, cyChange;
  626.  
  627.    if (wparam == FALSE)
  628.    {
  629.       // save the old screen resoulution
  630.         cxOld = LOWORD(lparam);
  631.       cyOld = HIWORD(lparam);
  632.    }
  633.    else
  634.    {
  635.       // move the window to a proportionally new size
  636.       cxNew = LOWORD(lparam);
  637.       cyNew = HIWORD(lparam);
  638.  
  639.       GetWindowRect(hwnd, &rcWindow);
  640.  
  641.         // Compute horizontal and vertical proportions for display
  642.           // resolution changes
  643.       cxChange = (float)cxNew / cxOld;
  644.       cyChange = (float)cyNew / cyOld;
  645.  
  646.         // Apply proportions to the top left and bottom right corners
  647.         // of the window.
  648.       rcNewWindow.left   = (LONG)(rcWindow.left   * cxChange);
  649.       rcNewWindow.right  = (LONG)(rcWindow.right  * cxChange);
  650.       rcNewWindow.top    = (LONG)(rcWindow.top    * cyChange);
  651.       rcNewWindow.bottom = (LONG)(rcWindow.bottom * cyChange);
  652.  
  653.       MoveWindow(hwnd, rcNewWindow.left, rcNewWindow.top,
  654.                 (rcNewWindow.right - rcNewWindow.left),
  655.             (rcNewWindow.bottom - rcNewWindow.top), TRUE);
  656.    }
  657.    return 0;
  658. }
  659.  
  660.  
  661. //
  662. //  FUNCTION: MsgDestroy(HWND, UINT, WPARAM, LPARAM)
  663. //
  664. //  PURPOSE: Calls PostQuitMessage().
  665. //
  666. //  PARAMETERS:
  667. //
  668. //    hwnd      - Window handle  (Unused)
  669. //    uMessage  - WM_DESTROY     (Unused)
  670. //    wparam    - Extra data     (Unused)
  671. //    lparam    - Extra data     (Unused)
  672. //
  673. //  RETURN VALUE:
  674. //
  675. //    Always returns 0 - Message handled
  676. //
  677. //  COMMENTS:
  678. //
  679. //
  680.  
  681. #pragma argsused
  682. LRESULT MsgDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  683. {
  684.      PostQuitMessage(0);
  685.      return 0;
  686. }
  687.  
  688.  
  689. //
  690. //  FUNCTION: CmdRefreshDisplay(HWND, WORD, WORD, HWND)
  691. //
  692. //  PURPOSE:  Refreshes the process list.
  693. //
  694. //  PARAMETERS:
  695. //    hwnd     - The window.         (unused)
  696. //    wCommand - Command number      (unused)
  697. //    wNotify  - Notification number (unused)
  698. //    hwndCtrl - NULL                (unused)
  699. //
  700. //  RETURN VALUE:
  701. //    Always returns 0 - command handled.
  702. //
  703. //  COMMENTS:
  704. //
  705. //
  706.  
  707. #pragma argsused
  708. LRESULT CmdRefreshDisplay(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  709. {
  710.     ListView_DeleteAllItems(g_hwndThread);
  711.     RefreshProcessList(g_hwndProcess);
  712.  
  713.      return 0;
  714. }
  715.  
  716.  
  717. //
  718. //  FUNCTION: CmdKillProcess(HWND, WORD, WORD, HWND)
  719. //
  720. //  PURPOSE:  Kills a user-specified process.
  721. //
  722. //  PARAMETERS:
  723. //    hwnd     - The window.         (unused)
  724. //    wCommand - Command number      (unused)
  725. //    wNotify  - Notification number (unused)
  726. //    hwndCtrl - NULL                (unused)
  727. //
  728. //  RETURN VALUE:
  729. //    Always returns 0 - command handled.
  730. //
  731. //  COMMENTS:
  732. //
  733. //
  734.  
  735. #pragma argsused
  736. LRESULT CmdKillProcess(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  737. {
  738.      DWORD dwPID;
  739.      int   nKill;
  740.     char  szMsg[MAX_PATH + 50];
  741.     char  szExe[MAX_PATH];
  742.  
  743.  
  744.     dwPID = ListView_GetSelectedPid(g_hwndProcess, szExe, sizeof(szExe));
  745.  
  746.     // First, make sure there is a process selected.  If so, ask user if
  747.     // he/she is sure that the process should be killed.  Only when the
  748.     // user is sure will we kill the process.
  749.  
  750.     if (dwPID != 0)
  751.      {
  752.         wsprintf (szMsg, "Are you sure you want to kill\n%s", szExe);
  753.         nKill = MessageBox (g_hwndProcess, 
  754.                              szMsg, 
  755.                              "PView95", 
  756.                             MB_YESNO|MB_DEFBUTTON2);
  757.         if (nKill == IDYES)
  758.         {
  759.             KillProcess (dwPID);
  760.             RefreshProcessList (g_hwndProcess);
  761.         }
  762.     }
  763.  
  764.     return 0;
  765. }
  766.  
  767.  
  768. //
  769. //  FUNCTION: CmdExit(HWND, WORD, WORD, HWND)
  770. //
  771. //  PURPOSE: Exit the application.
  772. //
  773. //  PARAMETERS:
  774. //    hwnd     -  The window.         (unused)
  775. //    wCommand -  Command number      (unused)
  776. //    wNotify  -  Notification number (unused)
  777. //    hwndCtrl -  NULL                (unused)
  778. //
  779. //  RETURN VALUE:
  780. //    Always returns 0 - command handled.
  781. //
  782. //  COMMENTS:
  783. //
  784. //
  785.  
  786. #pragma argsused
  787. LRESULT CmdExit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  788. {
  789.     DestroyWindow(hwnd);
  790.     return 0;
  791. }
  792.