home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / spy / app / dialogs.c next >
C/C++ Source or Header  |  1997-10-05  |  41KB  |  1,422 lines

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