home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / debug / deb / debmisc.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  42KB  |  1,038 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. // MODULE    : DEBMisc.C
  14. // PURPOSE   : Miscellaneous support functions for the Debug Event Browser
  15. // FUNCTIONS :
  16. //   StartDebuggee()               - starts a new debuggee process
  17. //   AttachToDebuggee()            - attaches to an existing process
  18. //   EnumProcessListFunc()         - enumeration func for active processes
  19. //   GetDebuggeeFileName()         - get the name of a debugee file to open
  20. //   ChooseNewFont()               - choose a new font
  21. //   ChooseNewBackColor()          - choose a new background color
  22. //   MakeCommonDebugEventString()  - create common debug event info string
  23. //   CreateTextButtonBar()         - create a text button bar
  24. //   CreateIconWindow()            - creates the icon window in the dialog
  25. //   GetPrivateProfileSettings()   - gets stored profile settings
  26. //   WritePrivateProfileSettings() - stores default settings in profile
  27. //   WritePrivateProfileInt()      - opposite of GetPrivateProfileInt()
  28. //   UpdateMenuSettings()          - update menu check marks
  29. //   OutOfMemoryMessageBox()       - displays an out of memory message box
  30. //   MaxDebuggeesMessageBox()      - displays max debuggees exceeded
  31. //   ErrorMessageBox()             - displays an error message box
  32. //   SubclassWindow()              - generic window subclass func
  33. //   SendWmSizeMessage()           - sends WM_SIZE with current size
  34. //   GetPathFromFullPathName()     - extracts path from a pathname
  35. //   CopyListBoxToClipboard()      - copies a listbox into the clipboard
  36. //   ListBoxInsert()               - insert a string into a listbox
  37. //   ListBoxPrintF()               - printf for listboxes
  38. //   StringPrintF()                - formats a string buffer
  39. //   StringAppendF()               - appends a formated string
  40. // COMMENTS  :
  41. //
  42. // ************************************************************************
  43. #define   STRICT               // enable strict typing
  44. #include <Windows.H>           // required for all Windows applications
  45. #include <CommDlg.H>           // GetOpenFileName(), ChooseFont(), etc.
  46. #include <Dlgs.H>              // templates and defines for the common dialogs
  47. #include <StdArg.H>            // va_list, va_start()
  48.  
  49. #include "LinkList.H"          //
  50. #include "ToolBar.H"           //
  51. #include "DEBMisc.H"           //
  52.  
  53.  
  54. // ************************************************************************
  55. // FUNCTION : StartDebuggee( LPTSTR, HWND )
  56. // PURPOSE  : starts a new debuggee process given a filename
  57. // COMMENTS :
  58. //   Return TRUE on success else FALSE.
  59. // ************************************************************************
  60. BOOL
  61. StartDebuggee( LPTSTR lpszDebuggeeFileName, HWND hWndListBox )
  62. {
  63.   static PDEB_STARTUP_INFO pDebStartupInfo;
  64.   static BOOL              fFirstTime = TRUE;
  65.  
  66.   static TCHAR szDebuggeeTitle[128];
  67.  
  68.   HANDLE hDebugEventThread;
  69.   DWORD  idDebugEventThread;
  70.  
  71.   //-- Load resource strings and init the OpenFileName struct
  72.   //   (do this only one time)
  73.   if( fFirstTime ) {
  74.     fFirstTime = FALSE;
  75.     LoadString( NULL, IDS_OFN_DEBUGGEE_TITLE, szDebuggeeTitle,
  76.       sizeof(szDebuggeeTitle)/sizeof(TCHAR) );
  77.   }
  78.  
  79.   //-- allocate the Debuggee Information structure
  80.   pDebStartupInfo = NULL;
  81.   pDebStartupInfo = (PDEB_STARTUP_INFO) VirtualAlloc(
  82.                                     pDebStartupInfo,
  83.                                     sizeof( DEB_STARTUP_INFO ),
  84.                                     MEM_RESERVE | MEM_COMMIT,
  85.                                     PAGE_READWRITE );
  86.  
  87.   //-- init the StartupInfo struct
  88.   (pDebStartupInfo->StartupInfo).cb          = sizeof( STARTUPINFO );
  89.   (pDebStartupInfo->StartupInfo).lpDesktop   = NULL;
  90.   (pDebStartupInfo->StartupInfo).lpTitle     = szDebuggeeTitle;
  91.   (pDebStartupInfo->StartupInfo).dwX         = 0;
  92.   (pDebStartupInfo->StartupInfo).dwY         = 0;
  93.   (pDebStartupInfo->StartupInfo).dwXSize     = 0;
  94.   (pDebStartupInfo->StartupInfo).dwYSize     = 0;
  95.   (pDebStartupInfo->StartupInfo).dwFlags     = (DWORD) NULL;
  96.   (pDebStartupInfo->StartupInfo).wShowWindow = SW_SHOWDEFAULT;
  97.  
  98.   (pDebStartupInfo->ProcessInfo).hProcess = NULL;
  99.  
  100.   //-- init other debuggee info
  101.   pDebStartupInfo->fActive       = FALSE;
  102.   pDebStartupInfo->dwProcessId   = (DWORD) NULL;
  103.   pDebStartupInfo->lpstrFileName = NULL;
  104.   pDebStartupInfo->lpstrPathName = lpszDebuggeeFileName;
  105.   pDebStartupInfo->hWndListBox   = hWndListBox;
  106.  
  107.   //-- now start and detach the debug event processing thread
  108.   if( !( hDebugEventThread = CreateThread(
  109.                                (LPSECURITY_ATTRIBUTES) NULL,
  110.                                (DWORD) 0,
  111.                                (LPTHREAD_START_ROUTINE) DebugEventThread,
  112.                                (LPVOID) pDebStartupInfo,
  113.                                (DWORD) NULL,
  114.                                (LPDWORD) &idDebugEventThread) ) ) {
  115.  
  116.     VirtualFree( pDebStartupInfo, 0, MEM_RELEASE );
  117.     return( FALSE );
  118.   }
  119.   else{
  120.     CloseHandle( hDebugEventThread );
  121.   }
  122.  
  123.   return( TRUE );
  124. }
  125.  
  126.  
  127. // ************************************************************************
  128. // FUNCTION : AttachToDebuggee( DWORD, HWND )
  129. // PURPOSE  : attaches to a currently running process
  130. // COMMENTS :
  131. //   Return TRUE on success else FALSE.
  132. // ************************************************************************
  133. BOOL
  134. AttachToDebuggee( DWORD dwProcessId, HWND hWndListBox )
  135. {
  136.   static PDEB_STARTUP_INFO pDebStartupInfo;
  137.   static BOOL              fFirstTime = TRUE;
  138.  
  139.   static TCHAR szDebuggeeTitle[128];
  140.  
  141.   HANDLE hDebugEventThread;
  142.   DWORD  idDebugEventThread;
  143.  
  144.   //-- Load resource strings and init the OpenFileName struct
  145.   //   (do this only one time)
  146.   if( fFirstTime ) {
  147.     fFirstTime = FALSE;
  148.     LoadString( NULL, IDS_OFN_DEBUGGEE_TITLE, szDebuggeeTitle,
  149.       sizeof(szDebuggeeTitle)/sizeof(TCHAR) );
  150.   }
  151.  
  152.   //-- allocate the Debuggee Information structure
  153.   pDebStartupInfo = NULL;
  154.   pDebStartupInfo = (PDEB_STARTUP_INFO) VirtualAlloc(
  155.                                     pDebStartupInfo,
  156.                                     sizeof( DEB_STARTUP_INFO ),
  157.                                     MEM_RESERVE | MEM_COMMIT,
  158.                                     PAGE_READWRITE );
  159.  
  160.   //-- init the StartupInfo struct
  161.   (pDebStartupInfo->StartupInfo).cb          = sizeof( STARTUPINFO );
  162.   (pDebStartupInfo->StartupInfo).lpDesktop   = NULL;
  163.   (pDebStartupInfo->StartupInfo).lpTitle     = szDebuggeeTitle;
  164.   (pDebStartupInfo->StartupInfo).dwX         = 0;
  165.   (pDebStartupInfo->StartupInfo).dwY         = 0;
  166.   (pDebStartupInfo->StartupInfo).dwXSize     = 0;
  167.   (pDebStartupInfo->StartupInfo).dwYSize     = 0;
  168.   (pDebStartupInfo->StartupInfo).dwFlags     = (DWORD) NULL;
  169.   (pDebStartupInfo->StartupInfo).wShowWindow = SW_SHOWDEFAULT;
  170.  
  171.   (pDebStartupInfo->ProcessInfo).hProcess = NULL;
  172.  
  173.   //-- init other debuggee info
  174.   pDebStartupInfo->fActive       = TRUE;
  175.   pDebStartupInfo->dwProcessId   = dwProcessId;
  176.   pDebStartupInfo->lpstrFileName = NULL;
  177.   pDebStartupInfo->lpstrPathName = NULL;
  178.   pDebStartupInfo->hWndListBox   = hWndListBox;
  179.  
  180.   //-- now start and detach the debug event processing thread
  181.   if( !( hDebugEventThread = CreateThread(
  182.                                (LPSECURITY_ATTRIBUTES) NULL,
  183.                                (DWORD) 0,
  184.                                (LPTHREAD_START_ROUTINE) DebugEventThread,
  185.                                (LPVOID) pDebStartupInfo,
  186.                                (DWORD) NULL,
  187.                                (LPDWORD) &idDebugEventThread) ) ) {
  188.  
  189.     VirtualFree( pDebStartupInfo, 0, MEM_RELEASE );
  190.     return( FALSE );
  191.   }
  192.   else{
  193.     CloseHandle( hDebugEventThread );
  194.   }
  195.  
  196.   return( TRUE );
  197. }
  198.  
  199.  
  200. // ************************************************************************
  201. // FUNCTION : EnumProcessListFunc( HWND, LPARAM )
  202. // PURPOSE  : Callback function for EnumWindows
  203. // COMMENTS : Inserts found window title strings into the listbox.
  204. //            Return !NULL to continue enumeration.
  205. // ************************************************************************
  206. BOOL CALLBACK
  207. EnumProcessListFunc( HWND hWnd, LPARAM lParam )
  208. {
  209.   static DWORD dwCurrentProcessId;
  210.   static BOOL  fFirstTime = TRUE;
  211.   static LONG  MaxStrLen  = 0;
  212.   static TCHAR TextBuffer[256];
  213.  
  214.   if( fFirstTime ) {
  215.     fFirstTime = FALSE;
  216.     dwCurrentProcessId = GetCurrentProcessId();
  217.   }
  218.  
  219.   if( hWnd ) {
  220.     GetWindowText( hWnd, (LPTSTR) &TextBuffer, sizeof(TextBuffer) );
  221.     if( *TextBuffer ) {
  222.       DWORD  dwProcessId;
  223.  
  224.       GetWindowThreadProcessId( hWnd, &dwProcessId );
  225.       if( dwProcessId != dwCurrentProcessId ) {
  226.         LONG Index;
  227.         HWND hWndListBox = (HWND) lParam;
  228.  
  229.         Index = ListBoxInsert( hWndListBox, &MaxStrLen, TextBuffer );
  230.         SendMessage( hWndListBox, LB_SETITEMDATA, (WPARAM) Index,
  231.           (LPARAM) dwProcessId );
  232.       }
  233.     }
  234.   }
  235.  
  236.   return( TRUE );
  237. }
  238.  
  239.  
  240. // ************************************************************************
  241. // FUNCTION : GetDebuggeeFileName( LPTSTR, HWND )
  242. // PURPOSE  : Get the name of a debugee file to open.
  243. // COMMENTS :
  244. //   Return TRUE on success else FALSE.
  245. // ************************************************************************
  246. BOOL
  247. GetDebuggeeFileName( LPTSTR lpszDebuggeeFileName, HWND hWnd )
  248. {
  249.   static BOOL  fFirstTime = TRUE;
  250.   static TCHAR szFilter[128]         = TEXT("");
  251.   static TCHAR szTitle[64]           = TEXT("");
  252.   static TCHAR szFileTitle[MAX_PATH] = TEXT("");
  253.   static TCHAR szFile[MAX_PATH]      = TEXT("");
  254.   static TCHAR szDefExt[8]           = TEXT("");
  255.   static OPENFILENAME OpenFileName;
  256.  
  257.   //-- Load resource strings and init the OpenFileName struct
  258.   //   (do this only one time)
  259.   if( fFirstTime ) {
  260.     static UINT FilterNameLen;
  261.  
  262.     fFirstTime = FALSE;
  263.     FilterNameLen = (UINT) LoadString( NULL, IDS_OFN_FILTERNAME,
  264.                              szFilter, sizeof(szFilter) );
  265.     FilterNameLen++;
  266.     LoadString( NULL, IDS_OFN_FILTER, &szFilter[FilterNameLen],
  267.       sizeof(szFilter)-FilterNameLen );
  268.     LoadString( NULL, IDS_OFN_TITLE, szTitle, sizeof(szTitle) );
  269.  
  270.     OpenFileName.lStructSize       = sizeof(OPENFILENAME);
  271.     OpenFileName.hwndOwner         = hWnd;
  272.     OpenFileName.hInstance         = (HANDLE) NULL;
  273.     OpenFileName.lpstrFilter       = szFilter;
  274.     OpenFileName.lpstrCustomFilter = NULL;
  275.     OpenFileName.nMaxCustFilter    = (DWORD) NULL;
  276.     OpenFileName.nFilterIndex      = 1L;
  277.     OpenFileName.lpstrFile         = szFile;
  278.     OpenFileName.nMaxFile          = sizeof(szFile);
  279.     OpenFileName.lpstrFileTitle    = szFileTitle;
  280.     OpenFileName.nMaxFileTitle     = sizeof(szFileTitle);
  281.     OpenFileName.lpstrInitialDir   = (Profile.fSavedDirectory ? Profile.szInitialDir : NULL);
  282.     OpenFileName.lpstrTitle        = (LPTSTR) szTitle;
  283.     OpenFileName.Flags             = OFN_HIDEREADONLY;
  284.     OpenFileName.nFileOffset       = (WORD) NULL;
  285.     OpenFileName.nFileExtension    = (WORD) NULL;
  286.     OpenFileName.lpstrDefExt       = szDefExt;
  287.     OpenFileName.lCustData         = (DWORD) NULL;
  288.     OpenFileName.lpfnHook          = (LPOFNHOOKPROC) NULL;
  289.     OpenFileName.lpTemplateName    = (LPTSTR) NULL;
  290.   }
  291.  
  292.   if( !GetOpenFileName( &OpenFileName ) ) {
  293.     return( FALSE );
  294.   }
  295.  
  296.   //-- store recent directory by stripping off the EXE name from the full path
  297.   GetPathFromFullPathName( (LPTSTR) OpenFileName.lpstrFile, Profile.szInitialDir,
  298.     sizeof(Profile.szInitialDir) );
  299.  
  300.   //-- copy name to return buffer
  301.   lstrcpy( lpszDebuggeeFileName, OpenFileName.lpstrFile );
  302.  
  303.   return( TRUE );
  304. }
  305.  
  306.  
  307. // ************************************************************************
  308. // FUNCTION : ChooseFontHookProc(  )
  309. // PURPOSE  : Disable the Effects group and its contents
  310. // COMMENTS :
  311. // ************************************************************************
  312. LRESULT CALLBACK
  313. ChooseFontHookProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  314. {
  315.   UNREFERENCED_PARAMETER( lParam );
  316.   UNREFERENCED_PARAMETER( wParam );
  317.  
  318.   switch( uMsg ) {
  319.  
  320.     case WM_INITDIALOG:
  321.       ShowWindow( GetDlgItem(hDlg, grp1), SW_HIDE );
  322.       ShowWindow( GetDlgItem(hDlg, chx1), SW_HIDE );
  323.       ShowWindow( GetDlgItem(hDlg, chx2), SW_HIDE );
  324.       break;
  325.  
  326.   }
  327.  
  328.   return( FALSE );
  329. }
  330.  
  331.  
  332. // ************************************************************************
  333. // FUNCTION : ChooseNewFont( HWND )
  334. // PURPOSE  : Choose a new font for a listbox
  335. // COMMENTS : Return TRUE on success else FALSE
  336. // ************************************************************************
  337. BOOL
  338. ChooseNewFont( HWND hWndListBox )
  339. {
  340.   static CHOOSEFONT ChooseFontStruct;
  341.   static BOOL       fFirstTime = TRUE;
  342.   HFONT             hFont;
  343.  
  344.   if( fFirstTime ) {
  345.     fFirstTime = FALSE;
  346.  
  347.     ChooseFontStruct.lStructSize    = sizeof( CHOOSEFONT );
  348.     ChooseFontStruct.hwndOwner      = hWndListBox;
  349.     ChooseFontStruct.hDC            = (HDC) NULL;
  350.     ChooseFontStruct.lpLogFont      = &(Profile.LogFont);
  351.     ChooseFontStruct.iPointSize     = (INT) NULL;
  352.     ChooseFontStruct.Flags          = CF_INITTOLOGFONTSTRUCT |
  353.                                       CF_SCREENFONTS | CF_EFFECTS |
  354.                                       CF_ENABLEHOOK;
  355.     ChooseFontStruct.rgbColors      = Profile.rgbForeColor;
  356.     ChooseFontStruct.lCustData      = (DWORD) NULL;
  357.     ChooseFontStruct.lpfnHook       = (LPCFHOOKPROC) ChooseFontHookProc;
  358.     ChooseFontStruct.lpTemplateName = (LPTSTR) NULL;
  359.     ChooseFontStruct.hInstance      = (HANDLE) NULL;
  360.     ChooseFontStruct.lpszStyle      = (LPTSTR) NULL;
  361.     ChooseFontStruct.nFontType      = SCREEN_FONTTYPE;
  362.     ChooseFontStruct.nSizeMin       = (INT) NULL;
  363.     ChooseFontStruct.nSizeMax       = (INT) NULL;
  364.   }
  365.  
  366.   if( ChooseFont( &ChooseFontStruct ) ) {
  367.     HDC    hDC;
  368.  
  369.     hFont = CreateFontIndirect( &(Profile.LogFont) );
  370.     hDC = GetDC( hWndListBox );
  371.     SelectObject( hDC, hFont );
  372.     Profile.rgbForeColor = ChooseFontStruct.rgbColors;
  373.     InvalidateRect( hWndListBox, NULL, TRUE );
  374.     SendMessage( hWndListBox, WM_CTLCOLORLISTBOX, (DWORD) hDC,
  375.       (LONG) hWndListBox );
  376.     SendMessage( hWndListBox, WM_SETFONT, (DWORD) hFont, TRUE );
  377.     ReleaseDC( hWndListBox, hDC );
  378.   }
  379.  
  380.   return( TRUE );
  381. }
  382.  
  383.  
  384. // ************************************************************************
  385. // FUNCTION : ChooseNewBackColor( HWND )
  386. // PURPOSE  : Choose the background color for a listbox
  387. // COMMENTS : Return TRUE on success else FALSE
  388. // ************************************************************************
  389. BOOL
  390. ChooseNewBackColor( HWND hWndListBox )
  391. {
  392.   static BOOL        fFirstTime = TRUE;
  393.   static CHOOSECOLOR ChooseColorStruct;
  394.   static DWORD       dwCustColors[16];
  395.  
  396.   if( fFirstTime ) {
  397.     int i;
  398.  
  399.     fFirstTime = FALSE;
  400.  
  401.     //-- set the custom colors to white
  402.     for( i = 0; i < 16; i++ )
  403.       dwCustColors[i] = RGB(255,255,255);
  404.  
  405.     ChooseColorStruct.lStructSize    = sizeof( CHOOSECOLOR );
  406.     ChooseColorStruct.hwndOwner      = hWndListBox;
  407.     ChooseColorStruct.hInstance      = (HANDLE) NULL;
  408.     ChooseColorStruct.rgbResult      = Profile.rgbBackColor;
  409.     ChooseColorStruct.lpCustColors   = (LPDWORD) dwCustColors;
  410.     ChooseColorStruct.Flags          = CC_RGBINIT;
  411.     ChooseColorStruct.lCustData      = 0L;
  412.     ChooseColorStruct.lpfnHook       = (LPCCHOOKPROC) NULL;
  413.     ChooseColorStruct.lpTemplateName = (LPTSTR) NULL;
  414.   }
  415.  
  416.   if( ChooseColor( &ChooseColorStruct ) ) {
  417.     HDC    hDC;
  418.  
  419.     Profile.rgbBackColor = (COLORREF) ChooseColorStruct.rgbResult;
  420.     hDC = GetDC( hWndListBox );
  421.     SendMessage( hWndListBox, WM_CTLCOLORLISTBOX, (DWORD) hDC,
  422.       (LONG) hWndListBox );
  423.     ReleaseDC( hWndListBox, hDC );
  424.     InvalidateRect( hWndListBox, NULL, TRUE );
  425.   }
  426.  
  427.   return( TRUE );
  428. }
  429.  
  430.  
  431. // ************************************************************************
  432. // FUNCTION : MakeCommonDebugEventString( LPTSTR, LPDEBUG_EVENT )
  433. // PURPOSE  : Fill in the Debug Event information into a string buffer
  434. // COMMENTS : The string buffer contains the information common to all
  435. //            debug events ( PID, TID ).
  436. // ************************************************************************
  437. BOOL
  438. MakeCommonDebugEventString( LPTSTR lpszBuffer, LPDEBUG_EVENT lpDebugEvent )
  439. {
  440.   StringPrintF( lpszBuffer, TEXT( "PID:0x%X \t TID:0x%X \t " ),
  441.     lpDebugEvent->dwProcessId, lpDebugEvent->dwThreadId );
  442.  
  443.   return( TRUE );
  444. }
  445.  
  446.  
  447. // ************************************************************************
  448. // FUNCTION : CreateTextButtonBar( HWND, LPINT )
  449. // PURPOSE  : Creates a Text Button Bar from the resource strings.
  450. // COMMENTS : Returns window handle to the created text button bar
  451. // ************************************************************************
  452. HWND
  453. CreateTextButtonBar( HWND hWndParent, LPINT lpTextButtonBarHeight )
  454. {
  455.   TEXTBUTTON   TextButton[9];
  456.   static TCHAR szButtonOpen[32];
  457.   static TCHAR szButtonAttach[32];
  458.   static TCHAR szButtonCut[32];
  459.   static TCHAR szButtonCopy[32];
  460.   static TCHAR szButtonDelete[32];
  461.   static TCHAR szButtonHelp[32];
  462.  
  463.   LoadString( NULL, IDS_BUTTON_OPEN,   szButtonOpen,   sizeof(szButtonOpen)/sizeof(TCHAR)   );
  464.   LoadString( NULL, IDS_BUTTON_ATTACH, szButtonAttach, sizeof(szButtonAttach)/sizeof(TCHAR) );
  465.   LoadString( NULL, IDS_BUTTON_CUT,    szButtonCut,    sizeof(szButtonCut)/sizeof(TCHAR)    );
  466.   LoadString( NULL, IDS_BUTTON_COPY,   szButtonCopy,   sizeof(szButtonCopy)/sizeof(TCHAR)   );
  467.   LoadString( NULL, IDS_BUTTON_DELETE, szButtonDelete, sizeof(szButtonDelete)/sizeof(TCHAR) );
  468.   LoadString( NULL, IDS_BUTTON_HELP,   szButtonHelp,   sizeof(szButtonHelp)/sizeof(TCHAR)   );
  469.  
  470.   TextButton[0].lpButtonText = szButtonOpen;
  471.   TextButton[0].idButton     = IDM_FILE_OPEN;
  472.   TextButton[0].hWndButton   = NULL;
  473.  
  474.   TextButton[1].lpButtonText = szButtonAttach;
  475.   TextButton[1].idButton     = IDM_FILE_ATTACH;
  476.   TextButton[1].hWndButton   = NULL;
  477.  
  478.   TextButton[2].lpButtonText = NULL;
  479.   TextButton[2].idButton     = TB_SPACE;
  480.   TextButton[2].hWndButton   = NULL;
  481.  
  482.   TextButton[3].lpButtonText = szButtonCut;
  483.   TextButton[3].idButton     = IDM_EDIT_CUT;
  484.   TextButton[3].hWndButton   = NULL;
  485.  
  486.   TextButton[4].lpButtonText = szButtonCopy;
  487.   TextButton[4].idButton     = IDM_EDIT_COPY;
  488.   TextButton[4].hWndButton   = NULL;
  489.  
  490.   TextButton[5].lpButtonText = szButtonDelete;
  491.   TextButton[5].idButton     = IDM_EDIT_DELETE;
  492.   TextButton[5].hWndButton   = NULL;
  493.  
  494.   TextButton[6].lpButtonText = NULL;
  495.   TextButton[6].idButton     = TB_SPACE;
  496.   TextButton[6].hWndButton   = NULL;
  497.  
  498.   TextButton[7].lpButtonText = szButtonHelp;
  499.   TextButton[7].idButton     = IDM_HELP_CONTENTS;
  500.   TextButton[7].hWndButton   = NULL;
  501.  
  502.   TextButton[8].lpButtonText = (LPTSTR) NULL;
  503.   TextButton[8].idButton     = (INT)   NULL;
  504.   TextButton[8].hWndButton   = (HWND)  NULL;
  505.  
  506.   return( TextButtonBar( hWndParent, TextButton, lpTextButtonBarHeight ) );
  507. }
  508.  
  509.  
  510. // ************************************************************************
  511. // FUNCTION : CreateIconWindow( HWND, LPCTSTR )
  512. // PURPOSE  :
  513. // COMMENTS :
  514. // ************************************************************************
  515. HWND
  516. CreateIconWindow( HWND hDlg, LPCTSTR lpstrIcon )
  517. {
  518.   return ( CreateWindow( TEXT( "static" ), lpstrIcon,
  519.              WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SS_ICON,
  520.              7, 5, 0, 0,
  521.              hDlg, NULL, GetModuleHandle( NULL ), NULL ) );
  522. }
  523.  
  524.  
  525. // ************************************************************************
  526. // FUNCTION : GetPrivateProfileSettings( LPCTSTR, LPCTSTR, PPROFILE )
  527. // PURPOSE  : Retrieves the stored preferences and options from the
  528. //            profile (registry)
  529. // COMMENTS :
  530. // ************************************************************************
  531. BOOL
  532. GetPrivateProfileSettings( LPCTSTR lpszAppTitle, LPCTSTR lpszIniPathName,
  533.   PPROFILE pProfile )
  534. {
  535.   pProfile->xPos       = (INT) GetPrivateProfileInt(  lpszAppTitle, TEXT( "xPos" ),       CW_USEDEFAULT, lpszIniPathName );
  536.   pProfile->yPos       = (INT) GetPrivateProfileInt(  lpszAppTitle, TEXT( "yPos" ),       CW_USEDEFAULT, lpszIniPathName );
  537.   pProfile->nWidth     = (INT) GetPrivateProfileInt(  lpszAppTitle, TEXT( "nWidth" ),     CW_USEDEFAULT, lpszIniPathName );
  538.   pProfile->nHeight    = (INT) GetPrivateProfileInt(  lpszAppTitle, TEXT( "nHeight" ),    CW_USEDEFAULT, lpszIniPathName );
  539.   pProfile->fMaximized = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fMaximized" ), (INT) FALSE,   lpszIniPathName );
  540.   pProfile->fMinimized = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fMinimized" ), (INT) FALSE,   lpszIniPathName );
  541.  
  542.   pProfile->fToolBar         = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fToolBar" ),         (INT) TRUE,  lpszIniPathName );
  543.   pProfile->fSavedDirectory  = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fSavedDirectory" ),  (INT) TRUE,  lpszIniPathName );
  544.   GetPrivateProfileString( lpszAppTitle, TEXT( "szInitialDir" ), NULL, pProfile->szInitialDir,
  545.     sizeof( pProfile->szInitialDir ), lpszIniPathName );
  546.  
  547.   pProfile->LogFont.lfHeight         = (LONG) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfHeight" ),         (INT) 13   ,       lpszIniPathName );
  548.   pProfile->LogFont.lfWidth          = (LONG) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfWidth" ),          (INT) 0    ,       lpszIniPathName );
  549.   pProfile->LogFont.lfWeight         = (LONG) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfWeight" ),         (INT) 400  ,       lpszIniPathName );
  550.   pProfile->LogFont.lfItalic         = (BYTE) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfItalic" ),         (INT) FALSE,       lpszIniPathName );
  551.   pProfile->LogFont.lfUnderline      = (BYTE) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfUnderline" ),      (INT) FALSE,       lpszIniPathName );
  552.   pProfile->LogFont.lfStrikeOut      = (BYTE) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfStrikeOut" ),      (INT) FALSE,       lpszIniPathName );
  553.   pProfile->LogFont.lfPitchAndFamily = (BYTE) GetPrivateProfileInt( lpszAppTitle, TEXT( "lfPitchAndFamily" ), (INT) FF_DONTCARE, lpszIniPathName );
  554.   GetPrivateProfileString( lpszAppTitle, TEXT( "lfFaceName" ), TEXT( "System" ), pProfile->LogFont.lfFaceName,
  555.     LF_FACESIZE, lpszIniPathName );
  556.   pProfile->rgbForeColor = (COLORREF) GetPrivateProfileInt( lpszAppTitle, TEXT( "rgbForeColor" ),
  557.                             (INT) GetSysColor(COLOR_WINDOWTEXT), lpszIniPathName );
  558.   pProfile->rgbBackColor = (COLORREF) GetPrivateProfileInt( lpszAppTitle, TEXT( "rgbBackColor" ),
  559.                             (INT) GetSysColor(COLOR_WINDOW), lpszIniPathName );
  560.  
  561.   pProfile->fClearOnNew      = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fClearOnNew" ),      (INT) TRUE,  lpszIniPathName );
  562.   pProfile->fVerbose         = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fVerbose" ),         (INT) FALSE, lpszIniPathName );
  563.   pProfile->fShowSymbols     = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fShowSymbols" ),     (INT) FALSE, lpszIniPathName );
  564.   pProfile->DebugMode        = (LONG) GetPrivateProfileInt( lpszAppTitle, TEXT( "DebugMode" ),        (INT) DEBUG_PROCESS        , lpszIniPathName );
  565.   pProfile->DebuggeePriority = (LONG) GetPrivateProfileInt( lpszAppTitle, TEXT( "DebuggeePriority" ), (INT) NORMAL_PRIORITY_CLASS, lpszIniPathName );
  566.   pProfile->DebugErrorLevel  = (DWORD) GetPrivateProfileInt( lpszAppTitle, TEXT( "DebugErrorLevel" ), (INT) 0, lpszIniPathName );
  567.   pProfile->fSavePreferences = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fSavePreferences" ), (INT) FALSE, lpszIniPathName );
  568.  
  569.   pProfile->fSaveOnExit      = (BOOL) GetPrivateProfileInt( lpszAppTitle, TEXT( "fSaveOnExit" ),      (INT) TRUE,  lpszIniPathName );
  570.  
  571.   return( TRUE );
  572. }
  573.  
  574.  
  575. // ************************************************************************
  576. // FUNCTION : WritePrivateProfileSettings( LPCTSTR, LPCTSTR, PPROFILE )
  577. // PURPOSE  : Saves the preferences and options to the profile (registry)
  578. // COMMENTS :
  579. // ************************************************************************
  580. BOOL
  581. WritePrivateProfileSettings( LPCTSTR lpszAppTitle, LPCTSTR lpszIniPathName,
  582.   PPROFILE pProfile )
  583. {
  584.   if( pProfile->fSaveOnExit ) {
  585.     WritePrivateProfileInt( lpszAppTitle, TEXT( "xPos" ),       (INT) pProfile->xPos,       lpszIniPathName );
  586.     WritePrivateProfileInt( lpszAppTitle, TEXT( "yPos" ),       (INT) pProfile->yPos,       lpszIniPathName );
  587.     WritePrivateProfileInt( lpszAppTitle, TEXT( "nWidth" ),     (INT) pProfile->nWidth,     lpszIniPathName );
  588.     WritePrivateProfileInt( lpszAppTitle, TEXT( "nHeight" ),    (INT) pProfile->nHeight,    lpszIniPathName );
  589.     WritePrivateProfileInt( lpszAppTitle, TEXT( "fMaximized" ), (INT) pProfile->fMaximized, lpszIniPathName );
  590.     WritePrivateProfileInt( lpszAppTitle, TEXT( "fMinimized" ), (INT) pProfile->fMinimized, lpszIniPathName );
  591.  
  592.     WritePrivateProfileInt( lpszAppTitle, TEXT( "fToolBar" ),         (INT) pProfile->fToolBar,         lpszIniPathName );
  593.     WritePrivateProfileInt( lpszAppTitle, TEXT( "fSavedDirectory" ),  (INT) pProfile->fSavedDirectory,  lpszIniPathName );
  594.     WritePrivateProfileString( lpszAppTitle, TEXT( "szInitialDir" ), pProfile->szInitialDir, lpszIniPathName );
  595.  
  596.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfHeight" ),         (INT) pProfile->LogFont.lfHeight,         lpszIniPathName );
  597.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfWidth" ),          (INT) pProfile->LogFont.lfWidth,          lpszIniPathName );
  598.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfWeight" ),         (INT) pProfile->LogFont.lfWeight,         lpszIniPathName );
  599.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfItalic" ),         (INT) pProfile->LogFont.lfItalic,         lpszIniPathName );
  600.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfUnderline" ),      (INT) pProfile->LogFont.lfUnderline,      lpszIniPathName );
  601.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfStrikeOut" ),      (INT) pProfile->LogFont.lfStrikeOut,      lpszIniPathName );
  602.     WritePrivateProfileInt( lpszAppTitle, TEXT( "lfPitchAndFamily" ), (INT) pProfile->LogFont.lfPitchAndFamily, lpszIniPathName );
  603.     WritePrivateProfileString( lpszAppTitle, TEXT( "lfFaceName" ), pProfile->LogFont.lfFaceName, lpszIniPathName );
  604.     WritePrivateProfileInt( lpszAppTitle, TEXT( "rgbForeColor" ), (INT) pProfile->rgbForeColor, lpszIniPathName );
  605.     WritePrivateProfileInt( lpszAppTitle, TEXT( "rgbBackColor" ), (INT) pProfile->rgbBackColor, lpszIniPathName );
  606.  
  607.     if( pProfile->fSavePreferences ) {
  608.       WritePrivateProfileInt( lpszAppTitle, TEXT( "fClearOnNew" ),  (INT) pProfile->fClearOnNew,  lpszIniPathName );
  609.       WritePrivateProfileInt( lpszAppTitle, TEXT( "fVerbose" ),     (INT) pProfile->fVerbose,     lpszIniPathName );
  610.       WritePrivateProfileInt( lpszAppTitle, TEXT( "fShowSymbols" ), (INT) pProfile->fShowSymbols, lpszIniPathName );
  611.       WritePrivateProfileInt( lpszAppTitle, TEXT( "DebugMode" ),        (INT) pProfile->DebugMode,        lpszIniPathName );
  612.       WritePrivateProfileInt( lpszAppTitle, TEXT( "DebuggeePriority" ), (INT) pProfile->DebuggeePriority, lpszIniPathName );
  613.       WritePrivateProfileInt( lpszAppTitle, TEXT( "DebugErrorLevel" ), (INT) pProfile->DebugErrorLevel, lpszIniPathName );
  614.     }
  615.     WritePrivateProfileInt( lpszAppTitle, TEXT( "fSavePreferences" ), (INT) pProfile->fSavePreferences, lpszIniPathName );
  616.   }
  617.   WritePrivateProfileInt( lpszAppTitle, TEXT( "fSaveOnExit" ), (INT) pProfile->fSaveOnExit, lpszIniPathName );
  618.  
  619.   return( TRUE );
  620. }
  621.  
  622.  
  623. // ************************************************************************
  624. // FUNCTION: WritePrivateProfileInt( LPCTSTR, LPCTSTR, INT, LPCTSTR )
  625. // PURPOSE : Writes the value of an integer from a specified keyname within
  626. //           a specified section of the Private Profile
  627. // COMMENTS: Matched pair to GetPrivateProfileInt
  628. // ************************************************************************
  629. BOOL
  630. WritePrivateProfileInt( LPCTSTR lpAppName, LPCTSTR lpKeyName, INT Value, LPCTSTR lpFileName )
  631. {
  632.   TCHAR ValBuf[16];
  633.  
  634.   wsprintf( ValBuf, TEXT( "%i" ), Value);
  635.  
  636.   return( WritePrivateProfileString( lpAppName, lpKeyName, ValBuf, lpFileName ) );
  637. }
  638.  
  639.  
  640. // ************************************************************************
  641. // FUNCTION : UpdateMenuSettings( HWND )
  642. // PURPOSE  : Adds check marks to active menu items
  643. // COMMENTS :
  644. // ************************************************************************
  645. BOOL
  646. UpdateMenuSettings( HWND hWnd )
  647. {
  648.   if( Profile.fToolBar )
  649.     CheckMenuItem( GetMenu(hWnd), IDM_OPTIONS_TOOLBAR, MF_CHECKED );
  650.   if( Profile.fSavedDirectory )
  651.     CheckMenuItem( GetMenu(hWnd), IDM_OPTIONS_SAVEDDIR, MF_CHECKED );
  652.   if( Profile.fSaveOnExit )
  653.     CheckMenuItem( GetMenu(hWnd), IDM_OPTIONS_SAVEONEXIT, MF_CHECKED );
  654.  
  655.   return( TRUE );
  656. }
  657.  
  658.  
  659. // ************************************************************************
  660. // FUNCTION : OutOfMemoryMessageBox( HWND )
  661. // PURPOSE  : If called, displays an "Out of Memory" message box
  662. // COMMENTS :
  663. // ************************************************************************
  664. BOOL
  665. OutOfMemoryMessageBox( HWND hWndOwner )
  666. {
  667.   MessageBox(
  668.     hWndOwner,
  669.     TEXT( "Out of Memory" ),
  670.     TEXT( "Memory Error" ),
  671.     MB_ICONSTOP | MB_APPLMODAL );
  672.  
  673.   return( TRUE );
  674. }
  675.  
  676.  
  677. // ************************************************************************
  678. // FUNCTION : MaxDebuggeesMessageBox( HWND )
  679. // PURPOSE  : If called, displays an "Max Debuggees" message box
  680. // COMMENTS :
  681. // ************************************************************************
  682. BOOL
  683. MaxDebuggeesMessageBox( HWND hWndOwner )
  684. {
  685.   MessageBox( hWndOwner,
  686.     TEXT( "This build of the Debug Event Browser\n" )
  687.     TEXT( "is limited to debugging only one debuggee\n" )
  688.     TEXT( "at a time." ),
  689.     TEXT( "Cannot Open Debuggee" ),
  690.     MB_OK | MB_ICONEXCLAMATION );
  691.  
  692.   return( TRUE );
  693. }
  694.  
  695.  
  696. // ========================================================================
  697. // helper functions
  698. // ========================================================================
  699.  
  700.  
  701. // ************************************************************************
  702. // FUNCTION : ErrorMessageBox( LPCTSTR, LPCTSTR, LPCTSTR, INT )
  703. // PURPOSE  : Displays an error message box with various error information
  704. //            and allows the user to terminate or continue the process.
  705. //            For a Win32 Application, GetLastError and FormatMessage are
  706. //            used to retrieve the last API error code and error message.
  707. // COMMENTS :
  708. // ************************************************************************
  709. BOOL
  710. ErrorMessageBox( LPCTSTR lpszText, LPCTSTR lpszTitle, LPCTSTR lpszFile,
  711.   INT Line )
  712. {
  713.   #define ERROR_BUFFER_SIZE 512
  714.  
  715.   static TCHAR Format[] =
  716.     TEXT( "%s\n\n"                                  )
  717.     TEXT( "-- Error Information --\n"               )
  718.     TEXT( "File : %s\n"                             )
  719.     TEXT( "Line : %d\n"                             )
  720.     TEXT( "Error Number : %d\n"                     )
  721.     TEXT( "Error Message : %s\n"                    )
  722.     TEXT( "\n"                                      )
  723.     TEXT( "Press OK to terminate this application." );
  724.  
  725.   LPTSTR lpFormatMessageBuffer;
  726.   DWORD  dwFormatMessage;
  727.   DWORD  dwGetLastError;
  728.   HLOCAL hMessageBoxBuffer;
  729.   LPVOID lpMessageBoxBuffer;
  730.  
  731.   //-- perform a simple check on the needed buffer size
  732.   if( lstrlen(lpszText) > (ERROR_BUFFER_SIZE - lstrlen(Format)) )
  733.     return( FALSE );
  734.  
  735.   //-- allocate the message box buffer
  736.   hMessageBoxBuffer  = LocalAlloc( LMEM_MOVEABLE, ERROR_BUFFER_SIZE );
  737.   lpMessageBoxBuffer = LocalLock( hMessageBoxBuffer );
  738.  
  739.   //-- get the system error and system error message
  740.   dwGetLastError = GetLastError();
  741.   dwFormatMessage = FormatMessage(
  742.                       FORMAT_MESSAGE_ALLOCATE_BUFFER
  743.                       | FORMAT_MESSAGE_FROM_SYSTEM,
  744.                       NULL, dwGetLastError, LANG_NEUTRAL,
  745.                       (LPTSTR) &lpFormatMessageBuffer, 0, NULL );
  746.   if( !dwFormatMessage )
  747.     lpFormatMessageBuffer = TEXT("FormatMessage() failed!");
  748.  
  749.   //-- format the error messge box string
  750.   wsprintf( lpMessageBoxBuffer, Format, lpszText, lpszFile, Line,
  751.     dwGetLastError, lpFormatMessageBuffer );
  752.  
  753.   // -- display the error and allow the user to terminate or continue
  754.   if( MessageBox( NULL, lpMessageBoxBuffer, lpszTitle,
  755.         MB_APPLMODAL | MB_ICONSTOP | MB_OKCANCEL )
  756.     == IDOK )
  757.     ExitProcess( 0 );
  758.  
  759.   //-- free all buffers
  760.   if( dwFormatMessage )
  761.     LocalFree( (HLOCAL) lpFormatMessageBuffer );
  762.   LocalFree( (HLOCAL) hMessageBoxBuffer );
  763.  
  764.   return( TRUE );
  765. }
  766.  
  767.  
  768.  
  769. // ************************************************************************
  770. // FUNCTION : SubclassWindow( HWND, WNDPROC )
  771. // PURPOSE  : Subclasses a window procedure
  772. // COMMENTS : Returns the old window procedure
  773. // ************************************************************************
  774. WNDPROC
  775. SubclassWindow( HWND hWnd, WNDPROC NewWndProc)
  776. {
  777.   WNDPROC OldWndProc;
  778.  
  779.   OldWndProc = (WNDPROC) GetWindowLong( hWnd, GWL_WNDPROC );
  780.   SetWindowLong( hWnd, GWL_WNDPROC, (LONG) NewWndProc );
  781.  
  782.   return OldWndProc;
  783. }
  784.  
  785.  
  786. // ************************************************************************
  787. // FUNCTION : SendWmSizeMessage( HWND )
  788. // PURPOSE  : Sends a WM_SIZE message containing the current size
  789. // COMMENTS : Forces a WM_SIZE message without actually changing the size
  790. // ************************************************************************
  791. BOOL
  792. SendWmSizeMessage( HWND hWnd )
  793. {
  794.   RECT Rect;
  795.  
  796.   if( !GetClientRect( hWnd, &Rect ) )
  797.     return( FALSE );
  798.  
  799.   return( SendMessage( hWnd, WM_SIZE, SIZENORMAL,
  800.             MAKELONG( Rect.right - Rect.left, Rect.bottom - Rect.top) ) );
  801. }
  802.  
  803.  
  804. // ************************************************************************
  805. // FUNCTION : GetPathFromFullPathName( LPCTSTR, LPTSTR, UINT )
  806. // PURPOSE  : Extracts the path given a full pathname
  807. // COMMENTS :
  808. // ************************************************************************
  809. UINT
  810. GetPathFromFullPathName( LPCTSTR lpFullPathName, LPTSTR lpPathBuffer,
  811.   UINT nPathBufferLength )
  812. {
  813.   UINT nLength;
  814.   int i, j;
  815.  
  816.   if( (nLength = (UINT) lstrlen( lpFullPathName ) ) > nPathBufferLength )
  817.     return( nLength );
  818.  
  819.   lstrcpy( lpPathBuffer, lpFullPathName );
  820.  
  821.   for( j = 0, i = nLength; (UINT)j < nLength;
  822.                   j += IsDBCSLeadByte(lpPathBuffer[j]) ? 2 : 1){
  823.       if( lpPathBuffer[j] == '\\' || lpPathBuffer[j] == ':' ){
  824.           i = j;
  825.       }
  826.   }
  827.   if( lpPathBuffer[i] == ':' )
  828.     lpPathBuffer[i+1] = '\0';
  829.   else
  830.     lpPathBuffer[i] = '\0';
  831.  
  832.   return( (UINT) i );
  833. }
  834.  
  835.  
  836. // ************************************************************************
  837. // FUNCTION : CopyListBoxToClipboard( HWND, LONG )
  838. // PURPOSE  : Copies the entire contents of a listbox into the clipboard.
  839. // COMMENTS : Returns TRUE on success, FALSE otherwise
  840. // ************************************************************************
  841. BOOL
  842. CopyListBoxToClipboard( HWND hWndListBox, LONG MaxStrLen )
  843. {
  844.   LPTSTR  lpDataBuffer;
  845.   HGLOBAL hDataBuffer;
  846.  
  847.   TCHAR  TempBuffer[256];
  848.   DWORD  dwItemCount;
  849.   DWORD  Count;
  850.   LONG   StrLen;
  851.   DWORD  dwMemSize;
  852.  
  853.   dwItemCount = (DWORD) SendMessage( hWndListBox, LB_GETCOUNT, 0 , 0 );
  854.   dwMemSize = dwItemCount * (DWORD) MaxStrLen;
  855.  
  856.   //-- limit the size copied to the clipboard
  857.   if( dwMemSize > 0xFFFFF )
  858.     dwMemSize = 0xFFFFF;
  859.  
  860.   if( !(hDataBuffer = GlobalAlloc( GMEM_DDESHARE, dwMemSize ) ) ) {
  861.     OutOfMemoryMessageBox( GetFocus() );
  862.     return( FALSE );
  863.   }
  864.   if( !(lpDataBuffer = (LPTSTR) GlobalLock( hDataBuffer ) ) ) {
  865.     GlobalFree( hDataBuffer );
  866.     OutOfMemoryMessageBox( GetFocus() );
  867.     return( FALSE );
  868.   }
  869.  
  870.   *lpDataBuffer = '\0';
  871.  
  872.   for( Count = 0; Count < dwItemCount; Count++ ) {
  873.     StrLen = SendMessage( hWndListBox, LB_GETTEXTLEN, Count, 0L );
  874.     if( StrLen > (sizeof(TempBuffer)-3) )
  875.       continue;
  876.     StrLen = SendMessage( hWndListBox, LB_GETTEXT, Count, (LPARAM) TempBuffer );
  877.     TempBuffer[StrLen]   = '\r';
  878.     TempBuffer[StrLen+1] = '\n';
  879.     TempBuffer[StrLen+2] = '\0';
  880.     lstrcat( lpDataBuffer, TempBuffer );
  881.   }
  882.  
  883.   GlobalUnlock( hDataBuffer );
  884.  
  885.   if( !OpenClipboard( hWndListBox ) ) {
  886.     Sleep( 250 );  // wait a quarter second and try again.
  887.     if( !OpenClipboard( hWndListBox ) ) {
  888.       MessageBox( GetFocus(),
  889.         TEXT( "Could not open the Clipboard!" ),
  890.         TEXT( "Cannot Open Clipboard" ),
  891.         MB_ICONSTOP | MB_APPLMODAL );
  892.       GlobalFree( hDataBuffer );
  893.       return( FALSE );
  894.     }
  895.   }
  896.   if( !EmptyClipboard() ) {
  897.     MessageBox( GetFocus(),
  898.       TEXT( "Could not empty the Clipboard!" ),
  899.       TEXT( "Cannot Empty Clipboard" ),
  900.       MB_ICONSTOP | MB_APPLMODAL );
  901.     GlobalFree( hDataBuffer );
  902.     return( FALSE );
  903.   }
  904.   if( !SetClipboardData( CF_TEXT, hDataBuffer ) ) {
  905.     MessageBox( GetFocus(),
  906.       TEXT( "Could not copy data to the Clipboard!" ),
  907.       TEXT( "Cannot Set Clipboard Data" ),
  908.       MB_ICONSTOP | MB_APPLMODAL );
  909.     GlobalFree( hDataBuffer );
  910.     return( FALSE );
  911.   }
  912.   CloseClipboard();
  913.  
  914.   return( TRUE );
  915. }
  916.  
  917.  
  918. // ************************************************************************
  919. // FUNCTION : ListBoxInsert( HWND, LPLONG, LPCTSTR )
  920. // PURPOSE  : Inserts the string into the listbox.
  921. // COMMENTS : Returns the index of the string inserted
  922. // ************************************************************************
  923. LONG
  924. ListBoxInsert( HWND hWndListBox, LPLONG lpMaxStrLen, LPCTSTR lpszString )
  925. {
  926.   static LONG MaxTextExtent = 0;
  927.  
  928.   LONG        Index;
  929.  
  930.   if( lpszString == NULL ) {
  931.     MaxTextExtent = 0;
  932.     SendMessage( hWndListBox, LB_SETHORIZONTALEXTENT, 0, 0 );
  933.     return( 0 );
  934.   }
  935.  
  936.   if( hWndListBox != NULL ) {
  937.     HDC  hDC;
  938.     SIZE Size;
  939.     LONG StrLen;
  940.  
  941.     if( (StrLen = lstrlen( lpszString)) > *lpMaxStrLen )
  942.       *lpMaxStrLen = StrLen;
  943.     hDC = GetDC( hWndListBox );
  944.     GetTextExtentPoint( hDC, lpszString, StrLen, &Size );
  945.     ReleaseDC( hWndListBox, hDC );
  946.     if( Size.cx > MaxTextExtent ) {
  947.       MaxTextExtent = Size.cx;
  948.       SendMessage( hWndListBox, LB_SETHORIZONTALEXTENT, (WPARAM) (MaxTextExtent*1.1), 0 );
  949.     }
  950.     Index = SendMessage( hWndListBox, LB_ADDSTRING, 0, (LPARAM) lpszString );
  951.     SendMessage( hWndListBox, LB_SETCURSEL, Index, 0 );
  952.   }
  953.  
  954.   return( Index );
  955. }
  956.  
  957.  
  958. // ************************************************************************
  959. // FUNCTION : ListBoxPrintF( HWND, LPCTSTR, ... )
  960. // PURPOSE  : Inserts the string format into the listbox.
  961. // COMMENTS : Returns the index of the last string inserted
  962. // ************************************************************************
  963. LONG
  964. ListBoxPrintF( HWND hWndListBox, LPCTSTR szFormat, ... )
  965. {
  966.   static TCHAR szBuffer[ 1024 ];
  967.  
  968.   va_list valist;
  969.   LONG    Index;
  970.   LPTSTR  lpCurrentString, lpCurrentChar;
  971.  
  972.   va_start( valist, szFormat );
  973.   wvsprintf( szBuffer, szFormat, valist );
  974.   va_end( valist );
  975.  
  976.   //-- insert strings line-by-line
  977.   for( lpCurrentString = lpCurrentChar = szBuffer; *lpCurrentChar != '\0'; ) {
  978.     if( *lpCurrentChar == '\n' ) {
  979.       LPTSTR lpNextChar = CharNext( lpCurrentChar );
  980.       *lpCurrentChar = '\0';
  981.       Index = ListBoxInsert( hWndListBox, &(Global.MaxStrLen), lpCurrentString );
  982.       lpCurrentString = lpCurrentChar = lpNextChar;
  983.     }
  984.     else
  985.       lpCurrentChar = CharNext( lpCurrentChar );
  986.   }
  987.   Index = ListBoxInsert( hWndListBox, &(Global.MaxStrLen), lpCurrentString );
  988.  
  989.   return( Index );
  990. }
  991.  
  992.  
  993. // ************************************************************************
  994. // FUNCTION : StringPrintF( LPTSTR, LPCTSTR, ... )
  995. // PURPOSE  : Formats a string buffer according to the format-control
  996. //            string.  This function is wsprintf but the return
  997. //            values is a pointer to the string instead of the count.
  998. // COMMENTS :
  999. // ************************************************************************
  1000. LPTSTR
  1001. StringPrintF( LPTSTR lpString, LPCTSTR szFormat, ...  )
  1002. {
  1003.   va_list valist;
  1004.  
  1005.   va_start( valist, szFormat );
  1006.   wvsprintf( lpString, szFormat, valist );
  1007.   va_end( valist );
  1008.  
  1009.   return( lpString );
  1010. }
  1011.  
  1012.  
  1013. // ************************************************************************
  1014. // FUNCTION : StringAppendF( LPTSTR, LPCTSTR, ... )
  1015. // PURPOSE  : Append a variable number of characters and values to the end
  1016. //            of an existing string buffer according to the format string
  1017. //            (which uses standard printf() formating notation).
  1018. // COMMENTS :
  1019. // ************************************************************************
  1020. BOOL
  1021. StringAppendF( LPTSTR lpszBuffer, LPCTSTR szFormat, ... )
  1022. {
  1023.   static TCHAR szLgBuffer[1024];
  1024.  
  1025.   va_list valist;
  1026.   int n;
  1027.  
  1028.   //-- add event specific information
  1029.   va_start( valist, szFormat );
  1030.   n = wvsprintf( szLgBuffer, szFormat, valist );
  1031.   va_end( valist );
  1032.  
  1033.   //-- append information to the string buffer
  1034.   lstrcat( lpszBuffer, szLgBuffer );
  1035.  
  1036.   return( TRUE );
  1037. }
  1038.