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

Windows编程

开发平台:

Visual C++

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