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

Windows编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////
  2. //
  3. // CSTEXT
  4. // A sample application that shows how to display complex scripts such
  5. // as Arabic, Hebrew, Thai, or Indic scripts.
  6. //
  7. // This sample works best if executed on a platform enabled for complex 
  8. // scripts, such as Arabic, Hebrew, or Thai Windows NT 4.0 or Windows 95,
  9. // or Windows NT 5.0 with the appropriate locale installed.
  10. //
  11. // The WndProc function puts out text typed by the user to the client area
  12. // in two ways: 1) using ExtTextOut to put out each character as it 
  13. // is typed by the user, and 2) saving each character typed in a 
  14. // buffer and putting out the whole buffer using ExtTextOut.
  15. //
  16. // If you run the program on a system that supports complex scripts, such as
  17. // Arabic, Hebrew, or Thai Windows NT, and switch the keyboard to one of 
  18. // those languages, you will see different results in the two output lines.
  19. // For example, on Arabic Windows NT, the line of characters displayed one 
  20. // by one will show only the stand-alone Arabic characters, without joining, 
  21. // and without the proper bidirectional layout. The line displayed using 
  22. // the whole buffer will be shown correctly
  23. //
  24. // Choose the help menu for guidelines on programming for complex scripts.
  25. //
  26. // Written by F. Avery Bishop, with advice from David C. W. Brown.
  27. //
  28. // Copyright (c) 1997, Microsoft Corporation. All rights reserved.
  29. //
  30. /////////////////////////////////////////////////////////////////////////
  31. #include "cstext.h"
  32. #include <stdarg.h>
  33. #include <windows.h>
  34. #include <tchar.h>
  35. #include "resource.h"
  36. #ifndef UNICODE
  37. #pragma message("Warning: This sample works best as a Unicode application")
  38. #endif
  39. // Global variables
  40. int         g_xStartOneChar = XSTART ;  // X position to display next character
  41. HINSTANCE   g_hInstance ;
  42. TCHAR       g_szTitle[MAX_MESSAGE] ;    // Title bar text
  43. // Function Prototypes, in the order defined
  44. LRESULT CALLBACK WndProc         (HWND , UINT , WPARAM , LPARAM) ;
  45. BOOL CALLBACK    EditDialogProc  (HWND , UINT , WPARAM , LPARAM) ;
  46. BOOL CALLBACK    HelpDialogProc  (HWND , UINT , WPARAM , LPARAM) ;
  47. void             InitializeFont  (HWND , LONG, LPCHOOSEFONT , LPLOGFONT) ;
  48. BOOL             InitApplication (HINSTANCE , LPTSTR) ;
  49. BOOL             InitInstance    (HINSTANCE , LPTSTR , int) ;
  50. int              RcMessageBox    (HWND , int , int , ...) ;
  51. //
  52. //   FUNCTION: WndProc (HWND, UINT, WPARAM, LPARAM)
  53. //
  54. //   PURPOSE: Window Procedure
  55. //
  56. //   COMMENTS:
  57. //          This function puts out text typed by the user to the client area
  58. //          in two ways: 1) using ExtTextOut to put out each character as it 
  59. //          is typed by the user, and 2) saving each character typed in a 
  60. //          buffer and putting out the whole buffer using ExtTextOut. 
  61. //
  62. LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  63. {
  64.     static HFONT    hTextFont ;        // Font for text typed by user
  65.     static TCHAR    szOutputBuffer[BUFFER_SIZE] ; // Buffer of characters typed
  66.     static int      nChars = 0 ;       // Current size of buffer
  67.     static RECT     rcBufferLine = {0,0,0,0} ;// Rectangle for the text to be displayed
  68.     static UINT     uiAlign = TA_LEFT ;// Alignment and reading order flag
  69.     static CHOOSEFONT cf ;             // This is static to keep last values as defaults
  70.     static LOGFONT  lf ;               // Same for this.
  71.     
  72.     PAINTSTRUCT     ps ;               // Standard paint structure
  73.     HDC             hDc ;              // HDC used in two ways. See WM_CHAR and WM_PAINT below
  74.     SIZE            sOneChar ;         // Used in GetTextExtentPoint32.
  75.     // Normally these should be in resources so they can be localized.
  76.     TCHAR           szCharLabel[] 
  77.                     = TEXT("Characters displayed one by one, as typed:") ;
  78.     TCHAR           szBuffLabel[] 
  79.                     = TEXT("All text in the line displayed in one call to ExtTextOut:") ;
  80.     TEXTMETRIC      tm ;
  81.     
  82.     int nxStartBuffer, nyStartBuffer ;  // x and y positions to display text.
  83.     int cCharWidths ;                   // Count of character widths, used in GetCharWidth32
  84.     
  85.     switch (message)
  86.     {
  87.     case WM_CREATE :
  88.         
  89.         InitializeFont (hWnd, 20, &cf, &lf) ; // Routine defined below
  90.         hTextFont = CreateFontIndirect (&lf) ;
  91.         
  92.         if (NULL == hTextFont) {
  93.             RcMessageBox (hWnd, IDS_CHOOSEFONT_FAILED, MB_ICONEXCLAMATION | MB_OK);
  94.             break ;
  95.         } ;
  96.         
  97.         return 0 ;
  98.         
  99.     case WM_CHAR :  // Process keyboard input
  100.         
  101.         switch ((TCHAR) wParam)
  102.         {
  103.         case VK_BACK :
  104.             
  105.             if (nChars > 0){
  106.                 nChars-- ;
  107.                 
  108.                 // Reset starting point for next character output
  109.                 hDc = GetDC(hWnd) ;
  110.                 SelectObject(hDc, hTextFont) ;
  111.                 GetTextExtentPoint32(hDc, szOutputBuffer, nChars, &sOneChar) ;
  112.                 ReleaseDC(hWnd, hDc) ;
  113.                 g_xStartOneChar = sOneChar.cx + XSTART;
  114.                 
  115.                 InvalidateRect (hWnd, NULL, TRUE) ;
  116.             }
  117.             break ;
  118.             
  119.         case VK_RETURN :    
  120.             
  121.             // This sample ignores return. Most apps will add CR/LF or exit.
  122.             break ;
  123.             
  124.         case VK_ESCAPE :
  125.         case VK_END :
  126.         case VK_HOME :
  127.             
  128.             // Processing other non-printable characters is left as an exercise
  129.             break ;
  130.             
  131.         default:
  132.             
  133.             // Process all normal characters
  134.             
  135.         // First use the old (incorrect) method to display only the last
  136.         // character typed
  137.         
  138.             // NOTE: This is an example of what *not* to do, because
  139.             // characters that should join or otherwise interact 
  140.             // typographically will show as separate, stand alone characters.
  141.             hDc = GetDC (hWnd) ;
  142.             SelectObject (hDc, hTextFont) ;
  143.             SetBkMode (hDc, TRANSPARENT) ;
  144.             ExtTextOut (hDc, g_xStartOneChar, YSTART, 0,
  145.                 NULL, (LPCTSTR) &wParam, 1, NULL) ;
  146.             
  147.             // Get the next character position
  148.             GetCharWidth (hDc, (UINT) wParam, (UINT) wParam, &cCharWidths) ;
  149.             // This assumes left to right scripts, so it will break on
  150.             // Arabic and Hebrew!
  151.             g_xStartOneChar += cCharWidths ; 
  152.             ReleaseDC (hWnd, hDc) ;
  153.             
  154.         // Next, display the whole buffer of all characters typed in so far
  155.             szOutputBuffer[nChars] = (TCHAR) wParam ;
  156.             if (nChars < BUFFER_SIZE-1) {
  157.                 nChars++ ;
  158.             }
  159.             // This will generate a WM_PAINT message. In the processing 
  160.             // of WM_PAINT below, we display the text buffer in the 
  161.             // rectangle rcBufferLine. This is the recommended approach.
  162.             InvalidateRect (hWnd, &rcBufferLine, TRUE) ;
  163.         }
  164.         
  165.         return 0 ;
  166.     
  167.     case WM_PAINT :
  168.         
  169.         hDc = BeginPaint (hWnd, &ps) ;
  170.         
  171.         SelectObject (hDc, hTextFont) ;
  172.         
  173.         // Get line positions for the current font
  174.         GetTextMetrics (hDc, &tm) ;
  175.         
  176.         nyStartBuffer = YSTART + 3*tm.tmHeight ;
  177.         
  178.         GetClientRect (hWnd, &rcBufferLine) ;
  179.         
  180.         rcBufferLine.top = nyStartBuffer ;
  181.         rcBufferLine.bottom = nyStartBuffer + tm.tmHeight ;
  182.         
  183.         // Set the x position for right or left aligned text
  184.         if (uiAlign & TA_RIGHT) {
  185.             nxStartBuffer = rcBufferLine.right - XSTART ;
  186.         } else {
  187.             nxStartBuffer = XSTART ;
  188.         }
  189.         
  190.         SetTextAlign (hDc, uiAlign) ;
  191.         
  192.         // Write the whole text buffer in the "character by character" rectangle
  193.         // Note how the complex script comes out right this time.
  194.         // This only happens when the whole client area is invalidated, i.e., 
  195.         // when the user types backspace, clears the buffer, or changes the 
  196.         // font, or when the window is covered and uncovered.
  197.         ExtTextOut (hDc, nxStartBuffer, YSTART, ETO_OPAQUE, 
  198.             NULL, szOutputBuffer, nChars, NULL) ;
  199.         
  200.         // Write the whole text buffer in the line buffer rectangle
  201.         // This happens every time the user enters a character, which 
  202.         // is why this line always looks right, even for complex scripts.
  203.         ExtTextOut (hDc, nxStartBuffer, nyStartBuffer, ETO_OPAQUE, 
  204.             &rcBufferLine, szOutputBuffer, nChars, NULL) ;
  205.         
  206.         // Write out labels describing the text
  207.         SelectObject(hDc, GetStockObject(ANSI_VAR_FONT)) ;
  208.         SetTextAlign(hDc, TA_LEFT) ;
  209.         GetTextMetrics (hDc, &tm) ;
  210.         
  211.         ExtTextOut (hDc, XSTART, YSTART-tm.tmHeight, ETO_OPAQUE, 
  212.             NULL, szCharLabel, lstrlen(szCharLabel), NULL) ;
  213.         ExtTextOut (hDc, XSTART, nyStartBuffer-tm.tmHeight, ETO_OPAQUE, 
  214.             NULL, szBuffLabel, lstrlen(szBuffLabel), NULL) ;
  215.         
  216.         EndPaint (hWnd, &ps) ;
  217.         
  218.         return 0 ;
  219.         
  220.     case WM_COMMAND :
  221.         
  222.         switch (LOWORD(wParam)) 
  223.         {
  224.         case IDM_EDIT_CLEAR :
  225.             // Clear the character buffer
  226.             nChars = 0 ;
  227.             
  228.             // Reset starting point for next character output
  229.             g_xStartOneChar = XSTART ;
  230.             InvalidateRect (hWnd, NULL, TRUE) ;
  231.             
  232.             break ;
  233.             
  234.         case IDM_EDITCONTROL :
  235.             // Use an edit control to enter and display text.
  236.             // This is the recommended approach, because all
  237.             // complex script processing is handled by the system.
  238.             // Complex script support is also available in the 
  239.             // Richedit control (not shown here).
  240.             DialogBox (g_hInstance, MAKEINTRESOURCE(IDD_CSSAMPLE), NULL, EditDialogProc) ;
  241.             
  242.             break ;
  243.             
  244.         case IDM_EDIT_TOGGLEALIGN :
  245.             // This aligns the text to the left or right
  246.             // edge of the client area. It is NOT the same
  247.             // as reading order.
  248.             if (uiAlign & TA_RIGHT){
  249.                 uiAlign = uiAlign & ~TA_RIGHT ;
  250.             } else {
  251.                 uiAlign = uiAlign | TA_RIGHT & ~TA_LEFT ;
  252.             }
  253.             
  254.             InvalidateRect (hWnd, NULL, TRUE) ;
  255.             
  256.             break ;
  257.             
  258.         case IDM_EDIT_TOGGLEREADING :
  259.             // This will set the reading order as LTR, as is used
  260.             // for European and Asian scripts, or RTL, the most common
  261.             // reading area in Middle Eastern scripts such as Arabic
  262.             // and Hebrew.
  263.             uiAlign ^= TA_RTLREADING ;
  264.             InvalidateRect (hWnd, NULL, TRUE) ;
  265.             
  266.             break ;
  267.             
  268.         case IDM_EDIT_SETFONT :
  269.             // Let the user change font.
  270.             ChooseFont (&cf) ;
  271.             if (hTextFont){
  272.                 DeleteObject (hTextFont) ;
  273.             }
  274.             
  275.             hTextFont = CreateFontIndirect (&lf) ;
  276.             
  277.             if (NULL == hTextFont) {
  278.                 RcMessageBox (hWnd, IDS_CHOOSEFONT_FAILED, MB_ICONEXCLAMATION | MB_OK) ;
  279.                 break ;
  280.             }
  281.             
  282.             RcMessageBox(hWnd, IDS_FONTCHANGED , MB_OK, lf.lfFaceName) ;
  283.             
  284.             // Reset starting point for next character output
  285.             hDc = GetDC(hWnd) ;
  286.             SelectObject(hDc, hTextFont) ;
  287.             GetTextExtentPoint32(hDc, szOutputBuffer, nChars, &sOneChar) ;
  288.             ReleaseDC(hWnd, hDc) ;
  289.             g_xStartOneChar = sOneChar.cx + XSTART ;
  290.             
  291.             InvalidateRect (hWnd, NULL, TRUE) ;
  292.             
  293.             break ;
  294.             
  295.         case IDM_ABOUT_HELP :
  296.             
  297.             DialogBox (g_hInstance, MAKEINTRESOURCE(IDD_HELP), NULL, HelpDialogProc) ;
  298.             
  299.             break;
  300.             
  301.         case IDM_ABOUT_ABOUT :
  302.             
  303.             DialogBox (g_hInstance, MAKEINTRESOURCE(IDD_ABOUT), NULL, HelpDialogProc);
  304.             
  305.             break ;
  306.             
  307.         case IDM_EXIT :
  308.             
  309.             DestroyWindow (hWnd) ;
  310.             
  311.             break ;
  312.             
  313.         default :
  314.             
  315.             return 0 ;  
  316.         }
  317.         
  318.         return 0 ;
  319.         
  320.         case WM_DESTROY :
  321.             
  322.             PostQuitMessage (0) ;
  323.             
  324.             return 0 ;
  325.             
  326.         default : 
  327.             return (DefWindowProc(hWnd, message, wParam, lParam)) ;
  328.    }
  329. }
  330. //
  331. //   FUNCTION: BOOL CALLBACK EditDialogProc (HWND , UINT , WPARAM , LPARAM)
  332. //
  333. //   PURPOSE: Dialog procedure for the edit control dialog box.
  334. //
  335. //   COMMENTS:
  336. //        This is standard processing for edit controls.
  337. //
  338. BOOL CALLBACK EditDialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  339. {
  340.     static HFONT        hEditFont ;
  341.     static CHOOSEFONT   cf ; 
  342.     static LOGFONT      lf ;
  343.     HWND                hWndEdit ;
  344.     
  345.     switch (uMsg)
  346.     {
  347.     case WM_INITDIALOG :
  348.         
  349.         InitializeFont (hDlg, 24, &cf, &lf) ;
  350.         hEditFont = CreateFontIndirect (&lf) ;
  351.         
  352.         // Set font of edit control
  353.         SendDlgItemMessage (hDlg, ID_EDITCONTROL, WM_SETFONT, 
  354.             (WPARAM) hEditFont,  MAKELPARAM(TRUE, 0)) ;
  355.         
  356.         return TRUE ;
  357.         
  358.     case WM_CLOSE :
  359.         
  360.         EndDialog (hDlg, wParam) ; 
  361.         
  362.         return 0 ;
  363.         
  364.     case WM_COMMAND :
  365.         
  366.         switch (wParam)
  367.         {
  368.         case IDE_EDIT_FONT :
  369.             
  370.             if (hEditFont) {
  371.                 DeleteObject (hEditFont) ;
  372.             }
  373.             
  374.             ChooseFont (&cf) ;
  375.             hEditFont = CreateFontIndirect (&lf) ;
  376.             
  377.             SendDlgItemMessage (hDlg, ID_EDITCONTROL, WM_SETFONT, 
  378.                 (WPARAM) hEditFont,  MAKELPARAM(TRUE, 0)) ;
  379.             
  380.             break ;
  381.             
  382.         case IDE_CLEAR :
  383.             
  384.             hWndEdit = GetDlgItem (hDlg, ID_EDITCONTROL) ;
  385.             SetWindowText (hWndEdit, TEXT("")) ;
  386.             
  387.             break ;
  388.             
  389.         case IDE_CLOSE :
  390.             
  391.             DeleteObject (hEditFont) ;
  392.             EndDialog (hDlg, wParam) ; 
  393.         }
  394.     }
  395.     
  396.     return FALSE ;
  397. }
  398. //
  399. //   FUNCTION: BOOL CALLBACK HelpDialogProc (HWND , UINT , WPARAM , LPARAM)
  400. //
  401. //   PURPOSE: Dialog procedure for the Help dialog box.
  402. //
  403. //   COMMENTS:
  404. //        This does nothing but close the dialog box.
  405. //
  406. BOOL CALLBACK HelpDialogProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  407. {
  408.     switch (uMsg)
  409.     {
  410.     case WM_CLOSE :
  411.         
  412.         EndDialog (hDlg, wParam) ; 
  413.         return 0 ;
  414.         
  415.     case WM_COMMAND :
  416.         
  417.         switch (wParam)
  418.         {
  419.         case IDOK :
  420.             
  421.             EndDialog (hDlg, wParam) ; 
  422.         }
  423.     }
  424.     
  425.     return FALSE ;
  426. }
  427. //
  428. //   FUNCTION: _tWinMain (HINSTANCE , HINSTANCE , LPTSTR , int)
  429. //
  430. //   PURPOSE: Standard WinMain function
  431. //
  432. //   COMMENTS:
  433. //        The prototype is _tWinMain, so it can be compiled either as
  434. //        a Unicode or an ANSI application. 
  435. //
  436. int WINAPI _tWinMain (HINSTANCE hInstance, HINSTANCE hPrev, 
  437.                       LPSTR pszCmdLine, int nCmdShow) 
  438. {
  439.     TCHAR szAppName[] = TEXT("Complex Script Display") ;
  440.     MSG msg ;
  441.     HANDLE hAccelTable ;
  442.     
  443.     // Perform application initialization:
  444.     if (!InitApplication (hInstance, szAppName)) {
  445.         return FALSE ;
  446.     }
  447.     // Perform instance initialization:
  448.     if (!InitInstance (hInstance, szAppName, nCmdShow)) {
  449.         return FALSE ;
  450.     }
  451.     
  452.     hAccelTable = LoadAccelerators (hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)) ;
  453.     
  454.     if (!hAccelTable) {
  455.         return 0 ;
  456.     }
  457.     
  458.     // Main message loop:
  459.     while (GetMessage (&msg, NULL, 0, 0)) 
  460.     {
  461.         if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
  462.             TranslateMessage (&msg) ;
  463.             DispatchMessage (&msg) ;
  464.         }
  465.     }
  466.     return 0 ;
  467. //
  468. //   FUNCTION: InitializeFont (HWND , LONG , LPCHOOSEFONT , LPLOGFONT)
  469. //
  470. //   PURPOSE:  Fills in font structures with initial values. 
  471. //
  472. //   REMARKS:  Since it contains only assignment statements, this function does no
  473. //             error checking, has no return value..
  474. //
  475. void InitializeFont (HWND hWnd, LONG lHeight, LPCHOOSEFONT lpCf, LPLOGFONT lpLf)
  476. {
  477.     lpCf->lStructSize   = sizeof (CHOOSEFONT) ;
  478.     lpCf->hwndOwner     = hWnd ;
  479.     lpCf->hDC           = NULL ;
  480.     lpCf->lpLogFont     = lpLf;
  481.     lpCf->iPointSize    = 10;
  482.     lpCf->Flags         = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT
  483.         | CF_NOSIZESEL ;
  484.     lpCf->rgbColors     = RGB (0,0,0);
  485.     lpCf->lCustData     = 0;
  486.     lpCf->lpfnHook      = NULL;
  487.     lpCf->lpTemplateName= NULL;
  488.     lpCf->hInstance     = g_hInstance;
  489.     lpCf->lpszStyle     = NULL;
  490.     lpCf->nFontType     = SIMULATED_FONTTYPE;
  491.     lpCf->nSizeMin      = 0;
  492.     lpCf->nSizeMax      = 0;
  493.     
  494.     lpLf->lfHeight      = lHeight ; 
  495.     lpLf->lfWidth       = 0 ; 
  496.     lpLf->lfEscapement  = 0 ; 
  497.     lpLf->lfOrientation = 0 ; 
  498.     lpLf->lfWeight      = FW_NORMAL ; 
  499.     lpLf->lfItalic      = FALSE ; 
  500.     lpLf->lfUnderline   = FALSE ; 
  501.     lpLf->lfStrikeOut   = FALSE ; 
  502.     lpLf->lfCharSet     = DEFAULT_CHARSET ; 
  503.     lpLf->lfOutPrecision= OUT_DEFAULT_PRECIS ; 
  504.     lpLf->lfClipPrecision = CLIP_DEFAULT_PRECIS ; 
  505.     lpLf->lfQuality     = DEFAULT_QUALITY ; 
  506.     lpLf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE ; 
  507.     lstrcpy(lpLf->lfFaceName, TEXT("Arial")) ;
  508.     lpLf->lfFaceName[LF_FACESIZE] = 0 ; 
  509. }
  510. //
  511. //   FUNCTION: InitApplication(HINSTANCE, LPTSTR)
  512. //
  513. //   PURPOSE:  Fills in window class structure with parameters that describe
  514. //   the main window, and registers the window.
  515. //
  516. BOOL InitApplication (HINSTANCE hInstance, LPTSTR szAppName)
  517. {
  518.     
  519.     WNDCLASS  wc ; 
  520.     
  521.     wc.style         = CS_HREDRAW | CS_VREDRAW ;
  522.     wc.lpfnWndProc   = (WNDPROC) WndProc ;
  523.     wc.cbClsExtra    = 0 ;
  524.     wc.cbWndExtra    = 0 ;
  525.     wc.hInstance     = hInstance ;
  526.     wc.hIcon         = LoadIcon  (NULL, IDI_APPLICATION) ; 
  527.     wc.hCursor       = LoadCursor  (NULL, IDC_ARROW) ;
  528.     wc.hbrBackground =  (HBRUSH) (COLOR_WINDOW+1) ;
  529.     wc.lpszMenuName  = MAKEINTRESOURCE (IDR_MENU1) ;
  530.     wc.lpszClassName = szAppName ;
  531.     
  532.     return  (RegisterClass(&wc)) ;
  533. }
  534. //
  535. //   FUNCTION: InitInstance (HANDLE, LPTSTR, int)
  536. //
  537. //   PURPOSE: Saves instance handle and creates main window
  538. //
  539. //   COMMENTS:
  540. //
  541. //        This function saved the instance handle in a global variable and
  542. //        created and displays the main program window.
  543. //
  544. BOOL InitInstance (HINSTANCE hInstance, LPTSTR szAppName, int nCmdShow)
  545. {
  546.     HWND hWnd ;
  547.     
  548.     g_hInstance = hInstance ; // Store instance handle in global variable
  549.     
  550.     LoadString (hInstance, IDS_TITLE, g_szTitle, MAX_MESSAGE) ;
  551.     
  552.     hWnd = CreateWindow (szAppName, g_szTitle, WS_OVERLAPPEDWINDOW,
  553.         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
  554.         NULL, NULL, hInstance, NULL) ;
  555.     
  556.     if (!hWnd) {
  557.         return FALSE ;
  558.     }
  559.     
  560.     ShowWindow (hWnd, nCmdShow) ;
  561.     UpdateWindow (hWnd) ;
  562.     
  563.     return TRUE ;
  564. }
  565. //
  566. //  Function RcMessageBox (HWND, INT, INT, ...)
  567. //
  568. //  Purpose: Display a message box with formated output similar to sprintf
  569. //
  570. //  Remarks:
  571. //      This function loads the string identified by nMessageID from the 
  572. //      resource segment, uses vsprintf to format it using the variable
  573. //      parameters, and displays it to the user in a message box using the
  574. //      icon specified by nIcons.
  575. //
  576. int RcMessageBox (HWND hWnd, int nMessageID, int nIcons, ...)
  577. {
  578.     // This can be changed to get the current lang id.
  579.     WORD wCurrentLang = MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US) ;
  580.     TCHAR szLoadBuff[MAX_MESSAGE], szOutPutBuff[3*MAX_MESSAGE] ;
  581.     va_list valArgs ;
  582.     
  583.     va_start (valArgs, nIcons) ;
  584.     
  585.     LoadString (g_hInstance, nMessageID, szLoadBuff, MAX_MESSAGE) ;
  586.     
  587.     wvsprintf (szOutPutBuff, szLoadBuff, valArgs) ;
  588.     
  589.     va_end (valArgs) ;
  590.     
  591.     return (MessageBoxEx (hWnd, szOutPutBuff, g_szTitle, nIcons, wCurrentLang)) ;
  592. }