home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / imagedit / imagedit.c < prev    next >
C/C++ Source or Header  |  1995-12-04  |  35KB  |  1,041 lines

  1.     /***************************************************************************
  2.      *                                                                         *
  3.      *  MODULE      : imagedit.c                                               *
  4.      *                                                                         *
  5.      *  DESCRIPTION : Contains main entry-level routine for ImagEdit.          *
  6.      *                                                                         *
  7.      *  FUNCTIONS   : WinMain ()        -  Program entry point.                *
  8.      *                                                                         *
  9.      *  HISTORY     : 3/14/89 - LR                                             *
  10.      *                                                                         *
  11.      ***************************************************************************/
  12.     
  13.     #include "imagedit.h"
  14.     #include "dialogs.h"
  15.     #include "ids.h"
  16.     
  17.     #include <string.h>
  18.     #include <stdlib.h>
  19.  
  20.      #include <windowsx.h>
  21.     #include <commdlg.h>
  22.     
  23.     
  24.     /*
  25.      * External declarations for the Windows variables that contain
  26.      * command line information.
  27.      */
  28.     extern INT __argc;
  29.     extern CHAR **__argv;
  30.     
  31.     
  32.     STATICFN BOOL NEAR InitApplication(VOID);
  33.     STATICFN BOOL NEAR InitInstance(LPSTR lpCmdLine, INT cmdShow);
  34.     STATICFN VOID NEAR PenWinRegister(VOID);
  35.     STATICFN VOID NEAR ReadEnv(VOID);
  36.     STATICFN VOID NEAR WriteEnv(VOID);
  37.     STATICFN VOID NEAR SizeRibbons(HWND hwnd);
  38.     STATICFN VOID NEAR CleanUp(VOID);
  39.     
  40.     static RECT grcAppPos;              // Saves the app's window pos.
  41.     static WORD gmsgHelp;               // Registered help msg from commdlg.dll
  42.     static BOOL fStartAsIcon = FALSE;   // TRUE if app is started minimized.
  43.     
  44.     /*
  45.      * Contains the address of the Pen Windows callback.
  46.      */
  47.     typedef VOID ( APIENTRY *LPFNPENWIN)(WORD, BOOL);
  48.     static LPFNPENWIN lpfnRegisterPenApp;
  49.     
  50.     
  51.     
  52.     /****************************************************************************
  53.      *                                                                          *
  54.      *  FUNCTION :int PASCAL WinMain(hInstance,hPrevInstance,lpCmdLine,cmdShow) *
  55.      *                                                                          *
  56.      *  PURPOSE  :Serves as program entry point and contains message loop       *
  57.      *                                                                          *
  58.      ****************************************************************************/
  59.     
  60.     INT WINAPI
  61.     WinMain(
  62.         HINSTANCE hInstance,
  63.         HINSTANCE hPrevInstance,
  64.         LPSTR lpCmdLine,
  65.         INT nCmdShow)
  66.     {
  67.         MSG msg;
  68.     
  69.         DBGStackReport(TRUE);
  70.     
  71.         ghInst = hInstance;
  72.     
  73.         /* if this is the first instance then call initialization procedure */
  74.         if (!hPrevInstance) {
  75.             if (!InitApplication())
  76.                 return FALSE;
  77.         }
  78.     
  79.         if (!InitInstance(lpCmdLine, nCmdShow))
  80.             return FALSE;
  81.  
  82.     while (GetMessage(&msg, NULL, 0, 0)) {
  83.  
  84.                 if (!TranslateAccelerator(ghwndMain, haccelTbl, &msg)) {
  85.                     TranslateMessage(&msg);
  86.                     DispatchMessage(&msg);
  87.                 }
  88.     }
  89.     
  90.         DBGStackReport(FALSE);
  91.     
  92.         /*
  93.          * Return the value from PostQuitMessage.
  94.          */
  95.         return msg.wParam;
  96.     }
  97.     
  98.     
  99.     /****************************************************************************
  100.      *                                                                          *
  101.      *  FUNCTION   : InitApplication()                                          *
  102.      *                                                                          *
  103.      *  PURPOSE    : To create all ImagEdit's window classes, namely those of   *
  104.      *               the parent window, edit window, mode window and "palette"  *
  105.      *               window.                                                    *
  106.      *                                                                          *
  107.      *  RETURNS    : TRUE if class registration was successful, FALSE otherwise *
  108.      *                                                                          *
  109.      *  SIDE EFFECTS: All class variables affected for all windows.             *
  110.      *                                                                          *
  111.      ****************************************************************************/
  112.     
  113.     STATICFN BOOL NEAR InitApplication(VOID)
  114.     {
  115.         WNDCLASS wc;
  116.     
  117.         /* assign values and register the parent window class */
  118.         wc.style = 0;
  119.         wc.lpfnWndProc = MainWndProc;
  120.         wc.cbClsExtra = 0;
  121.         wc.cbWndExtra = 0;
  122.         wc.hInstance = ghInst;
  123.         wc.hIcon = LoadIcon(ghInst, MAKEINTRESOURCE(IDICON_IMAGEDIT));
  124.         wc.hCursor =  LoadCursor(NULL, IDC_ARROW);
  125.         wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
  126.         wc.lpszMenuName = "imagedit";
  127.         wc.lpszClassName = szMainClass;
  128.         if (!RegisterClass(&wc))
  129.             return FALSE;
  130.     
  131.         wc.style = CS_DBLCLKS;
  132.         wc.lpfnWndProc = ColorBoxWndProc;
  133.         wc.cbClsExtra = 0;
  134.         wc.cbWndExtra = 0;
  135.         wc.hInstance = ghInst;
  136.         wc.hIcon = NULL;
  137.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  138.         wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  139.         wc.lpszMenuName = (LPSTR)NULL;
  140.         wc.lpszClassName = szColorBoxClass;
  141.         if (!RegisterClass(&wc))
  142.             return FALSE;
  143.     
  144.         wc.style = 0;
  145.         wc.lpfnWndProc = ColorLRWndProc;
  146.         wc.cbClsExtra = 0;
  147.         wc.cbWndExtra = 0;
  148.         wc.hInstance = ghInst;
  149.         wc.hIcon = NULL;
  150.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  151.         wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  152.         wc.lpszMenuName = (LPSTR)NULL;
  153.         wc.lpszClassName = szColorLRClass;
  154.         if (!RegisterClass(&wc))
  155.             return FALSE;
  156.     
  157.         wc.style = CS_DBLCLKS;
  158.         wc.lpfnWndProc = WorkWndProc;
  159.         wc.cbClsExtra = 0;
  160.         wc.cbWndExtra = 0;
  161.         wc.hInstance = ghInst;
  162.         wc.hIcon = NULL;
  163.         wc.hCursor = (HCURSOR)NULL;
  164.         wc.hbrBackground = (HBRUSH)NULL;
  165.         wc.lpszMenuName  = (LPSTR)NULL;
  166.         wc.lpszClassName = szWorkClass;
  167.         if (!RegisterClass(&wc))
  168.             return FALSE;
  169.     
  170.         wc.style = 0;
  171.         wc.lpfnWndProc = ToolboxWndProc;
  172.         wc.cbClsExtra = 0;
  173.         wc.cbWndExtra = 0;
  174.         wc.hInstance = ghInst;
  175.         wc.hIcon = NULL;
  176.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  177.         wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  178.         wc.lpszMenuName = NULL;
  179.         wc.lpszClassName = szToolboxClass;
  180.         if (!RegisterClass(&wc))
  181.             return FALSE;
  182.     
  183.         wc.style = 0;
  184.         wc.lpfnWndProc = ToolBtnWndProc;
  185.         wc.cbClsExtra = 0;
  186.         wc.cbWndExtra = 0;
  187.         wc.hInstance = ghInst;
  188.         wc.hIcon = NULL;
  189.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  190.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  191.         wc.lpszMenuName = NULL;
  192.         wc.lpszClassName = szToolBtnClass;
  193.         if (!RegisterClass(&wc))
  194.             return FALSE;
  195.     
  196.         wc.style = 0;
  197.         wc.lpfnWndProc = ViewWndProc;
  198.         wc.cbClsExtra = 0;
  199.         wc.cbWndExtra = 0;
  200.         wc.hInstance = ghInst;
  201.         wc.hIcon = NULL;
  202.         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  203.         wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  204.         wc.lpszMenuName = NULL;
  205.         wc.lpszClassName = szViewClass;
  206.         if (!RegisterClass(&wc))
  207.             return FALSE;
  208.     
  209.         return TRUE;
  210.     }
  211.     
  212.     
  213.     
  214.     /****************************************************************************
  215.      *                                                                          *
  216.      *  FUNCTION   : InitInstance(lpCmdLine, cmdShow)                           *
  217.      *                                                                          *
  218.      *  PURPOSE    : Load strings from resource file, make procedure instances  *
  219.      *               of all dialog functions, create ImagEdit's windows, color  *
  220.      *               "palettes", tool cursors and do a variety of other initial-*
  221.      *               izations. Also prepare ImagEdit if started up from cmd line*
  222.      *               with an argument. Some of these may be redundant, since a  *
  223.      *               lot of pBrush stuff has been retained here.                *
  224.      *                                                                          *
  225.      *  SIDE EFFECTS: numerous                                                  *
  226.      *                                                                          *
  227.      ****************************************************************************/
  228.     
  229.     STATICFN BOOL NEAR InitInstance(
  230.         LPSTR lpCmdLine,
  231.         INT cmdShow)
  232.     {
  233.         INT i;
  234.         INT iScrollBarWidth;        /* width of vertical scrollbar */
  235.         INT iScrollBarHeight;       /* height of horizontal scrollbar */
  236.         INT iScreenWid;
  237.         INT iScreenHgt;             /* full screen width and height */
  238.         INT x;
  239.         INT y;
  240.         INT cx;
  241.         INT cy;
  242.         BOOL fMaximized;
  243.         RECT rcColor;
  244.         RECT rcClient;
  245.         RECT rc;
  246.         POINT pt;
  247.     
  248.         /*
  249.          * Load the "Out of memory." string now, since we may not be able to
  250.          * load it if/when it needs to be displayed.
  251.          */
  252.         ids(IDS_OUTOFMEMORY);
  253.     
  254.         /*
  255.          * Register for Pen Windows, if it is present.
  256.          */
  257.         PenWinRegister();
  258.     
  259.         /* register private ImagEdit clipboard format for icons and cursors */
  260.         if (!(ClipboardFormat = RegisterClipboardFormat("ImagEdit")))
  261.             return FALSE;
  262.     
  263.         if (!(haccelTbl = LoadAccelerators(ghInst, "imagedit")))
  264.             return FALSE;
  265.     
  266.         hcurWait = LoadCursor(NULL, IDC_WAIT);
  267.         gaTools[TOOL_PENCIL].hcur =
  268.                 LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_PENCIL));
  269.         gaTools[TOOL_BRUSH].hcur =
  270.                 LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_BRUSH));
  271.         gaTools[TOOL_SELECT].hcur =
  272.         gaTools[TOOL_LINE].hcur =
  273.         gaTools[TOOL_RECT].hcur =
  274.         gaTools[TOOL_SOLIDRECT].hcur =
  275.         gaTools[TOOL_CIRCLE].hcur =
  276.         gaTools[TOOL_SOLIDCIRCLE].hcur =
  277.                 LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_CROSS));
  278.         gaTools[TOOL_FLOODFILL].hcur =
  279.                 LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_FLOOD));
  280.         gaTools[TOOL_HOTSPOT].hcur =
  281.                 LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_HOTSPOT));
  282.     
  283.         /*
  284.          * Select the default tool.  Since the toolbox is not created yet,
  285.          * this just sets up some globals.
  286.          */
  287.         ToolboxSelectTool(TOOL_FIRST);
  288.     
  289.         /*
  290.          * Create a dark gray pen for use in borders later.
  291.          */
  292.         if (!(hpenDarkGray = CreatePen(PS_SOLID, 1, RGB_DARKGRAY)))
  293.             return FALSE;
  294.     
  295.         /*
  296.          * Initialize the two color palettes to the default colors.
  297.          */
  298.         for (i = 0; i < COLORSMAX; i++) {
  299.             gargbColor[i] = gargbDefaultColor[i];
  300.             gargbMono[i] = gargbDefaultMono[i];
  301.         }
  302.     
  303.         /* get some system parameters */
  304.         iScrollBarWidth  = GetSystemMetrics(SM_CXVSCROLL);
  305.         iScrollBarHeight = GetSystemMetrics(SM_CYHSCROLL);
  306.         iScreenWid       = GetSystemMetrics(SM_CXFULLSCREEN);
  307.         iScreenHgt       = GetSystemMetrics(SM_CYFULLSCREEN);
  308.         gcyBorder = GetSystemMetrics(SM_CYBORDER);
  309.     
  310.         /*
  311.          * Build the help file name path.  Assume the help file is in the
  312.          * same directory as the executable.
  313.          */
  314.         GetModuleFileName(ghInst, gszHelpFile, CCHMAXPATH);
  315.         *FileInPath(gszHelpFile) = '\0';
  316.         lstrcat(gszHelpFile, ids(IDS_HELPFILE));
  317.     
  318.         /*
  319.          * Register the message for help from the common dialogs.
  320.          */
  321.         gmsgHelp = RegisterWindowMessage(HELPMSGSTRING);
  322.     
  323.         /*
  324.          * Hook the message filter stream so that we can detect F1 keystrokes.
  325.          */
  326.         lpfnMsgFilterHookFunc =
  327.                 MakeProcInstance((FARPROC)MsgFilterHookFunc, ghInst);
  328.         ghhkMsgFilter =
  329.                 SetWindowsHook(WH_MSGFILTER, lpfnMsgFilterHookFunc);
  330.     
  331.         if (!ReadWindowPos(szAppPos, &x, &y, &cx, &cy, &fMaximized)) {
  332.             x = 2 * iScrollBarWidth;
  333.             y = iScrollBarHeight;
  334.             cx = min(iScreenWid - (4 * iScrollBarWidth), MAXDEFAULTAPPCX);
  335.             cy = min(iScreenHgt - (6 * iScrollBarHeight), MAXDEFAULTAPPCY);
  336.             fMaximized = FALSE;
  337.         }
  338.     
  339.         /* create parent window */
  340.         ghwndMain = CreateWindow(szMainClass, ids(IDS_PGMTITLE),
  341.                 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  342.                 x, y, cx, cy, NULL, NULL, ghInst, NULL);
  343.     
  344.         if (ghwndMain == NULL) {
  345.             Message(MSG_OUTOFMEMORY);
  346.             return FALSE;
  347.         }
  348.     
  349.         /*
  350.          * Read the preferences data saved in the ini file.
  351.          */
  352.         ReadEnv();
  353.     
  354.         /*
  355.          * Create the Toolbox and the View window (invisible).
  356.          */
  357.         ToolboxCreate();
  358.         ViewCreate();
  359.     
  360.         lpfnColorDlgProc = (WNDPROC)MakeProcInstance(
  361.                 (FARPROC)ColorDlgProc, ghInst);
  362.         ghwndColor = CreateDialog(ghInst, MAKEINTRESOURCE(DID_COLOR),
  363.                 ghwndMain, lpfnColorDlgProc);
  364.     
  365.         ghwndWork = CreateWindow(szWorkClass, NULL,
  366.                 WS_CHILD | WS_BORDER,
  367.                 0, 0, 0, 0,
  368.                 ghwndMain,
  369.                 NULL, ghInst, NULL);
  370.     
  371.         /*
  372.          * Build the device table.
  373.          */
  374.         InitDeviceList();
  375.     
  376.         SetColorPalette(gnColors, giType, TRUE);
  377.         SetScreenColor(grgbScreenDefault);
  378.     
  379.         if (!ReadWindowPos(szColorPos, &x, &y, &cx, &cy, &fMaximized)) {
  380.             /*
  381.              * The previous position of the Color palette couldn't be found.
  382.              * Position the palette just below the bottom left corner of the
  383.              * client area of the editor, but make sure it is completely
  384.              * visible.
  385.              */
  386.             GetWindowRect(ghwndColor, &rcColor);
  387.             GetClientRect(ghwndMain, &rcClient);
  388.             cx = rcColor.right - rcColor.left;
  389.             cy = rcColor.bottom - rcColor.top;
  390.             pt.x = rcClient.left + (2 * PALETTEMARGIN);
  391.             pt.y = rcClient.bottom + (2 * PALETTEMARGIN);
  392.             ClientToScreen(ghwndMain, &pt);
  393.             SetRect(&rc, pt.x, pt.y, pt.x + cx, pt.y + cy);
  394.             FitRectToScreen(&rc);
  395.             x = rc.left;
  396.             y = rc.top;
  397.         }
  398.     
  399.         SetWindowPos(ghwndColor, NULL, x, y, 0, 0,
  400.                 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
  401.     
  402.         SetFileName(NULL);
  403.     
  404.         /*
  405.          * If the app was saved when maximized (and they didn't start it up
  406.          * with some kind of an option to have it minimized or in some
  407.          * other funny initial state from the shell), then cause it to
  408.          * be maximized when shown.
  409.          */
  410.         if (fMaximized && (cmdShow == SW_SHOWNORMAL || cmdShow == SW_SHOW))
  411.             cmdShow = SW_SHOWMAXIMIZED;
  412.     
  413.         ShowWindow(ghwndMain, cmdShow);
  414.         UpdateWindow(ghwndMain);
  415.     
  416.         /*
  417.          * Did the user start this app minimized from the program manager?
  418.          */
  419.         if (IsIconic(ghwndMain)) {
  420.             /*
  421.              * Set a flag.  The showing of the palettes will be deferred
  422.              * until the app is restored.
  423.              */
  424.             fStartAsIcon = TRUE;
  425.         }
  426.         else {
  427.             /*
  428.              * If they had the Toolbox/Color Palette before, show them now.
  429.              */
  430.             ToolboxShow(gfShowToolbox);
  431.             ColorShow(gfShowColor);
  432.         }
  433.     
  434.         /*
  435.          * If there was a command line argument specified, try and open
  436.          * it as the initial file.
  437.          */
  438.         if (__argc > 1)
  439.             OpenCmdLineFile(__argv[1]);
  440.     
  441.         return TRUE;
  442.     }
  443.     
  444.     
  445.     
  446.     /************************************************************************
  447.     * PenWinRegister
  448.     *
  449.     * This function will register for Pen Windows, if it is present.
  450.     *
  451.     ************************************************************************/
  452.     
  453.     STATICFN VOID NEAR PenWinRegister(VOID)
  454.     {
  455.         HANDLE hmod;
  456.     
  457.         if (!(hmod = (HANDLE)GetSystemMetrics(SM_PENWINDOWS)))
  458.             return;
  459.     
  460.         if (lpfnRegisterPenApp =
  461.                 (LPFNPENWIN)GetProcAddress(hmod, "RegisterPenApp"))
  462.             (*lpfnRegisterPenApp)(1, TRUE);     // Be Pen-Enhanced!
  463.     }
  464.     
  465.     
  466.     
  467.     /************************************************************************
  468.     * MainWndProc
  469.     *
  470.     * Main window procedure for ImagEdit.
  471.     *
  472.     * History:
  473.     *
  474.     ************************************************************************/
  475.     
  476.     WINDOWPROC MainWndProc(
  477.         HWND hwnd,
  478.         UINT msg,
  479.         WPARAM wParam,
  480.         LPARAM lParam)
  481.     {
  482.         switch (msg) {
  483.             case WM_CREATE:
  484.                 {
  485.                     RECT rc;
  486.     
  487.                     /*
  488.                      * Create the PropBar window.
  489.                      */
  490.                     lpfnPropBarDlgProc = (WNDPROC)MakeProcInstance(
  491.                             (FARPROC)PropBarDlgProc, ghInst);
  492.                     CreateDialog(ghInst, MAKEINTRESOURCE(DID_PROPBAR), hwnd,
  493.                             lpfnPropBarDlgProc);
  494.     
  495.                     /*
  496.                      * Save away its height for sizing later (like when
  497.                      * the app is minimized then restored).
  498.                      */
  499.                     GetWindowRect(ghwndPropBar, &rc);
  500.                     gcyPropBar = rc.bottom - rc.top;
  501.                 }
  502.     
  503.                 break;
  504.     
  505.             case WM_NCCALCSIZE:
  506.                 /*
  507.                  * Save away what is going to be the new window position.
  508.                  */
  509.                 if (!IsIconic(hwnd) && !IsZoomed(hwnd))
  510.                     grcAppPos = *((LPRECT)lParam);
  511.     
  512.                 /*
  513.                  * Now let the DefWindowProc calculate the client area normally.
  514.                  */
  515.                 goto DoDefault;
  516.     
  517.             case WM_ACTIVATE:
  518.                 /*
  519.                  * If the main window is getting activated, there is no
  520.                  * currently active dialog.
  521.                  */
  522.                 if (GET_WM_ACTIVATE_STATE(wParam, lParam))
  523.                     gidCurrentDlg = 0;
  524.     
  525.                 goto DoDefault;
  526.     
  527.             case WM_INITMENU:
  528.                 if (GetMenu(ghwndMain) == (HMENU)wParam)
  529.                     InitMenu((HMENU)wParam);
  530.     
  531.                 break;
  532.     
  533.             case WM_COMMAND:
  534.                 MenuCmd(GET_WM_COMMAND_ID(wParam, lParam));
  535.                 break;
  536.     
  537.             case WM_SIZE:
  538.                 SizeRibbons(hwnd);
  539.     
  540.                 if (wParam != SIZEICONIC)
  541.                     WorkReset();
  542.     
  543.                 /*
  544.                  * Did the app start minimized and is it being restored
  545.                  * for the first time?  If so, show the palettes as
  546.                  * the user has requested.
  547.                  */
  548.                 if (fStartAsIcon && !IsIconic(hwnd)) {
  549.                     ToolboxShow(gfShowToolbox);
  550.                     ColorShow(gfShowColor);
  551.                     fStartAsIcon = FALSE;
  552.                 }
  553.     
  554.                 break;
  555.     
  556.             case WM_MENUSELECT:
  557.                 if (GET_WM_MENUSELECT_FLAGS(wParam, lParam) &
  558.                         (MF_POPUP | MF_SYSMENU))
  559.                     gMenuSelected = 0;
  560.                 else
  561.                     gMenuSelected = GET_WM_MENUSELECT_CMD(wParam, lParam);
  562.     
  563.                 break;
  564.     
  565.             case WM_CLOSE:
  566.                 if (VerifySaveFile()) {
  567.                     DestroyWindow(hwnd);
  568.                     CleanUp();
  569.                 }
  570.     
  571.                 break;
  572.     
  573.             case WM_DESTROY:
  574.                 /*
  575.                  * Save the position of the app's window.
  576.                  */
  577.                 WriteWindowPos(&grcAppPos, IsZoomed(hwnd), szAppPos);
  578.     
  579.                 WinHelp(ghwndMain, gszHelpFile, HELP_QUIT, 0L);
  580.     
  581.                 PostQuitMessage(0);
  582.     
  583.                 break;
  584.     
  585.             case WM_QUERYENDSESSION:
  586.                 return VerifySaveFile();
  587.     
  588.             default:
  589.                 /*
  590.                  * Is this the registered help message from one of the common
  591.                  * dialogs?  If so, show the help for it.
  592.                  *
  593.                  * The check to be sure gmsgHelp is non-zero is just in
  594.                  * case the call to register the help message failed
  595.                  * (it will return zero) and there happens to be a zero
  596.                  * message that gets sent to this window somehow.
  597.                  */
  598.                 if (msg == gmsgHelp && gmsgHelp) {
  599.                     ShowHelp(FALSE);
  600.                     return 0;
  601.                 }
  602.     
  603.             DoDefault:
  604.                 return DefWindowProc(hwnd, msg, wParam, lParam);
  605.         }
  606.     
  607.         return 0;
  608.     }
  609.     
  610.     
  611.     
  612.     /************************************************************************
  613.     * ReadWindowPos
  614.     *
  615.     * This function retrieves the saved window position for a window and
  616.     * returns it in the specified variables.  It is used between sessions
  617.     * to restore the application windows to the position they had when
  618.     * the editor was last exited.
  619.     *
  620.     * Returns TRUE if the position could be read, or FALSE otherwise.
  621.     * If FALSE is returned, the values in the specified variables are
  622.     * not valid!  The caller must be able to handle a FALSE return and
  623.     * supply a default position for the window.
  624.     *
  625.     * Arguments:
  626.     *   PSTR pstrKeyName  - KeyName the position was saved under.
  627.     *   PINT px           - Saved x position.
  628.     *   PINT py           - Saved y position.
  629.     *   PINT pcx          - Saved width.
  630.     *   PINT pcy          - Saved height.
  631.     *   BOOL *pfMaximized - Set to TRUE if window was maximized when saved.
  632.     *
  633.     * History:
  634.     *
  635.     ************************************************************************/
  636.     
  637.     BOOL ReadWindowPos(
  638.         PSTR pstrKeyName,
  639.         PINT px,
  640.         PINT py,
  641.         PINT pcx,
  642.         PINT pcy,
  643.         BOOL *pfMaximized)
  644.     {
  645.         static CHAR szSep[] = " ,";
  646.         CHAR szBuf[CCHTEXTMAX];
  647.         PSTR pstr;
  648.     
  649.         if (!GetPrivateProfileString(ids(IDS_APPNAME),
  650.                 pstrKeyName, "", szBuf, CCHTEXTMAX, ids(IDS_IMAGEDITINI)))
  651.             return FALSE;
  652.     
  653.         if (!(pstr = strtok(szBuf, szSep)))
  654.             return FALSE;
  655.     
  656.         *px = atoi(pstr);
  657.     
  658.         if (!(pstr = strtok(NULL, szSep)))
  659.             return FALSE;
  660.     
  661.         *py = atoi(pstr);
  662.     
  663.         if (!(pstr = strtok(NULL, szSep)))
  664.             return FALSE;
  665.     
  666.         *pcx = atoi(pstr);
  667.     
  668.         if (!(pstr = strtok(NULL, szSep)))
  669.             return FALSE;
  670.     
  671.         *pcy = atoi(pstr);
  672.     
  673.         /*
  674.          * If there is a "1" following the coordinates, the window was
  675.          * maximized when it was saved.
  676.          */
  677.         *pfMaximized = FALSE;
  678.         if ((pstr = strtok(NULL, szSep)) && atoi(pstr) == 1)
  679.             *pfMaximized = TRUE;
  680.     
  681.         /*
  682.          * Don't allow a zero sized window.
  683.          */
  684.         if (*pcx == 0 || *pcy == 0)
  685.             return FALSE;
  686.     
  687.         /*
  688.          * Return success.
  689.          */
  690.         return TRUE;
  691.     }
  692.     
  693.     
  694.     
  695.     /************************************************************************
  696.     * WriteWindowPos
  697.     *
  698.     * This function writes the position of a window to the
  699.     * editor's profile file under the specified keyname.
  700.     * The ReadWindowPos function is the counterpart of this
  701.     * function.
  702.     *
  703.     * Arguments:
  704.     *   PRECT prc        - Rectangle for the "restored" window size.
  705.     *   BOOL fMaximized  - TRUE if the window is maximized.
  706.     *   PSTR pstrKeyName - KeyName to save the position under.
  707.     *
  708.     * History:
  709.     *
  710.     ************************************************************************/
  711.     
  712.     VOID WriteWindowPos(
  713.         PRECT prc,
  714.         BOOL fMaximized,
  715.         PSTR pstrKeyName)
  716.     {
  717.         CHAR szBuf[CCHTEXTMAX];
  718.     
  719.         wsprintf(szBuf, "%d %d %d %d", prc->left, prc->top,
  720.                 prc->right - prc->left, prc->bottom - prc->top);
  721.     
  722.         if (fMaximized)
  723.             strcat(szBuf, " 1");
  724.     
  725.         WritePrivateProfileString(ids(IDS_APPNAME),
  726.                 pstrKeyName, szBuf, ids(IDS_IMAGEDITINI));
  727.     }
  728.     
  729.     
  730.     
  731.     /*************************************************************************
  732.     * ReadEnv
  733.     *
  734.     * This function initializes variables from their counterparts
  735.     * in the private profile file for ImagEdit.  The application
  736.     * merely needs to construct an array of INIENTRY structures
  737.     * to describe the variables that must be initialized.
  738.     *
  739.     * Note that the original value read from the profile is saved when
  740.     * it is read.  This allows us to optimize what needs to be written
  741.     * out with WriteEnv.
  742.     *
  743.     * History:
  744.     *
  745.     *************************************************************************/
  746.     
  747.     STATICFN VOID NEAR ReadEnv(VOID)
  748.     {
  749.         register INT i;
  750.         HDC hdc;
  751.         CHAR szBuf[CCHTEXTMAX];
  752.         DWORD rgb;
  753.     
  754.         for (i = 0; gaie[i].pstrKeyName; i++) {
  755.             *gaie[i].pnVar = gaie[i].nSave =
  756.                     GetPrivateProfileInt(ids(IDS_APPNAME),
  757.                     gaie[i].pstrKeyName, gaie[i].nDefault,
  758.                     ids(IDS_IMAGEDITINI));
  759.         }
  760.     
  761.         /*
  762.          * Look for the saved screen color.
  763.          */
  764.         if (GetPrivateProfileString(ids(IDS_APPNAME), szrgbScreen, "",
  765.                 szBuf, CCHTEXTMAX, ids(IDS_IMAGEDITINI))) {
  766.             rgb = (DWORD)atol(szBuf);
  767.         }
  768.         else {
  769.             /*
  770.              * The last screen color was not found.  The default will be
  771.              * the current system screen background color.
  772.              */
  773.             rgb = GetSysColor(COLOR_BACKGROUND);
  774.         }
  775.     
  776.         /*
  777.          * Make the ImagEdit default screen color a solid color.
  778.          */
  779.         hdc = GetDC(ghwndMain);
  780.         grgbScreenDefault = GetNearestColor(hdc, rgb);
  781.         ReleaseDC(ghwndMain, hdc);
  782.     }
  783.     
  784.     
  785.     
  786.     /*************************************************************************
  787.     * WriteEnv
  788.     *
  789.     * This function is the counterpart to ReadEnv.  It saves values
  790.     * in the profile file.
  791.     *
  792.     * History:
  793.     *
  794.     *************************************************************************/
  795.     
  796.     STATICFN VOID NEAR WriteEnv(VOID)
  797.     {
  798.         register INT i;
  799.         CHAR szBuf[CCHTEXTMAX];
  800.     
  801.         for (i = 0; gaie[i].pstrKeyName; i++) {
  802.             /*
  803.              * Has the user changed the value since it was read?
  804.              */
  805.             if (gaie[i].nSave != *gaie[i].pnVar) {
  806.                 /*
  807.                  * If the new value is the same as the default value,
  808.                  * erase the entry from the ini file.  Otherwise,
  809.                  * write the user-specified value out.
  810.                  */
  811.                 if (*gaie[i].pnVar == gaie[i].nDefault) {
  812.                     WritePrivateProfileString(ids(IDS_APPNAME),
  813.                             gaie[i].pstrKeyName, NULL, ids(IDS_IMAGEDITINI));
  814.                 }
  815.                 else {
  816.                     itoa(*gaie[i].pnVar, szBuf, 10);
  817.                     WritePrivateProfileString(ids(IDS_APPNAME),
  818.                             gaie[i].pstrKeyName, szBuf, ids(IDS_IMAGEDITINI));
  819.                 }
  820.             }
  821.         }
  822.     
  823.         /*
  824.          * Save the current screen color.
  825.          */
  826.         ltoa((LONG)grgbScreen, szBuf, 10);
  827.         WritePrivateProfileString(ids(IDS_APPNAME),
  828.                 szrgbScreen, szBuf, ids(IDS_IMAGEDITINI));
  829.     }
  830.     
  831.     
  832.     
  833.     /************************************************************************
  834.     * SizeRibbons
  835.     *
  836.     * This function positions and sizes the child ribbons in the editor.
  837.     * It needs to be called any time the size of the main windows changes.
  838.     *
  839.     * Arguments:
  840.     *   HWND hwnd - Parent window handle.
  841.     *
  842.     * History:
  843.     *
  844.     ************************************************************************/
  845.     
  846.     STATICFN VOID NEAR SizeRibbons(
  847.         HWND hwnd)
  848.     {
  849.         RECT rcClient;
  850.     
  851.         if (ghwndPropBar && !IsIconic(hwnd)) {
  852.             /*
  853.              * Get the client area.
  854.              */
  855.             GetClientRect(hwnd, &rcClient);
  856.     
  857.             /*
  858.              * Size/move the PropBar window to fit
  859.              * the new client area.
  860.              */
  861.             SetWindowPos(ghwndPropBar, NULL,
  862.                     0, 0,
  863.                     rcClient.right - rcClient.left,
  864.                     min(rcClient.bottom - rcClient.top, gcyPropBar),
  865.                     SWP_NOACTIVATE | SWP_NOZORDER);
  866.         }
  867.     }
  868.     
  869.     
  870.     
  871.     /************************************************************************
  872.     * CleanUp
  873.     *
  874.     * Cleans up all the resources allocated by the editor.
  875.     *
  876.     * History:
  877.     *
  878.     ************************************************************************/
  879.     
  880.     STATICFN VOID NEAR CleanUp(VOID)
  881.     {
  882.         WriteEnv();
  883.     
  884.         if (ghdcANDMask) {
  885.             DeleteDC(ghdcANDMask);
  886.             DeleteObject(ghbmANDMask);
  887.         }
  888.         if (ghdcImage) {
  889.             DeleteDC(ghdcImage);
  890.             DeleteObject(ghbmImage);
  891.         }
  892.     
  893.         ImageFreeUndo();
  894.     
  895.         if (hpenDarkGray)
  896.             DeleteObject(hpenDarkGray);
  897.     
  898.         if (ghbrLeft)
  899.             DeleteObject(ghbrLeft);
  900.     
  901.         if (ghbrLeftSolid)
  902.             DeleteObject(ghbrLeftSolid);
  903.     
  904.         if (ghbrRight)
  905.             DeleteObject(ghbrRight);
  906.     
  907.         if (ghbrRightSolid)
  908.             DeleteObject(ghbrRightSolid);
  909.     
  910.         if (ghbrScreen)
  911.             DeleteObject(ghbrScreen);
  912.     
  913.         if (ghbrInverse)
  914.             DeleteObject(ghbrInverse);
  915.     
  916.         if (ghpenLeft)
  917.             DeleteObject(ghpenLeft);
  918.     
  919.         if (ghpenRight)
  920.             DeleteObject(ghpenRight);
  921.     
  922.         ImageLinkFreeList();
  923.     
  924.         if (lpfnMsgFilterHookFunc) {
  925.             UnhookWindowsHook(WH_MSGFILTER, lpfnMsgFilterHookFunc);
  926.             FreeProcInstance(lpfnMsgFilterHookFunc);
  927.         }
  928.     
  929.         if (lpfnPropBarDlgProc)
  930.             FreeProcInstance((FARPROC)lpfnPropBarDlgProc);
  931.     
  932.         if (lpfnColorDlgProc)
  933.             FreeProcInstance((FARPROC)lpfnColorDlgProc);
  934.     }
  935.  
  936. /****************************************************************************
  937.     My_mbschr:  strchr() DBCS version
  938. ****************************************************************************/
  939. unsigned char * _CRTAPI1 My_mbschr(
  940.     unsigned char *psz, unsigned short uiSep)
  941. {
  942.     while (*psz != '\0' && *psz != uiSep) {
  943.         psz = CharNext(psz);
  944.     }
  945.     if (*psz == '\0' && uiSep != '\0') {
  946.         return NULL;
  947.     } else {
  948.         return psz;
  949.     }
  950. }
  951. /****************************************************************************
  952.     My_mbstok:  strtok() DBCS version
  953. ****************************************************************************/
  954. unsigned char * _CRTAPI1 My_mbstok(
  955.     unsigned char *pszSrc, unsigned char *pszSep)
  956. {
  957.     static char *pszSave = NULL;
  958.     char *pszHead;
  959.     char *psz;
  960.  
  961.     if (pszSrc == NULL) {
  962.         if (pszSave == NULL) {
  963.             return NULL;
  964.         } else {
  965.             psz = pszSave;
  966.         }
  967.     } else {
  968.         psz = pszSrc;
  969.     }
  970.  
  971.     /*********************************************/
  972.     /* Skip delimiters to find a head of a token */
  973.     /*********************************************/
  974.     while (*psz) {
  975.         if (IsDBCSLeadByte(*psz)) {
  976.             break;
  977.         } else if (NULL == My_mbschr(pszSep, *psz)) {
  978.             break;
  979.         }
  980.         psz++;
  981.     }
  982.     if (*psz == '\0') {
  983.         //No more token
  984.         return (pszSave = NULL);
  985.     }
  986.     pszHead = psz;
  987.  
  988.     /******************************/
  989.     /* Search a Tail of the token */
  990.     /******************************/
  991.     while (*psz) {
  992.         if (IsDBCSLeadByte(*psz)) {
  993.             psz += 2;
  994.             continue;
  995.         } else if (NULL != My_mbschr(pszSep, *psz)) {
  996.             break;
  997.         }
  998.         psz++;
  999.     }
  1000.     if (*psz == '\0') {
  1001.         pszSave = NULL;
  1002.     } else {
  1003.         //Found next delimiter
  1004.         pszSave = psz + 1;
  1005.         *psz = '\0';
  1006.     }
  1007.     return pszHead;
  1008. }
  1009. /****************************************************************************
  1010.     My_mbsncat:
  1011. ****************************************************************************/
  1012. unsigned char * _CRTAPI1 My_mbsncat(
  1013.     unsigned char *psz1, const unsigned char *psz2, size_t Length)
  1014. {
  1015.     int nLen = (int)Length;
  1016.     unsigned char *pszSv = psz1;
  1017.  
  1018.     while ('\0' != *psz1) {
  1019.         psz1++;
  1020.     }
  1021.  
  1022.     while (0 < nLen) {
  1023.         if (*psz2 == '\0') {
  1024.             *psz1++ = '\0';
  1025.             nLen--;
  1026.         } else if (IsDBCSLeadByte(*psz2)) {
  1027.             if (nLen == 1) {
  1028.                 *psz1 = '\0';
  1029.             } else {
  1030.                 *psz1++ = *psz2++;
  1031.                 *psz1++ = *psz2++;
  1032.             }
  1033.             nLen -= 2;
  1034.         } else {
  1035.             *psz1++ = *psz2++;
  1036.             nLen--;
  1037.         }
  1038.     }
  1039.     return pszSv;
  1040. }
  1041.