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 / icmview.c < prev    next >
C/C++ Source or Header  |  1997-09-07  |  27KB  |  807 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-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  FILE:
  9. //    ICMVIEW.C
  10. //
  11. //  PURPOSE:
  12. //
  13. //
  14. //  PLATFORMS:
  15. //    Windows 95, Windows NT
  16. //
  17. //  SPECIAL INSTRUCTIONS: N/A
  18. //
  19.  
  20. // Windows Header Files:
  21. #pragma warning(disable:4001)   // Single-line comment warnings
  22. #pragma warning(disable:4115)   // Named type definition in parentheses
  23. #pragma warning(disable:4201)   // Nameless struct/union warning
  24. #pragma warning(disable:4214)   // Bit field types other than int warnings
  25. #pragma warning(disable:4514)   // Unreferenced inline function has been removed
  26.  
  27. // Windows Header Files:
  28. #include <Windows.h>
  29. #include <WindowsX.h>
  30. #include "icm.h"
  31.  
  32. // Restore the warnings--leave the single-line comment warning OFF
  33. #pragma warning(default:4115)   // Named type definition in parentheses
  34. #pragma warning(default:4201)   // Nameless struct/union warning
  35. #pragma warning(default:4214)   // Bit field types other than int warnings
  36.  
  37. // C RunTime Header Files
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <malloc.h>
  41. #include <memory.h>
  42. #include <tchar.h>
  43.  
  44. // Local Header Files
  45. #include "Resource.h"
  46.  
  47. #define   ICMVIEW_INTERNAL
  48. #include "ICMView.h"
  49. #undef    ICMVIEW_INTERNAL
  50.  
  51. #include "Print.H"
  52. #include "DibInfo.H"
  53. #include "Dialogs.H"
  54. #include "AppInit.H"
  55. #include "child.h"
  56. #include "Debug.h"
  57.  
  58.  
  59. // Global Variables:
  60. HINSTANCE   ghInst;                         // Global instance handle
  61. TCHAR       gstTitle[MAX_STRING];           // The title bar text
  62. HWND        ghAppWnd;                       // Handle to application window
  63. HWND        ghWndMDIClient;
  64. DWORD       gdwLastError;                   // Used to track last error value
  65. TCHAR       gstProfilesDir[MAX_PATH];       // System directory for ICM profiles
  66.  
  67. // Foward declarations of functions included in this code module:
  68. LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  69.  
  70. //
  71. //  FUNCTION: WinMain(HANDLE, HANDLE, LPTSTR, int)
  72. //
  73. //  PURPOSE: Entry point for the application.
  74. //
  75. //  COMMENTS:
  76. //
  77. //      This function initializes the application and processes the
  78. //      message loop.
  79. //
  80. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  81. {
  82.     MSG msg;
  83.     HANDLE hAccelTable;
  84.  
  85.     if (!hPrevInstance)
  86.     {
  87.         // Perform instance initialization:
  88.         if (!InitApplication(hInstance))
  89.         {
  90.             return (FALSE);
  91.         }
  92.     }
  93.  
  94.     // Perform application initialization:
  95.     if (!InitInstance(hInstance, nCmdShow))
  96.     {
  97.         return (FALSE);
  98.     }
  99.  
  100.     hAccelTable = LoadAccelerators (hInstance, APPNAME);
  101.     ASSERT(hAccelTable);
  102.  
  103.     // Main message loop:
  104.     while (GetMessage(&msg, NULL, 0, 0))
  105.     {
  106.         if ((!TranslateMDISysAccel (ghWndMDIClient, &msg))
  107.             && (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)))
  108.         {
  109.             TranslateMessage(&msg);
  110.             DispatchMessage(&msg);
  111.         }
  112.     }
  113.     return (msg.wParam);
  114.     lpCmdLine; // This will prevent 'unused formal parameter' warnings
  115. }
  116.  
  117. //
  118. //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
  119. //
  120. //  PURPOSE:  Processes messages for the main window.
  121. //
  122. //  MESSAGES:
  123. //
  124. //      WM_COMMAND - process the application menu
  125. //      WM_PAINT - Paint the main window
  126. //      WM_DESTROY - post a quit message and return
  127. //      WM_DISPLAYCHANGE - message sent to Plug & Play systems when the display changes
  128. //      WM_RBUTTONDOWN - Right mouse click -- put up context menu here if appropriate
  129. //      WM_NCRBUTTONUP - User has clicked the right button on the application's system menu
  130. //
  131. //
  132. LRESULT CALLBACK WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
  133. {
  134.     int         wmId, wmEvent;
  135.     POINT       pnt;
  136.     HMENU       hMenu;
  137.     int         iDlg;
  138.  
  139.     // Init variables
  140.     iDlg = 0;
  141.  
  142.     switch (uiMsg)
  143.     {
  144.  
  145.         case WM_INITMENUPOPUP:
  146.             InitImageMenu(hwnd);
  147.             break;
  148.  
  149.         case WM_CREATE:
  150.             {
  151.                 CLIENTCREATESTRUCT ccs;
  152.  
  153.                 // Find window menu where children will be listed
  154.                 ccs.hWindowMenu  = GetSubMenu (GetMenu (hwnd), WINDOWMENU_POS);
  155.                 ccs.idFirstChild = FIRSTCHILD;
  156.  
  157.                 // Create the MDI client window, which will fill the client area
  158.                 ghWndMDIClient = CreateWindow (
  159.                                               __TEXT("MDICLIENT"),
  160.                                               NULL,
  161.                                               WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
  162.                                               0,
  163.                                               0,
  164.                                               0,
  165.                                               0,
  166.                                               hwnd,
  167.                                               (HMENU) 0xCAC,
  168.                                               ghInst,
  169.                                               (LPTSTR)&ccs);
  170.  
  171.                 ShowWindow (ghWndMDIClient, SW_SHOW);
  172.                 break;
  173.             }
  174.  
  175.         case WM_COMMAND:
  176.             wmId    = LOWORD(wParam); // Remember, these are...
  177.             wmEvent = HIWORD(wParam); // ...different for Win32!
  178.  
  179.             //Parse the menu selections:
  180.             switch (wmId)
  181.             {
  182.                 case IDM_HELP_ABOUT:
  183.                     DialogBox(ghInst, __TEXT("AboutBox"), hwnd, (DLGPROC)About);
  184.                     break;
  185.  
  186.                 case IDM_FILE_EXIT:
  187.                     DestroyWindow (hwnd);
  188.                     break;
  189.  
  190.                 case IDM_FILE_OPEN:
  191.                     fOpenNewImage(hwnd, NULL);
  192.                     break;
  193.  
  194.                 case IDM_WINDOW_CASCADE:
  195.                     SendMessage(ghWndMDIClient, WM_MDICASCADE, 0, 0);;
  196.                     break;
  197.  
  198.                 case IDM_WINDOW_TILE_HORIZONTAL:
  199.                     SendMessage(ghWndMDIClient, WM_MDITILE, (WPARAM)MDITILE_HORIZONTAL, 0);;
  200.                     break;
  201.  
  202.                 case IDM_WINDOW_TILE_VERTICAL:
  203.                     SendMessage(ghWndMDIClient, WM_MDITILE, (WPARAM)MDITILE_VERTICAL, 0);;
  204.                     break;
  205.  
  206.                 case IDM_WINDOW_ARRANGE:
  207.                     SendMessage(ghWndMDIClient, WM_MDIICONARRANGE, 0, 0);
  208.                     break;
  209.  
  210.                 case IDM_FILE_RECENT:
  211.                 case IDM_FILE_RECENT1:
  212.                 case IDM_FILE_RECENT2:
  213.                 case IDM_FILE_RECENT3:
  214.                     {
  215.                         HANDLE  hRecent;
  216.                         LPTSTR  *ppszRecent;
  217.                         LPTSTR  lpszFileName;
  218.  
  219.                         // Get handle to recent file list table.
  220.                         hRecent = GetProp(hwnd, APP_RECENT);
  221.                         if (NULL != hRecent)
  222.                         {
  223.                             // Get pointer to recent file array.
  224.                             ppszRecent = (LPTSTR*) GlobalLock(hRecent);
  225.                             ASSERT(NULL != ppszRecent);
  226.  
  227.                             // Copy file name into buffer.
  228.                             lpszFileName = GlobalAlloc(GPTR,(lstrlen(ppszRecent[ wmId - IDM_FILE_RECENT]) +1) * sizeof(TCHAR));
  229.  
  230.                             // Open the file.
  231.                             if (lpszFileName != NULL)
  232.                             {
  233.                                 // Copy recent file name to file name buffer.
  234.                                 _tcscpy(lpszFileName, ppszRecent[ wmId - IDM_FILE_RECENT]);
  235.                                 GlobalUnlock(hRecent);
  236.  
  237.                                 // Open new image of recent file.
  238.                                 fOpenNewImage(hwnd, lpszFileName);
  239.                             }
  240.                         }
  241.                     }
  242.                     break;
  243.  
  244.                 default:
  245.                     {
  246.                         HWND  hwndActiveChild;
  247.  
  248.                         hwndActiveChild = GetCurrentMDIWnd();
  249.                         ASSERT(hwndActiveChild != NULL);
  250.                         if (hwndActiveChild)
  251.                         {
  252.                             PostMessage(hwndActiveChild, uiMsg, wmId, wmEvent);
  253.                         }
  254.                         break;
  255.                     }
  256.             }
  257.             break;
  258.  
  259.         case WM_RBUTTONDOWN: // RightClick in windows client area...
  260.             pnt.x = LOWORD(lParam);
  261.             pnt.y = HIWORD(lParam);
  262.             ClientToScreen(hwnd, (LPPOINT) &pnt);
  263.             hMenu = GetSubMenu (GetMenu (hwnd), 2);
  264.             if (hMenu)
  265.             {
  266.                 TrackPopupMenu (hMenu, 0, pnt.x, pnt.y, 0, hwnd, NULL);
  267.             }
  268.             else  // Couldn't find the menu...
  269.             {
  270.                 MessageBeep(0);
  271.             }
  272.             break;
  273.  
  274.         case WM_DISPLAYCHANGE: // Only comes through on plug'n'play systems
  275.             {
  276.                 SIZE szScreen;
  277.                 BOOL fChanged = (BOOL)wParam;
  278.  
  279.                 szScreen.cx = LOWORD(lParam);
  280.                 szScreen.cy = HIWORD(lParam);
  281.             }
  282.             break;
  283.  
  284.         case WM_CLOSE:
  285.             DestroyWindow(hwnd);
  286.             return 1L;
  287.  
  288.         case WM_DESTROY:
  289.             {
  290.                 DWORD             dwFlags = 0L;
  291.                 HANDLE            hRecent;
  292.                 WINDOWPLACEMENT   WndPlacement;
  293.  
  294.                 // Store application settings.
  295.                 dwFlags |= IsZoomed(hwnd) ? IVF_MAXIMIZED : 0L;
  296.                 WndPlacement.length = sizeof(WINDOWPLACEMENT);
  297.                 GetWindowPlacement(hwnd, &WndPlacement);
  298.                 hRecent = GetProp(hwnd, APP_RECENT);
  299.                 SetSettings(&WndPlacement.rcNormalPosition, dwFlags, hRecent);
  300.  
  301.                 // Remove recent file attachment and free memory.
  302.                 RemoveProp(hwnd, APP_RECENT);
  303.                 GlobalFree(hRecent);
  304.             }
  305.             PostQuitMessage(0);
  306.             break;
  307.  
  308.         case WM_QUERYNEWPALETTE:
  309.             {
  310.                 HWND hwndActive;
  311.  
  312.                 hwndActive = GetCurrentMDIWnd();
  313.                 if (NULL != hwndActive)
  314.                 {
  315.                     return SendMessage(hwndActive, MYWM_QUERYNEWPALETTE, (WPARAM) hwnd, 0L);
  316.                 }
  317.                 return FALSE;
  318.             }
  319.  
  320.         case WM_SIZE:
  321.             InvalidateRect(hwnd, NULL, TRUE);
  322.             break;
  323.     }
  324.     return DefFrameProc(hwnd,ghWndMDIClient, uiMsg, wParam, lParam);
  325. }
  326.  
  327. //
  328. //  FUNCTION: About(HWND, unsigned, WORD, LONG)
  329. //
  330. //  PURPOSE:  Processes messages for "About" dialog box
  331. //              This version allows greater flexibility over the contents of the 'About' box,
  332. //              by pulling out values from the 'Version' resource.
  333. //
  334. //  MESSAGES:
  335. //
  336. //      WM_INITDIALOG - initialize dialog box
  337. //      WM_COMMAND    - Input received
  338. //
  339. //
  340. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  341. {
  342.     static  HFONT hfontDlg;         // Font for dialog text
  343.     static  HFONT hFinePrint;       // Font for 'fine print' in dialog
  344.     DWORD   dwVerInfoSize;          // Size of version information block
  345.     LPTSTR   lpVersion;              // String pointer to 'version' text
  346.     DWORD   dwVerHnd=0;             // An 'ignored' parameter, always '0'
  347.     UINT    uVersionLen;
  348.     int     iRootLen;
  349.     BOOL    bRetCode;
  350.     int     i;
  351.     TCHAR   szFullPath[256];
  352.     TCHAR   szResult[256];
  353.     TCHAR   szGetName[256];
  354.     DWORD   dwVersion;
  355.     TCHAR   szVersion[40];
  356.     DWORD   dwResult;
  357.  
  358.     wParam = wParam; //Eliminate 'unused formal parameter' warning
  359.     lParam = lParam; //Eliminate 'unused formal parameter' warning
  360.  
  361.     switch (message)
  362.     {
  363.         case WM_INITDIALOG:
  364.             ShowWindow (hDlg, SW_HIDE);
  365.             hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VARIABLE_PITCH | FF_SWISS, __TEXT(""));
  366.             hFinePrint = CreateFont(11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VARIABLE_PITCH | FF_SWISS, __TEXT(""));
  367.             CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
  368.             GetModuleFileName (ghInst, szFullPath, sizeof(szFullPath));
  369.  
  370.             // Now let's dive in and pull out the version information:
  371.             dwVerInfoSize = GetFileVersionInfoSize(szFullPath, &dwVerHnd);
  372.             if (dwVerInfoSize)
  373.             {
  374.                 LPTSTR   lpstrVffInfo;
  375.                 HANDLE  hMem;
  376.                 hMem = GlobalAlloc(GMEM_MOVEABLE, dwVerInfoSize);
  377.                 lpstrVffInfo  = GlobalLock(hMem);
  378.                 GetFileVersionInfo(szFullPath, dwVerHnd, dwVerInfoSize, lpstrVffInfo);
  379.  
  380.                 // The below 'hex' value looks a little confusing, but
  381.                 // essentially what it is, is the hexidecimal representation
  382.                 // of a couple different values that represent the language
  383.                 // and character set that we are wanting string values for.
  384.                 // 040904E4 is a very common one, because it means:
  385.                 //   US English, Windows MultiLingual characterset
  386.                 // Or to pull it all apart:
  387.                 // 04//////        = SUBLANG_ENGLISH_USA
  388.                 // --09////        = LANG_ENGLISH
  389.                 // ////04E4 = 1252 = Codepage for Windows:Multilingual
  390.                 _tcscpy(szGetName, __TEXT("\\StringFileInfo\\040904E4\\"));
  391.                 iRootLen = lstrlen(szGetName); // Save this position
  392.  
  393.                 // Set the title of the dialog:
  394.                 lstrcat (szGetName, __TEXT("ProductName"));
  395.                 bRetCode = VerQueryValue((LPVOID)lpstrVffInfo, (LPTSTR)szGetName, (LPVOID)&lpVersion, (UINT *)&uVersionLen);
  396.                 _tcscpy(szResult, __TEXT("About "));
  397.                 lstrcat(szResult, lpVersion);
  398.                 SetWindowText (hDlg, szResult);
  399.  
  400.                 // Walk through the dialog items that we want to replace:
  401.                 for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
  402.                 {
  403.                     GetDlgItemText(hDlg, i, szResult, sizeof(szResult));
  404.                     szGetName[iRootLen] = __TEXT('\0');
  405.                     lstrcat (szGetName, szResult);
  406.                     uVersionLen   = 0;
  407.                     lpVersion     = NULL;
  408.                     bRetCode      =  VerQueryValue((LPVOID)lpstrVffInfo, (LPTSTR)szGetName, (LPVOID)&lpVersion, (UINT *)&uVersionLen);
  409.  
  410.                     if ( bRetCode && uVersionLen && lpVersion)
  411.                     {
  412.                         // Replace dialog item text with version info
  413.                         _tcscpy(szResult, lpVersion);
  414.                         SetDlgItemText(hDlg, i, szResult);
  415.                     }
  416.                     else
  417.                     {
  418.                         dwResult = GetLastError();
  419.                         wsprintf (szResult,__TEXT("Error %lu"), dwResult);
  420.                         SetDlgItemText (hDlg, i, szResult);
  421.                     }
  422.                     SendMessage (GetDlgItem (hDlg, i), WM_SETFONT, (UINT)((i==DLG_VERLAST)?hFinePrint:hfontDlg), TRUE);
  423.                 } // for (i = DLG_VERFIRST; i <= DLG_VERLAST; i++)
  424.                 GlobalUnlock(hMem);
  425.                 GlobalFree(hMem);
  426.             }
  427.             else
  428.             {
  429.                 // No version information available.
  430.             } // if (dwVerInfoSize)
  431.  
  432.             SendMessage (GetDlgItem (hDlg, IDC_LABEL), WM_SETFONT, (WPARAM)hfontDlg,(LPARAM)TRUE);
  433.  
  434.             // We are  using GetVersion rather then GetVersionEx
  435.             // because earlier versions of Windows NT and Win32s
  436.             // didn't include GetVersionEx:
  437.             dwVersion = GetVersion();
  438.             if (dwVersion < 0x80000000)
  439.             {
  440.                 // Windows NT
  441.                 wsprintf (szVersion,__TEXT("Microsoft Windows NT %u.%u (Build: %u)"), (DWORD)(LOBYTE(LOWORD(dwVersion))), (DWORD)(HIBYTE(LOWORD(dwVersion))),(DWORD)(HIWORD(dwVersion)) );
  442.             }
  443.             else
  444.             {
  445.                 if (LOBYTE(LOWORD(dwVersion)) < 4)
  446.                 {
  447.                     // Win32s
  448.                     wsprintf (szVersion, __TEXT("Microsoft Win32s %u.%u (Build: %u)"), (DWORD)(LOBYTE(LOWORD(dwVersion))), (DWORD)(HIBYTE(LOWORD(dwVersion))),(DWORD)(HIWORD(dwVersion) & ~0x8000) );
  449.                 }
  450.                 else
  451.                 {
  452.                     // Windows 95
  453.                     wsprintf (szVersion, __TEXT("Microsoft Windows 95 %u.%u"), (DWORD)(LOBYTE(LOWORD(dwVersion))), (DWORD)(HIBYTE(LOWORD(dwVersion))) );
  454.                 }
  455.             }
  456.             SetWindowText (GetDlgItem(hDlg, IDC_OSVERSION), szVersion);
  457.             ShowWindow (hDlg, SW_SHOW);
  458.             return (TRUE);
  459.  
  460.         case WM_COMMAND:
  461.             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  462.             {
  463.                 EndDialog(hDlg, TRUE);
  464.                 DeleteObject (hfontDlg);
  465.                 DeleteObject (hFinePrint);
  466.                 return (TRUE);
  467.             }
  468.             break;
  469.     }
  470.     return FALSE;
  471. }
  472.  
  473. //
  474. //   FUNCTION: CenterWindow(HWND, HWND)
  475. //
  476. //   PURPOSE: Centers one window over another.
  477. //
  478. //   COMMENTS:
  479. //
  480. //        In this function, we save the instance handle in a global variable and
  481. //        create and display the main program window.
  482. //
  483. //              This function will center one window over another ensuring that
  484. //              the placement of the window is within the 'working area', meaning
  485. //              that it is both within the display limits of the screen, and not
  486. //              obscured by the tray or other framing elements of the desktop.
  487. BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
  488. {
  489.     RECT    rChild, rParent, rWorkArea;
  490.     int     wChild, hChild, wParent, hParent;
  491.     int     xNew, yNew;
  492.     BOOL    bResult;
  493.  
  494.     // Get the Height and Width of the child window
  495.     GetWindowRect (hwndChild, &rChild);
  496.     wChild = rChild.right - rChild.left;
  497.     hChild = rChild.bottom - rChild.top;
  498.  
  499.     // Get the Height and Width of the parent window
  500.     GetWindowRect (hwndParent, &rParent);
  501.     wParent = rParent.right - rParent.left;
  502.     hParent = rParent.bottom - rParent.top;
  503.  
  504.     // Get the limits of the 'workarea'
  505.     bResult = SystemParametersInfo(
  506.                                   SPI_GETWORKAREA,
  507.                                   sizeof(RECT),
  508.                                   &rWorkArea,
  509.                                   0);
  510.     if (!bResult)
  511.     {
  512.         rWorkArea.left = rWorkArea.top = 0;
  513.         rWorkArea.right = GetSystemMetrics(SM_CXSCREEN);
  514.         rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN);
  515.     }
  516.     // Calculate new X position, then adjust for workarea
  517.     xNew = rParent.left + ((wParent - wChild) / 2);
  518.     if (xNew < rWorkArea.left)
  519.     {
  520.         xNew = rWorkArea.left;
  521.     }
  522.     else if ((xNew + wChild) > rWorkArea.right)
  523.     {
  524.         xNew = rWorkArea.right - wChild;
  525.     }
  526.     // Calcualte new Y position, then adjust for workarea
  527.     yNew = rParent.top + ((hParent - hChild) /2);
  528.     if (yNew < rWorkArea.top)
  529.     {
  530.         yNew = rWorkArea.top;
  531.     }
  532.     else if ((yNew + hChild) > rWorkArea.bottom)
  533.     {
  534.         yNew = rWorkArea.bottom - hChild;
  535.     }
  536.  
  537.     //Set it and return
  538.     return(SetWindowPos(hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER));
  539. }
  540.  
  541. //////////////////////////////////////////////////////////////////////////
  542. //  Function:  CopyString
  543. //
  544. //  Description:
  545. //    Allocates space and copies one LPTSTR into a new one.  Allocates
  546. //    exactly as much memory as necessary.
  547. //
  548. //  Parameters:
  549. //    LPTSTR    Source string to be copied.
  550. //
  551. //  Returns:
  552. //    LPTSTR  Pointer to copy of string; NULL if failure.
  553. //
  554. //  Comments:
  555. //
  556. //
  557. //////////////////////////////////////////////////////////////////////////
  558. LPTSTR CopyString(LPTSTR  lpszSrc)
  559. {
  560.     // Local variables
  561.     LPTSTR    lpszDest;
  562.     int       iStrLen;
  563.  
  564.     //  Initialize variables
  565.     lpszDest = NULL;
  566.  
  567.     if (lpszSrc == NULL)
  568.     {
  569.         DebugMsg(__TEXT("ICMVIEW.C : CopyString : lpszSrc == NULL\r\n"));
  570.         return(NULL);
  571.     }
  572.     iStrLen = ((int)(lstrlen(lpszSrc) +1) * sizeof(TCHAR));
  573.     lpszDest = GlobalAlloc(GPTR, iStrLen);
  574.     _tcscpy(lpszDest, lpszSrc);
  575.     return(lpszDest);
  576. }   // End of function CopyString
  577.  
  578.  
  579. //////////////////////////////////////////////////////////////////////////
  580. //  Function:  UpdateString
  581. //
  582. //  Description:
  583. //    Replaces target string with source string.  Frees target first
  584. //    if necessary.
  585. //
  586. //  Parameters:
  587. //    LPTSTR    Destination string
  588. //    LPTSTR    Source string
  589. //
  590. //  Returns:
  591. //    LPTSTR    Destination string.
  592. //
  593. //  Comments:
  594. //
  595. //
  596. //////////////////////////////////////////////////////////////////////////
  597. BOOL UpdateString(LPTSTR *lpszDest, LPTSTR lpszSrc)
  598. {
  599.     // Local variables
  600.     HGLOBAL hMem, hDest;
  601.     LPTSTR  lpszNew;
  602.  
  603.     //  Initialize variables
  604.     if (NULL == lpszSrc)
  605.     {
  606.         DebugMsg(__TEXT("ICMVIEW.C : UpdateString : NULL source\r\n"));
  607.         *lpszDest = NULL;
  608.         return(FALSE);
  609.     }
  610.  
  611.     if (NULL != *lpszDest)
  612.     {
  613.         hDest = GlobalHandle(*lpszDest);
  614.         GlobalUnlock(hDest);
  615.         GlobalFree(hDest);
  616.     }
  617.     hMem = GlobalAlloc(GPTR, (1 + lstrlen(lpszSrc))* sizeof(TCHAR));
  618.     if (NULL == hMem)
  619.     {
  620.         DebugMsg(__TEXT("UpdateString : GlobalAlloc failed\r\n"));
  621.         return(FALSE);
  622.     }
  623.     lpszNew = GlobalLock(hMem);
  624.     _tcscpy(lpszNew, lpszSrc);
  625.     *lpszDest = lpszNew;
  626.     return(TRUE);
  627. }   // End of function UpdateString
  628.  
  629.  
  630.  
  631. BOOL ConvertIntent(DWORD dwOrig, DWORD dwDirection, LPDWORD lpdwXlate)
  632. {
  633.     DWORD   adwIntents[MAX_ICC_INTENT + 1] = { LCS_GM_IMAGES, LCS_GM_GRAPHICS, LCS_GM_BUSINESS, LCS_GM_GRAPHICS};
  634.     int     idx;
  635.  
  636.     ASSERT((ICC_TO_LCS == dwDirection) || (LCS_TO_ICC == dwDirection));
  637.     *lpdwXlate = (DWORD)-1;
  638.  
  639.     switch (dwDirection)
  640.     {
  641.         case LCS_TO_ICC:
  642.             for (idx = MAX_ICC_INTENT+1; idx >0; idx--)
  643.             {
  644.                 if (adwIntents[idx] == dwOrig)
  645.                 {
  646.                     *lpdwXlate = idx;
  647.                     return(TRUE);
  648.                 }
  649.             }
  650.             break;
  651.  
  652.         case ICC_TO_LCS:
  653.             if (dwOrig <= MAX_ICC_INTENT)
  654.             {
  655.                 *lpdwXlate = adwIntents[dwOrig];
  656.                 return(TRUE);
  657.             }
  658.         default:
  659.             SetLastError(ERROR_INVALID_PARAMETER);
  660.             return(FALSE);
  661.             break;
  662.     }
  663.     return(FALSE);
  664. }
  665.  
  666. //////////////////////////////////////////////////////////////////////////
  667. //  Function:  SetDWFlags
  668. //
  669. //  Description:
  670. //    Sets flag values in a DWORD flag.
  671. //
  672. //  Parameters:
  673. //    LPDWORD Pointer to flag variable to be changed.
  674. //    DWORD   Value to be set/cleared.
  675. //    BOOL    Indicates if value is to be set or cleared.
  676. //
  677. //  Returns:
  678. //    DWORD   Value of flag variable prior to call.
  679. //
  680. //  Comments:
  681. //
  682. //////////////////////////////////////////////////////////////////////////
  683. DWORD SetDWFlags(LPDWORD lpdwFlag, DWORD dwBitValue, BOOL bSet)
  684. {
  685.     // Initialize variables
  686.     if (bSet)
  687.     {
  688.         (*lpdwFlag) |= dwBitValue;
  689.     }
  690.     else
  691.     {
  692.         (*lpdwFlag) &= (~dwBitValue);
  693.     }
  694.     return(*lpdwFlag);
  695. } // End of function SetDWFlags
  696.  
  697.  
  698. //////////////////////////////////////////////////////////////////////////
  699. //  Function:  InitImageMenu
  700. //
  701. //  Description:
  702. //    Handles the WM_CONTEXTMENU message
  703. //
  704. //  Parameters:
  705. //    @@@
  706. //
  707. //  Returns:
  708. //    LRESULT
  709. //
  710. //  Comments:
  711. //
  712. //
  713. //////////////////////////////////////////////////////////////////////////
  714. HMENU InitImageMenu(HWND hwnd)
  715. {
  716.     // Local variables
  717.     HMENU       hMenu, hActiveMenu;
  718.     UINT        uiMenuFlag;
  719.     LPDIBINFO   lpDIBInfo;
  720.     HWND        hwndImage;
  721.  
  722.     //  Initialize variables
  723.     lpDIBInfo = NULL;
  724.  
  725.     hwndImage = GetCurrentMDIWnd();
  726.     if (hwndImage)  // we have an active child window
  727.     {
  728.         lpDIBInfo = GetDIBInfoPtr(hwndImage);
  729.         if (!lpDIBInfo)
  730.         {
  731.             return(NULL);
  732.         }
  733.     }
  734.  
  735.     if (hwnd == ghAppWnd) // dealing with main app window
  736.     {
  737.         hMenu = GetMenu(hwnd);
  738.         hActiveMenu = GetSubMenu(hMenu, IsZoomed(hwndImage) ? 1 : 0);
  739.         uiMenuFlag = (hwndImage != NULL) ? MF_ENABLED : MF_GRAYED;
  740.         EnableMenuItem(hActiveMenu, IDM_FILE_CLOSE, uiMenuFlag);
  741.         EnableMenuItem(hActiveMenu, IDM_FILE_PRINT_SETUP, uiMenuFlag);
  742.         EnableMenuItem(hActiveMenu, IDM_FILE_PRINT, uiMenuFlag);
  743.         EnableMenuItem(hActiveMenu, IDM_FILE_DISPLAY, uiMenuFlag);
  744.         EnableMenuItem(hActiveMenu, IDM_FILE_CONFIGURE_ICM, uiMenuFlag);
  745.         EnableMenuItem(hActiveMenu, ID_FILE_SAVEAS, uiMenuFlag);
  746.     }
  747.     else  // dealing with child window--must init context menu
  748.     {
  749.         hMenu = LoadMenu(ghInst, __TEXT("ImageContext"));
  750.         hActiveMenu = GetSubMenu(hMenu, 0);
  751.     }
  752.  
  753.     // Check EITHER ICM 2.0 or ICM 1.0 (Inside DC or Outside DC)
  754.     if (hActiveMenu && lpDIBInfo)
  755.     {
  756.         uiMenuFlag = (CHECK_DWFLAG(lpDIBInfo->dwICMFlags, ICMVFLAGS_ICM20) ? MF_CHECKED : MF_UNCHECKED);
  757.         CheckMenuItem(hActiveMenu, IDM_FILE_ICM20, uiMenuFlag);
  758.         CheckMenuItem(hActiveMenu, IDM_FILE_ICM10, uiMenuFlag == MF_CHECKED ? MF_UNCHECKED : MF_CHECKED);
  759.     }
  760.  
  761.     if (lpDIBInfo)
  762.         GlobalUnlock(GlobalHandle(lpDIBInfo));
  763.  
  764.     return(hActiveMenu);
  765. }   // End of function InitImageMenu
  766.  
  767. //////////////////////////////////////////////////////////////////////////
  768. //  Function:  GetBaseFilename
  769. //
  770. //  Description:
  771. //
  772. //
  773. //  Parameters:
  774. //      @@@
  775. //
  776. //  Returns:
  777. //      BOOL
  778. //
  779. //  Comments:
  780. //
  781. //
  782. //////////////////////////////////////////////////////////////////////////
  783. BOOL GetBaseFilename(LPTSTR lpszFilename, LPTSTR *lpszBaseFilename)
  784. {
  785.     // Local variables
  786.     TCHAR   stFile[MAX_PATH], stExt[MAX_PATH];
  787.  
  788.     //  ASSERTs and parameter validations
  789.     ASSERT(NULL != lpszFilename);
  790.     if (NULL == lpszFilename)
  791.     {
  792.         SetLastError(ERROR_INVALID_PARAMETER);
  793.         return(FALSE);
  794.     }
  795.  
  796.     //  Initialize variables
  797.     _tsplitpath(lpszFilename, NULL, NULL, stFile, stExt);
  798.     (*lpszBaseFilename) = (LPTSTR)GlobalAlloc(GPTR, ((_tcslen(stFile) + _tcslen(stExt) + 1 ) * sizeof(TCHAR)));
  799.     if (NULL != *lpszBaseFilename)
  800.     {
  801.         _stprintf(*lpszBaseFilename, __TEXT("%s%s"), stFile, stExt);
  802.     }
  803.     //  Cleanup any allocated resources
  804.     return(NULL != *(lpszBaseFilename));
  805. } // End of function GetBaseFilename
  806.  
  807.