DIALOGS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:40k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright (C) 1993-1997 Microsoft Corporation.
  4. *       All rights reserved. 
  5. *       This source code is only intended as a supplement to 
  6. *       Microsoft Development Tools and/or WinHelp documentation.
  7. *       See these sources for detailed information regarding the 
  8. *       Microsoft samples programs.
  9. ******************************************************************************/
  10. /*****************************************************************************
  11. *
  12. * Module: dialogs.c
  13. *
  14. *   Contains dialog procs for the Windows debugging Spy SDK applet.
  15. *
  16. * Functions:
  17. *
  18. *   MyDialogBox()
  19. *   AboutDlgProc()
  20. *   SelectWindowDlgProc()
  21. *   OutputDlgProc()
  22. *   SelectFont()
  23. *   MessagesDlgProc()
  24. *   SelectWindowCommand()
  25. *   FillListBox()
  26. *   AddOneWindow()
  27. *   MakeWindowName()
  28. *   FindHwndInListBox()
  29. *   HighlightWindow()
  30. *   SelectWindowUpdateInfo()
  31. *   SelectWindowEnableFields()
  32. *   OutputCommand()
  33. *   MessagesInit()
  34. *   MessagesCommand()
  35. *   MessagesUpdateCheckBoxes()
  36. *
  37. * Comments:
  38. *
  39. *****************************************************************************/
  40. #include "spy.h"
  41. #include <commdlg.h>
  42. #define DINV                3
  43. PRIVATE HWND ghwndSpyingOnTemp;     // Temp when selecting hwnd to spy on.
  44. PRIVATE HWND ghwndDlgBeingFilled = NULL;
  45. PRIVATE BOOL bBorderOn = FALSE;
  46. PRIVATE INT gcItemsSave;
  47. PRIVATE BOOL SelectWindowCommand(HWND hwnd, INT nCmd, INT nNotifyCode);
  48. PRIVATE VOID FillListBox(HWND hDlg, HWND hwndList, HWND hwnd);
  49. BOOL CALLBACK AddOneWindow(HWND hwnd, LPARAM hwndListLP);
  50. PRIVATE VOID MakeWindowName(HWND hwnd, LPSTR lpString, INT nStringLen);
  51. PRIVATE INT FindHwndInListBox(HWND hwndList, HWND hSpyWnd);
  52. PRIVATE VOID HighlightWindow(HWND hwnd, BOOL fDraw);
  53. PRIVATE VOID SelectWindowUpdateInfo(HWND hDlg, HWND hwnd);
  54. PRIVATE VOID SelectWindowEnableFields(HWND hwnd, BOOL fEnable);
  55. PRIVATE BOOL OutputCommand(HWND hwnd, INT nCmd, INT nNotifyCode);
  56. PRIVATE VOID MessagesInit(HWND hwnd);
  57. PRIVATE BOOL MessagesCommand(HWND hwnd, INT nCmd, INT nNotifyCode);
  58. PRIVATE VOID MessagesUpdateCheckBoxes(HWND hwnd);
  59. CHAR szConsoleWindowClass[] = "ConsoleWindowClass";
  60. /*****************************************************************************
  61. * MyDialogBox
  62. *
  63. * Puts up the specified dialog.
  64. *
  65. * Arguments:
  66. *   INT idDlg          - The resource id of the dialog to display.
  67. *   DLGPROC pfnDlgProc - The dialog proc to use.
  68. *
  69. * Returns:
  70. *   The return value from DialogBox (whatever the dialog proc passes
  71. *   to EndDialog).
  72. *****************************************************************************/
  73. BOOL
  74. MyDialogBox(
  75.     INT idDlg,
  76.     DLGPROC pfnDlgProc
  77.     )
  78. {
  79.     return DialogBox(ghInst, MAKEINTRESOURCE(idDlg), ghwndSpyApp, pfnDlgProc);
  80. }
  81. /*****************************************************************************
  82. * AboutDlgProc
  83. *
  84. *   Dialog proc for the About box.
  85. *
  86. *****************************************************************************/
  87. BOOL CALLBACK
  88. AboutDlgProc(
  89.     HWND hwnd,
  90.     UINT msg,
  91.     WPARAM wParam,
  92.     LPARAM lParam
  93.     )
  94. {
  95.     switch (msg) {
  96.         case WM_INITDIALOG:
  97.             return TRUE;
  98.         case WM_COMMAND:
  99.             EndDialog(hwnd, IDOK);
  100.             break;
  101.     }
  102.     return FALSE;
  103. }
  104. /*****************************************************************************
  105. * SelectWindowDlgProc
  106. *
  107. * Dialog proc for the Select Window dialog.  This dialog allows the user
  108. * to select which window they want to spy on.
  109. *
  110. * Arguments:
  111. *   HWND hwnd       - Window handle of the dialog.
  112. *   UINT msg        - Message sent to window.
  113. *   WPARAM wParam   - Message parameter.
  114. *   LPARAM lParam   - Message parameter.
  115. *
  116. * Returns:
  117. *   The value that the dialog proc should return, based on the processing
  118. *   of the specific WM_COMMAND message received.
  119. *****************************************************************************/
  120. BOOL CALLBACK
  121. SelectWindowDlgProc(
  122.     HWND hwnd,
  123.     UINT msg,
  124.     WPARAM wParam,
  125.     LPARAM lParam
  126.     )
  127. {
  128.     HWND hwndList;
  129.     INT nIndex;
  130.     UNREFERENCED_PARAMETER(lParam);
  131.     switch (msg)
  132.     {
  133.         case WM_INITDIALOG:
  134.             hwndList = GetDlgItem(hwnd, DID_SELWINLIST);
  135.             ghwndSpyingOnTemp = ghwndSpyingOn == HWND_ALL ? NULL : (ghwndSpyingOn == NULL ? NULL
  136.                 : GetParent(ghwndSpyingOn));
  137.             FillListBox(hwnd, hwndList, ghwndSpyingOnTemp);
  138.             nIndex = FindHwndInListBox(hwndList, ghwndSpyingOn == HWND_ALL ? NULL
  139.                 : ghwndSpyingOn);
  140.             SendMessage(hwndList, LB_SETCURSEL, nIndex, 0);
  141.             ghwndSpyingOnTemp = (HWND)SendMessage(hwndList, LB_GETITEMDATA, nIndex, 0);
  142.             SelectWindowUpdateInfo(hwnd, ghwndSpyingOnTemp);
  143.             CheckDlgButton(hwnd, DID_SELWINALLWINDOWS, gfSpyAll);
  144.             SelectWindowEnableFields(hwnd, !gfSpyAll);
  145.             SetFocus(hwnd);
  146.             HighlightWindow(ghwndSpyingOnTemp, TRUE);
  147.             return TRUE;
  148.         case WM_NCLBUTTONDOWN:
  149.             if (wParam == HTCAPTION)
  150.             {
  151.                 //
  152.                 // The mouse is down for a move of the dialog, so clean up the
  153.                 // border stuff.
  154.                 //
  155.                 if (bBorderOn)
  156.                     HighlightWindow(ghwndSpyingOnTemp, FALSE);
  157.             }
  158.             return FALSE;
  159.         case WM_KEYDOWN:
  160.         case WM_LBUTTONUP:
  161.         case WM_NCLBUTTONUP:
  162.             //
  163.             // The mouse is up from a move of the dialog, so put up the
  164.             // border stuff again.
  165.             //
  166.             if (!bBorderOn)
  167.                 HighlightWindow(ghwndSpyingOnTemp, TRUE);
  168.             return FALSE;
  169.         case WM_CANCELMODE:
  170.             return FALSE;
  171.         case WM_COMMAND:
  172.             return SelectWindowCommand(hwnd, LOWORD(wParam), HIWORD(wParam));
  173.     }
  174.     return FALSE;
  175. }
  176. /*****************************************************************************
  177. * SelectWindowCommand
  178. *
  179. * Handles thw WM_COMMAND messages for the Select Window dialog.
  180. *
  181. * Arguments:
  182. *   HWND hwnd       - Window handle of the dialog.
  183. *   INT nCmd        - Command value.
  184. *   INT nNotifyCode - The notify code.
  185. *
  186. * Returns:
  187. *   The value that the dialog proc should return, based on the processing
  188. *   of the specific WM_COMMAND message received.
  189. *****************************************************************************/
  190. PRIVATE BOOL
  191. SelectWindowCommand(
  192.     HWND hwnd,
  193.     INT nCmd,
  194.     INT nNotifyCode
  195.     )
  196. {
  197.     INT nIndex;
  198.     HWND hwndList;
  199.     CHAR rgString[32];
  200.     switch (nCmd)
  201.     {
  202.         case IDOK:
  203.             SetWindowToSpyOn(IsDlgButtonChecked(hwnd, DID_SELWINALLWINDOWS) ?
  204.                 HWND_ALL : ghwndSpyingOnTemp);
  205.             if (bBorderOn)
  206.                 HighlightWindow(ghwndSpyingOnTemp, FALSE);
  207.             EndDialog(hwnd, IDOK);
  208.             return TRUE;
  209.         case IDCANCEL:
  210.             if (bBorderOn)
  211.                 HighlightWindow(ghwndSpyingOnTemp, FALSE);
  212.             EndDialog(hwnd, IDCANCEL);
  213.             return TRUE;
  214.         case DID_SELWINLIST:
  215.             //
  216.             // User single clicked or doubled clicked in listbox -
  217.             //   Single click means select a window to spy on
  218.             //   Double click means enumerate all the children of that window.
  219.             //
  220.             hwndList = GetDlgItem(hwnd, DID_SELWINLIST);
  221.             switch (nNotifyCode)
  222.             {
  223.                 case LBN_SELCHANGE:
  224.                     //
  225.                     // Single click case. Select a window to spy upon.
  226.                     //
  227.                     // Get the window handle, set it as the window to spy on.
  228.                     //
  229.                     if (bBorderOn)
  230.                         HighlightWindow(ghwndSpyingOnTemp, FALSE);
  231.                     nIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0);
  232.                     ghwndSpyingOnTemp = (HWND)SendMessage(hwndList, LB_GETITEMDATA,
  233.                         nIndex, 0);
  234.                     SelectWindowUpdateInfo(hwnd, ghwndSpyingOnTemp);
  235.                     HighlightWindow(ghwndSpyingOnTemp, TRUE);
  236.                     break;
  237.                 case LBN_DBLCLK:
  238.                     //
  239.                     // Double click case - first click has already been
  240.                     // processed as single click. In this case, the user has
  241.                     // requested to look at all the children of a given
  242.                     // selection.
  243.                     //
  244.                     // Get the current selection, and check to see if it is the
  245.                     // " [ parent.. ]" entry. If so, go up one level first.
  246.                     //
  247.                     SetCursor(LoadCursor(NULL, IDC_WAIT));
  248.                     if (bBorderOn)
  249.                         HighlightWindow(ghwndSpyingOnTemp, FALSE);
  250.                     nIndex = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0);
  251.                     ghwndSpyingOnTemp = (HWND)SendMessage(hwndList, LB_GETITEMDATA,
  252.                         nIndex, 0);
  253.                     SendMessage(hwndList, LB_GETTEXT, nIndex, (LPARAM)rgString);
  254.                     if (rgString[0] == ' ')
  255.                     {
  256.                         // At top?  If so, we are done.
  257.                         if (ghwndSpyingOnTemp == NULL)
  258.                         {
  259.                             SetCursor(LoadCursor(NULL, IDC_ARROW));
  260.                             break;
  261.                         }
  262.                         ghwndSpyingOnTemp = GetParent(ghwndSpyingOnTemp);
  263.                     }
  264.                     SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
  265.                     FillListBox(hwnd, hwndList, ghwndSpyingOnTemp);
  266.                     nIndex = FindHwndInListBox(hwndList, ghwndSpyingOnTemp);
  267.                     SendMessage(hwndList, LB_SETCURSEL, nIndex, 0);
  268.                     ghwndSpyingOnTemp = (HWND)SendMessage(hwndList, LB_GETITEMDATA,
  269.                         nIndex, 0);
  270.                     HighlightWindow(ghwndSpyingOnTemp,TRUE);
  271.                     SelectWindowUpdateInfo(hwnd, ghwndSpyingOnTemp);
  272.                     SetCursor(LoadCursor(NULL, IDC_ARROW));
  273.                     break;
  274.             }
  275.             break;
  276.         case DID_SELWINALLWINDOWS:
  277.             SelectWindowEnableFields(hwnd,
  278.                 !IsDlgButtonChecked(hwnd, DID_SELWINALLWINDOWS));
  279.             break;
  280.     }
  281.     return FALSE;
  282. }
  283. /*****************************************************************************
  284. * FillListBox
  285. *
  286. * Fills the listbox in the Select Window dialog with the names of
  287. * the child windows of the given window.
  288. *
  289. * Arguments:
  290. *   hDlg     - Window handle of the dialog window
  291. *   hwndList - Handle to the listbox within the dialog.
  292. *   hwnd     - Parent whose children to enumerate.
  293. *
  294. * Returns:
  295. *   VOID
  296. *****************************************************************************/
  297. PRIVATE VOID
  298. FillListBox(
  299.     HWND hDlg,
  300.     HWND hwndList,
  301.     HWND hwnd
  302.     )
  303. {
  304.     INT nIndex;
  305.     //
  306.     // First fill the list box with child windows
  307.     //
  308.     // Make sure we display the list box after things are added.
  309.     //
  310.     SendMessage(hwndList, WM_SETREDRAW, 0, 0);
  311.     //
  312.     // remember which dialog we are processing
  313.     //
  314.     ghwndDlgBeingFilled = hDlg;
  315.     if (hwnd == NULL)
  316.     {
  317.         //
  318.         // Enumerate the top level separately... gross unsymmetry, but
  319.         // hey.
  320.         //
  321.         EnumWindows(AddOneWindow, (LPARAM)hwndList);
  322.     }
  323.     else
  324.     {
  325.         EnumChildWindows(hwnd, AddOneWindow, (LPARAM)hwndList);
  326.     }
  327.     //
  328.     // Now give the user a method of getting back to the parent. The space at
  329.     // the beginning of the " [parent]" string identifies the entry as the
  330.     // parent entry and makes it different from all the other entries since
  331.     // the others start with a handle number of some sort.
  332.     //
  333.     nIndex = SendMessage(hwndList, LB_ADDSTRING, 0,
  334.                         (LPARAM)(LPCTSTR)LoadResourceString(IDS_PARENT));
  335.     SendMessage(hwndList, LB_SETITEMDATA, nIndex, (LONG)hwnd);
  336.     //
  337.     // Now do the redraw...
  338.     //
  339.     SendMessage(hwndList, WM_SETREDRAW, 1, 0);
  340. }
  341. /*****************************************************************************
  342. * AddOneWindow
  343. *
  344. * Gets the windows to add to the list of windows to spy on.
  345. *
  346. * Arguments:
  347. *     HWND hwnd - handle of the window to add.
  348. *     HWND hwndList - handle to the listbox.
  349. *
  350. * Returns:
  351. *     TRUE - if a window was created.
  352. *****************************************************************************/
  353. #define CCH_RGBUF   32
  354. BOOL CALLBACK
  355. AddOneWindow(
  356.     HWND hwnd,
  357.     LPARAM hwndListLP
  358.     )
  359. {
  360.     CHAR rgBuf[CCH_RGBUF];
  361.     INT nIndex;
  362.     HWND htemp;
  363.     HWND hwndList = (HWND)hwndListLP;
  364.     //
  365.     // Make sure we don't add any window that has anything to do with
  366.     // the dialog or any other spy window
  367.     //
  368.     htemp = GetParent(hwnd);
  369.     // Don't put console windows in the list since they can not be hooked
  370.     if (GetClassName(hwnd, rgBuf, CCH_RGBUF) != 0 &&
  371.         strcmp(rgBuf, szConsoleWindowClass) == 0 )
  372.     {
  373.         return 1;
  374.     }
  375.     // Don't put windows that belong to spy in the list
  376.     if (hwnd == ghwndDlgBeingFilled || htemp == ghwndDlgBeingFilled
  377.         || hwnd == ghwndSpyApp
  378.         || htemp == ghwndSpyApp || hwnd == ghwndPrintf || htemp == ghwndPrintf
  379.         || hwnd == ghwndSpyHook || htemp == ghwndSpyHook)
  380.     {
  381.         return 1;
  382.     }
  383.     MakeWindowName(hwnd, rgBuf, CCH_RGBUF);
  384.     nIndex = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)rgBuf);
  385.     if (nIndex == LB_ERR || nIndex == LB_ERRSPACE)
  386.         return 0;
  387.     if (SendMessage(hwndList, LB_SETITEMDATA, nIndex, (LPARAM)hwnd) == LB_ERR)
  388.         return 0;
  389.     return 1;
  390. }
  391. /*****************************************************************************
  392. * MakeWindowName
  393. *
  394. * Builds the window name from the window handle passed in.
  395. *
  396. * Arguments:
  397. *     HWND hwnd - handle to the window.
  398. *     LPSTR lpString - String to put window name into.
  399. *     INT nSTringLen - Length of window string.
  400. *
  401. * Returns:
  402. *     VOID
  403. *****************************************************************************/
  404. PRIVATE VOID
  405. MakeWindowName(
  406.     HWND hwnd,
  407.     LPSTR lpString,
  408.     INT nStringLen
  409.     )
  410. {
  411.     wsprintf(lpString, "%8.8lX:", hwnd);
  412.     if (hwnd == NULL || !IsWindow(hwnd))
  413.     {
  414.         lstrcat(lpString, "!!!");
  415.     }
  416.     else
  417.     {
  418.         GetWindowText(hwnd, lpString + 9, nStringLen - 9);
  419.     }
  420. }
  421. /*****************************************************************************
  422. * FindHwndInListBox
  423. *
  424. * Gets the window from the list of windows in the listbox.
  425. *
  426. * Arguments:
  427. *     HWND hwndList - handle to the listbox.
  428. *     HWND hSpyWnd - handle to the spy window.
  429. *
  430. * Returns:
  431. *     INT - Index to the window in the listbox. 
  432. *****************************************************************************/
  433. PRIVATE INT
  434. FindHwndInListBox(
  435.     HWND hwndList,
  436.     HWND hSpyWnd
  437.     )
  438. {
  439.     CHAR rgBuf[9];
  440.     INT nIndex;
  441.     wsprintf(rgBuf, "%08lX", (LONG)hSpyWnd);
  442.     nIndex = SendMessage(hwndList, LB_FINDSTRING, (WPARAM)-1, (LPARAM)rgBuf);
  443.     if (nIndex == LB_ERR)
  444.         nIndex = 0;
  445.     return nIndex;
  446. }
  447. /*****************************************************************************
  448. * HighlightWindow
  449. *
  450. * Used to temporarily highlight the window that the user has selected from
  451. * the Select Window dialog.  It does this by inverting a border around the
  452. * window.
  453. *
  454. * Arguments:
  455. *     HWND hwnd - handle to the selected window.
  456. *     BOOL fdraw - whether to draw the window inverted on non-inverted.
  457. *
  458. * Returns:
  459. *     VOID
  460. *****************************************************************************/
  461. PRIVATE VOID
  462. HighlightWindow(
  463.     HWND hwnd,
  464.     BOOL fDraw
  465.     )
  466. {
  467.     HDC hdc;
  468.     RECT rc;
  469.     bBorderOn = fDraw;
  470.     if (hwnd == NULL || !IsWindow(hwnd))
  471.         return;
  472.     hdc = GetWindowDC(hwnd);
  473.     GetWindowRect(hwnd, &rc);
  474.     OffsetRect(&rc, -rc.left, -rc.top);
  475.     if (!IsRectEmpty(&rc))
  476.     {
  477.         PatBlt(hdc, rc.left, rc.top, rc.right - rc.left, DINV,  DSTINVERT);
  478.         PatBlt(hdc, rc.left, rc.bottom - DINV, DINV,
  479.             -(rc.bottom - rc.top - 2 * DINV), DSTINVERT);
  480.         PatBlt(hdc, rc.right - DINV, rc.top + DINV, DINV,
  481.             rc.bottom - rc.top - 2 * DINV, DSTINVERT);
  482.         PatBlt(hdc, rc.right, rc.bottom - DINV, -(rc.right - rc.left),
  483.             DINV, DSTINVERT);
  484.     }
  485.     ReleaseDC(hwnd, hdc);
  486. }
  487. /*****************************************************************************
  488. * SelectWindowUpdateInfo
  489. *
  490. * Updates the informational fields in the Select Window dialog when
  491. * a new window is selected from the hwnd listbox.
  492. *
  493. * Arguments:
  494. *     HWND hDlg - handle to the select window dialog box.
  495. *     HWND hwnd - handle to the new window selected.
  496. *
  497. * Returns:
  498. *     VOID
  499. *****************************************************************************/
  500. PRIVATE VOID
  501. SelectWindowUpdateInfo(
  502.     HWND hDlg,
  503.     HWND hwnd
  504.     )
  505. {
  506.     HWND hParent;
  507.     DWORD dwStyle;
  508.     RECT rc;
  509.     CHAR szTemp[MAXSTRING];
  510.     if (hwnd)
  511.     {
  512.         hParent = GetParent(hwnd);
  513.         dwStyle = GetWindowLong(hwnd, GWL_STYLE);
  514.         MakeWindowName(hwnd, szTemp, MAXSTRING);
  515.         SetDlgItemText(hDlg, DID_SELWINWINDOW, szTemp);
  516.         GetClassName(hwnd, szTemp, MAXSTRING);
  517.         SetDlgItemText(hDlg, DID_SELWINCLASS, szTemp);
  518.         if (hParent)
  519.         {
  520.             MakeWindowName(hParent, szTemp, MAXSTRING);
  521.             SetDlgItemText(hDlg, DID_SELWINPARENT, szTemp);
  522.         }
  523.         else
  524.         {
  525.             SetDlgItemText(hDlg, DID_SELWINPARENT,
  526.                            LoadResourceString(IDS_NOPARENT));
  527.         }
  528.         GetWindowRect(hwnd, &rc);
  529.         wsprintf(szTemp, "(%d,%d)-(%d,%d) %dx%d", rc,
  530.             rc.right-rc.left, rc.bottom-rc.top);
  531.         SetDlgItemText(hDlg, DID_SELWINRECT, szTemp);
  532.         if (dwStyle & WS_POPUP)
  533.             wsprintf (szTemp, "%08lX: WS_POPUP", dwStyle);
  534.         else if (dwStyle & WS_CHILD)
  535.             wsprintf (szTemp, "%08lX: WS_CHILD, ID: %lX", dwStyle,
  536.             GetWindowLong(hwnd, GWL_ID));
  537.         else if (dwStyle & WS_ICONIC)
  538.             wsprintf (szTemp, "%08lX: WS_ICONIC", dwStyle);
  539.         else
  540.             wsprintf (szTemp, "%08lX: WS_OVERLAPPED", dwStyle);
  541.         SetDlgItemText(hDlg, DID_SELWINSTYLE, szTemp);
  542.     }
  543.     else
  544.     {
  545.         TCHAR lpBuf[256];
  546.         LoadString(GetModuleHandle(NULL), IDS_UNDEFINED, lpBuf, sizeof(lpBuf));
  547.         SetDlgItemText(hDlg, DID_SELWINWINDOW, lpBuf);
  548.         SetDlgItemText(hDlg, DID_SELWINCLASS,  lpBuf);
  549.         SetDlgItemText(hDlg, DID_SELWINPARENT, lpBuf);
  550.         SetDlgItemText(hDlg, DID_SELWINRECT,   lpBuf);
  551.         SetDlgItemText(hDlg, DID_SELWINSTYLE,  lpBuf);
  552.     }
  553. }
  554. /*****************************************************************************
  555. * SelectWindowEnableFields
  556. *
  557. * Enables/disables the different fields in the Select Window dialog
  558. * based on whether the user wants to spy on all windows or individually
  559. * select one.
  560. *
  561. * Arguments:
  562. *   HWND hwnd    - Dialog window handle.
  563. *   BOOL fEnable - TRUE to enable the fields, FALSE to disable them.
  564. *
  565. * Returns:
  566. *   VOID
  567. *****************************************************************************/
  568. PRIVATE VOID
  569. SelectWindowEnableFields(
  570.     HWND hwnd,
  571.     BOOL fEnable
  572.     )
  573. {
  574.     EnableWindow(GetDlgItem(hwnd, DID_SELWINLIST), fEnable);
  575.     EnableWindow(GetDlgItem(hwnd, DID_SELWINWINDOW), fEnable);
  576.     EnableWindow(GetDlgItem(hwnd, DID_SELWINCLASS), fEnable);
  577.     EnableWindow(GetDlgItem(hwnd, DID_SELWINPARENT), fEnable);
  578.     EnableWindow(GetDlgItem(hwnd, DID_SELWINRECT), fEnable);
  579.     EnableWindow(GetDlgItem(hwnd, DID_SELWINSTYLE), fEnable);
  580. }
  581. /*****************************************************************************
  582. * OutputDlgProc
  583. *
  584. * Dialog proc for the Output dialog.
  585. *
  586. * Arguments:
  587. *   HWND hwnd - handle to the output dialog
  588. *   UINT msg - message sent to output dialog
  589. *   WPARAM wParam - message parameter.
  590. *   LPARAM lParam - message parameter.
  591. *
  592. * Returns:
  593. *   The value that the dialog proc should return, based on the processing
  594. *   of the specific WM_COMMAND message received.
  595. *
  596. *****************************************************************************/
  597. BOOL CALLBACK
  598. OutputDlgProc(
  599.     HWND hwnd,
  600.     UINT msg,
  601.     WPARAM wParam,
  602.     LPARAM lParam
  603.     )
  604. {
  605.     switch (msg)
  606.     {
  607.         case WM_INITDIALOG:
  608.             CheckDlgButton(hwnd, DID_OUTPUTWINDOW, gfOutputWin);
  609.             CheckDlgButton(hwnd, DID_OUTPUTCOM1, gfOutputCom1);
  610.             CheckDlgButton(hwnd, DID_OUTPUTFILE, gfOutputFile);
  611.             SetDlgItemText(hwnd, DID_OUTPUTFILENAME, gszFile);
  612.             SetDlgItemInt(hwnd, DID_OUTPUTLINES, gnLines, FALSE);
  613.             return TRUE;
  614.         case WM_COMMAND:
  615.             return OutputCommand(hwnd, LOWORD(wParam), HIWORD(wParam));
  616.     }
  617.     return FALSE;
  618. }
  619. /*****************************************************************************
  620. * OutputCommand
  621. *
  622. * Handles the WM_COMMAND messages for the Output dialog.
  623. *
  624. * Arguments:
  625. *   HWND hwnd       - Window handle of the dialog.
  626. *   INT nCmd        - Command value.
  627. *   INT nNotifyCode - The notify code.
  628. *
  629. * Returns:
  630. *   The value that the dialog proc should return, based on the processing
  631. *   of the specific WM_COMMAND message received.
  632. *
  633. *****************************************************************************/
  634. PRIVATE BOOL
  635. OutputCommand(
  636.     HWND hwnd,
  637.     INT nCmd,
  638.     INT nNotifyCode
  639.     )
  640. {
  641.     HFILE fh;
  642.     INT i;
  643.     CHAR szTemp[MAXSTRING];
  644.     switch (nCmd)
  645.     {
  646.         case IDOK:
  647.             i = GetDlgItemInt(hwnd, DID_OUTPUTLINES, &i, FALSE);
  648.             if (i != gnLines)
  649.             {
  650.                 if ( i > 0 && i <= LINES_MAX)
  651.                 {
  652.                     gnLines = i;
  653.                     MyCreatePrintfWin(ghwndSpyApp);
  654.                 }
  655.                 else
  656.                 {
  657.                     Message(MB_OK | MB_ICONEXCLAMATION,
  658.                         LoadResourceString(IDS_ERROR_WND_LINE), LINES_MAX);
  659.                     SetFocus(GetDlgItem(hwnd, DID_OUTPUTLINES));
  660.                     break;
  661.                 }
  662.             }
  663.             gfOutputWin = IsDlgButtonChecked(hwnd, DID_OUTPUTWINDOW);
  664.             gfOutputCom1 = IsDlgButtonChecked(hwnd, DID_OUTPUTCOM1);
  665.             gfOutputFile = IsDlgButtonChecked(hwnd, DID_OUTPUTFILE);
  666.             if (gfOutputFile)
  667.             {
  668.                 GetDlgItemText(hwnd, DID_OUTPUTFILENAME, szTemp, MAXSTRING);
  669.                 /*
  670.                  * If they changed the filename, or the file is not open
  671.                  * then open it.
  672.                  */
  673.                 if (lstrcmp(gszFile, szTemp) != 0 || gfhFile == 0)
  674.                 {
  675.                     fh = _lcreat(szTemp, 0);
  676.                     if (fh == (HFILE)(-1))
  677.                     {
  678.                         if (Message(MB_OKCANCEL | MB_ICONEXCLAMATION,
  679.                             LoadResourceString(IDS_ERROR_CANT_OPEN_FILE), szTemp) == IDCANCEL)
  680.                         {
  681.                             EndDialog(hwnd, FALSE);
  682.                         }
  683.                         return TRUE;
  684.                     }
  685.                     lstrcpy(gszFile, szTemp);
  686.                     if (gfhFile)
  687.                         _lclose(gfhFile);
  688.                     gfhFile = fh;
  689.                 }
  690.             }
  691.             else
  692.             {
  693.                 if (gfhFile)
  694.                 {
  695.                     _lclose(gfhFile);
  696.                     gfhFile = 0;
  697.                 }
  698.             }
  699.             if (gfOutputCom1)
  700.             {
  701.                 if (gfhCom1 != INVALID_HANDLE_VALUE)
  702.                     CloseHandle(gfhCom1);
  703.                 gfhCom1 = CreateFile(
  704.                         "com1",
  705.                         GENERIC_WRITE,
  706.                         0,                    // exclusive access
  707.                         NULL,                 // no security attrs
  708.                         OPEN_EXISTING,
  709.                         FILE_ATTRIBUTE_NORMAL,
  710.                         NULL);
  711.                 if (gfhCom1 == INVALID_HANDLE_VALUE)
  712.                 {
  713.                     if (Message(MB_OKCANCEL | MB_ICONEXCLAMATION,
  714.                         LoadResourceString(IDS_ERROR_CANT_OPEN_COM1)) == IDCANCEL)
  715.                     {
  716.                         EndDialog(hwnd, FALSE);
  717.                     }
  718.                     return TRUE;
  719.                 }
  720.             }
  721.             else
  722.             {
  723.                 if (gfhCom1 != INVALID_HANDLE_VALUE)
  724.                 {
  725.                     CloseHandle(gfhCom1);
  726.                 }
  727.             }
  728.             EndDialog(hwnd, TRUE);
  729.             return TRUE;
  730.         case IDCANCEL:
  731.             EndDialog(hwnd, FALSE);
  732.             return TRUE;
  733.     }
  734.     return FALSE;
  735. }
  736. /*****************************************************************************
  737. * SelectFont
  738. *
  739. * Allows the user to select a new font for the display.
  740. *
  741. * Arguments:
  742. *    none
  743. *
  744. * Returns:
  745. *    VOID
  746. *****************************************************************************/
  747. VOID
  748. SelectFont(
  749.     VOID
  750.     )
  751. {
  752.     CHOOSEFONT cf;
  753.     LOGFONT lf;
  754.     HFONT hfontNew;
  755.     GetObject(ghfontPrintf, sizeof(LOGFONT), (LPVOID)&lf);
  756.     cf.lStructSize = sizeof(cf);
  757.     cf.hwndOwner = ghwndSpyApp;
  758.     cf.hDC = NULL;
  759.     cf.lpLogFont = &lf;
  760.     cf.iPointSize = 0;
  761.     cf.Flags = CF_ANSIONLY | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT
  762.         | CF_SCREENFONTS;
  763.     cf.rgbColors = 0;
  764.     cf.lCustData = 0;
  765.     cf.lpfnHook = NULL;
  766.     cf.lpTemplateName = NULL;
  767.     cf.hInstance = NULL;
  768.     cf.lpszStyle = NULL;
  769.     cf.nFontType = 0;
  770.     cf.nSizeMin = 0;
  771.     cf.nSizeMax = 0;
  772.     if (ChooseFont(&cf))
  773.     {
  774.         if (hfontNew = CreateFontIndirect(&lf))
  775.         {
  776.             SetPrintfFont(ghwndPrintf, hfontNew);
  777.             ghfontPrintf = hfontNew;
  778.         }
  779.     }
  780. }
  781. /*****************************************************************************
  782. * MessagesDlgProc
  783. *
  784. * Dialog proc for the Messages dialog.  This dialog allows the user
  785. * to select which messages they want to spy on.
  786. *
  787. * Arguments:
  788. *    HWND hwnd - handle to the dialog window.
  789. *    UINT msg - message to the window
  790. *    WPARAM wParam - message parameter
  791. *    LPARAM lParam - message parameter
  792. *
  793. * Returns:
  794. *   The value that the dialog proc should return, based on the processing
  795. *   of the specific WM_COMMAND message received.
  796. *****************************************************************************/
  797. BOOL CALLBACK
  798. MessagesDlgProc(
  799.     HWND hwnd,
  800.     UINT msg,
  801.     WPARAM wParam,
  802.     LPARAM lParam
  803.     )
  804. {
  805.     switch (msg)
  806.     {
  807.         case WM_INITDIALOG:
  808.             MessagesInit(hwnd);
  809.             return TRUE;
  810.         case WM_COMMAND:
  811.             return MessagesCommand(hwnd, LOWORD(wParam), HIWORD(wParam));
  812.     }
  813.     return FALSE;
  814. }
  815. /*****************************************************************************
  816. * MessagesInit
  817. *
  818. * Initializes the messages dialog.
  819. *
  820. * Arguments:
  821. *   HWND hwnd - Dialog window handle.
  822. *
  823. * Returns:
  824. *   VOID
  825. *****************************************************************************/
  826. PRIVATE VOID
  827. MessagesInit(
  828.     HWND hwnd
  829.     )
  830. {
  831.     HWND hwndList;
  832.     INT i;
  833.     INT j;
  834.     INT iSel;
  835.     PMSGDESC pmd;
  836.     for (j = 0; j < gcMsgGroups; j++)
  837.         gaMsgGroup[j].cUseCount = 0;
  838.     hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  839.     for (i = 0, pmd = gaMsgs; i < gcMessages; i++, pmd++)
  840.     {
  841.         iSel = (INT)SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)pmd->pszMsg);
  842.         SendMessage(hwndList, LB_SETITEMDATA, iSel, (LPARAM)pmd);
  843.         if (pmd->Flags & MTF_SELECTED)
  844.         {
  845.             SendMessage(hwndList, LB_SETSEL, TRUE, iSel);
  846.             for (j = 0; j < gcMsgGroups; j++)
  847.             {
  848.                 if (gaMsgGroup[j].flMask & pmd->Flags)
  849.                     gaMsgGroup[j].cUseCount++;
  850.             }
  851.         }
  852.     }
  853.     //
  854.     // Set the selection rectangle to the first item in the listbox.
  855.     //
  856.     SendMessage(hwndList, LB_SETCARETINDEX, 0, FALSE);
  857.     //
  858.     // Loop through all the message groups.
  859.     //
  860.     for (j = 0; j < gcMsgGroups; j++)
  861.     {
  862.         //
  863.         // Is at least one message in the group selected?
  864.         //
  865.         if (gaMsgGroup[j].cUseCount)
  866.         {
  867.             //
  868.             // Check the corresponding checkbox.  If all messages
  869.             // in the group are selected, the checkbox is checked.
  870.             // If only some are selected, the checkbox is set to
  871.             // grayed (3-state).
  872.             //
  873.             CheckDlgButton(hwnd, gaMsgGroup[j].idCheckBox,
  874.                 (gaMsgGroup[j].cUseCount == gaMsgGroup[j].cMsgs) ? 1 : 2);
  875.         }
  876.     }
  877.     if (gfMsgsUser)
  878.         CheckDlgButton(hwnd, DID_MSGSUSER, 1);
  879.     if (gfMsgsUnknown)
  880.         CheckDlgButton(hwnd, DID_MSGSUNKNOWN, 1);
  881.     gcItemsSave = SendMessage(hwndList, LB_GETSELITEMS,
  882.         gcMessages, (LPARAM)gaiSelected);
  883. }
  884. /*****************************************************************************
  885. * MessagesCommand
  886. *
  887. * Handles the WM_COMMAND messages for the Messages dialog.
  888. *
  889. * Arguments:
  890. *   HWND hwnd       - Window handle of the dialog.
  891. *   INT nCmd        - Command value.
  892. *   INT nNotifyCode - The notify code.
  893. *
  894. * Returns:
  895. *   The value that the dialog proc should return, based on the processing
  896. *   of the specific WM_COMMAND message received.
  897. *
  898. *****************************************************************************/
  899. PRIVATE BOOL
  900. MessagesCommand(
  901.     HWND hwnd,
  902.     INT nCmd,
  903.     INT nNotifyCode
  904.     )
  905. {
  906.     INT i;
  907.     INT j;
  908.     PMSGGROUP pmg;
  909.     PMSGDESC pmd;
  910.     BOOL fChecked;
  911.     HWND hwndList;
  912.     INT cItems;
  913.     BOOL fSel;
  914.     INT iSel;
  915.     INT cSelItemsMax;
  916.     INT iTopIndex;
  917.     switch (nCmd)
  918.     {
  919.         case DID_MSGSLIST:
  920.             if (nNotifyCode == LBN_SELCHANGE)
  921.             {
  922.                 hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  923.                 cItems = SendMessage(hwndList, LB_GETSELITEMS,
  924.                     gcMessages, (LPARAM)gaiSelected2);
  925.                 if (cItems == gcItemsSave)
  926.                 {
  927.                     //
  928.                     // Nothing changed except for the selection
  929.                     // rectangle moving.  We are done.
  930.                     //
  931.                     break;
  932.                 }
  933.                 if (cItems > gcItemsSave)
  934.                 {
  935.                     //
  936.                     // A message was selected.  Look for it.
  937.                     //
  938.                     for (i = 0; i < gcItemsSave &&
  939.                         gaiSelected[i] == gaiSelected2[i]; i++)
  940.                         ;
  941.                     iSel = gaiSelected2[i];
  942.                     fSel = TRUE;
  943.                 }
  944.                 else
  945.                 {
  946.                     //
  947.                     // A message was unselected.  Look for it.
  948.                     //
  949.                     for (i = 0; i < cItems &&
  950.                         gaiSelected[i] == gaiSelected2[i]; i++)
  951.                         ;
  952.                     iSel = gaiSelected[i];
  953.                     fSel = FALSE;
  954.                 }
  955.                 //
  956.                 // Get the currently selected item.  It was either
  957.                 // just turned on or off.
  958.                 //
  959.                 pmd = (PMSGDESC)SendMessage(hwndList, LB_GETITEMDATA, iSel, 0);
  960.                 //
  961.                 // Loop through the message groups and update the use
  962.                 // counts for all groups that contain this message.
  963.                 //
  964.                 for (i = 0; i < gcMsgGroups; i++)
  965.                 {
  966.                     if (pmd->Flags & gaMsgGroup[i].flMask)
  967.                     {
  968.                         gaMsgGroup[i].cUseCount += fSel ? 1 : -1;
  969.                     }
  970.                 }
  971.                 //
  972.                 // Be sure that the checkboxes reflect the updated
  973.                 // status of the message group use counts.
  974.                 //
  975.                 MessagesUpdateCheckBoxes(hwnd);
  976.                 //
  977.                 // Save away the new selected item array.
  978.                 //
  979.                 cSelItemsMax = max(cItems, gcItemsSave);
  980.                 for (i = 0; i < cSelItemsMax; i++)
  981.                 {
  982.                     gaiSelected[i] = gaiSelected2[i];
  983.                 }
  984.                 gcItemsSave = cItems;
  985.             }
  986.             break;
  987.         case DID_MSGSALL:
  988.             hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  989.             SendMessage(hwndList, LB_SETSEL, TRUE, (LPARAM)-1);
  990.             for (i = 0; i < gcMsgGroups; i++)
  991.             {
  992.                 gaMsgGroup[i].cUseCount = gaMsgGroup[i].cMsgs;
  993.                 CheckDlgButton(hwnd, gaMsgGroup[i].idCheckBox, 1);
  994.             }
  995.             gcItemsSave = SendMessage(hwndList, LB_GETSELITEMS, gcMessages,
  996.                 (LPARAM)gaiSelected);
  997.             CheckDlgButton(hwnd, DID_MSGSUSER, 1);
  998.             CheckDlgButton(hwnd, DID_MSGSUNKNOWN, 1);
  999.             break;
  1000.         case DID_MSGSNONE:
  1001.             hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  1002.             SendMessage(hwndList, LB_SETSEL, FALSE, (LPARAM)-1);
  1003.             for (i = 0; i < gcMsgGroups; i++)
  1004.             {
  1005.                 gaMsgGroup[i].cUseCount = 0;
  1006.                 CheckDlgButton(hwnd, gaMsgGroup[i].idCheckBox, 0);
  1007.             }
  1008.             gcItemsSave = 0;
  1009.             CheckDlgButton(hwnd, DID_MSGSUSER, 0);
  1010.             CheckDlgButton(hwnd, DID_MSGSUNKNOWN, 0);
  1011.             break;
  1012.         case DID_MSGSDDE:
  1013.         case DID_MSGSCLIP:
  1014.         case DID_MSGSMOUSE:
  1015.         case DID_MSGSNC:
  1016.         case DID_MSGSKEYBD:
  1017. #ifdef FE_IME
  1018.         case DID_MSGSIME:
  1019. #endif
  1020.         case DID_MSGSBM:
  1021.         case DID_MSGSCB:
  1022.         case DID_MSGSEM:
  1023.         case DID_MSGSLB:
  1024.         case DID_MSGSSTM:
  1025.             for (i = 0; i < gcMsgGroups; i++)
  1026.             {
  1027.                 if (gaMsgGroup[i].idCheckBox == nCmd)
  1028.                 {
  1029.                     pmg = &gaMsgGroup[i];
  1030.                     break;
  1031.                 }
  1032.             }
  1033.             fChecked = IsDlgButtonChecked(hwnd, pmg->idCheckBox);
  1034.             if (fChecked == 1)
  1035.                 fChecked = FALSE;
  1036.             else
  1037.                 fChecked = TRUE;
  1038.             hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  1039.             if (fChecked)
  1040.             {
  1041.                 SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  1042.                 iTopIndex = SendMessage(hwndList, LB_GETTOPINDEX, 0, 0);
  1043.             }
  1044.             //
  1045.             // Get the list of currently selected items.
  1046.             //
  1047.             cItems = SendMessage(hwndList, LB_GETSELITEMS,
  1048.                 gcMessages, (LPARAM)gaiSelected);
  1049.             //
  1050.             // Look for all the messages in this group.
  1051.             //
  1052.             for (i = 0, iSel = 0; i < gcMessages; i++)
  1053.             {
  1054.                 pmd = (PMSGDESC)SendMessage(hwndList, LB_GETITEMDATA, i, 0);
  1055.                 if (pmd->Flags & pmg->flMask)
  1056.                 {
  1057.                     //
  1058.                     // Bump up through the list of selected items, looking
  1059.                     // to see if this item is currently selected.
  1060.                     //
  1061.                     for (fSel = FALSE; iSel < cItems &&
  1062.                         gaiSelected[iSel] <= i; iSel++)
  1063.                     {
  1064.                         //
  1065.                         // A match was found.  The item is selected.
  1066.                         //
  1067.                         if(gaiSelected[iSel] == i)
  1068.                         {
  1069.                             fSel = TRUE;
  1070.                             break;
  1071.                         }
  1072.                     }
  1073.                     //
  1074.                     // Is the current selection state of the item
  1075.                     // different from the desired selection state?
  1076.                     //
  1077.                     if (fSel != fChecked)
  1078.                     {
  1079.                         //
  1080.                         // Update the use counts of all groups that contain
  1081.                         // this message.
  1082.                         //
  1083.                         for (j = 0; j < gcMsgGroups; j++)
  1084.                         {
  1085.                             if (pmd->Flags & gaMsgGroup[j].flMask)
  1086.                             {
  1087.                                 gaMsgGroup[j].cUseCount += fChecked ? 1 : -1;
  1088.                             }
  1089.                         }
  1090.                         //
  1091.                         // Select/deselect the message in the list box.
  1092.                         //
  1093.                         SendMessage(hwndList, LB_SETSEL, fChecked, i);
  1094.                     }
  1095.                 }
  1096.             }
  1097.             //
  1098.             // Be sure that the checkboxes reflect the updated
  1099.             // status of the message group use counts.
  1100.             //
  1101.             MessagesUpdateCheckBoxes(hwnd);
  1102.             if (fChecked)
  1103.             {
  1104.                 SendMessage(hwndList, LB_SETTOPINDEX, iTopIndex, 0);
  1105.                 SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  1106.                 InvalidateRect(hwndList, NULL, FALSE);
  1107.             }
  1108.             gcItemsSave = SendMessage(hwndList, LB_GETSELITEMS,
  1109.                 gcMessages, (LPARAM)gaiSelected);
  1110.             break;
  1111.         case IDOK:
  1112.             hwndList = GetDlgItem(hwnd, DID_MSGSLIST);
  1113.             cItems = SendMessage(hwndList, LB_GETSELITEMS,
  1114.                 gcMessages, (LPARAM)gaiSelected);
  1115.             //
  1116.             // Unselect all messages.
  1117.             //
  1118.             for (i = 0; i < gcMessages; i++)
  1119.                 gaMsgs[i].Flags &= ~MTF_SELECTED;
  1120.             //
  1121.             // Mark all the messages that are selected.
  1122.             //
  1123.             for (i = 0; i < cItems; i++)
  1124.             {
  1125.                 pmd = (PMSGDESC)SendMessage(hwndList, LB_GETITEMDATA,
  1126.                     gaiSelected[i], 0);
  1127.                 pmd->Flags |= MTF_SELECTED;
  1128.             }
  1129.             if (IsDlgButtonChecked(hwnd, DID_MSGSUSER))
  1130.                 gfMsgsUser = TRUE;
  1131.             else
  1132.                 gfMsgsUser = FALSE;
  1133.             if (IsDlgButtonChecked(hwnd, DID_MSGSUNKNOWN))
  1134.                 gfMsgsUnknown = TRUE;
  1135.             else
  1136.                 gfMsgsUnknown = FALSE;
  1137. #if 0  //Debug code!
  1138. for (i = 0; i < gcMsgGroups; i++)
  1139. {
  1140.     iSel = 0;
  1141.     for (j = 0; j < cItems; j++)
  1142.     {
  1143.         pmd = (PMSGDESC)SendMessage(hwndList, LB_GETITEMDATA,
  1144.             gaiSelected[j], 0);
  1145.         if (pmd->Flags & gaMsgGroup[i].flMask)
  1146.             iSel++;
  1147.     }
  1148.     if (iSel != gaMsgGroup[i].cUseCount)
  1149.     {
  1150.         DbgPrintf("Use counts are wrong!!!");
  1151.         for (j = 0; j < gcMsgGroups; j++)
  1152.         {
  1153.             DbgPrintf("cMsgs:%d Use:%d", gaMsgGroup[j].cMsgs, gaMsgGroup[j].cUseCount);
  1154.         }
  1155.     }
  1156. }
  1157. #endif // end debug code
  1158.             EndDialog(hwnd, IDOK);
  1159.             return TRUE;
  1160.         case IDCANCEL:
  1161.             EndDialog(hwnd, IDCANCEL);
  1162.             return TRUE;
  1163.     }
  1164.     return FALSE;
  1165. }
  1166. /*****************************************************************************
  1167. * MessagesUpdateCheckBoxes
  1168. *
  1169. * Updates the message group checkboxes in the Messages dialog.
  1170. * This routine should be called when the use counts in the
  1171. * message group table are changed, so that the state of the
  1172. * checkboxes will get updated also.
  1173. *
  1174. * Arguments:
  1175. *   HWND hwnd - Dialog window handle.
  1176. *
  1177. * Returns:
  1178. *   VOID
  1179. *****************************************************************************/
  1180. PRIVATE VOID
  1181. MessagesUpdateCheckBoxes(
  1182.     HWND hwnd
  1183.     )
  1184. {
  1185.     INT i;
  1186.     INT fState;
  1187.     for (i = 0; i < gcMsgGroups; i++)
  1188.     {
  1189.         if (gaMsgGroup[i].cUseCount == gaMsgGroup[i].cMsgs)
  1190.             fState = 1;
  1191.         else if (gaMsgGroup[i].cUseCount == 0)
  1192.             fState = 0;
  1193.         else
  1194.             fState = 2;
  1195.         CheckDlgButton(hwnd, gaMsgGroup[i].idCheckBox, fState);
  1196.     }
  1197. }