home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / icm20 / icmview / appinit.c next >
C/C++ Source or Header  |  1997-09-07  |  20KB  |  652 lines

  1. //THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. //ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. //THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright  1994-1996  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  FILE:
  9. //    INIT.C
  10. //
  11. //  PURPOSE:
  12. //    Initializes ICMVIEW.
  13. //
  14. //  PLATFORMS:
  15. //    Windows 95, Windows NT
  16. //
  17. //  SPECIAL INSTRUCTIONS: N/A
  18. //
  19.  
  20. // Windows Header Files:
  21. // Windows Header Files:
  22. #pragma warning(disable:4001)   // Single-line comment warnings
  23. #pragma warning(disable:4115)   // Named type definition in parentheses
  24. #pragma warning(disable:4201)   // Nameless struct/union warning
  25. #pragma warning(disable:4214)   // Bit field types other than int warnings
  26. #pragma warning(disable:4514)   // Unreferenced inline function has been removed
  27.  
  28. // Windows Header Files:
  29. #include <Windows.h>
  30. #include <WindowsX.h>
  31. #include <commctrl.h>
  32. #include "icm.h"
  33.  
  34. // Restore the warnings--leave the single-line comment warning OFF
  35. #pragma warning(default:4115)   // Named type definition in parentheses
  36. #pragma warning(default:4201)   // Nameless struct/union warning
  37. #pragma warning(default:4214)   // Bit field types other than int warnings
  38.  
  39. // C RunTime Header Files
  40. #include <stdlib.h>
  41. #include <tchar.h>
  42.  
  43. // Local Header Files
  44. #include "AppInit.h"
  45. #include "icmview.h"
  46. #include "child.h"
  47. #include "DibInfo.H"
  48. #include "debug.h"
  49. #include "resource.h"
  50.  
  51.  
  52. #define RECENT_MENU         0
  53. #define RECENT_POSITION     11
  54.  
  55.  
  56. // local definitions
  57. BOOL RegisterICMViewClasses(HINSTANCE);
  58. BOOL CreateGlobalDIBInfo(void);
  59. BOOL GetSettings(LPRECT, LPDWORD, HANDLE);
  60. BOOL UpdateRecentFiles(HWND, HANDLE);
  61. int RegisterCMMProc(LPCTSTR lpszFileName);
  62.  
  63. // default settings
  64.  
  65. // external functions
  66.  
  67. // external data
  68.  
  69. // public data
  70.  
  71. // private data
  72.  
  73. //
  74. // Public functions
  75. //
  76.  
  77. //////////////////////////////////////////////////////////////////////////
  78. //  Function:  InitApplication
  79. //
  80. //  Description:
  81. //    Initializes window data and registers window class.
  82. //
  83. //  Parameters:
  84. //    HINSTANCE   Instance handle.
  85. //
  86. //  Returns:
  87. //    BOOL    Success indicator
  88. //
  89. //  Comments:
  90. //
  91. //
  92. //////////////////////////////////////////////////////////////////////////
  93. BOOL  InitApplication(HINSTANCE hInstance)
  94. {
  95.     //  Initialize variables
  96.     SetLastError(0);
  97.  
  98.     return RegisterICMViewClasses(hInstance);
  99. }   // End of function InitApplication
  100.  
  101.  
  102. //////////////////////////////////////////////////////////////////////////
  103. //  Function:  InitInstance
  104. //
  105. //  Description:
  106. //    Initializes this instance and saves an instance handle.
  107. //
  108. //  Parameters:
  109. //    HINSTANCE Instance handle
  110. //    int       Integer identifying initial display mode@@@
  111. //
  112. //  Returns:
  113. //    BOOL    Success indicator.
  114. //
  115. //  Comments:
  116. //
  117. //
  118. //////////////////////////////////////////////////////////////////////////
  119. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  120. {
  121.     // Local variables
  122.     HDC       hDisplay = GetDC(NULL);
  123.     int       nScreenWidth = GetDeviceCaps(hDisplay, HORZRES);
  124.     int       nScreenHeight = GetDeviceCaps(hDisplay, VERTRES);
  125.     HWND      hWnd;
  126.     RECT      rCoord;
  127.     DWORD     dwFlags = 0L;
  128.     HANDLE    hRecent = NULL;
  129.     DWORD     dwPathSize;
  130.  
  131.     // No longer need display DC.
  132.     if (hDisplay)
  133.         ReleaseDC(NULL, hDisplay);
  134.  
  135.     //  Initialize variables
  136.     ghInst = hInstance; // Store instance handle in our global variable
  137.  
  138.     // Get stored coordinates from last run.
  139.     GetSettings(&rCoord, &dwFlags, &hRecent);
  140.     if ( ((rCoord.left + rCoord.right)/2 < 0)
  141.          ||
  142.          ((rCoord.left + rCoord.right)/2 > nScreenWidth)
  143.          ||
  144.          ((rCoord.top + rCoord.bottom)/2 < 0)
  145.          ||
  146.          ((rCoord.top + rCoord.bottom)/2 > nScreenHeight)
  147.          ||
  148.          ( (double)(rCoord.right - rCoord.left)/(double)(nScreenHeight) * 1.1
  149.            >= (double)(nScreenWidth)/(double)(rCoord.bottom - rCoord.top) )
  150.        )
  151.     {
  152.         SetRect(&rCoord, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT);
  153.     }
  154.     else
  155.     {
  156.         // Set right and bottom to width and height.
  157.         rCoord.right -= rCoord.left;
  158.         rCoord.bottom -= rCoord.top;
  159.     }
  160.  
  161.     // Create the window using stored coordinates.
  162.     _tcscpy(gstTitle, APPNAME);
  163.     hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, APPNAME, gstTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  164.                           rCoord.left, rCoord.top, rCoord.right, rCoord.bottom, NULL, NULL, hInstance, NULL);
  165.  
  166.     if (!hWnd)  // Couldn't create main window, exit w/FAILURE code
  167.     {
  168.         DebugMsg(__TEXT("InitInstance:  CreateWindow failed.\r\n"));
  169.         return (FALSE);
  170.     }
  171.     ghAppWnd = hWnd;  // Save main application window handle
  172.  
  173.     // Attach recent files to main window and display them.
  174.     SetProp(hWnd, APP_RECENT, hRecent);
  175.     UpdateRecentFiles(hWnd, hRecent);
  176.  
  177.     // Store profiles directory
  178.     dwPathSize = MAX_PATH;
  179.     GetColorDirectory(NULL, gstProfilesDir, &dwPathSize);
  180.  
  181.     if (!CreateGlobalDIBInfo())
  182.     {
  183.         DebugMsg(__TEXT("InitInstance:  CreateGlobalDIBInfo failed\r\n"));
  184.         return(FALSE);
  185.     }
  186.     InitCommonControls();
  187.  
  188.     // Figure out how the window should be shown.
  189.     if ((SW_NORMAL == nCmdShow) && (IVF_MAXIMIZED & dwFlags))
  190.     {
  191.         nCmdShow = SW_MAXIMIZE;
  192.     }
  193.  
  194.     // Show window.
  195.     ShowWindow(hWnd, nCmdShow);
  196.     UpdateWindow(hWnd);
  197.  
  198.     return (TRUE);
  199. }   // End of function InitInstance
  200.  
  201. //
  202. // Private functions
  203. //
  204.  
  205. //////////////////////////////////////////////////////////////////////////
  206. //  Function:  RegisterICMViewClasses
  207. //
  208. //  Description:
  209. //    Registers the window class
  210. //
  211. //  Parameters:
  212. //    @@@
  213. //
  214. //  Returns:
  215. //    BOOL
  216. //
  217. //  Comments:
  218. //    This function and its usage is only necessary if you want this code
  219. //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
  220. //    function that was added to Windows 95. It is important to call this
  221. //    function so that the application will get 'well formed' small icons
  222. //    associated with it.
  223. //
  224. //////////////////////////////////////////////////////////////////////////
  225. BOOL RegisterICMViewClasses(HINSTANCE hInstance)
  226. {
  227.     // Local variables
  228.     BOOL          bAppClass, bChildClass;   // Booleans indicate if classes registered successfully
  229.     WNDCLASSEX    wcex;
  230.  
  231.     //  Initialize variables
  232.     bAppClass = bChildClass = FALSE;
  233.     wcex.style         = 0;
  234.     wcex.lpfnWndProc   = (WNDPROC)WndProc;
  235.     wcex.cbClsExtra    = 0;
  236.     wcex.cbWndExtra    = ICMVIEW_CBWNDEXTRA;
  237.     wcex.hInstance     = hInstance;
  238.     wcex.hIcon         = LoadIcon (hInstance, APPNAME);
  239.     wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
  240.     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  241.  
  242.     // Set menu depending upon Operating System
  243.     wcex.lpszMenuName = APPNAME;
  244.     wcex.lpszClassName = APPNAME;
  245.  
  246.     // Added elements for Windows 95:
  247.     wcex.cbSize = sizeof(WNDCLASSEX);
  248.     wcex.hIconSm = LoadIcon(wcex.hInstance, __TEXT("SMALL"));
  249.  
  250.     // Register App Class
  251.     bAppClass = RegisterClassEx(&wcex);
  252.  
  253.     if (bAppClass)
  254.     {
  255.         // Register the child class
  256.         wcex.style         = CS_SAVEBITS;
  257.         wcex.lpfnWndProc   = ChildWndProc;
  258.         wcex.lpszMenuName  = (LPCTSTR)NULL;
  259.         wcex.cbWndExtra    = CHILD_CBWNDEXTRA;
  260.         wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  261.         wcex.lpszClassName = CHILD_CLASSNAME;
  262.         wcex.hIcon         = NULL;
  263.         bChildClass = RegisterClassEx(&wcex);
  264.     }
  265.     return    (   bAppClass    &&    bChildClass);
  266. }   // End of function RegisterICMViewClasses
  267.  
  268. //////////////////////////////////////////////////////////////////////////
  269. //  Function:  CreateGlobalDIBInfo
  270. //
  271. //  Description:
  272. //    Creates and initializes the DIBINFO structure for the global ICMVIEW application window.
  273. //
  274. //  Parameters:
  275. //    @@@
  276. //
  277. //  Returns:
  278. //    BOOL
  279. //
  280. //  Comments:
  281. //
  282. //
  283. //////////////////////////////////////////////////////////////////////////
  284. BOOL CreateGlobalDIBInfo(void)
  285. {
  286.     // Local variables
  287.     HGLOBAL     hDIBInfo;
  288.     LPDIBINFO   lpDIBInfo;
  289.  
  290.     //  Initialize variables
  291.     hDIBInfo = CreateDIBInfo();
  292.     if (NULL == hDIBInfo)
  293.     {
  294.         DebugMsg(__TEXT("CreateGlobalDIBInfo:  CreateDIBInfo failed.\r\n"));
  295.         return(FALSE);
  296.     }
  297.     lpDIBInfo = GlobalLock(hDIBInfo);
  298.     lpDIBInfo->hWndOwner = ghAppWnd;
  299.     GlobalUnlock(hDIBInfo);
  300.     SetWindowLong(ghAppWnd, GWL_DIBINFO, (LONG)hDIBInfo);
  301.     GetDefaultICMInfo();
  302.     return(TRUE);
  303. }   // End of function CreateGlobalDIBInfo
  304.  
  305.  
  306. //////////////////////////////////////////////////////////////////////////
  307. //  Function:  GetSettings
  308. //
  309. //  Description:
  310. //    Grabs stored settings from registry.
  311. //
  312. //  Parameters:
  313. //    lpRect    Pointer to rect of window position and size.
  314. //    phRecent  Pointer to handle of an array of most recent files.
  315. //
  316. //  Returns:
  317. //    BOOL
  318. //
  319. //  Comments:
  320. //
  321. //
  322. //////////////////////////////////////////////////////////////////////////
  323. BOOL GetSettings(LPRECT lpRect, LPDWORD pdwFlags, LPHANDLE phRecent)
  324. {
  325.     HKEY    hKey;
  326.     LONG    lResult;
  327.     DWORD   dwSize;
  328.     DWORD   dwType;
  329.  
  330.  
  331.     // Initialize coordinates and recent file list in case we fail.
  332.     if (NULL != phRecent)
  333.     {
  334.         // Free and re-allocate.
  335.         if (NULL != *phRecent)
  336.         {
  337.             GlobalFree(*phRecent);
  338.         }
  339.  
  340.         // Allocate string table.
  341.         *phRecent = GlobalAlloc(GHND, (sizeof(LPTSTR) + MAX_PATH * sizeof(TCHAR)) * MAX_RECENT);
  342.     }
  343.     if (NULL != lpRect)
  344.     {
  345.         SetRect(lpRect, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT);
  346.     }
  347.  
  348.     // Open top level registry to application settings.
  349.     lResult = RegOpenKeyEx(HKEY_CURRENT_USER, APP_REG, 0L, KEY_ALL_ACCESS, &hKey);
  350.     if (ERROR_SUCCESS == lResult)
  351.     {
  352.         // INVARIANT:  Application registry key exists.
  353.         // If lpRect is non-null, attempt to get the stored window coord.
  354.         if (NULL != lpRect)
  355.         {
  356.             dwSize = sizeof(RECT);
  357.             RegQueryValueEx(hKey, APP_COORD, NULL, &dwType, (LPBYTE)lpRect, &dwSize);
  358.         }
  359.  
  360.         // Get stored state flags.
  361.         dwSize = sizeof(DWORD);
  362.         RegQueryValueEx(hKey, APP_FLAGS, NULL, &dwType, (LPBYTE)pdwFlags, &dwSize);
  363.  
  364.         // If ppszRecent is non-null, attempt to get the stored recent file list.
  365.         if (NULL != phRecent)
  366.         {
  367.             TCHAR    szReg[32];
  368.             DWORD   dwCount;
  369.             LPTSTR  *ppszRecent;
  370.  
  371.             // Make sure alloc succeded from above.
  372.             if (NULL == *phRecent)
  373.             {
  374.                 RegCloseKey(hKey);
  375.                 return FALSE;
  376.             }
  377.             ppszRecent = (LPTSTR*)GlobalLock(*phRecent);
  378.  
  379.             // Get each of the recent files.
  380.             for (dwCount = 0; dwCount < MAX_RECENT; dwCount++)
  381.             {
  382.                 // Build the key name to the nth recent file.
  383.                 wsprintf(szReg, __TEXT("%s%d"), APP_RECENT, dwCount);
  384.  
  385.                 // Get the size of the recent file string.
  386.                 dwSize = 0;
  387.                 lResult = RegQueryValueEx(hKey, szReg, NULL, &dwType, NULL, &dwSize);
  388.  
  389.                 // Alloc the string and attempt to get the recent file.
  390.                 if ((ERROR_SUCCESS == lResult) && (0 != dwSize))
  391.                 {
  392.                     ASSERT(dwSize <= MAX_PATH);
  393.                     ppszRecent[dwCount] = (LPTSTR) ((LPBYTE)(ppszRecent + MAX_RECENT) + MAX_PATH
  394.                                                     * sizeof(TCHAR) * dwCount);
  395.                     if (NULL != ppszRecent[dwCount])
  396.                     {
  397.                         RegQueryValueEx(hKey, szReg, NULL, &dwType, (LPBYTE)ppszRecent[dwCount], &dwSize);
  398.                     }
  399.                 }
  400.             }
  401.         }
  402.         RegCloseKey(hKey);
  403.         GlobalUnlock(*phRecent);
  404.     }
  405.     return TRUE;
  406. }
  407.  
  408.  
  409. //////////////////////////////////////////////////////////////////////////
  410. //  Function:  SetSettings
  411. //
  412. //  Description:
  413. //    Store settings into registry.
  414. //
  415. //  Parameters:
  416. //    lpRect          Pointer to rect of window position and size.
  417. //    ppszRecent      Pointer to an array of most recent files.
  418. //
  419. //  Returns:
  420. //    BOOL
  421. //
  422. //  Comments:
  423. //
  424. //
  425. //////////////////////////////////////////////////////////////////////////
  426. BOOL SetSettings(LPRECT lpRect, DWORD dwFlags, HANDLE hRecent)
  427. {
  428.     HKEY    hKey;
  429.     LONG    lResult;
  430.     DWORD   dwType;
  431.     LPTSTR  *ppszRecent = NULL;
  432.  
  433.     // Open top level registry to application settings.
  434.     lResult = RegCreateKeyEx(HKEY_CURRENT_USER, APP_REG, 0L, NULL,
  435.                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  436.                              &hKey, &dwType);
  437.     if (ERROR_SUCCESS == lResult)
  438.     {
  439.         // INVARIANT:  Application registry key exists or has been created.
  440.         // If lpRect is non-null, attempt to store the window coord.
  441.         if (NULL != lpRect)
  442.         {
  443.             RegSetValueEx(hKey, APP_COORD, 0, REG_BINARY, (LPBYTE)lpRect, sizeof(RECT));
  444.         }
  445.  
  446.         // Store ICMView state flags.
  447.         RegSetValueEx(hKey, APP_FLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
  448.  
  449.         // If ppszRecent is non-null, attempt to store recent file list.
  450.         if (NULL != hRecent)
  451.         {
  452.             ppszRecent = (LPTSTR*) GlobalLock(hRecent);
  453.         }
  454.         if (NULL != ppszRecent)
  455.         {
  456.             TCHAR    szReg[32];
  457.             DWORD   dwCount;
  458.  
  459.  
  460.             // Set each of the recent files.
  461.             for (dwCount = 0; dwCount < MAX_RECENT; dwCount++)
  462.             {
  463.                 // Build the key name to the nth recent file.
  464.                 wsprintf(szReg, __TEXT("%s%d"), APP_RECENT, dwCount);
  465.  
  466.                 // Set the the recent file string.
  467.                 if (NULL != ppszRecent[dwCount])
  468.                 {
  469.                     RegSetValueEx(hKey, szReg, 0, REG_SZ, (LPBYTE)ppszRecent[dwCount],
  470.                                   lstrlen(ppszRecent[dwCount]) * sizeof(TCHAR) );
  471.                 }
  472.             }
  473.             GlobalUnlock(hRecent);
  474.         }
  475.         RegCloseKey(hKey);
  476.     }
  477.     return TRUE;
  478. }
  479.  
  480.  
  481. //////////////////////////////////////////////////////////////////////////
  482. //  Function:  AddRecentFile
  483. //
  484. //  Description:
  485. //    Adds and displays recent file strins.
  486. //
  487. //  Parameters:
  488. //    hWnd                    Window that was menu and prop for recent file list.
  489. //    lpszFileName    File name string to add to recent files list.
  490. //
  491. //  Returns:
  492. //    BOOL
  493. //
  494. //  Comments:
  495. //
  496. //
  497. //////////////////////////////////////////////////////////////////////////
  498. BOOL AddRecentFile(HWND hWnd, LPTSTR lpszFileName)
  499. {
  500.     int             nFind;
  501.     int             nCount;
  502.     HANDLE  hRecent;
  503.     LPTSTR  *ppszRecent;
  504.  
  505.     // Make sure valid paramters.
  506.     if (!IsWindow(hWnd) || (NULL == lpszFileName) ||(lstrlen(lpszFileName) == 0))
  507.     {
  508.         return FALSE;
  509.     }
  510.  
  511.     // Get Recent file list.
  512.     hRecent = GetProp(hWnd, APP_RECENT);
  513.     if (NULL == hRecent)
  514.     {
  515.         return FALSE;
  516.     }
  517.  
  518.     // Get pointer to string array.
  519.     ppszRecent = (LPTSTR*) GlobalLock(hRecent);
  520.     ASSERT(ppszRecent != NULL);
  521.  
  522.     // Search array for an occurence of the string
  523.     // we are adding.
  524.     for (nFind = 0; (nFind < MAX_RECENT) && (NULL != ppszRecent[nFind])
  525.         && lstrcmpi(ppszRecent[nFind], lpszFileName); nFind++);
  526.  
  527.     // Make sure that nFind element is valid string.
  528.     // nFind - 1 should be non null or not indexed.
  529.     if ( (nFind < MAX_RECENT) && (NULL == ppszRecent[nFind]))
  530.     {
  531.         ppszRecent[nFind] = (LPTSTR)((LPBYTE)(ppszRecent + MAX_RECENT) + MAX_PATH * sizeof(TCHAR) * nFind);
  532.     }
  533.  
  534.     // Move strings from nFind to zero down one to make room
  535.     // to add string to top of list.
  536.     for (nCount = __min(nFind, MAX_RECENT -1); nCount > 0; nCount--)
  537.         _tcscpy(ppszRecent[nCount], ppszRecent[nCount -1]);
  538.  
  539.     // Add file to first position.
  540.     _tcscpy(ppszRecent[0], lpszFileName);
  541.  
  542.     // Unlock array.
  543.     GlobalUnlock(hRecent);
  544.  
  545.     // Display strings.
  546.     UpdateRecentFiles(hWnd, hRecent);
  547.  
  548.     return TRUE;
  549. }
  550.  
  551.  
  552. //////////////////////////////////////////////////////////////////////////
  553. //  Function:  UpdateRecentFiles
  554. //
  555. //  Description:
  556. //    Displays recent files.
  557. //
  558. //  Parameters:
  559. //
  560. //    hWnd            Window that was menu and prop for recent file list.
  561. //    hRecent         Handle to an array of most recent files.
  562. //
  563. //  Returns:
  564. //    BOOL
  565. //
  566. //  Comments:
  567. //
  568. //
  569. //////////////////////////////////////////////////////////////////////////
  570.  
  571. BOOL UpdateRecentFiles(HWND hWnd, HANDLE hRecent)
  572. {
  573.     int                    nMenuAdjust;
  574.     int                    nCount;
  575.     TCHAR                  szTemp[MAX_PATH + 4];
  576.     HWND                   hwndActiveChild;
  577.     HMENU                  hMenu;
  578.     LPTSTR                 *ppszRecent;
  579.     MENUITEMINFO          ItemInfo;
  580.  
  581.     // Validate paramters.
  582.     if ( !IsWindow(hWnd) || (NULL == hRecent) )
  583.     {
  584.         return FALSE;
  585.     }
  586.  
  587.     // Get current active MDI window and check to see
  588.     // if it is maximized.  Need to add 1 to menu if it
  589.     // is maximized.
  590.     hwndActiveChild = GetCurrentMDIWnd();
  591.     nMenuAdjust = 0;
  592.     if (IsZoomed(hwndActiveChild))
  593.     {
  594.         nMenuAdjust = 1;
  595.     }
  596.  
  597.     // Get file menu.
  598.     hMenu = GetMenu(hWnd);
  599.     ASSERT(hMenu != NULL);
  600.     hMenu = GetSubMenu(hMenu, RECENT_MENU + nMenuAdjust);
  601.     ASSERT(hMenu != NULL);
  602.     ASSERT(GetMenuItemCount(hMenu) > RECENT_POSITION);
  603.  
  604.     // Get pointer to recent file array.
  605.     ppszRecent = (LPTSTR*) GlobalLock(hRecent);
  606.     ASSERT(ppszRecent != NULL);
  607.  
  608.     // Add each string in recent file list to menu.
  609.     // Replace menu items until separator, then insert them.
  610.     for (nCount = 0; nCount < MAX_RECENT; nCount++)
  611.     {
  612.         // Only add strings that are not null or zero length.
  613.         if ( (NULL != ppszRecent[nCount]) && (lstrlen(ppszRecent[nCount]) != 0) )
  614.         {
  615.             // Build recent file menu string.
  616.             wsprintf(szTemp, __TEXT("&%d %s"), nCount +1, ppszRecent[nCount]);
  617.  
  618.             // Determine if replacing item or inserting.
  619.             memset(&ItemInfo, 0, sizeof(MENUITEMINFO));
  620.             ItemInfo.cbSize = sizeof(MENUITEMINFO);
  621.             ItemInfo.fMask = MIIM_TYPE;
  622.             GetMenuItemInfo(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
  623.             if (MFT_SEPARATOR == ItemInfo.fType)
  624.             {
  625.                 // Insert item. MIIM_ID
  626.                 ItemInfo.fMask = MIIM_TYPE | MIIM_ID;
  627.                 ItemInfo.wID = IDM_FILE_RECENT + nCount;
  628.                 ItemInfo.fType = MFT_STRING;
  629.                 ItemInfo.dwTypeData = szTemp;
  630.                 ItemInfo.cch = lstrlen(ItemInfo.dwTypeData);
  631.                 InsertMenuItem(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
  632.             }
  633.             else
  634.             {
  635.                 // Replace menu item.
  636.                 ItemInfo.fMask = MIIM_TYPE | MIIM_STATE;
  637.                 ItemInfo.fState = MFS_ENABLED;
  638.                 ItemInfo.fType = MFT_STRING;
  639.                 ItemInfo.dwTypeData = szTemp;
  640.                 ItemInfo.cch = lstrlen(ItemInfo.dwTypeData);
  641.                 SetMenuItemInfo(hMenu, RECENT_POSITION + nCount, TRUE, &ItemInfo);
  642.             }
  643.         }
  644.     }
  645.  
  646.     // Unlock recent array.
  647.     GlobalUnlock(hRecent);
  648.     return TRUE;
  649. }
  650.  
  651.  
  652.