home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / perfmon / utils.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  43KB  |  1,575 lines

  1. /*
  2. ==============================================================================
  3.  
  4.   Application:
  5.  
  6.             Microsoft Windows NT (TM) Performance Monitor
  7.  
  8.   File:
  9.             utils.c -- miscellaneous utility routines.  
  10.  
  11.             This file contains miscellaneous utiltity routines, mostly 
  12.             low-level windows helpers. These routines are not specific
  13.             to the perfmon utillity.
  14.  
  15.   Copyright 1992-1997, Microsoft Corporation. All Rights Reserved.
  16.   Microsoft Confidential.
  17. ==============================================================================
  18. */
  19.  
  20.  
  21. //==========================================================================//
  22. //                                  Includes                                //
  23. //==========================================================================//
  24.  
  25.  
  26.  
  27. #include <stdarg.h>  // For ANSI variable args. Dont use UNIX <varargs.h>
  28. #include <stdlib.h>  // For itoa
  29. #include <stdio.h>   // for vsprintf.
  30. #include <string.h>  // for strtok
  31. #include <wchar.h>   // for swscanf
  32.  
  33. #include "perfmon.h"
  34. #include "pmemory.h"        // for MemoryXXX (mallloc-type) routines
  35. #include "utils.h"
  36. #include "pmhelpid.h"       // IDs for WinHelp
  37. #include "perfmops.h"       // for ConvertDecimalPoint() & ReconvertDecimalPoint()
  38. #include "sizes.h"
  39.  
  40. //==========================================================================//
  41. //                                  Constants                               //
  42. //==========================================================================//
  43.  
  44.  
  45. #define DOS_FILES                0x0000   // Ordinary files
  46. #define DOS_READONLY             0x0001   // Read-only files
  47. #define DOS_HIDDEN               0x0002   // Hidden files
  48. #define DOS_SYSTEM               0x0004   // System files
  49. #define DOS_SUBDIRECTORIES       0x0010   // Subdirectories
  50. #define DOS_ARCHIVES             0x0020   // Archives
  51. #define DOS_LIB_DIR              0x2000   // LB_DIR flag
  52. #define DOS_DRIVES               0x4000   // Drives
  53. #define DOS_EXCLUSIVE            0x8000   // Exclusive bit
  54. #define DOS_DRIVES_DIRECTORIES   0xC010   // Find drives and directories only
  55.  
  56.  
  57. #define WILD_ONE                 '?'
  58. #define WILD_ANY                 '*'
  59.  
  60.  
  61.  
  62.  
  63. //==========================================================================//
  64. //                              Local Functions                             //
  65. //==========================================================================//
  66.  
  67.  
  68.  
  69. void ClientRectToScreen (HWND hWnd,
  70.                          LPRECT lpRect)
  71. /*
  72.    Effect:        Remaps lpRect from client coordinates to screen
  73.                   coordinates. Analogous to ClientToScreen for rectangles.
  74.  
  75.    Note:          To convert a rectangle from the client coordinates of
  76.                   Wnd1 to the client coordinates of Wnd2, call:
  77.  
  78.                         ClientRectToScreen (hWnd1, &rect) ;
  79.                         ScreenRectToClient (hWnd2, &rect) ;
  80.  
  81.    See Also:      ClientToScreen (windows), ScreenRectToClient.
  82.  
  83.    Internals:     Since a rectangle is really only two points, let
  84.                   windows do the work with ClientToScreen.
  85. */
  86.    {  /* ClientRectToScreen */
  87.    POINT    pt1, pt2 ;
  88.  
  89.    pt1.x = lpRect->left ;
  90.    pt1.y = lpRect->top ;
  91.  
  92.    pt2.x = lpRect->right ;
  93.    pt2.y = lpRect->bottom ;
  94.  
  95.    ClientToScreen (hWnd, &pt1) ;
  96.    ClientToScreen (hWnd, &pt2) ;
  97.  
  98.    lpRect->left = pt1.x ;
  99.    lpRect->top = pt1.y ;
  100.  
  101.    lpRect->right = pt2.x ;
  102.    lpRect->bottom = pt2.y ;
  103.    }  // ClientRectToScreen
  104.  
  105.  
  106. void ScreenRectToClient (HWND hWnd, LPRECT lpRect)
  107. /*
  108.    Effect:        Remaps lpRect from screen coordinates to client
  109.                   coordinates. Analogous to ScreenToClient for rectangles.
  110.  
  111.    Note:          To convert a rectangle from the client coordinates of
  112.                   Wnd1 to the client coordinates of Wnd2, call:
  113.  
  114.                         ClientRectToScreen (hWnd1, &rect) ;
  115.                         ScreenRectToClient (hWnd2, &rect) ;
  116.  
  117.    See Also:      ScreenToClient (windows), ClientRectToScreen.
  118.  
  119.    Internals:     Since a rectangle is really only two points, let
  120.                   windows do the work with ScreenToClient.
  121. */
  122.    {  // ScreenRectToClient
  123.    POINT    pt1, pt2 ;
  124.  
  125.    pt1.x = lpRect->left ;
  126.    pt1.y = lpRect->top ;
  127.  
  128.    pt2.x = lpRect->right ;
  129.    pt2.y = lpRect->bottom ;
  130.  
  131.    ScreenToClient (hWnd, &pt1) ;
  132.    ScreenToClient (hWnd, &pt2) ;
  133.  
  134.    lpRect->left = pt1.x ;
  135.    lpRect->top = pt1.y ;
  136.  
  137.    lpRect->right = pt2.x ;
  138.    lpRect->bottom = pt2.y ;
  139.    }  // ScreenRectToClient
  140.  
  141.  
  142. //==========================================================================//
  143. //                             Exported Functions                           //
  144. //==========================================================================//
  145.  
  146.  
  147. void Line (HDC hDC,
  148.            HPEN hPen,
  149.            int x1, int y1,
  150.            int x2, int y2)
  151.    {  // Line
  152.    HPEN           hPenPrevious ;
  153.  
  154.    if (hPen)
  155.       hPenPrevious = SelectPen (hDC, hPen) ;
  156.    MoveToEx (hDC, x1, y1, NULL) ;
  157.    LineTo (hDC, x2, y2) ;
  158.    if (hPen)
  159.       SelectObject (hDC, hPenPrevious) ;
  160.    }  // Line
  161.  
  162. #if 0
  163. void HLine (HDC hDC,
  164.             HPEN hPen,
  165.             int x1, 
  166.             int x2, 
  167.             int y)
  168.    {  // HLine
  169.    Line (hDC, hPen, x1, y, x2, y) ;
  170.    }
  171.  
  172.  
  173. void VLine (HDC hDC,
  174.             HPEN hPen,
  175.             int x,
  176.             int y1,
  177.             int y2)
  178.    {  // VLine
  179.    Line (hDC, hPen, x, y1, x, y2) ;
  180.    }  // VLine
  181. #endif
  182.  
  183. #ifdef  KEEP_UTIL
  184. void Fill (HDC hDC,
  185.            DWORD rgbColor,
  186.            LPRECT lpRect)
  187.    {  // Fill
  188.    HBRUSH         hBrush ;
  189.  
  190.    hBrush = CreateSolidBrush (rgbColor) ;
  191.  
  192.    FillRect (hDC, lpRect, hBrush) ;
  193.  
  194.    DeleteBrush (hBrush) ;
  195.    }  // Fill
  196.  
  197. void ThreeDConvex (HDC hDC,
  198.                int x1, int y1, 
  199.                int x2, int y2)
  200.    {  // ThreeDConvex
  201.    HBRUSH         hBrushPrevious ;
  202.    POINT          aPoints [8] ;
  203.    DWORD          aCounts [2] ;
  204.    HPEN           hPenPrevious ;
  205.  
  206.  
  207.    //┌────────────────────────────┐
  208.    //│ Draw Face                  │
  209.    //└────────────────────────────┘
  210.  
  211.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  212.    PatBlt (hDC, 
  213.            x1 + ThreeDPad, y1 + ThreeDPad, 
  214.            x2 - x1 - ThreeDPad, y2 - y1 - ThreeDPad, 
  215.            PATCOPY) ;
  216.    SelectBrush (hDC, hBrushPrevious) ;
  217.  
  218.    //┌────────────────────────────┐
  219.    //│ Draw Highlight             │
  220.    //└────────────────────────────┘
  221.  
  222.    if (hPenHighlight)
  223.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  224.  
  225.    aPoints [0].x = x1 ;
  226.    aPoints [0].y = y2 - 1 ;   // this works slightly diff. than Line ??
  227.    aPoints [1].x = x1 ;
  228.    aPoints [1].y = y1 ;
  229.    aPoints [2].x = x2 ;
  230.    aPoints [2].y = y1 ;
  231.  
  232.    aPoints [3].x = x1 + 1 ;
  233.    aPoints [3].y = y2 - 1 ;
  234.    aPoints [4].x = x1 + 1 ;
  235.    aPoints [4].y = y1 + 1 ;
  236.    aPoints [5].x = x2 - 1 ;
  237.    aPoints [5].y = y1 + 1 ;
  238.  
  239.    aCounts [0] = 3 ;
  240.    aCounts [1] = 3 ;
  241.  
  242.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  243.    
  244.    
  245.    if (hPenHighlight)
  246.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  247.  
  248. //   HLine (hDC, hPenHighlight, x1, x2, y1) ;              // outside top line
  249. //   HLine (hDC, hPenHighlight, x1 + 1, x2 - 1, y1 + 1) ;  // inside top line
  250. //   VLine (hDC, hPenHighlight, x1, y1, y2) ;              // outside left line
  251. //   VLine (hDC, hPenHighlight, x1 + 1, y1 + 1, y2 - 1) ;  // inside left line
  252.  
  253.    //┌────────────────────────────┐
  254.    //│ Draw Shadow                │
  255.    //└────────────────────────────┘
  256.  
  257.    if (hPenShadow)
  258.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  259.  
  260.    aPoints [0].x = x1 + 1 ;
  261.    aPoints [0].y = y2 - 1 ;
  262.    aPoints [1].x = x2 ;
  263.    aPoints [1].y = y2 - 1 ;
  264.    aPoints [2].x = x2 ;
  265.    aPoints [2].y = y2 - 2 ;
  266.    aPoints [3].x = x1 + 2 ;
  267.    aPoints [3].y = y2 - 2 ;
  268.  
  269.    aPoints [4].x = x2 - 1 ;
  270.    aPoints [4].y = y1 ;
  271.    aPoints [5].x = x2 - 1 ;
  272.    aPoints [5].y = y2 - 1;
  273.    aPoints [6].x = x2 - 2 ;
  274.    aPoints [6].y = y2 - 1 ;
  275.    aPoints [7].x = x2 - 2 ;
  276.    aPoints [7].y = y1 ;
  277.  
  278.    aCounts [0] = 4 ;
  279.    aCounts [1] = 4 ;
  280.  
  281.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  282.    
  283.    
  284.    if (hPenShadow)
  285.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  286.  
  287. //   HLine (hDC, hPenShadow, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  288. //   HLine (hDC, hPenShadow, x1 + 2, x2, y2 - 2) ;   // inside bottom line
  289. //   VLine (hDC, hPenShadow, x2 - 1, y1 + 1, y2) ;   // outside right line
  290. //   VLine (hDC, hPenShadow, x2 - 2, y1 + 2, y2) ;   // inside right line
  291.  
  292.    }  // ThreeDConvex
  293.  
  294.  
  295.  
  296. void ThreeDConcave (HDC hDC,
  297.                     int x1, int y1, 
  298.                     int x2, int y2,
  299.                     BOOL bFace)
  300.    {  // ThreeDConcave
  301.    HBRUSH         hBrushPrevious ;
  302.    POINT          aPoints [6] ;
  303.    DWORD          aCounts [2] ;
  304.    HPEN           hPenPrevious ;
  305.  
  306.  
  307.    //┌────────────────────────────┐
  308.    //│ Draw Face                  │
  309.    //└────────────────────────────┘
  310.  
  311.    if (bFace)
  312.       {
  313.       hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  314.       PatBlt (hDC, 
  315.               x1 + ThreeDPad, y1 + ThreeDPad, 
  316.               x2 - x1 - ThreeDPad, y2 - y1 - ThreeDPad, 
  317.               PATCOPY) ;
  318.       SelectBrush (hDC, hBrushPrevious) ;
  319.       }
  320.  
  321.    //┌────────────────────────────┐
  322.    //│ Draw Shadow                │
  323.    //└────────────────────────────┘
  324.  
  325. #if 1
  326.    if (hPenShadow)
  327.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  328.  
  329.    aPoints [0].x = x1 ;
  330.    aPoints [0].y = y2 - 1 ;
  331.    aPoints [1].x = x1 ;
  332.    aPoints [1].y = y1 ;
  333.    aPoints [2].x = x2 ;
  334.    aPoints [2].y = y1 ;
  335.  
  336.    aPoints [3].x = x1 + 1 ;
  337.    aPoints [3].y = y2 - 1 ;
  338.    aPoints [4].x = x1 + 1 ;
  339.    aPoints [4].y = y1 + 1 ;
  340.    aPoints [5].x = x2 - 1 ;
  341.    aPoints [5].y = y1 + 1 ;
  342.  
  343.    aCounts [0] = 3 ;
  344.    aCounts [1] = 3 ;
  345.  
  346.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  347.    
  348.    if (hPenShadow)
  349.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  350.  
  351. #else
  352.    HLine (hDC, hPenShadow, x1, x2, y1) ;              // outside top line
  353.    HLine (hDC, hPenShadow, x1 + 1, x2 - 1, y1 + 1) ;  // inside top line
  354.    VLine (hDC, hPenShadow, x1, y1, y2) ;              // outside left line
  355.    VLine (hDC, hPenShadow, x1 + 1, y1 + 1, y2 - 1) ;  // inside left line
  356. #endif
  357.  
  358.    //┌────────────────────────────┐
  359.    //│ Draw Highlight             │
  360.    //└────────────────────────────┘
  361.  
  362. #if 1
  363.    if (hPenHighlight)
  364.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  365.  
  366.    aPoints [0].x = x1 + 1 ;
  367.    aPoints [0].y = y2 - 1 ;
  368.    aPoints [1].x = x2 ;
  369.    aPoints [1].y = y2 - 1 ;
  370.  
  371.    aPoints [2].x = x2 - 1 ;
  372.    aPoints [2].y = y2 - 1 ;
  373.    aPoints [3].x = x2 - 1 ;
  374.    aPoints [3].y = y1 ;
  375.  
  376.    aCounts [0] = 2 ;
  377.    aCounts [1] = 2 ;
  378.  
  379.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  380.    
  381.    if (hPenHighlight)
  382.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  383.  
  384. #else
  385.    HLine (hDC, hPenHighlight, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  386.    VLine (hDC, hPenHighlight, x2 - 1, y1 + 1, y2) ;   // outside right line
  387. #endif   
  388.    }  // ThreeDConcave
  389. #endif // KEEP_UTIL
  390.  
  391.      
  392. void ThreeDConvex1 (HDC hDC,
  393.                     int x1, int y1, 
  394.                     int x2, int y2)
  395.    {  // ThreeDConvex1
  396.    HBRUSH         hBrushPrevious ;
  397.    POINT          aPoints [6] ;
  398.    DWORD          aCounts [2] ;
  399.    HPEN           hPenPrevious ;
  400.  
  401.  
  402.    //┌────────────────────────────┐
  403.    //│ Draw Face                  │
  404.    //└────────────────────────────┘
  405. #if 1
  406.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  407.    PatBlt (hDC, 
  408.            x1 + 1, y1 + 1, 
  409.            x2 - x1 - 1, y2 - y1 - 1, 
  410.            PATCOPY) ;
  411.    SelectBrush (hDC, hBrushPrevious) ;
  412.  
  413.    //┌────────────────────────────┐
  414.    //│ Draw Highlight             │
  415.    //└────────────────────────────┘
  416.  
  417.    if (hPenHighlight)
  418.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  419.  
  420.    aPoints [0].x = x1 ;
  421.    aPoints [0].y = y2 - 1 ;
  422.    aPoints [1].x = x1 ;
  423.    aPoints [1].y = y1 ;
  424.    aPoints [2].x = x2 ;
  425.    aPoints [2].y = y1 ;
  426.  
  427.    Polyline (hDC, aPoints, 3) ;
  428.    
  429.    if (hPenHighlight)
  430.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  431.  
  432. #else
  433.    HLine (hDC, hPenHighlight, x1, x2, y1) ;              // outside top line
  434.    VLine (hDC, hPenHighlight, x1, y1, y2) ;              // outside left line
  435. #endif
  436.  
  437.    //┌────────────────────────────┐
  438.    //│ Draw Shadow                │
  439.    //└────────────────────────────┘
  440.  
  441. #if 1
  442.    if (hPenShadow)
  443.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  444.  
  445.    aPoints [0].x = x1 + 1 ;
  446.    aPoints [0].y = y2 - 1 ;
  447.    aPoints [1].x = x2 ;
  448.    aPoints [1].y = y2 - 1 ;
  449.  
  450.    aPoints [2].x = x2 - 1 ;
  451.    aPoints [2].y = y2 - 1 ;
  452.    aPoints [3].x = x2 - 1 ;
  453.    aPoints [3].y = y1 ;
  454.  
  455.    aCounts [0] = 2 ;
  456.    aCounts [1] = 2 ;
  457.  
  458.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  459.    
  460.    if (hPenShadow)
  461.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  462. #else
  463.    HLine (hDC, hPenShadow, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  464.    VLine (hDC, hPenShadow, x2 - 1, y1 + 1, y2) ;   // outside right line
  465. #endif
  466.  
  467.    }  // ThreeDConvex1
  468.  
  469.  
  470.  
  471. void ThreeDConcave1 (HDC hDC,
  472.                      int x1, int y1, 
  473.                      int x2, int y2)
  474.    {  // ThreeDConcave1
  475.    HBRUSH         hBrushPrevious ;
  476.    POINT          aPoints [6] ;
  477.    DWORD          aCounts [2] ;
  478.    HPEN           hPenPrevious ;
  479.  
  480.  
  481.    //┌────────────────────────────┐
  482.    //│ Draw Face                  │
  483.    //└────────────────────────────┘
  484.  
  485.    hBrushPrevious = SelectBrush (hDC, hBrushFace) ;
  486.    PatBlt (hDC, 
  487.            x1 + 1, y1 + 1, 
  488.            x2 - x1 - 1, y2 - y1 - 1, 
  489.            PATCOPY) ;
  490.    SelectBrush (hDC, hBrushPrevious) ;
  491.  
  492.    //┌────────────────────────────┐
  493.    //│ Draw Shadow                │
  494.    //└────────────────────────────┘
  495.  
  496. #if 1
  497.    if (hPenShadow)
  498.       hPenPrevious = SelectPen (hDC, hPenShadow) ;
  499.  
  500.    aPoints [0].x = x1 ;
  501.    aPoints [0].y = y2 - 1 ;
  502.    aPoints [1].x = x1 ;
  503.    aPoints [1].y = y1 ;
  504.    aPoints [2].x = x2 ;
  505.    aPoints [2].y = y1 ;
  506.  
  507.    Polyline (hDC, aPoints, 3) ;
  508.    
  509.    if (hPenShadow)
  510.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  511. #else
  512.    HLine (hDC, hPenShadow, x1, x2, y1) ;              // outside top line
  513.    VLine (hDC, hPenShadow, x1, y1, y2) ;              // outside left line
  514. #endif
  515.  
  516.    //┌────────────────────────────┐
  517.    //│ Draw Highlight             │
  518.    //└────────────────────────────┘
  519. #if 1
  520.    if (hPenHighlight)
  521.       hPenPrevious = SelectPen (hDC, hPenHighlight) ;
  522.  
  523.    aPoints [0].x = x1 + 1 ;
  524.    aPoints [0].y = y2 - 1 ;
  525.    aPoints [1].x = x2 ;
  526.    aPoints [1].y = y2 - 1 ;
  527.  
  528.    aPoints [2].x = x2 - 1 ;
  529.    aPoints [2].y = y2 - 2 ;
  530.    aPoints [3].x = x2 - 1 ;
  531.    aPoints [3].y = y1 ;
  532.  
  533.    aCounts [0] = 2 ;
  534.    aCounts [1] = 2 ;
  535.  
  536.    PolyPolyline (hDC, aPoints, aCounts, 2) ;
  537.    
  538.    if (hPenHighlight)
  539.       hPenPrevious = SelectPen (hDC, hPenPrevious) ;
  540. #else
  541.    HLine (hDC, hPenHighlight, x1 + 1, x2, y2 - 1) ;   // outside bottom line
  542.    VLine (hDC, hPenHighlight, x2 - 1, y1 + 1, y2) ;   // outside right line
  543. #endif
  544.    
  545.    }  // ThreeDConcave1
  546.  
  547.  
  548. int TextWidth (HDC hDC, LPTSTR lpszText)
  549.    {
  550.    SIZE           size ;
  551.  
  552.    if (!lpszText)
  553.       return (0) ;
  554.  
  555.    GetTextExtentPoint (hDC, lpszText, lstrlen (lpszText), &size) ;
  556.    return  (size.cx) ;
  557.    }
  558.  
  559.  
  560. int _cdecl DlgErrorBox (HWND hDlg, UINT id, ...)
  561.    {
  562.    TCHAR          szMessageFmt [FilePathLen + 1] ;
  563.    TCHAR          szBuffer [FilePathLen * 2] ;
  564.    va_list        vaList ;
  565.    int            NumOfChar ;
  566.    TCHAR          szApplication [WindowCaptionLen] ;
  567.  
  568.    NumOfChar = StringLoad (id, szMessageFmt) ;
  569.  
  570.    if (NumOfChar)
  571.       {
  572.       va_start (vaList, id) ;
  573.       TSPRINTF (szBuffer, szMessageFmt, va_arg(vaList, LPTSTR)) ;
  574.       va_end (vaList) ;
  575.  
  576.       StringLoad (IDS_APPNAME, szApplication) ;
  577.  
  578.       MessageBox (hDlg, szBuffer, szApplication,
  579.          MB_OK | MB_ICONSTOP | MB_TASKMODAL) ;
  580.       }
  581.  
  582.    return (0) ;
  583.    }
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590. int FontHeight (HDC hDC, 
  591.                  BOOL bIncludeLeading)
  592.    {  // FontHeight
  593.    TEXTMETRIC     tm ;
  594.  
  595.    GetTextMetrics (hDC, &tm) ;
  596.    if (bIncludeLeading)
  597.       return (tm.tmHeight + tm.tmExternalLeading) ;
  598.    else
  599.       return (tm.tmHeight) ;
  600.    }  // FontHeight
  601.  
  602.  
  603.  
  604. int TextAvgWidth (HDC hDC,
  605.                   int iNumChars)
  606.    {
  607.    TEXTMETRIC     tm ;
  608.    int            xAvgWidth ;
  609.  
  610.    GetTextMetrics (hDC, &tm) ;
  611.  
  612.    xAvgWidth = iNumChars * tm.tmAveCharWidth ;
  613.  
  614.    // add 10% slop
  615.    return (MulDiv (xAvgWidth, 11, 10)) ;   
  616.    }
  617.  
  618.  
  619. void WindowCenter (HWND hWnd)
  620. /*
  621.    Effect:        Center the window hWnd in the center of the screen.
  622.                   Physically update the windows appearance as well.
  623.  
  624.    Globals:       xScreenWidth, yScreenHeight.
  625. */
  626.    {  // WindowCenter
  627.    RECT           rectWindow ;
  628.    int            xWindowWidth, yWindowHeight ;
  629.  
  630.    GetWindowRect (hWnd, &rectWindow) ;
  631.    xWindowWidth = rectWindow.right - rectWindow.left ;
  632.    yWindowHeight = rectWindow.bottom - rectWindow.top ;
  633.  
  634.    MoveWindow (hWnd,
  635.                (xScreenWidth - xWindowWidth) / 2,
  636.                (yScreenHeight - yWindowHeight) / 2,
  637.                xWindowWidth,
  638.                yWindowHeight,
  639.                TRUE) ;
  640.    }  // WindowCenter
  641.  
  642.  
  643.  
  644. BOOL DialogMove (HDLG hDlg,
  645.                  WORD wControlID,
  646.                  int xPos, 
  647.                  int yPos,
  648.                  int xWidth,
  649.                  int yHeight)
  650. /*
  651.    Effect:        Move the control identified by wControlID in the dialog  
  652.                   hDlg to the new position (xPos, yPos), and resize to
  653.                   (xWidth, yHeight). If any of these values are NOCHANGE, retain
  654.                   the current value.
  655.  
  656.    Examples:      DialogMove (hDlg, IDD_FOO, 10, 20, NOCHANGE, NOCHANGE)
  657.                      moves control but does not resize it
  658.  
  659.                   DialogMove (hDlg, IDD_FOO, NOCHANGE, NOCHANGE, 100, NOCHANGE)
  660.                      sets width of control to 100
  661. */                     
  662.    {  // DialogMove
  663.    HWND        hWndControl ;
  664.    RECT        rectControl ;
  665.  
  666.    hWndControl = DialogControl (hDlg, wControlID) ;
  667.    if (!hWndControl)
  668.       return (FALSE) ;
  669.    GetWindowRect (hWndControl, &rectControl) ;
  670.    ScreenRectToClient (hDlg, &rectControl) ;
  671.  
  672.    MoveWindow (hWndControl,
  673.                (xPos == NOCHANGE) ? rectControl.left : xPos,
  674.                (yPos == NOCHANGE) ? rectControl.top : yPos,
  675.                (xWidth == NOCHANGE) ? rectControl.right - rectControl.left : xWidth,
  676.                (yHeight == NOCHANGE) ? rectControl.bottom - rectControl.top : yHeight,
  677.                TRUE) ;
  678.  
  679.    return (TRUE) ;
  680.    }  // DialogMove
  681.  
  682.  
  683. int DialogWidth (HDLG hDlg, 
  684.                  WORD wControlID)
  685.    {
  686.    HWND           hWndControl ;
  687.    RECT           rectControl ;
  688.  
  689.    hWndControl = DialogControl (hDlg, wControlID) ;
  690.    if (!hWndControl)
  691.       return (0) ;
  692.  
  693.    GetWindowRect (hWndControl, &rectControl) ;
  694.    return (rectControl.right - rectControl.left) ;
  695.    }
  696.    
  697.  
  698. int DialogHeight (HDLG hDlg, 
  699.                   WORD wControlID)
  700.    {
  701.    HWND           hWndControl ;
  702.    RECT           rectControl ;
  703.  
  704.    hWndControl = DialogControl (hDlg, wControlID) ;
  705.    if (!hWndControl)
  706.       return (0) ;
  707.  
  708.    GetWindowRect (hWndControl, &rectControl) ;
  709.    return (rectControl.bottom - rectControl.top) ;
  710.    }
  711.    
  712.  
  713. int DialogXPos (HDLG hDlg,
  714.                 WORD wControlID)
  715.    {  // DialogXPos
  716.    HWND           hWndControl ;
  717.    RECT           rectControl ;
  718.  
  719.    hWndControl = DialogControl (hDlg, wControlID) ;
  720.    if (!hWndControl)
  721.       return (0) ;
  722.  
  723.    GetWindowRect (hWndControl, &rectControl) ;
  724.    ScreenRectToClient (hDlg, &rectControl) ;
  725.  
  726.    return  (rectControl.left) ;
  727.    }  // DialogXPos
  728.  
  729.  
  730. int DialogYPos (HDLG hDlg,
  731.                 WORD wControlID)
  732.    {  // DialogYPos
  733.    HWND           hWndControl ;
  734.    RECT           rectControl ;
  735.  
  736.    hWndControl = DialogControl (hDlg, wControlID) ;
  737.    if (!hWndControl)
  738.       return (0) ;
  739.  
  740.    GetWindowRect (hWndControl, &rectControl) ;
  741.    ScreenRectToClient (hDlg, &rectControl) ;
  742.  
  743.    return  (rectControl.top) ;
  744.    }  // DialogYPos
  745.  
  746.  
  747. void DialogEnable (HDLG hDlg,
  748.                    WORD wID,
  749.                    BOOL bEnable)
  750. /*
  751.    Effect:        Enable or disable (based on bEnable) the control 
  752.                   identified by wID in dialog hDlg.
  753.  
  754.    See Also:      DialogShow.
  755. */
  756.    {  // DialogEnable
  757.    HCONTROL       hControl ;
  758.  
  759.    hControl = GetDlgItem (hDlg, wID) ;
  760.    if (hControl)
  761.       EnableWindow (hControl, bEnable) ;
  762.    }  // DialogEnable
  763.  
  764.  
  765. void DialogShow (HDLG hDlg,
  766.                  WORD wID,
  767.                  BOOL bShow)
  768.    {  // DialogShow
  769.    HCONTROL       hControl ;
  770.  
  771.    hControl = GetDlgItem (hDlg, wID) ;
  772.    if (hControl)
  773.       ShowWindow (hControl, bShow ? SW_SHOW : SW_HIDE) ;
  774.    }  // DialogShow
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781. BOOL _cdecl DialogSetText (HDLG hDlg,
  782.                            WORD wControlID,
  783.                            WORD wStringID,
  784.                            ...)
  785.    {  // DialogSetText
  786.    TCHAR           szFormat [ControlStringLen] ;
  787.    TCHAR           szText [ControlStringLen] ;
  788.    va_list         vaList ;
  789.  
  790.    if (LoadString (hInstance, wStringID,
  791.                    szFormat, ControlStringLen - 1))
  792.       {
  793.       va_start (vaList, wStringID) ;
  794.       TSPRINTF (szText, szFormat, va_arg(vaList, LPTSTR)) ;
  795.       va_end (vaList) ;
  796.  
  797.       SetDlgItemText (hDlg, wControlID, szText) ;
  798.       return (TRUE) ;
  799.       }  // if
  800.    else
  801.       return (FALSE) ;
  802.    }  // DialogSetText
  803.  
  804.  
  805. // Bug - lpszFormat could contain % in it
  806. #if 0
  807. BOOL _cdecl DialogSetString (HDLG hDlg,
  808.                              WORD wControlID,
  809.                              LPTSTR lpszFormat,
  810.                              ...)
  811.    {  // DialogSetString
  812.    TCHAR          szText [ControlStringLen] ;
  813.    va_list        vaList ;
  814.  
  815.    va_start (vaList, lpszFormat) ;
  816.    TSPRINTF (szText, lpszFormat, va_arg(vaList, LPTSTR)) ;
  817.    va_end (vaList) ;
  818.  
  819.    SetDlgItemText (hDlg, wControlID, szText) ;
  820.    return (TRUE) ;
  821.    }  // DialogSetString
  822. #endif
  823.  
  824.  
  825. LPTSTR LongToCommaString (LONG lNumber,
  826.                           LPTSTR lpszText)
  827.    {  // LongToCommaString
  828.    BOOL           bNegative ;
  829.    TCHAR          szTemp1 [40] ;
  830.    TCHAR          szTemp2 [40] ;
  831.    LPTSTR         lpsz1 ;
  832.    LPTSTR         lpsz2 ;
  833.    int            i ;
  834.    int            iDigit ;
  835.  
  836.    // 1. Convert the number to a reversed string.
  837.    lpsz1 = szTemp1 ;
  838.    bNegative = (lNumber < 0) ;
  839.    lNumber = labs (lNumber) ;
  840.  
  841.    if (lNumber)
  842.       while (lNumber)
  843.          {
  844.          iDigit = (int) (lNumber % 10L) ;
  845.          lNumber /= 10L ;
  846.          *lpsz1++ = (TCHAR) (TEXT('0') + iDigit) ;
  847.          }
  848.    else
  849.       *lpsz1++ = TEXT('0') ;
  850.    *lpsz1++ = TEXT('\0') ;
  851.  
  852.  
  853.    // 2. reverse the string and add commas
  854.    lpsz1 = szTemp1 + lstrlen (szTemp1) - 1 ;
  855.    lpsz2 = szTemp2 ;
  856.  
  857.    if (bNegative)
  858.       *lpsz2++ = TEXT('-') ;
  859.  
  860.    for (i = lstrlen (szTemp1) - 1;
  861.         i >= 0 ;
  862.         i--)
  863.       {  // for
  864.       *lpsz2++ = *lpsz1-- ;
  865.       if (i && !(i % 3))
  866.          *lpsz2++ = TEXT(',') ;
  867.       }  // for
  868.    *lpsz2++ = TEXT('\0') ;
  869.  
  870.    return (lstrcpy (lpszText, szTemp2)) ;
  871.    }  // LongToCommaString
  872.  
  873.  
  874.  
  875. BOOL MenuSetPopup (HWND hWnd,
  876.                    int iPosition,
  877.                    WORD  wControlID,
  878.                    LPTSTR lpszResourceID)
  879.    {
  880.    HMENU          hMenuMain ;
  881.    HMENU          hMenuPopup ;
  882.    TCHAR          szTopChoice [MenuStringLen + 1] ;
  883.  
  884.    hMenuMain = GetMenu (hWnd) ;
  885.    hMenuPopup = LoadMenu (hInstance, lpszResourceID) ;
  886.  
  887.    if (!hMenuMain || !hMenuPopup)
  888.       return (FALSE) ;
  889.  
  890.    StringLoad (wControlID, szTopChoice) ;
  891.    return (ModifyMenu (hMenuMain, iPosition, MF_BYPOSITION | MF_POPUP,
  892.                        (UINT) hMenuPopup, szTopChoice)) ;
  893.    }               
  894.          
  895.  
  896.    
  897. LPTSTR FileCombine (LPTSTR lpszFileSpec,
  898.                     LPTSTR lpszFileDirectory,
  899.                     LPTSTR lpszFileName)
  900.    {  // FileCombine
  901.  
  902.    int      stringLen ;
  903.    TCHAR    DIRECTORY_DELIMITER[2] ;
  904.  
  905.    DIRECTORY_DELIMITER[0] = TEXT('\\') ;
  906.    DIRECTORY_DELIMITER[1] = TEXT('\0') ;
  907.  
  908.    lstrcpy (lpszFileSpec, lpszFileDirectory) ;
  909.  
  910.    stringLen = lstrlen (lpszFileSpec) ;
  911.    if (stringLen > 0 &&
  912.        lpszFileSpec [stringLen - 1] != DIRECTORY_DELIMITER [0])
  913.       lstrcat (lpszFileSpec, DIRECTORY_DELIMITER) ;
  914.  
  915.    lstrcat (lpszFileSpec, lpszFileName) ;
  916.  
  917.    return (lpszFileSpec) ;
  918.    }  // FileCombine
  919.  
  920. // This routine extract the filename portion from a given full-path filename
  921. LPTSTR ExtractFileName (LPTSTR pFileSpec)
  922.    {
  923.    LPTSTR   pFileName = NULL ;
  924.    TCHAR    DIRECTORY_DELIMITER1 = TEXT('\\') ;
  925.    TCHAR    DIRECTORY_DELIMITER2 = TEXT(':') ;
  926.  
  927.    if (pFileSpec)
  928.       {
  929.       pFileName = pFileSpec + lstrlen (pFileSpec) ;
  930.  
  931.       while (*pFileName != DIRECTORY_DELIMITER1 &&
  932.          *pFileName != DIRECTORY_DELIMITER2)
  933.          {
  934.          if (pFileName == pFileSpec)
  935.             {
  936.             // done when no directory delimiter is found
  937.             break ;
  938.             }
  939.          pFileName-- ;
  940.          }
  941.       
  942.       if (*pFileName == DIRECTORY_DELIMITER1 ||
  943.          *pFileName == DIRECTORY_DELIMITER2)
  944.          {
  945.          // directory delimiter found, point the 
  946.          // filename right after it
  947.          pFileName++ ;
  948.          }
  949.       }
  950.    return pFileName ;
  951.    }  // ExtractFileName
  952.  
  953. int CBAddInt (HWND hWndCB,
  954.               int iValue)
  955.    {  // CBAddInt
  956.    TCHAR       szValue [ShortTextLen + 1] ;
  957.    CHAR        szCharValue [ShortTextLen + 1] ;
  958.  
  959.    itoa (iValue, (LPSTR)szCharValue, 10) ;
  960. #ifdef UNICODE
  961.    mbstowcs (szValue, (LPSTR)szCharValue, strlen((LPSTR)szCharValue)+1) ;
  962.    return (CBAdd (hWndCB, szValue)) ;
  963. #else
  964.    return (CBAdd (hWndCB, szCharValue)) ;
  965. #endif
  966.  
  967.    }  // CBAddInt
  968.  
  969. void DialogSetInterval (HDLG hDlg,
  970.                         WORD wControlID,
  971.                         int  IntervalMSec)
  972.    {
  973.    TCHAR          szValue [MiscTextLen] ;
  974.  
  975.    TSPRINTF (szValue, TEXT("%3.3f"),
  976.             (FLOAT)(IntervalMSec) / (FLOAT)1000.0) ;
  977.    ConvertDecimalPoint (szValue) ;
  978.    SetDlgItemText (hDlg, wControlID, szValue) ;
  979.    }
  980.  
  981. void DialogSetFloat (HDLG hDlg,
  982.                      WORD wControlID,
  983.                      FLOAT eValue)
  984.    {
  985.    TCHAR          szValue [40] ;
  986.    FLOAT          tempValue = eValue ;
  987.  
  988.    if (tempValue < (FLOAT) 0.0)
  989.       {
  990.       tempValue = - tempValue ;
  991.       }
  992.  
  993.    if (tempValue < (FLOAT) 1.0E+8)
  994.       {
  995.       TSPRINTF (szValue, TEXT("%1.4f"), eValue) ;
  996.       }
  997.    else
  998.       {
  999.       TSPRINTF (szValue, TEXT("%14.6e"), eValue) ;
  1000.       }
  1001.    ConvertDecimalPoint (szValue) ;
  1002.  
  1003.    SetDlgItemText (hDlg, wControlID, szValue) ;
  1004.    }
  1005.  
  1006.  
  1007. FLOAT DialogFloat (HDLG hDlg, 
  1008.                    WORD wControlID,
  1009.                    BOOL *pbOK)
  1010. /*
  1011.    Effect:        Return a floating point representation of the string
  1012.                   value found in the control wControlID of hDlg.
  1013.  
  1014.    Internals:     We use sscanf instead of atof becuase atof returns a 
  1015.                   double. This may or may not be the right thing to do.
  1016. */
  1017.    {  // DialogFloat
  1018.    TCHAR          szValue [ShortTextLen+1] ;
  1019.    FLOAT          eValue ;
  1020.    int            iNumScanned ;
  1021.  
  1022.    DialogText (hDlg, wControlID, szValue) ;
  1023.    ReconvertDecimalPoint (szValue) ;
  1024.    iNumScanned = swscanf (szValue, TEXT("%e"), &eValue) ;
  1025.  
  1026.    if (pbOK)
  1027.       *pbOK = (iNumScanned == 1) ;
  1028.  
  1029.    return (eValue) ;
  1030.    }  // DialogFloat
  1031.  
  1032.  
  1033.  
  1034. LPTSTR StringAllocate (LPTSTR lpszText1)
  1035.    {  // StringAllocate
  1036.    LPTSTR         lpszText2 ;
  1037.  
  1038.    if (!lpszText1)
  1039.       return (NULL) ;
  1040.  
  1041.    if (lstrlen (lpszText1) == 0)
  1042.       return (NULL) ;
  1043.  
  1044.    lpszText2 = MemoryAllocate ((lstrlen (lpszText1)+1) * sizeof (TCHAR)) ;
  1045.    if (lpszText2)
  1046.       lstrcpy (lpszText2, lpszText1) ;
  1047.  
  1048.    return  (lpszText2) ;
  1049.    }  // StringAllocate
  1050.  
  1051.  
  1052.  
  1053. int DivRound (int iNumerator, int iDenominator)
  1054. /*
  1055.    Effect:        Return the quotient (iNumerator / iDenominator).
  1056.                   Round the quotient to the nearest integer.
  1057.                   This function is similar to normal integer division (/),
  1058.                   but normal division always rounds down.
  1059.  
  1060.    Note:          Surely there must already be a runtime version of this,
  1061.                   but I couldn't find it. 
  1062.  
  1063.    Note:          This function originally used the runtime div function
  1064.                   instead of (/ and %), but the div runtime function is
  1065.                   now broken (build 265).   
  1066. */
  1067.    {  // DivRound
  1068.    int            iQuotient ;
  1069.    int            iRemainder ;
  1070.  
  1071.  
  1072.    iQuotient = iNumerator / iDenominator ;
  1073.    iRemainder = iNumerator % iDenominator ;
  1074.  
  1075.    if (iRemainder >= (iDenominator / 2))
  1076.       iQuotient++ ;
  1077.  
  1078.    return (iQuotient) ;
  1079.    }
  1080.  
  1081.  
  1082. BOOL MenuEnableItem (HMENU hMenu,
  1083.                      WORD wID,
  1084.                      BOOL bEnable)
  1085. /*
  1086.    Effect:        Enable or disable, depending on bEnable, the menu item
  1087.                   associated with id wID in the menu hMenu.
  1088.  
  1089.                   Any disabled menu items are displayed grayed out.
  1090.  
  1091.    See Also:      EnableMenuItem (windows).
  1092. */
  1093.    {  // MenuEnableItem
  1094.    return (EnableMenuItem (hMenu, wID,
  1095.                            bEnable ?
  1096.                               (MF_ENABLED | MF_BYCOMMAND) :
  1097.                               (MF_GRAYED | MF_BYCOMMAND))) ;
  1098.    }  // MenuEnableItem
  1099.  
  1100. void BitmapDimemsion (HBITMAP hBitmap, int *pHeight, int *pWidth)
  1101.    {  // BitmapDimemsion
  1102.    BITMAP  bm ;
  1103.  
  1104.    GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
  1105.    if (pHeight)
  1106.       *pHeight = bm.bmHeight ;
  1107.    if (pWidth)
  1108.       *pWidth = bm.bmWidth ;
  1109.    }  // BitmapDimemsion
  1110.  
  1111.  
  1112. int WindowHeight (HWND hWnd)
  1113.    {  // WindowHeight
  1114.    RECT           rectWindow ;
  1115.  
  1116.    GetWindowRect (hWnd, &rectWindow) ;
  1117.    return (rectWindow.bottom - rectWindow.top) ;
  1118.    }  // WindowHeight
  1119.  
  1120.  
  1121. #ifdef KEEP_UTIL
  1122. int WindowWidth (HWND hWnd)
  1123.    {  // WindowWidth
  1124.    RECT           rectWindow ;
  1125.  
  1126.    GetWindowRect (hWnd, &rectWindow) ;
  1127.    return (rectWindow.right - rectWindow.left) ;
  1128.    }  // WindowWidth
  1129.  
  1130.  
  1131. void WindowResize (HWND hWnd,
  1132.                    int xWidth,
  1133.                    int yHeight)
  1134. /*
  1135.    Effect:        Change the size of the window hWnd, leaving the
  1136.                   starting position intact.  Redraw the window.
  1137.  
  1138.                   If either xWidth or yHeight is NULL, keep the
  1139.                   corresponding dimension unchanged.
  1140.  
  1141.    Internals:     Since hWnd may be a child of another parent, we need
  1142.                   to scale the MoveWindow arguments to be in the client
  1143.                   coordinates of the parent.
  1144.             
  1145. */
  1146.    {  // WindowResize
  1147.    RECT           rectWindow ;
  1148.    HWND           hWndParent ;
  1149.  
  1150.    GetWindowRect (hWnd, &rectWindow) ;
  1151.    hWndParent = WindowParent (hWnd) ;
  1152.  
  1153.    if (hWndParent)
  1154.       ScreenRectToClient (hWndParent, &rectWindow) ;
  1155.    
  1156.    MoveWindow (hWnd,
  1157.                rectWindow.left,
  1158.                rectWindow.top,
  1159.                xWidth ? xWidth : rectWindow.right - rectWindow.left,
  1160.                yHeight ? yHeight : rectWindow.bottom - rectWindow.top,
  1161.                TRUE) ;
  1162.    }  // WindowResize
  1163. #endif
  1164.  
  1165.  
  1166.  
  1167.  
  1168. void WindowSetTopmost (HWND hWnd, BOOL bTopmost)
  1169. /*
  1170.    Effect:        Set or clear the "topmost" attribute of hWnd. If a window
  1171.                   is "topmost", it remains ontop of other windows, even ones
  1172.                   that have the focus.
  1173. */
  1174.    {
  1175.    SetWindowPos (hWnd, bTopmost ? HWND_TOPMOST : HWND_NOTOPMOST,
  1176.                  0, 0, 0, 0,
  1177.                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE) ;
  1178.    }
  1179.  
  1180.  
  1181. void WindowEnableTitle (HWND hWnd, BOOL bTitle)
  1182.    {
  1183.    DWORD          dwStyle ;
  1184.  
  1185.  
  1186.    dwStyle = WindowStyle (hWnd) ;
  1187.    
  1188.    if (bTitle)
  1189.       dwStyle = WS_TILEDWINDOW | dwStyle ;
  1190.    else
  1191.       dwStyle = 
  1192.          dwStyle & 
  1193.          ~ (WS_DLGFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) ;
  1194.  
  1195.    if (!bTitle)
  1196.       SetMenu (hWnd, NULL) ;
  1197.  
  1198.    WindowSetStyle (hWnd, dwStyle) ;
  1199.    SetWindowPos (hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  1200.                  SWP_NOZORDER | SWP_FRAMECHANGED );
  1201.    }
  1202.  
  1203. // removing the following routines since LINK32 is not doing that for us
  1204. #ifdef  KEEP_UTIL
  1205. int MessageBoxResource (HWND hWndParent,
  1206.                         WORD wTextID,
  1207.                         WORD wTitleID,
  1208.                         UINT uiStyle)
  1209. /*
  1210.    Effect:        Just like MessageBox, but takes the title and format
  1211.                   strings from the resoure. In addition, the format string
  1212.                   is used as a printf style format, combined with the 
  1213.                   additional arguments.
  1214. */
  1215.    {  // MessageBoxResource
  1216.    TCHAR          szText [MessageLen + 1] ;
  1217.    TCHAR          szCaption [WindowCaptionLen + 1] ;
  1218.  
  1219.    StringLoad (wTextID, szText) ;
  1220.    StringLoad (wTitleID, szCaption) ;
  1221.  
  1222.    return (MessageBox (hWndParent, szText, szCaption, uiStyle)) ;
  1223.    }  // MessageBoxResource
  1224.  
  1225.  
  1226. #define WndProcKey   TEXT("OLDWNDPROC")
  1227.  
  1228. FARPROC WindowSetWndProc (HWND hWnd,
  1229.                           HANDLE hInstance,
  1230.                           FARPROC lpfnNewWndProc)
  1231. /*
  1232.    Effect:     Replace the window procedure of hWnd with lpfnNewWndProc.
  1233.                Return the existing window procedure.
  1234.  
  1235.    Note:       For proper subclassing, NewWndProc should pass all
  1236.                unhandled messages to the original wndproc.
  1237.  
  1238.    Called By:  WindowSubclass, WindowUnsubclass.
  1239. */
  1240.    {  // WindowSetWndProc
  1241.    FARPROC     lpfnNewProcInstance ;
  1242.    FARPROC     lpfnOldProc ;
  1243.  
  1244.    lpfnOldProc = (FARPROC) GetWindowLong (hWnd, GWL_WNDPROC) ;
  1245.    lpfnNewProcInstance = MakeProcInstance (lpfnNewWndProc, hInstance) ;
  1246.    SetWindowLong (hWnd, GWL_WNDPROC, (long) lpfnNewProcInstance) ;
  1247.  
  1248.    return (lpfnOldProc) ;
  1249.    }  // WindowSetWndProc
  1250.  
  1251. WNDPROC WindowGetOriginalWndProc (HWND hWnd)
  1252. /*
  1253.    Effect:        Return a far pointer to the "original" wndproc for
  1254.                   hWnd.
  1255.  
  1256.    Assert:        WindowSetOriginalProc was already called on this hWnd.
  1257.  
  1258.    See Also:      WindowSetOriginalWndProc.
  1259. */
  1260.    {  // WindowGetOriginalWndProc
  1261.    return (WNDPROC) GetProp (hWnd, WndProcKey) ;
  1262.    }  // WindowGetOriginalWndProc
  1263.  
  1264.  
  1265. void WindowSetOriginalWndProc (HWND hWnd,
  1266.                                FARPROC lpfnWndProc)
  1267. /*
  1268.    Effect:        Save away a far pointer to the "original" wndproc for
  1269.                   hWnd.
  1270.  
  1271.    See Also:      WindowGetOriginalProc.
  1272. */
  1273.    {  // WindowSetOriginalProc
  1274.    SetProp (hWnd, WndProcKey, (LPSTR) lpfnWndProc) ;
  1275.    }  // WindowSetOriginalProc
  1276.  
  1277.  
  1278. void WindowSubclass (HWND hWnd,
  1279.                      HANDLE hInstance,
  1280.                      FARPROC lpfnNewWndProc)
  1281. /*
  1282.    Effect:        Replace the wndproc for hWnd with lpfnNewWndProc.
  1283.                   Save away a pointer to the original procedure.
  1284.  
  1285.    See Also:      WindowUnsubclass.
  1286. */
  1287.    {  // WindowSubclass
  1288.    FARPROC     lpfnOldWndProc ;
  1289.  
  1290.    lpfnOldWndProc = WindowSetWndProc (hWnd, hInstance, lpfnNewWndProc) ;
  1291.    WindowSetOriginalWndProc (hWnd, lpfnOldWndProc) ;
  1292.    }  // WindowSubclass
  1293.  
  1294.  
  1295. LONG WindowCallOriginalWndProc (HWND hWnd,
  1296.                                 UINT msg,
  1297.                                 WPARAM wParam,
  1298.                                 LPARAM lParam)
  1299.    {
  1300.    WNDPROC        lpfnOriginalWndProc ;
  1301.  
  1302.    lpfnOriginalWndProc = WindowGetOriginalWndProc (hWnd) ;
  1303.    if (lpfnOriginalWndProc)
  1304.       return ((LONG) CallWindowProc (lpfnOriginalWndProc,
  1305.                                      hWnd, msg, wParam, lParam)) ;
  1306.    else return (FALSE) ;
  1307.    }
  1308.  
  1309.  
  1310.  
  1311. LRESULT APIENTRY FocusCtlWndProc (HWND hWnd,
  1312.                                   UINT wMsg,
  1313.                                   WPARAM wParam,
  1314.                                   LPARAM lParam)
  1315.    {  // FocusCtlWndProc
  1316.    BOOL           bCallDefProc ;
  1317.    LRESULT        lReturnValue ;
  1318.  
  1319.  
  1320.    bCallDefProc = TRUE ;
  1321.    lReturnValue = 0L ;
  1322.  
  1323.    switch (wMsg)
  1324.       {  // switch
  1325.       case WM_SETFOCUS:
  1326.          SendMessage (WindowParent (hWnd), 
  1327.                       WM_DLGSETFOCUS, WindowID (hWnd), 0) ;
  1328.          break ;
  1329.  
  1330.  
  1331.       case WM_KILLFOCUS:
  1332.          SendMessage (WindowParent (hWnd), 
  1333.                       WM_DLGKILLFOCUS, WindowID (hWnd), 0) ;
  1334.          break ;
  1335.  
  1336.       default:
  1337.          bCallDefProc = TRUE ;
  1338.       }  // switch
  1339.  
  1340.  
  1341.    if (bCallDefProc)
  1342.       lReturnValue = WindowCallOriginalWndProc (hWnd, wMsg, wParam, lParam) ;
  1343.  
  1344.    return (lReturnValue);
  1345.    }  // FocusWndProc
  1346.  
  1347.  
  1348.  
  1349. BOOL DlgFocus (HDLG hDlg, WORD wControlID)
  1350.    {  // DlgFocus
  1351.    HWND           hWndControl ;
  1352.  
  1353.    hWndControl = DialogControl (hDlg, wControlID) ;
  1354.    if (!hWndControl)
  1355.       return (FALSE) ;
  1356.  
  1357.    WindowSubclass (hWndControl, hInstance, (FARPROC) FocusCtlWndProc) ;
  1358.    return (TRUE) ;
  1359.    }  // DlgFocus
  1360.  
  1361.  
  1362. BOOL DeviceNumColors (HDC hDC)
  1363.    {  // DeviceNumColors
  1364.    int            nPlanes ;
  1365.    int            nBitsPixel ;
  1366.  
  1367.    nPlanes = GetDeviceCaps (hDC, PLANES) ;
  1368.    nBitsPixel = GetDeviceCaps (hDC, BITSPIXEL) ;
  1369.  
  1370.    return (1 << (nPlanes * nBitsPixel)) ;
  1371.    }  // DeviceNumColors
  1372.  
  1373.  
  1374. void DrawBitmap (HDC hDC,
  1375.                  HBITMAP hBitmap,
  1376.                  int xPos,
  1377.                  int yPos,
  1378.                  LONG  lROPCode)
  1379.    {  // DrawBitmap
  1380.    BITMAP  bm ;
  1381.    HDC     hDCMemory ;
  1382.  
  1383.    hDCMemory = CreateCompatibleDC (hDC) ;
  1384.    SelectObject (hDCMemory, hBitmap) ;
  1385.  
  1386.    GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ;
  1387.  
  1388.    BitBlt (hDC,                     // DC for Destination surface
  1389.            xPos, yPos,              // location in destination surface
  1390.            bm.bmWidth, bm.bmHeight, // dimension of bitmap
  1391.            hDCMemory,               // DC for Source surface
  1392.            0, 0,                    // location in source surface
  1393.            lROPCode) ;              // ROP code
  1394.  
  1395.    DeleteDC (hDCMemory) ;
  1396.    }  // DrawBitmap
  1397.  
  1398.  
  1399. #endif  // KEEP_UTIL
  1400.  
  1401. #ifdef PERFMON_DEBUG
  1402.  
  1403. #define MikeBufferSize         256
  1404.  
  1405.  
  1406. int _cdecl mike (TCHAR *szFormat, ...)
  1407. /*
  1408.    Note:          This function returns a value so that it can more easily
  1409.                   be used in conditional expressions.
  1410. */
  1411.    {  // mike
  1412.    TCHAR          szBuffer [MikeBufferSize] ;
  1413.    va_list        vaList ;
  1414.  
  1415.    va_start (vaList, szFormat) ;
  1416.    TSPRINTF (szBuffer, szFormat, va_arg(vaList, LPTSTR)) ;
  1417.    va_end (vaList) ;
  1418.  
  1419.    MessageBox (NULL, szBuffer, TEXT("Debug"), MB_OK | MB_TASKMODAL) ;
  1420.    return (0) ;
  1421.    }  // mike
  1422.  
  1423.  
  1424.  
  1425. int _cdecl mike1 (TCHAR *szFormat, ...)
  1426. /*
  1427.    Note:          This function returns a value so that it can more easily
  1428.                   be used in conditional expressions.
  1429. */
  1430.    {  //  mike1
  1431.    TCHAR           szBuffer [MikeBufferSize] ;
  1432.    va_list        vaList ;
  1433.    HDC            hDC ;
  1434.    RECT           rect ;
  1435.   
  1436.    va_start (vaList, szFormat) ;
  1437.    TSPRINTF (szBuffer, szFormat, va_arg(vaList, LPTSTR)) ;
  1438.    va_end (vaList) ;
  1439.  
  1440.    rect.left = 0 ;
  1441.    rect.right = xScreenWidth ;
  1442.    rect.top = 0 ;
  1443.    rect.bottom = 20 ;
  1444.  
  1445.    hDC = CreateScreenDC () ;
  1446.    ExtTextOut (hDC, 0, 0, ETO_OPAQUE, &rect, 
  1447.                szBuffer, lstrlen (szBuffer), NULL) ;
  1448.    DeleteDC (hDC) ;
  1449.  
  1450.    return (0) ;
  1451.    }  // mike1
  1452.  
  1453. int _cdecl mike2 (TCHAR *szFormat, ...)
  1454. /*
  1455.    Note:          This function returns a value so that it can more easily
  1456.                   be used in conditional expressions.
  1457. */
  1458.    {  //  mike2
  1459.    TCHAR           szBuffer [MikeBufferSize] ;
  1460.    va_list        vaList ;
  1461.   
  1462.    va_start (vaList, szFormat) ;
  1463.    TSPRINTF (szBuffer, szFormat, va_arg(vaList, LPTSTR)) ;
  1464.    va_end (vaList) ;
  1465.  
  1466.    OutputDebugString (szBuffer) ;
  1467.  
  1468.    return (0) ;
  1469.    }  // mike2
  1470. #endif      // PERFMON_DEBUG
  1471.  
  1472.  
  1473. #ifdef KEEP_UTIL
  1474. int inttok (LPSTR lpszText, LPSTR lpszDelimiters)
  1475.    {  // inttok
  1476.  
  1477.    // Inttok only works with LPSTRs because of the atoi & strtok
  1478.    
  1479.    LPSTR   lpszToken ;
  1480.  
  1481.    lpszToken = strtok (lpszText, lpszDelimiters) ;
  1482.  
  1483.    if (lpszToken)
  1484.       return (atoi (lpszToken)) ;
  1485.    else
  1486.       return (0) ;
  1487.    }  // inttok
  1488.  
  1489.  
  1490. void WindowPlacementToString (PWINDOWPLACEMENT pWP, 
  1491.                               LPTSTR lpszText)
  1492.    {
  1493.    TSPRINTF (lpszText, TEXT("%d %d %d %d %d %d %d %d %d"),
  1494.             pWP->showCmd, 
  1495.             pWP->ptMinPosition.x,
  1496.             pWP->ptMinPosition.y,
  1497.             pWP->ptMaxPosition.x,
  1498.             pWP->ptMaxPosition.y,
  1499.             pWP->rcNormalPosition.left,
  1500.             pWP->rcNormalPosition.top,
  1501.             pWP->rcNormalPosition.right,
  1502.             pWP->rcNormalPosition.bottom) ;
  1503.    }
  1504.  
  1505.  
  1506. void StringToWindowPlacement (LPTSTR lpszText,
  1507.                               PWINDOWPLACEMENT pWP)
  1508.    {  // StringToWindowPlacement
  1509.    int            iNumScanned ;
  1510.    
  1511.    iNumScanned = swscanf (lpszText, TEXT("%d %d %d %d %d %d %d %d %d"),
  1512.             &pWP->showCmd, 
  1513.             &pWP->ptMinPosition.x,
  1514.             &pWP->ptMinPosition.y,
  1515.             &pWP->ptMaxPosition.x,
  1516.             &pWP->ptMaxPosition.y,
  1517.             &pWP->rcNormalPosition.left,
  1518.             &pWP->rcNormalPosition.top,
  1519.             &pWP->rcNormalPosition.right,
  1520.             &pWP->rcNormalPosition.bottom) ;
  1521.    }  // StringToWindowPlacement
  1522. #endif  // KEEP_UTIL
  1523.  
  1524.  
  1525.  
  1526. int LogFontHeight (HDC hDC,
  1527.                    int iPointSize)
  1528. /*
  1529.    Effect:        Return the appropriate pixel height for the lfHeight
  1530.                   field of the LOGFONT structure for the requested point
  1531.                   size. This size depends on the number of pixels per
  1532.                   logical inch of the current display context, hDC.
  1533.  
  1534.    Called By:     Any function which wants to create a particular
  1535.                   point-height font.
  1536. */
  1537.    {  // LogFontHeight
  1538.    return (-MulDiv (iPointSize, GetDeviceCaps (hDC, LOGPIXELSY), 72)) ;
  1539.    }  // LogFontHeight
  1540.  
  1541.  
  1542. // this routine converts the input menu id into help id.
  1543. DWORD MenuIDToHelpID (DWORD MenuID)
  1544.    {
  1545.    DWORD HelpID = 0 ;
  1546.  
  1547.    if (MenuID >= IDM_FIRSTMENUID && MenuID <= IDM_LASTMENUID)
  1548.       {
  1549.       // only special cases...
  1550.       if (MenuID >= IDM_OPTIONSREFRESHNOWCHART &&
  1551.           MenuID <= IDM_OPTIONSREFRESHNOWREPORT)
  1552.          {
  1553.          HelpID = HC_PM_MENU_OPTIONSREFRESHNOW ;
  1554.          }
  1555.       else
  1556.          {
  1557.          HelpID = MenuID - MENUIDTOHELPID ;
  1558.          }
  1559. #ifndef ADVANCED_PERFMON
  1560.       // need to convert these 2 IDs for Perf. Meter
  1561.       if (HelpID == HC_PM_MENU_HELPABOUT)
  1562.          {
  1563.          HelpID = HC_NTPM_MENU_HELPABOUT ;
  1564.          }
  1565.       else if (HelpID == HC_PM_MENU_FILEEXIT)
  1566.          {
  1567.          HelpID = HC_NTPM_MENU_FILEEXIT ;
  1568.          }
  1569. #endif
  1570.       }
  1571.  
  1572.    return (HelpID) ;
  1573.    }
  1574.  
  1575.