home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / msj / v07n03 / toolhelp.exe / TASKMSTR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-01  |  32.1 KB  |  1,000 lines

  1. /*-------------------------------------------------------------*\
  2.  |  TaskMstr.C  -- Display current Windows tasks and memory    |
  3.  |                 usage.                                      |
  4. \*-------------------------------------------------------------*/
  5. #include <Windows.H>
  6. #include <WindowsX.H>
  7. #include <ToolHelp.H>
  8. #include <Memory.H>
  9. #include "TaskMstr.H"
  10.  
  11.  
  12. /*-------------------------------------------------------------*\
  13.  |                      Global Variables.                      |
  14. \*-------------------------------------------------------------*/
  15. APPCOLORS           ac;
  16. APPMETRICS          am;
  17. char                achBuffer[BUFSIZE];
  18. char                achAppTitle[] = "Task Master";
  19. char            *   achSegType[] =
  20.                         {"Dyna-Segs",
  21.                          "DGroup",
  22.                          "Other Data",
  23.                          "Code",
  24.                          "Task DB",
  25.                          "Resource",
  26.                          "Module DB",
  27.                          "Free",
  28.                          "Internal",
  29.                          "Sentinel",
  30.                          "Burgermaster"
  31.                         };
  32. DWORD               dwTaskMax;
  33. DWORD               dwSegMax;
  34. DWORD               dwModuleTot[SEGTYPE_COUNT];
  35. FARPROC             lpfnNotify;
  36. GLOBALENTRY _huge * lpheList;
  37. HBRUSH              hbr1;
  38. HBRUSH              hbr2;
  39. HFONT               hfont;
  40. HICON               hIconDefault;
  41. HINSTANCE           hInst;
  42. HWND                hwndMain;
  43. HWND                hwndTask;
  44. HWND                hwndModule;
  45. int                 cSegments;
  46. int                 cTaskList;
  47. int                 iCurTask = 0;
  48. int                 nTaskFactor;
  49. int                 nSegFactor;
  50. LPTASKLIST          lptlList;
  51.  
  52.  
  53. /*-------------------------------------------------------------*\
  54.  |                 Main Function:  WinMain.                    |
  55. \*-------------------------------------------------------------*/
  56. int PASCAL WinMain (HANDLE hInstance,   HANDLE hPrevInstance,
  57.                     LPSTR  lpszCmdLine, int    cmdShow)
  58.     {
  59.     HDC         hdc;
  60.     MSG         msg;
  61.     WNDCLASS    wc;
  62.  
  63.     if (hwndMain = FindWindow ("TaskMstr:MAIN", NULL) )
  64.         {
  65.         if (IsIconic (hwndMain) )
  66.             {
  67.             ShowWindow (hwndMain, SW_RESTORE);
  68.             }
  69.         BringWindowToTop (hwndMain);
  70.         return 0;
  71.         }
  72.  
  73.     // Save global copy of instance handle.
  74.     hInst = hInstance;
  75.  
  76.     // Save empty icon for application's without icons.
  77.     hIconDefault = LoadIcon (NULL, IDI_APPLICATION);
  78.  
  79.     // Initialize application metric table...
  80.     hdc = GetDC (NULL);
  81.     trInitMetrics(hdc);
  82.  
  83.     // ...and application color table.
  84.     ac.cColors = GetDeviceCaps (hdc, NUMCOLORS);
  85.     trInitColors();
  86.     ReleaseDC (NULL, hdc);
  87.  
  88.     //  Install ToolHelp call-back notification procedure.
  89.     //
  90.     lpfnNotify = MakeProcInstance (trToolHelpNotify, hInst);
  91.     NotifyRegister (NULL, lpfnNotify, NF_NORMAL);
  92.  
  93.     //  Do usual application startup.
  94.     wc.lpszClassName = "TaskMstr:MAIN";
  95.     wc.hInstance     = hInstance;
  96.     wc.lpfnWndProc   = TaskMstrWndProc;
  97.     wc.hCursor       = LoadCursor (hInstance, "hand");
  98.     wc.hIcon         = LoadIcon (hInstance,"snapshot");
  99.     wc.lpszMenuName  = NULL;
  100.     wc.hbrBackground = COLOR_WINDOW+1;
  101.     wc.style         = NULL;
  102.     wc.cbClsExtra    = 0;
  103.     wc.cbWndExtra    = 0;
  104.  
  105.     RegisterClass( &wc);
  106.  
  107.     hwndMain = CreateWindow("TaskMstr:MAIN",      /* Class name.   */
  108.                             achAppTitle,          /* Title.        */
  109.                             WS_OVERLAPPEDWINDOW,  /* Style bits.   */
  110.                             CW_USEDEFAULT,        /* x - default.  */
  111.                             0,                    /* y - default.  */
  112.                             am.win_cxInit,        /* cx - default. */
  113.                             am.win_cyInit,        /* cy - default. */
  114.                             NULL,                 /* No parent.    */
  115.                             NULL,                 /* Class menu.   */
  116.                             hInstance,            /* Creator.      */
  117.                             NULL);                /* Params.       */
  118.  
  119.     ShowWindow (hwndMain, cmdShow);
  120.  
  121.     // Create 'peek at system data' timer.
  122.     SetTimer (hwndMain, 1, 5000, 0);
  123.  
  124.     while (GetMessage(&msg, 0, 0, 0))
  125.         {
  126.         TranslateMessage(&msg);       /*  Keyboard input.      */
  127.         DispatchMessage(&msg);
  128.         }
  129.  
  130.     //  Clean up GDI brushes.
  131.     DeleteBrush (hbr1);
  132.     DeleteBrush (hbr2);
  133.     DeleteFont (hfont);
  134.  
  135.     //  Detach ToolHelp call-back notification.
  136.     //
  137.     NotifyUnRegister (NULL);
  138.     FreeProcInstance (lpfnNotify);
  139.  
  140.     return 0;
  141.     }
  142.  
  143. /*-------------------------------------------------------------*\
  144.  |             Window Procedure:  TaskMstrWndProc.             |
  145. \*-------------------------------------------------------------*/
  146. long FAR PASCAL TaskMstrWndProc (HWND   hwnd,   UINT wMsg,
  147.                                  WPARAM wParam, LPARAM lParam)
  148.     {
  149.     switch (wMsg)
  150.         {
  151.         case WM_COMMAND:
  152.             HANDLE_WM_COMMAND(hwnd,wParam, lParam,
  153.                               trMain_OnCommand);
  154.             break;
  155.  
  156.         case WM_CREATE:
  157.             return ( HANDLE_WM_CREATE(hwnd, wParam,lParam,
  158.                                       trMain_OnCreate) );
  159.             break;
  160.  
  161.         case WM_DESTROY:
  162.             HANDLE_WM_DESTROY(hwnd,wParam,lParam,
  163.                               trMain_OnDestroy);
  164.             break;
  165.  
  166.         case WM_DRAWITEM:
  167.             HANDLE_WM_DRAWITEM(hwnd,wParam,lParam,
  168.                                trMain_OnDrawItem);
  169.             break;
  170.  
  171.         case WM_GETMINMAXINFO:
  172.             HANDLE_WM_GETMINMAXINFO(hwnd,wParam,lParam,
  173.                                     trMain_GetMinMaxInfo);
  174.             break;
  175.  
  176.         case WM_MEASUREITEM:
  177.             HANDLE_WM_MEASUREITEM(hwnd,wParam,lParam,
  178.                                   trMain_MeasureItem);
  179.             break;
  180.  
  181.         case WM_SIZE:
  182.             HANDLE_WM_SIZE(hwnd,wParam,lParam,trMain_Size);
  183.             break;
  184.  
  185.         case WM_SETFOCUS:
  186.             HANDLE_WM_SETFOCUS(hwnd,wParam,lParam,
  187.                                trMain_SetFocus);
  188.             break;
  189.  
  190.         case WM_TIMER:
  191.             HANDLE_WM_TIMER(hwnd,wParam,lParam,trMain_Timer);
  192.             break;
  193.  
  194.         case AM_BUILDTASKLIST:
  195.             trMain_BuildTaskList();
  196.             break;
  197.  
  198.         case AM_ERROR:
  199.             trMain_Error(hwnd, wParam);
  200.             break;
  201.  
  202.         default:
  203.             return(DefWindowProc(hwnd,wMsg,wParam,lParam));
  204.             break;
  205.         }
  206.     return 0L;
  207.     }
  208.  
  209.  
  210. /*-------------------------------------------------------------*\
  211.  |                 TaskMstrWndProc  WM_COMMAND.                |
  212. \*-------------------------------------------------------------*/
  213. VOID NEAR PASCAL
  214. trMain_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  215.  
  216.     {
  217.     if (        id == IDL_TASK &&
  218.         codeNotify == LBN_SELCHANGE)
  219.         {
  220.         iCurTask = ListBox_GetCurSel(hwndTask);
  221.         trCalcSegmentList();
  222.         }
  223.     }
  224.  
  225.  
  226. /*-------------------------------------------------------------*\
  227.  |                 TaskMstrWndProc  WM_CREATE.                 |
  228. \*-------------------------------------------------------------*/
  229. BOOL NEAR PASCAL
  230. trMain_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct)
  231.  
  232.     {
  233.     // Create a listbox to act as a task list window.
  234.     hwndTask = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
  235.                               "listbox",            /* Class name.   */
  236.                               "",                   /* Title.        */
  237.                               WS_CHILD           |  /* Style bits.   */
  238.                               WS_VISIBLE         |
  239.                               WS_HSCROLL         |
  240.                               WS_BORDER          |
  241.                               LBS_USETABSTOPS    |
  242.                               LBS_OWNERDRAWFIXED |
  243.                               LBS_NOTIFY         |
  244.                               LBS_NOINTEGRALHEIGHT,
  245.                               0,                    /* x.            */
  246.                               0,                    /* y.            */
  247.                               0,                    /* cx.           */
  248.                               0,                    /* cy.           */
  249.                               hwnd,                 /* Parent window.*/
  250.                               IDL_TASK,             /* Child Id.     */
  251.                               hInst,                /* Creator.      */
  252.                               NULL);                /* Params.       */
  253.  
  254.     // Create a listbox to act as a task list window.
  255.     hwndModule = CreateWindowEx(WS_EX_NOPARENTNOTIFY,
  256.                                 "listbox",            /* Class name.   */
  257.                                 "",                   /* Title.        */
  258.                                 WS_CHILD           |  /* Style bits.   */
  259.                                 WS_VISIBLE         |
  260.                                 WS_HSCROLL         |
  261.                                 WS_BORDER          |
  262.                                 LBS_USETABSTOPS    |
  263.                                 LBS_OWNERDRAWFIXED |
  264.                                 LBS_NOINTEGRALHEIGHT,
  265.                                 0,                    /* x.            */
  266.                                 0,                    /* y.            */
  267.                                 0,                    /* cx.           */
  268.                                 0,                    /* cy.           */
  269.                                 hwnd,                 /* Parent window.*/
  270.                                 IDL_MODULE,           /* Child Id.     */
  271.                                 hInst,                /* Creator.      */
  272.                                 NULL);                /* Params.       */
  273.  
  274.     // Create empty segment list.
  275.     //
  276.     lpheList = (GLOBALENTRY _huge *)
  277.                GlobalAllocPtr(GMEM_MOVEABLE,
  278.                               SEG_INIT_COUNT * sizeof(GLOBALENTRY));
  279.  
  280.     if (!lpheList)
  281.         {
  282.         SendMessage (hwnd, AM_ERROR, ERR_OUTOFMEMORY, 0);
  283.         return FALSE;
  284.         }
  285.  
  286.     // Fill in dummy module data list.
  287.     trFillSegmentListbox();
  288.  
  289.     // Create segment list, module list & task list.
  290.     //
  291.     trBuildSegmentList();
  292.     trBuildTaskList();
  293.  
  294.     hwndMain = hwnd;
  295.     trCalcTaskList();
  296.     trFillTaskListbox(hwndTask);
  297.  
  298.     trCalcSegmentList();
  299.  
  300.     // Kick start initial display.
  301.     PostMessage (hwndMain, WM_TIMER, 0, 0L);
  302.     ListBox_SetCurSel (hwndTask, 0);
  303.     ListBox_SetTopIndex (hwndTask, 0);
  304.  
  305.     return TRUE;
  306.     }
  307.  
  308.  
  309. /*-------------------------------------------------------------*\
  310.  |                 TaskMstrWndProc  WM_DESTROY.                |
  311. \*-------------------------------------------------------------*/
  312. VOID NEAR PASCAL
  313. trMain_OnDestroy (HWND hwnd)
  314.     {
  315.     GlobalFreePtr(lpheList);  // Free segment list.
  316.     GlobalFreePtr(lptlList);  // Free task list.
  317.     PostQuitMessage(0);
  318.     }
  319.  
  320. /*-------------------------------------------------------------*\
  321.  |                TaskMstrWndProc  WM_DRAWITEM.                |
  322. \*-------------------------------------------------------------*/
  323. VOID NEAR PASCAL
  324. trMain_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT FAR* lpDrawItem)
  325.     {
  326.  
  327.     if (lpDrawItem->CtlID == IDL_TASK)
  328.         trDrawTaskItems (lpDrawItem);
  329.     else
  330.         trDrawModuleItems (lpDrawItem);
  331.     }
  332.  
  333.  
  334. /*-------------------------------------------------------------*\
  335.  |              TaskMstrWndProc  WM_GETMINMAXINFO.             |
  336. \*-------------------------------------------------------------*/
  337. VOID NEAR PASCAL
  338. trMain_GetMinMaxInfo(HWND hwnd, MINMAXINFO FAR* lpMinMaxInfo)
  339.     {
  340.     lpMinMaxInfo->ptMinTrackSize.x = am.win_xMinTracking;
  341.     lpMinMaxInfo->ptMinTrackSize.y = am.win_yMinTracking;
  342.     }
  343.  
  344.  
  345. /*-------------------------------------------------------------*\
  346.  |               TaskMstrWndProc  WM_MEASUREITEM.              |
  347. \*-------------------------------------------------------------*/
  348. VOID NEAR PASCAL
  349. trMain_MeasureItem(HWND hwnd, MEASUREITEMSTRUCT FAR* lpMeasureItem)
  350.     {
  351.     if (lpMeasureItem->CtlID == IDL_TASK)
  352.         lpMeasureItem->itemHeight = am.lbTask_cyHeight;
  353.     else
  354.         lpMeasureItem->itemHeight = am.lbModule_cyHeight;
  355.     }
  356.  
  357.  
  358. /*-------------------------------------------------------------*\
  359.  |                  TaskMstrWndProc  WM_SIZE.                  |
  360. \*-------------------------------------------------------------*/
  361. VOID NEAR PASCAL
  362. trMain_Size(HWND hwnd, UINT state, int cx, int cy)
  363.     {
  364.     int xChild;
  365.     int yChild;
  366.     int cxChild;
  367.     int cyChild;
  368.  
  369.     xChild  = 0 - am.sm_cxBorder;
  370.     yChild  = 0 - am.sm_cyBorder;
  371.     cxChild = cx / 2 + am.sm_cxBorder;
  372.     cyChild = cy + 2 * am.sm_cyBorder;
  373.  
  374.     // Put task listbox on the left half...
  375.     //
  376.     MoveWindow (hwndTask,
  377.                 xChild,
  378.                 yChild,
  379.                 cxChild,
  380.                 cyChild,
  381.                 TRUE);
  382.  
  383.     // ...and module listbox on the right half.
  384.                + (2 * am.sm_cxBorder);
  385.                + (2 * am.sm_cyBorder);
  386.     xChild  = cxChild - (2 * am.sm_cxBorder);
  387.     cxChild += 2 * am.sm_cxBorder;
  388.     MoveWindow (hwndModule,
  389.                 xChild,
  390.                 yChild,
  391.                 cxChild,
  392.                 cyChild,
  393.                 TRUE);
  394.  
  395.     InvalidateRect (hwndTask, NULL, TRUE);
  396.     InvalidateRect (hwndModule, NULL, TRUE);
  397.     }
  398.  
  399.  
  400. /*-------------------------------------------------------------*\
  401.  |                TaskMstrWndProc  WM_SETFOCUS.                |
  402. \*-------------------------------------------------------------*/
  403. VOID NEAR PASCAL
  404. trMain_SetFocus(HWND hwnd, HWND hwndOldFocus)
  405.     {
  406.     SetFocus (hwndTask);
  407.     }
  408.  
  409.  
  410. /*-------------------------------------------------------------*\
  411.  |                  TaskMstrWndProc  WM_TIMER.                 |
  412. \*-------------------------------------------------------------*/
  413. VOID NEAR PASCAL
  414. trMain_Timer(HWND hwnd, UINT id)
  415.     {
  416.     trBuildSegmentList();
  417.  
  418.     trCalcSegmentList();
  419.     trCalcTaskList();
  420.     }
  421.  
  422.  
  423. /*-------------------------------------------------------------*\
  424.  |              TaskMstrWndProc  AM_BUILDTASKLIST.             |
  425. \*-------------------------------------------------------------*/
  426. VOID NEAR PASCAL
  427. trMain_BuildTaskList()
  428.     {
  429.     trBuildSegmentList();
  430.     trBuildTaskList();
  431.  
  432.     trCalcTaskList();
  433.     trFillTaskListbox(hwndTask);
  434.  
  435.     trCalcSegmentList();
  436.  
  437.     InvalidateRect (hwndTask, NULL, FALSE);
  438.     }
  439.  
  440.  
  441. /*-------------------------------------------------------------*\
  442.  |                  TaskMstrWndProc  AM_ERROR.                 |
  443. \*-------------------------------------------------------------*/
  444. VOID NEAR PASCAL
  445. trMain_Error(HWND hwnd, WORD error)
  446.     {
  447.     int  cb;
  448.  
  449. Retry:
  450.     cb = LoadString (hInst, STR_ERRBASE+error,
  451.                      achBuffer, BUFSIZE);
  452.     if (cb == 0)
  453.         {
  454.         if (error != ERR_MISSING)
  455.             {
  456.             error = ERR_MISSING;
  457.             goto Retry;
  458.             }
  459.         }
  460.  
  461.     MessageBox (hwnd, achBuffer, achAppTitle, MB_OK);
  462.     }
  463.  
  464.  
  465. /*-------------------------------------------------------------*\
  466.  |      trDrawModuleItems: Draw module info in list box.       |
  467. \*-------------------------------------------------------------*/
  468. VOID NEAR PASCAL
  469. trDrawModuleItems (const DRAWITEMSTRUCT FAR*  lpdraw)
  470.     {
  471.     DWORD        rgb;
  472.     HDC          hdc;
  473.     int          cbText;
  474.     int          xText;
  475.     int          xWidth;
  476.     int          cxBlock;
  477.     int          cxPixels;
  478.     int          cxMax;
  479.     int          yText;
  480.     int          iSaveDC;
  481.     int          Y1;
  482.     RECT         rClient;
  483.     RECT         rDraw;
  484.     WORD         wType;
  485.  
  486.     // Make a local copy of DRAWITEMSTRUCT data.
  487.     hdc      = lpdraw->hDC;
  488.     rDraw    = lpdraw->rcItem;
  489.     wType    = (WORD)lpdraw->itemData;
  490.  
  491.     if ((lpdraw->itemAction & ODA_SELECT) ||
  492.         (lpdraw->itemAction & ODA_DRAWENTIRE))
  493.         {
  494.         // Push DC data on DC-stack.
  495.         iSaveDC = SaveDC (hdc);
  496.  
  497.         // Set up DC.
  498.         SetTextColor (hdc, ac.rgbBlack);
  499.         SetBkColor (hdc, ac.rgbForeSelect);
  500.         SetTextAlign (hdc, TA_RIGHT | TA_BASELINE);
  501.         SelectObject (hdc, hfont);
  502.  
  503.         xText = rDraw.left + am.tx_xModuleText;
  504.         yText = rDraw.top  + am.tx_yModuleText;
  505.  
  506.         cbText = wsprintf (achBuffer, "%s: ",
  507.                            (LPSTR)achSegType[wType]);
  508.  
  509.         rDraw.right = am.tx_xModuleText;
  510.         ExtTextOut (hdc, xText, yText, ETO_OPAQUE | ETO_CLIPPED,
  511.                     &rDraw, achBuffer, cbText, 0);
  512.  
  513.         // Get ready to draw object size & percent bar.
  514.         SetTextAlign (hdc, TA_LEFT | TA_BASELINE);
  515.  
  516.         // Set up buffer with object size info.
  517.         cbText = wsprintf (achBuffer, "  %ld bytes",
  518.                            dwModuleTot[wType]);
  519.  
  520.         // Calculate scaled segment size.
  521.         cxBlock  = (int) (dwModuleTot[wType]/ nSegFactor);
  522.         cxPixels = (int) lpdraw->rcItem.right -
  523.                          am.tx_xModuleText + 1;
  524.         cxMax    = (int) (dwSegMax/ nSegFactor);
  525.         xWidth = MulDiv (cxBlock, cxPixels, cxMax);
  526.  
  527.         // Draw object size & percent bar.
  528.         SetTextColor (hdc, ac.rgbForeSelect);
  529.         rgb = ac.rgbSolidColors[wType];
  530.         SetBkColor (hdc, rgb);
  531.         rDraw.left  = rDraw.right;
  532.         rDraw.right = rDraw.right + xWidth;
  533.         ExtTextOut (hdc, xText, yText, ETO_OPAQUE | ETO_CLIPPED,
  534.                     &rDraw, achBuffer, cbText, 0);
  535.  
  536.         // White out remaining percent bar.
  537.         rgb = ac.rgbSolidColors[wType];
  538.         SetTextColor (hdc, rgb);
  539.         SetBkColor (hdc, ac.rgbForeSelect);
  540.         rDraw.left  = rDraw.right;
  541.         rDraw.right = lpdraw->rcItem.right;
  542.         ExtTextOut (hdc, xText, yText, ETO_OPAQUE  | ETO_CLIPPED,
  543.                     &rDraw, achBuffer, cbText, 0);
  544.  
  545.         // Pop DC data from DC-stack.
  546.         RestoreDC (hdc, iSaveDC);
  547.  
  548.         // Draw bottom border of item -- only if NOT at bottom
  549.         // of client area.
  550.         GetClientRect (hwndModule, &rClient);
  551.         Y1 = rDraw.bottom - am.sm_cyBorder;
  552.         if (Y1 != rClient.bottom - am.sm_cyBorder)
  553.             {
  554.             MoveTo (hdc, lpdraw->rcItem.left,    Y1);
  555.             LineTo (hdc, lpdraw->rcItem.right+1, Y1);
  556.             }
  557.         }
  558.     }
  559.  
  560.  
  561. /*-------------------------------------------------------------*\
  562.  |         trDrawTaskItems: Draw task info in list box.        |
  563. \*-------------------------------------------------------------*/
  564. VOID NEAR PASCAL
  565. trDrawTaskItems (const DRAWITEMSTRUCT FAR*  lpdraw)
  566.     {
  567.     DWORD  dw;
  568.     HDC    hdc;
  569.     int    cbText;
  570.     int    xText;
  571.     int    yText;
  572.     int    iText;
  573.     int    X1;
  574.     int    Y1;
  575.     int    X2;
  576.     int    Y2;
  577.     int    iSaveDC;
  578.     POINT  pt;
  579.     RECT   rClient;
  580.     RECT   rDraw;
  581.  
  582.     hdc      = lpdraw->hDC;
  583.     rDraw    = lpdraw->rcItem;
  584.     X1       = rDraw.left + am.xIcon;
  585.     Y1       = rDraw.top  + am.yIcon;
  586.     xText    = rDraw.left + am.tx_xMargin;
  587.     yText    = rDraw.top  + am.tx_yMargin;
  588.     iText    = (int)lpdraw->itemData;
  589.  
  590.     if ((lpdraw->itemAction & ODA_SELECT) ||
  591.         (lpdraw->itemAction & ODA_DRAWENTIRE))
  592.         {
  593.  
  594.         // Set up DC
  595.         iSaveDC = SaveDC (hdc);
  596.         SelectObject (hdc, hfont);
  597.         if (lpdraw->itemState & ODS_SELECTED)
  598.             {
  599.             SetTextColor (hdc, ac.rgbForeSelect);
  600.             SetBkColor (hdc, ac.rgbBackSelect);
  601.             }
  602.  
  603.         // Display Task name.
  604.         cbText = wsprintf (achBuffer, "%2d. %s", iText + 1,
  605.                            lptlList[iText].achWindowText);
  606.         ExtTextOut (hdc, xText, yText, ETO_OPAQUE, &rDraw,
  607.                     achBuffer, cbText, 0);
  608.  
  609.         // Draw icon associated with task's top-level window.
  610.         DrawIcon (hdc, X1, Y1, lptlList[iText].hIcon);
  611.  
  612.         // Draw labels for segment bars.
  613.         SetTextAlign (hdc, TA_RIGHT | TA_TOP);
  614.         X1 = am.tx_xTaskText;
  615.         Y1 = yText + am.tx_cyLine +
  616.              (am.bar_cyHeight/2) - (am.tx_cyLine/2);
  617.         cbText = wsprintf (achBuffer, "%s: ",
  618.                            (LPSTR)achSegType[GT_UNKNOWN]);
  619.         TextOut (hdc, X1, Y1, achBuffer, cbText);
  620.         Y1 += am.bar_cyHeight;
  621.         cbText = wsprintf (achBuffer, "%s: ",
  622.                            (LPSTR)achSegType[GT_DGROUP]);
  623.         TextOut (hdc, X1, Y1, achBuffer, cbText);
  624.  
  625.         // Draw bars for segment sizes.
  626.         SetMapMode (hdc, MM_ANISOTROPIC);
  627.         X1 = rDraw.left + am.tx_xTaskText;
  628.         Y1 = rDraw.top  + am.tx_yTaskText;
  629.  
  630.         SetViewportOrg (hdc, X1, Y1);
  631.         SetWindowExt   (hdc, (int)(dwTaskMax/ nTaskFactor), 1);
  632.         SetViewportExt (hdc, rDraw.right - X1, 1);
  633.  
  634.         X1 = 0;
  635.         Y1 = 0;
  636.  
  637.         // Draw Dyna-Segs Rectangle.
  638.         dw = lptlList[iText].dwGlobal;
  639.         dw = dw / nTaskFactor;
  640.         X2 = (int)dw;
  641.         Y2 = Y1 + am.bar_cyHeight + 1;
  642.         SelectObject (hdc, hbr1);
  643.         Rectangle (hdc, X1, Y1, X2, Y2);
  644.  
  645.         // Calculate maximum range of Rectangle
  646.         pt.x = rDraw.right;
  647.         pt.y = rDraw.bottom;
  648.         DPtoLP (hdc, &pt, 1);
  649.  
  650.         // Draw DGroup Rectangle
  651.         Y1 += am.bar_cyHeight;
  652.         X2 = X1 + ((int)(lptlList[iText].dwDGroup / nTaskFactor) );
  653.         Y2 = Y1 + am.bar_cyHeight + 1;
  654.         Y2 = min (Y2, pt.y);
  655.         SelectObject (hdc, hbr2);
  656.         Rectangle (hdc, X1, Y1, X2, Y2);
  657.  
  658.         // Draw size of each memory area.
  659.         SetBkMode (hdc, TRANSPARENT);
  660.         SetTextAlign (hdc, TA_LEFT | TA_TOP);
  661.  
  662.         X1 = am.tx_xTaskText + am.tx_xMargin;
  663.         Y1 = yText + am.tx_cyLine +
  664.              (am.bar_cyHeight/2) - (am.tx_cyLine/2);
  665.         SetViewportOrg (hdc, X1, Y1);
  666.  
  667.         X1 = 0;
  668.         Y1 = 0;
  669.  
  670.         cbText = wsprintf (achBuffer, "%lu bytes",
  671.                  lptlList[iText].dwGlobal);
  672.         TextOut (hdc, X1, Y1, achBuffer, cbText);
  673.  
  674.         Y1 += am.bar_cyHeight;
  675.         cbText = wsprintf (achBuffer, "%lu bytes",
  676.                            lptlList[iText].dwDGroup);
  677.         TextOut (hdc, X1, Y1, achBuffer, cbText);
  678.  
  679.         // Restore initial state of DC.
  680.         RestoreDC (hdc, iSaveDC);
  681.  
  682.         // Draw bottom border of item -- only if NOT at bottom
  683.         // of client area.
  684.         GetClientRect (hwndTask, &rClient);
  685.         Y1 = rDraw.bottom - am.sm_cyBorder;
  686.         if (Y1 != rClient.bottom - am.sm_cyBorder)
  687.             {
  688.             MoveTo (hdc, rDraw.left,    Y1);
  689.             LineTo (hdc, rDraw.right+1, Y1);
  690.             }
  691.         }
  692.  
  693.  
  694.     if (lpdraw->itemAction & ODA_FOCUS)
  695.         {
  696.         rDraw.left   += am.sm_cxBorder;
  697.         rDraw.top    += am.sm_cyBorder;
  698.         rDraw.right  -= am.sm_cxBorder;
  699.         rDraw.bottom -= am.sm_cyBorder * 2;
  700.         DrawFocusRect (hdc, &rDraw);
  701.         }
  702.     }
  703.  
  704.  
  705. /*-------------------------------------------------------------*\
  706.  |      trCalcSegmentList: Calculate tasks segment sizes.      |
  707. \*-------------------------------------------------------------*/
  708. void NEAR PASCAL
  709. trCalcSegmentList()
  710.     {
  711.     DWORD               dwModuleTotTemp[SEGTYPE_COUNT];
  712.     DWORD               dwSegMaxTemp;
  713.     GLOBALENTRY _huge * lpheTemp;
  714.     GLOBALENTRY         globalentry;
  715.     HMODULE             hModule;
  716.     HTASK               hTask;
  717.     int                 iSegment;
  718.     int                 iSegType;
  719.     RECT                rRepaint;
  720.     WORD                wType;
  721.  
  722.     hModule = lptlList[iCurTask].taskentry.hModule;
  723.     hTask   = lptlList[iCurTask].taskentry.hTask;
  724.  
  725.     // Init temporary total buffer to zero.
  726.     _fmemset (&dwModuleTotTemp[0], 0, sizeof(DWORD) * SEGTYPE_COUNT);
  727.  
  728.     // Loop through entire heap, totalling for each type.
  729.     for (iSegment = 0, lpheTemp = lpheList;
  730.          iSegment < cSegments;
  731.          iSegment++, lpheTemp++)
  732.         {
  733.         // Make a local copy of segment info values.
  734.         _fmemcpy (&globalentry, lpheTemp, sizeof (GLOBALENTRY) );
  735.  
  736.         // Check that segment is 'one of ours.'
  737.         if ( (globalentry.hOwner == hModule)     ||
  738.              (globalentry.hOwner == hTask  ) )
  739.             {
  740.  
  741.             // If segment type is in range, add it up.
  742.             wType = globalentry.wType;
  743.             if ((wType >= GT_UNKNOWN) &&
  744.                 (wType <= GT_BURGERMASTER) )
  745.                 {
  746.                 dwModuleTotTemp[wType] += globalentry.dwBlockSize;
  747.                 }
  748.  
  749.             } /* [if one of ours] */
  750.  
  751.         } /* [for iSegment] */
  752.  
  753.  
  754.     // Check maximum value & check for changed values.
  755.     dwSegMaxTemp = 0L;
  756.  
  757.     // Loop through type totals...
  758.     for (iSegType = 0; iSegType < SEGTYPE_COUNT; iSegType++)
  759.         {
  760.  
  761.         // ...if count has changed, generate a WM_PAINT.
  762.         if (dwModuleTot[iSegType] != dwModuleTotTemp[iSegType] )
  763.             {
  764.             dwModuleTot[iSegType] = dwModuleTotTemp[iSegType];
  765.  
  766.             // Generate a WM_PAINT in listbox.
  767.             ListBox_GetItemRect(hwndModule, iSegType, &rRepaint);
  768.             rRepaint.left  += am.tx_xModuleText;
  769.             InvalidateRect (hwndModule, &rRepaint, FALSE);
  770.             }
  771.  
  772.         // ... also check for max.
  773.         dwSegMaxTemp = max (dwModuleTot[iSegType], dwSegMaxTemp);
  774.  
  775.         }
  776.  
  777.     // If max has changed, repaint entire listbox.
  778.     if (dwSegMax != dwSegMaxTemp)
  779.         {
  780.         dwSegMax = dwSegMaxTemp;
  781.         GetClientRect (hwndModule, &rRepaint);
  782.         rRepaint.left = am.tx_xModuleText;
  783.         InvalidateRect (hwndModule, &rRepaint, FALSE);
  784.         }
  785.  
  786.     // Calc segment scaling to fit GDI's 16-bit coordinates.
  787.     //
  788.     nSegFactor = 1;
  789.     while ( (dwSegMax/ nSegFactor) > 0x8000L)
  790.         {
  791.         nSegFactor *= 2;
  792.         }
  793.     }
  794.  
  795.  
  796. /*-------------------------------------------------------------*\
  797.  |        trCalcTaskList: Calculate task segments sizes.       |
  798. \*-------------------------------------------------------------*/
  799. void NEAR PASCAL
  800. trCalcTaskList()
  801.     {
  802.     char                achWindowText[BUFSIZE];
  803.     DWORD               dwDGroupTemp;
  804.     DWORD               dwGlobalTemp;
  805.     DWORD               dwTaskMaxTemp;
  806.     GLOBALENTRY _huge * lpheTemp;
  807.     HICON               hIconTemp;
  808.     HWND                hwndChild;
  809.     HWND                hwndSearch;
  810.     register HTASK      hTask;
  811.     HINSTANCE           hwndInst;
  812.     int                 iTask;
  813.     int                 iSegment;
  814.     LPTASKLIST          lptlTemp;
  815.     MODULEENTRY         moduleentry;
  816.     RECT                rRepaint;
  817.     WORD                cbText;
  818.  
  819.     dwTaskMaxTemp = dwTaskMax;
  820.     dwTaskMax = 0L;
  821.  
  822.     for (iTask = 0, lptlTemp = lptlList;
  823.          iTask < cTaskList;
  824.          iTask++, lptlTemp++)
  825.         {
  826.         // Get first window in top-level window list.
  827.         //
  828.         hwndSearch = GetWindow (hwndMain, GW_HWNDFIRST);
  829.  
  830.         cbText = 1;
  831.         achWindowText[0] = '\0';
  832.         hIconTemp = 0;
  833.         while (hwndSearch)
  834.             {
  835.             hwndInst = GetWindowWord (hwndSearch, GWW_HINSTANCE);
  836.             if (hwndInst == lptlTemp->taskentry.hInst)
  837.                 {
  838.                 hwndChild = hwndSearch;
  839.                 while (hwndChild = GetParent (hwndChild))
  840.                     hwndSearch = hwndChild;
  841.  
  842.                 cbText = FORWARD_WM_GETTEXT(hwndSearch, BUFSIZE,
  843.                          achWindowText, SendMessage,) + 1;
  844.                 hIconTemp = GetClassWord (hwndSearch, GCW_HICON);
  845.                 hwndSearch = (HWND)0;
  846.                 }
  847.             else
  848.                 {
  849.                 hwndSearch = GetWindow (hwndSearch, GW_HWNDNEXT);
  850.                 }
  851.             }
  852.  
  853.         //  Save handle to icon.
  854.         lptlTemp->hIcon = (hIconTemp) ? hIconTemp : hIconDefault;
  855.  
  856.         //  Copy window text into task table.
  857.         if (achWindowText[0] != '\0')
  858.             _fmemcpy (lptlTemp->achWindowText, achWindowText, cbText);
  859.         else
  860.             {
  861.             moduleentry.dwSize = sizeof (MODULEENTRY);
  862.             ModuleFindHandle(&moduleentry, lptlTemp->taskentry.hModule);
  863.             cbText = lstrlen (&moduleentry.szModule[0]) + 1;
  864.             _fmemcpy (lptlTemp->achWindowText,
  865.                       &moduleentry.szModule[0], cbText);
  866.             }
  867.  
  868.         // Fetch size of DGroup segment.
  869.         //
  870.         dwDGroupTemp = GlobalSize (lptlTemp->taskentry.hInst);
  871.  
  872.         // Loop through segment table, adding up memory
  873.         // allocated from the global heap.
  874.         //
  875.         dwGlobalTemp = 0L;
  876.         hTask = lptlTemp->taskentry.hTask;
  877.         for (iSegment = 0, lpheTemp = lpheList;
  878.              iSegment < cSegments;
  879.              iSegment++, lpheTemp++)
  880.             {
  881.             if (hTask == lpheTemp->hOwner)
  882.                 {
  883.                 if (lpheTemp->wType == GT_UNKNOWN)
  884.                     {
  885.                     dwGlobalTemp += lpheTemp->dwBlockSize;
  886.                     }
  887.                 }
  888.  
  889.             } /* [for iSegment] */
  890.  
  891.         // If DGroup size has changed or
  892.         // if Global size has changed then generate WM_PAINT.
  893.         //
  894.         if (lptlTemp->dwDGroup != dwDGroupTemp ||
  895.             lptlTemp->dwGlobal != dwGlobalTemp )
  896.             {
  897.             // Update values in task list.
  898.             lptlTemp->dwDGroup = dwDGroupTemp;
  899.             lptlTemp->dwGlobal = dwGlobalTemp;
  900.  
  901.             // Generate a WM_PAINT in listbox.
  902.             ListBox_GetItemRect(hwndTask, iTask, &rRepaint);
  903.             rRepaint.left  += am.tx_xTaskText;
  904.             rRepaint.right += am.tx_yTaskText;
  905.             InvalidateRect (hwndTask, &rRepaint, FALSE);
  906.             }
  907.  
  908.         // Calculate maximum sizes, to allow proper scaling
  909.         // of task segment graph.
  910.         dwTaskMax = max (dwDGroupTemp, dwTaskMax);
  911.         dwTaskMax = max (dwGlobalTemp, dwTaskMax);
  912.  
  913.         } /* [for iTask] */
  914.  
  915.     // If there have been a change in list box scaling factor,
  916.     // repaint entire list box.
  917.     if (dwTaskMaxTemp != dwTaskMax)
  918.         {
  919.         GetClientRect (hwndTask, &rRepaint);
  920.         rRepaint.left = am.tx_xTaskText;
  921.         InvalidateRect (hwndTask, &rRepaint, FALSE);
  922.         }
  923.  
  924.     // Scale memory figures to fit in GDI's 16-bit coordinates.
  925.     //
  926.     nTaskFactor = 1;
  927.     while ( (dwTaskMax/ nTaskFactor) > 0x8000L)
  928.         {
  929.         nTaskFactor *= 2;
  930.         }
  931.     }
  932.  
  933.  
  934. /*-------------------------------------------------------------*\
  935.  |            trFillTaskListbox:  Fill task lisbox.            |
  936. \*-------------------------------------------------------------*/
  937. void NEAR PASCAL
  938. trFillTaskListbox(HWND hwndTask)
  939.     {
  940.     int  iCurSel;
  941.     int  iTask;
  942.  
  943.     // Get index of currently selected item.
  944.     iCurSel = ListBox_GetCurSel(hwndTask);
  945.  
  946.     // Purge listbox.
  947.     ListBox_ResetContent(hwndTask);
  948.  
  949.     // Fill listbox with task information
  950.     for (iTask = 0;
  951.          iTask < cTaskList;
  952.          iTask++)
  953.         {
  954.         //  Add item to listbox.
  955.         ListBox_AddItemData (hwndTask, iTask);
  956.         } /* [for iTask] */
  957.  
  958.     // Make sure selection stays in range.
  959.     iCurSel = min (iCurSel, cTaskList - 1);
  960.     iCurSel = max (iCurSel, 0);
  961.  
  962.     // Set selection to last item selected.
  963.     ListBox_SetCurSel(hwndTask, iCurSel);
  964.  
  965.     // Reset current task index.
  966.     iCurTask = iCurSel;
  967.     }
  968.  
  969.  
  970. /*-------------------------------------------------------------*\
  971.  |         trFillSegmentListbox:  Fill module listbox.          |
  972. \*-------------------------------------------------------------*/
  973. void NEAR PASCAL
  974. trFillSegmentListbox(void)
  975.     {
  976.     int iSegType;
  977.  
  978.     for (iSegType = 0; iSegType < SEGTYPE_COUNT; iSegType++)
  979.         {
  980.         //  Add item to listbox.
  981.         ListBox_AddItemData (hwndModule, iSegType);
  982.         }
  983.     }
  984.  
  985.  
  986. /*-------------------------------------------------------------*\
  987.  |    trToolHelpNotify:  Watch for tasks starting/stopping.    |
  988. \*-------------------------------------------------------------*/
  989. BOOL FAR PASCAL _export
  990. trToolHelpNotify (WORD wID, DWORD dwData)
  991.     {
  992.     if (wID == NFY_STARTTASK ||
  993.         wID == NFY_EXITTASK)
  994.         {
  995.         PostMessage (hwndMain, AM_BUILDTASKLIST, 0, 0L);
  996.         }
  997.  
  998.     return FALSE;
  999.     }
  1000.