Annotation of mstools/samples/sdktools/dlgedit/dlgedit.c, revision 1.1.1.1

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /****************************** Module Header *******************************
                     13: * Module Name: dlgedit.c
                     14: *
                     15: * Main function and window procedure for the Dialog Box Editor.
                     16: *
                     17: * Functions:
                     18: *
                     19: *   MainWndProc()
                     20: *   ReadWindowPos()
                     21: *   WriteWindowPos()
                     22: *   InitApplication()
                     23: *   InitInstance()
                     24: *   PenWinRegister()
                     25: *   GetSystemValues()
                     26: *   ReadEnv()
                     27: *   WriteEnv()
                     28: *   LoadSysColorBitmaps()
                     29: *   LoadAlterBitmap()
                     30: *   RGBInvertRGB()
                     31: *   SizeRibbons()
                     32: *   DialogTerminate()
                     33: *
                     34: * Comments:
                     35: *
                     36: * Because of the need for a dialog in both work and test mode to be
                     37: * shown relative to the client area of its parent, and because the
                     38: * editor has a ribbon control along the top of its client area, there
                     39: * needed to be another window created that will be the actual parent
                     40: * of the dialog being edited.  This window, called the ghwndSubClient
                     41: * window, is sized to be the size of the editors client area minus
                     42: * the height of the ribbon window at the top.  This makes it so that
                     43: * a dialog that has an origin of 0,0 will have the top edge of its
                     44: * client area just below the bottom of the ribbon window in the
                     45: * editor.  This window does not need any special processing.  It simply
                     46: * paints its background with the app workspace color, and is used as
                     47: * the basis for coordinate conversion for the dialog.
                     48: *
                     49: ****************************************************************************/
                     50: 
                     51: #include "dlgedit.h"
                     52: #include "dlgfuncs.h"
                     53: #include "dlgextrn.h"
                     54: #include "dialogs.h"
                     55: 
                     56: #include <commdlg.h>
                     57: 
                     58: #include <stdlib.h>
                     59: #include <string.h>
                     60: 
                     61: STATICFN BOOL InitApplication(HANDLE hInstance);
                     62: STATICFN BOOL InitInstance(HANDLE hInstance, INT nCmdShow);
                     63: STATICFN VOID PenWinRegister(VOID);
                     64: STATICFN VOID GetSystemValues(VOID);
                     65: STATICFN VOID ReadEnv(VOID);
                     66: STATICFN VOID WriteEnv(VOID);
                     67: STATICFN VOID LoadSysColorBitmaps(VOID);
                     68: STATICFN HBITMAP LoadAlterBitmap(INT idbm, DWORD rgbNew, DWORD rgbNew2);
                     69: STATICFN DWORD RGBInvertRGB(DWORD rgb);
                     70: STATICFN VOID SizeRibbons(HWND hwnd);
                     71: STATICFN VOID DialogTerminate(VOID);
                     72: 
                     73: static RECT grcAppPos;              // Saves the app's window pos.
                     74: static UINT gmsgHelp;               // Registered help message from commdlg.
                     75: static BOOL fStartAsIcon = FALSE;   // TRUE if app is started minimized.
                     76: 
                     77: /*
                     78:  * Contains the address of the Pen Windows callback.
                     79:  */
                     80: typedef VOID ( APIENTRY *LPFNPENWIN)(WORD, BOOL);
                     81: static LPFNPENWIN lpfnRegisterPenApp;
                     82: 
                     83: 
                     84: 
                     85: /************************************************************************
                     86: * WinMain
                     87: *
                     88: * This is the main function for the dialog editor.
                     89: *
                     90: ************************************************************************/
                     91: 
                     92: INT WINAPI WinMain(
                     93:     HINSTANCE hInstance,
                     94:     HINSTANCE hPrevInstance,
                     95:     LPSTR lpCmdLine,
                     96:     INT nCmdShow)
                     97: {
                     98:     MSG msg;
                     99: 
                    100:     if (!hPrevInstance) {
                    101:         if (!InitApplication(hInstance)) {
                    102:             Message(MSG_NOINIT);
                    103:             return FALSE;
                    104:         }
                    105:     }
                    106: 
                    107:     if (!InitInstance(hInstance, nCmdShow)) {
                    108:         Message(MSG_NOINIT);
                    109:         return FALSE;
                    110:     }
                    111: 
                    112:     while (GetMessage(&msg, NULL, 0, 0)) {
                    113:         if (!ghwndTestDlg || !IsDialogMessage(ghwndTestDlg, &msg)) {
                    114:             if (!hwndStatus || !IsDialogMessage(hwndStatus, &msg)) {
                    115:                 if (!TranslateAccelerator(ghwndMain, ghAccTable, &msg)) {
                    116:                     TranslateMessage(&msg);
                    117:                     DispatchMessage(&msg);
                    118:                 }
                    119:             }
                    120:         }
                    121:     }
                    122: 
                    123:     DialogTerminate();
                    124: 
                    125:     /*
                    126:      * Return the value from PostQuitMessage.
                    127:      */
                    128:     return msg.wParam;
                    129: }
                    130: 
                    131: 
                    132: 
                    133: /************************************************************************
                    134: * InitApplication
                    135: *
                    136: * Registers the window classes.
                    137: *
                    138: * Arguments:
                    139: *   HANDLE hInstance - Instance handle from WinMain.
                    140: *
                    141: * Returns:
                    142: *   TRUE if all of the window classes were created; otherwise, FALSE.
                    143: *
                    144: ************************************************************************/
                    145: 
                    146: STATICFN BOOL InitApplication(
                    147:     HANDLE hInstance)
                    148: {
                    149:     WNDCLASS wc;
                    150: 
                    151:     wc.style = CS_DBLCLKS;
                    152:     wc.lpfnWndProc = MainWndProc;
                    153:     wc.cbClsExtra = 0;
                    154:     wc.cbWndExtra = sizeof(DWORD);
                    155:     wc.hInstance = hInstance;
                    156:     wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDICON_DLGEDIT));
                    157:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    158:     wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
                    159:     wc.lpszMenuName = MAKEINTRESOURCE(IDMENU_MAIN);
                    160:     wc.lpszClassName = szMainClass;
                    161:     if (!RegisterClass(&wc))
                    162:         return FALSE;
                    163: 
                    164:     wc.style = 0;
                    165:     wc.lpfnWndProc = DefWindowProc;
                    166:     wc.cbClsExtra = 0;
                    167:     wc.cbWndExtra = 0;
                    168:     wc.hInstance = hInstance;
                    169:     wc.hIcon = NULL;
                    170:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    171:     wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
                    172:     wc.lpszMenuName = NULL;
                    173:     wc.lpszClassName = szSubClientClass;
                    174:     if (!RegisterClass(&wc))
                    175:         return FALSE;
                    176: 
                    177:     wc.style = CS_DBLCLKS;
                    178:     wc.lpfnWndProc = DragWndProc;
                    179:     wc.cbClsExtra = 0;
                    180:     wc.cbWndExtra = sizeof(DWORD);
                    181:     wc.hInstance = hInstance;
                    182:     wc.hIcon = NULL;
                    183:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    184:     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
                    185:     wc.lpszMenuName = NULL;
                    186:     wc.lpszClassName = szDragClass;
                    187:     if (!RegisterClass(&wc))
                    188:         return FALSE;
                    189: 
                    190:     wc.style = 0;
                    191:     wc.lpfnWndProc = ToolboxWndProc;
                    192:     wc.cbClsExtra = 0;
                    193:     wc.cbWndExtra = 0;
                    194:     wc.hInstance = hInstance;
                    195:     wc.hIcon = NULL;
                    196:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    197:     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
                    198:     wc.lpszMenuName = NULL;
                    199:     wc.lpszClassName = szToolboxClass;
                    200:     if (!RegisterClass(&wc))
                    201:         return FALSE;
                    202: 
                    203:     wc.style = 0;
                    204:     wc.lpfnWndProc = ToolBtnWndProc;
                    205:     wc.cbClsExtra = 0;
                    206:     wc.cbWndExtra = 0;
                    207:     wc.hInstance = hInstance;
                    208:     wc.hIcon = NULL;
                    209:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    210:     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
                    211:     wc.lpszMenuName = NULL;
                    212:     wc.lpszClassName = szToolBtnClass;
                    213:     if (!RegisterClass(&wc))
                    214:         return FALSE;
                    215: 
                    216:     wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
                    217:     wc.lpfnWndProc = CustomWndProc;
                    218:     wc.cbClsExtra = 0;
                    219:     wc.cbWndExtra = 0;
                    220:     wc.hInstance = hInstance;
                    221:     wc.hIcon = NULL;
                    222:     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                    223:     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
                    224:     wc.lpszMenuName = NULL;
                    225:     wc.lpszClassName = szCustomClass;
                    226:     if (!RegisterClass(&wc))
                    227:         return FALSE;
                    228: 
                    229:     return TRUE;
                    230: }
                    231: 
                    232: 
                    233: 
                    234: /************************************************************************
                    235: * InitInstance
                    236: *
                    237: * Initializes the dialog editor by loading resources, etc.
                    238: *
                    239: * Arguments:
                    240: *   HANDLE hInstance - Instance handle from WinMain.
                    241: *   int nCmdShow     - Show command from WinMain.
                    242: *
                    243: * Returns:
                    244: *   FALSE if any errors occurred during initialization
                    245: *
                    246: ************************************************************************/
                    247: 
                    248: STATICFN BOOL InitInstance(
                    249:     HANDLE hInstance,
                    250:     INT nCmdShow)
                    251: {
                    252:     HDC hDC;
                    253:     TEXTMETRIC tm;
                    254:     INT x;
                    255:     INT y;
                    256:     INT cx;
                    257:     INT cy;
                    258:     BOOL fMaximized;
                    259:     INT i;
                    260:     TCHAR szArg1[CCHTEXTMAX];
                    261: 
                    262:     ghInst = hInstance;
                    263: 
                    264:     /*
                    265:      * We need a mouse - make sure we have one.
                    266:      */
                    267:     if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
                    268:         Message(MSG_NOMOUSE);
                    269:         return FALSE;
                    270:     }
                    271: 
                    272:     /*
                    273:      * Register for Pen Windows, if it is present.
                    274:      */
                    275:     PenWinRegister();
                    276: 
                    277:     ghAccTable = LoadAccelerators(ghInst, MAKEINTRESOURCE(IDACCEL_MAIN));
                    278: 
                    279:     /*
                    280:      * Create a dark gray pen for use in borders later.
                    281:      */
                    282:     if (!(hpenDarkGray = CreatePen(PS_SOLID, 1, DARKGRAY)))
                    283:         return FALSE;
                    284: 
                    285:     /*
                    286:      * Get some system constants.
                    287:      */
                    288:     GetSystemValues();
                    289: 
                    290:     /*
                    291:      * Note that this must be done instead of using the text metrics,
                    292:      * because Windows internally generates a better average value for
                    293:      * proportional fonts, and we must match it or our dialogs will
                    294:      * be out of proportion.
                    295:      */
                    296:     gcxSysChar = LOWORD(GetDialogBaseUnits());
                    297:     gcySysChar = HIWORD(GetDialogBaseUnits());
                    298: 
                    299:     /*
                    300:      * Because some useful worker routines like WinToDUPoint use
                    301:      * the values in gcd.c*Char, set them to be the default font right
                    302:      * away.  When a dialog is loaded with a different font, they
                    303:      * will be modified.
                    304:      */
                    305:     gcd.cxChar = gcxSysChar;
                    306:     gcd.cyChar = gcySysChar;
                    307: 
                    308:     /*
                    309:      * Build the help file name path.  Assume the help file is in the
                    310:      * same directory as the executable.
                    311:      */
                    312:     GetModuleFileName(ghInst, gszHelpFile, CCHMAXPATH);
                    313:     *FileInPath(gszHelpFile) = CHAR_NULL;
                    314:     lstrcat(gszHelpFile, ids(IDS_HELPFILE));
                    315: 
                    316:     /*
                    317:      * Register the message for help from the common dialogs.
                    318:      */
                    319:     gmsgHelp = RegisterWindowMessage(HELPMSGSTRING);
                    320: 
                    321:     /*
                    322:      * Hook the message filter stream so that we can detect F1 keystrokes.
                    323:      */
                    324:     ghhkMsgFilter = SetWindowsHook(WH_MSGFILTER, (HOOKPROC)MsgFilterHookFunc);
                    325: 
                    326:     /*
                    327:      * Read the last position for the app.
                    328:      */
                    329:     if (!ReadWindowPos(szAppPos, &x, &y, &cx, &cy, &fMaximized)) {
                    330:         x = CW_USEDEFAULT;
                    331:         y = CW_USEDEFAULT;
                    332:         cx = CW_USEDEFAULT;
                    333:         cy = CW_USEDEFAULT;
                    334:         fMaximized = FALSE;
                    335:     }
                    336: 
                    337:     /*
                    338:      * Create the main window.
                    339:      */
                    340:     if (!(ghwndMain = CreateWindow(szMainClass, NULL,
                    341:             WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                    342:             x, y, cx, cy, NULL, NULL, hInstance, NULL)))
                    343:         return FALSE;
                    344: 
                    345:     ShowFileStatus(TRUE);
                    346: 
                    347:     /*
                    348:      * Read the Preferences data.
                    349:      */
                    350:     ReadEnv();
                    351: 
                    352:     /*
                    353:      * If the app was saved when maximized (and they didn't start it up
                    354:      * with some kind of an option to have it minimized or in some
                    355:      * other funny initial state from the shell), then cause it to
                    356:      * be maximized when shown.
                    357:      */
                    358:     if (fMaximized && (nCmdShow == SW_SHOWNORMAL || nCmdShow == SW_SHOW))
                    359:         nCmdShow = SW_SHOWMAXIMIZED;
                    360: 
                    361:     ShowWindow(ghwndMain, nCmdShow);
                    362:     UpdateWindow(ghwndMain);
                    363: 
                    364:     /*
                    365:      * Did the user start this app minimized from the program manager?
                    366:      */
                    367:     if (IsIconic(ghwndMain)) {
                    368:         /*
                    369:          * Set a flag.  The showing of the toolbox will be deferred
                    370:          * until the app is restored.
                    371:          */
                    372:         fStartAsIcon = TRUE;
                    373:     }
                    374:     else {
                    375:         /*
                    376:          * If they had the Toolbox before, show it now.
                    377:          */
                    378:         if (gfShowToolbox)
                    379:             ToolboxShow(TRUE);
                    380:     }
                    381: 
                    382:     hcurArrow = LoadCursor(NULL, IDC_ARROW);
                    383:     hcurWait = LoadCursor(NULL, IDC_WAIT);
                    384:     hcurOutSel = LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_OUTSEL));
                    385:     hcurMove = LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_MOVE));
                    386:     hcurInsert = LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_INSERT));
                    387:     hcurDropTool = LoadCursor(ghInst, MAKEINTRESOURCE(IDCUR_DROPTOOL));
                    388:     hcurSizeNESW = LoadCursor(NULL, IDC_SIZENESW);
                    389:     hcurSizeNS = LoadCursor(NULL, IDC_SIZENS);
                    390:     hcurSizeNWSE = LoadCursor(NULL, IDC_SIZENWSE);
                    391:     hcurSizeWE = LoadCursor(NULL, IDC_SIZEWE);
                    392: 
                    393:     if (!hcurArrow ||
                    394:             !hcurWait ||
                    395:             !hcurOutSel ||
                    396:             !hcurMove ||
                    397:             !hcurDropTool ||
                    398:             !hcurInsert)
                    399:         return FALSE;
                    400: 
                    401:     if ((hDC = GetDC(ghwndMain)) == NULL)
                    402:         return FALSE;
                    403: 
                    404:     GetTextMetrics(hDC, &tm);
                    405: 
                    406:     gcyPixelsPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
                    407: 
                    408:     /*
                    409:      * Create a memory DC for drawing bitmaps.
                    410:      */
                    411:     ghDCMem = CreateCompatibleDC(hDC);
                    412: 
                    413:     ReleaseDC(ghwndMain, hDC);
                    414: 
                    415:     /*
                    416:      * Load the bitmaps that depend on system colors.
                    417:      */
                    418:     LoadSysColorBitmaps();
                    419: 
                    420:     fmtDlg = RegisterClipboardFormat(L"DIALOG");
                    421: 
                    422:     /*
                    423:      * Initialize the icon control ordinal to the icon id from our exe
                    424:      * that we will use to show these kind of controls.
                    425:      */
                    426:     WriteOrd(&gordIcon, IDICON_ICON);
                    427: 
                    428:     /*
                    429:      * Initialize the default text fields in the awcd array.  Because
                    430:      * CCONTROLS does not include the dialog type, it has to be done
                    431:      * separately.
                    432:      */
                    433:     awcd[W_DIALOG].pszTextDefault = ids(awcd[W_DIALOG].idsTextDefault);
                    434:     for (i = 0; i < CCONTROLS; i++)
                    435:         awcd[i].pszTextDefault = ids(awcd[i].idsTextDefault);
                    436: 
                    437:     /*
                    438:      * If there was a command line argument specified, try and open
                    439:      * it as the initial file.
                    440:      */
                    441:     if (__argc > 1) {
                    442:         MultiByteToWideChar(CP_ACP, 0, __argv[1], -1, szArg1, CCHTEXTMAX);
                    443:         OpenCmdLineFile(szArg1);
                    444:     }
                    445: 
                    446:     /*
                    447:      * Be sure the focus is on the main window.  This corrects a
                    448:      * problem where the accelerators don't initially work because
                    449:      * the focus gets placed on the Properties Bar.
                    450:      */
                    451:     SetFocus(ghwndMain);
                    452: 
                    453:     return TRUE;
                    454: }
                    455: 
                    456: 
                    457: 
                    458: /************************************************************************
                    459: * PenWinRegister
                    460: *
                    461: * This function will register for Pen Windows, if it is present.
                    462: *
                    463: ************************************************************************/
                    464: 
                    465: STATICFN VOID PenWinRegister(VOID)
                    466: {
                    467:     HANDLE hmod;
                    468: 
                    469:     if (!(hmod = (HANDLE)GetSystemMetrics(SM_PENWINDOWS)))
                    470:         return;
                    471: 
                    472:     if (lpfnRegisterPenApp =
                    473:             (LPFNPENWIN)GetProcAddress(hmod, "RegisterPenApp"))
                    474:         (*lpfnRegisterPenApp)(1, TRUE);     // Be Pen-Enhanced!
                    475: }
                    476: 
                    477: 
                    478: 
                    479: /************************************************************************
                    480: * GetSystemValues
                    481: *
                    482: * This function reads various system values.  It is called at init time,
                    483: * as well as if we are informed by a WM_SYSVALUECHANGED message that
                    484: * some of these values have been changed.
                    485: *
                    486: ************************************************************************/
                    487: 
                    488: STATICFN VOID GetSystemValues(VOID)
                    489: {
                    490:     gcyBorder = GetSystemMetrics(SM_CYBORDER);
                    491: 
                    492:     /*
                    493:      * The distance that the mouse can move during a pre-drag operation
                    494:      * before starting to drag the control anyways is based on the
                    495:      * mouse double-click movement distances in the system.
                    496:      */
                    497:     gcxPreDragMax = GetSystemMetrics(SM_CXDOUBLECLK);
                    498:     gcyPreDragMax = GetSystemMetrics(SM_CYDOUBLECLK);
                    499: 
                    500:     /*
                    501:      * The number of milliseconds that the pre-drag debounce time lasts.
                    502:      */
                    503:     gmsecPreDrag = 250;
                    504: }
                    505: 
                    506: 
                    507: 
                    508: /************************************************************************
                    509: * ReadWindowPos
                    510: *
                    511: * This function retrieves the saved window position for a window and
                    512: * returns it in the specified variables.  It is used between sessions
                    513: * to restore the application windows to the position they had when
                    514: * the editor was last exited.
                    515: *
                    516: * Arguments:
                    517: *   LPTSTR pszKeyName  - KeyName the position was saved under.
                    518: *   PINT px            - Saved x position.
                    519: *   PINT py            - Saved y position.
                    520: *   PINT pcx           - Saved width.
                    521: *   PINT pcy           - Saved height.
                    522: *   BOOL *pfMaximized  - Set to TRUE if window was maximized when saved.
                    523: *
                    524: * Returns: 
                    525: *   TRUE if the position could be read, or FALSE otherwise.
                    526: *   If FALSE is returned, the values in the specified variables are
                    527: *   not valid!  The caller must be able to handle a FALSE return and
                    528: *   supply a default position for the window.
                    529: *
                    530: ************************************************************************/
                    531: 
                    532: BOOL ReadWindowPos(
                    533:     LPTSTR pszKeyName,
                    534:     PINT px,
                    535:     PINT py,
                    536:     PINT pcx,
                    537:     PINT pcy,
                    538:     BOOL *pfMaximized)
                    539: {
                    540:     static CHAR szSep[] = " ,";
                    541:     TCHAR szBuf[CCHTEXTMAX];
                    542:     CHAR szBufAnsi[CCHTEXTMAX];
                    543:     PSTR psz;
                    544:     BOOL fDefCharUsed;
                    545: 
                    546:     if (!GetPrivateProfileString(ids(IDS_APPNAME),
                    547:             pszKeyName, szEmpty, szBuf, CCHTEXTMAX, ids(IDS_DLGEDITINI)))
                    548:         return FALSE;
                    549: 
                    550:     WideCharToMultiByte(CP_ACP, 0, szBuf, -1, szBufAnsi, CCHTEXTMAX,
                    551:             NULL, &fDefCharUsed);
                    552: 
                    553:     if (!(psz = strtok(szBufAnsi, szSep)))
                    554:         return FALSE;
                    555: 
                    556:     *px = atoi(psz);
                    557: 
                    558:     if (!(psz = strtok(NULL, szSep)))
                    559:         return FALSE;
                    560: 
                    561:     *py = atoi(psz);
                    562: 
                    563:     if (!(psz = strtok(NULL, szSep)))
                    564:         return FALSE;
                    565: 
                    566:     *pcx = atoi(psz);
                    567: 
                    568:     if (!(psz = strtok(NULL, szSep)))
                    569:         return FALSE;
                    570: 
                    571:     *pcy = atoi(psz);
                    572: 
                    573:     /*
                    574:      * If there is a "1" following the coordinates, the window was
                    575:      * maximized when it was saved.
                    576:      */
                    577:     *pfMaximized = FALSE;
                    578:     if ((psz = strtok(NULL, szSep)) && atoi(psz) == 1)
                    579:         *pfMaximized = TRUE;
                    580: 
                    581:     /*
                    582:      * Don't allow a zero sized window.
                    583:      */
                    584:     if (*pcx == 0 || *pcy == 0)
                    585:         return FALSE;
                    586: 
                    587:     /*
                    588:      * Return success.
                    589:      */
                    590:     return TRUE;
                    591: 
                    592: }
                    593: 
                    594: 
                    595: 
                    596: /************************************************************************
                    597: * WriteWindowPos
                    598: *
                    599: * This function writes the position of a window to the
                    600: * editor's profile file under the specified keyname.
                    601: * The ReadWindowPos function is the counterpart of this
                    602: * function.
                    603: *
                    604: * Arguments:
                    605: *   PRECT prc          - Rectangle for the "restored" window size.
                    606: *   BOOL fMaximized    - TRUE if the window is maximized.
                    607: *   LPTSTR pszKeyName  - KeyName to save the position under.
                    608: *
                    609: ************************************************************************/
                    610: 
                    611: VOID WriteWindowPos(
                    612:     PRECT prc,
                    613:     BOOL fMaximized,
                    614:     LPTSTR pszKeyName)
                    615: {
                    616:     TCHAR szBuf[CCHTEXTMAX];
                    617: 
                    618:     wsprintf(szBuf, L"%d %d %d %d", prc->left, prc->top,
                    619:             prc->right - prc->left, prc->bottom - prc->top);
                    620: 
                    621:     if (fMaximized)
                    622:         lstrcat(szBuf, L" 1");
                    623: 
                    624:     WritePrivateProfileString(ids(IDS_APPNAME),
                    625:             pszKeyName, szBuf, ids(IDS_DLGEDITINI));
                    626: }
                    627: 
                    628: 
                    629: 
                    630: /*************************************************************************
                    631: * ReadEnv
                    632: *
                    633: * This function initializes variables from their counterparts
                    634: * in the private profile file for DlgEdit.  The application
                    635: * merely needs to construct an array of INIENTRY structures
                    636: * to describe the variables that must be initialized.
                    637: *
                    638: * Note that the original value read from the profile is saved when
                    639: * it is read.  This allows us to optimize what needs to be written
                    640: * out with WriteEnv.
                    641: *
                    642: *************************************************************************/
                    643: 
                    644: STATICFN VOID ReadEnv(VOID)
                    645: {
                    646:     register INT i;
                    647: 
                    648:     for (i = 0; gaie[i].pszKeyName; i++) {
                    649:         *gaie[i].pnVar = gaie[i].nSave =
                    650:                 GetPrivateProfileInt(ids(IDS_APPNAME),
                    651:                 gaie[i].pszKeyName, gaie[i].nDefault,
                    652:                 ids(IDS_DLGEDITINI));
                    653:     }
                    654: 
                    655:     ReadCustomProfile();
                    656: }
                    657: 
                    658: 
                    659: 
                    660: /*************************************************************************
                    661: * WriteEnv
                    662: *
                    663: * This function is the counterpart to ReadEnv.  It saves values
                    664: * in the profile file.
                    665: *
                    666: *************************************************************************/
                    667: 
                    668: STATICFN VOID WriteEnv(VOID)
                    669: {
                    670:     register INT i;
                    671:     TCHAR szBuf[17];
                    672: 
                    673:     for (i = 0; gaie[i].pszKeyName; i++) {
                    674:         /*
                    675:          * Has the user changed the value since it was read?
                    676:          */
                    677:         if (gaie[i].nSave != *gaie[i].pnVar) {
                    678:             /*
                    679:              * If the new value is the same as the default value,
                    680:              * erase the entry from the ini file.  Otherwise,
                    681:              * write the user-specified value out.
                    682:              */
                    683:             if (*gaie[i].pnVar == gaie[i].nDefault) {
                    684:                 WritePrivateProfileString(ids(IDS_APPNAME),
                    685:                         gaie[i].pszKeyName, NULL, ids(IDS_DLGEDITINI));
                    686:             }
                    687:             else {
                    688:                 itoaw(*gaie[i].pnVar, szBuf, 10);
                    689:                 WritePrivateProfileString(ids(IDS_APPNAME),
                    690:                         gaie[i].pszKeyName, szBuf, ids(IDS_DLGEDITINI));
                    691:             }
                    692:         }
                    693:     }
                    694: 
                    695:     WriteCustomProfile();
                    696: }
                    697: 
                    698: 
                    699: 
                    700: /************************************************************************
                    701: * MainWndProc
                    702: *
                    703: * This is the window procedure for the "dlgedit" class.  This is the
                    704: * class of the main dialog editor "client" window.
                    705: *
                    706: ************************************************************************/
                    707: 
                    708: WINDOWPROC MainWndProc(
                    709:     HWND hwnd,
                    710:     UINT msg,
                    711:     WPARAM wParam,
                    712:     LPARAM lParam)
                    713: {
                    714:     switch (msg) {
                    715:         case WM_CREATE:
                    716:             {
                    717:                 RECT rc;
                    718: 
                    719:                 /*
                    720:                  * Create the status window.
                    721:                  */
                    722:                 CreateDialog(ghInst, MAKEINTRESOURCE(DID_STATUS),
                    723:                         hwnd, StatusDlgProc);
                    724: 
                    725:                 /*
                    726:                  * Save away its height for sizing later (like when
                    727:                  * the app is minimized then restored).
                    728:                  */
                    729:                 GetWindowRect(hwndStatus, &rc);
                    730:                 gcyStatus = rc.bottom - rc.top;
                    731: 
                    732:                 ghwndSubClient = CreateWindow(szSubClientClass, NULL,
                    733:                         WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
                    734:                         hwnd, NULL, ghInst, NULL);
                    735: 
                    736:                 ghMenuMain = GetMenu(hwnd);
                    737:                 LoadMenuBitmaps(ghMenuMain);
                    738:             }
                    739: 
                    740:             break;
                    741: 
                    742:         case WM_ACTIVATE:
                    743:             /*
                    744:              * If the main window is getting activated, there is no
                    745:              * currently active dialog.
                    746:              */
                    747:             if (LOWORD(wParam))
                    748:                 gidCurrentDlg = 0;
                    749: 
                    750:             goto DoDefault;
                    751: 
                    752:         case WM_INITMENU:
                    753:             if (GetMenu(ghwndMain) == (HMENU)wParam)
                    754:                 InitMenu((HMENU)wParam);
                    755: 
                    756:             break;
                    757: 
                    758:         case WM_MENUSELECT:
                    759:             if (HIWORD(wParam) &
                    760:                     (MF_POPUP | MF_SYSMENU))
                    761:                 gMenuSelected = 0;
                    762:             else
                    763:                 gMenuSelected = LOWORD(wParam);
                    764: 
                    765:             break;
                    766: 
                    767:         case WM_COMMAND:
                    768:             DialogMenu(LOWORD(wParam));
                    769:             break;
                    770: 
                    771:         case WM_KEYDOWN:
                    772:             switch (wParam) {
                    773:                 case VK_UP:
                    774:                 case VK_DOWN:
                    775:                 case VK_LEFT:
                    776:                 case VK_RIGHT:
                    777:                     if ((GetKeyState(VK_SHIFT) & 0x8000) ||
                    778:                             (GetKeyState(VK_CONTROL) & 0x8000))
                    779:                         break;
                    780: 
                    781:                     /*
                    782:                      * Ignore it if we are not in a normal state
                    783:                      * (don't allow when dragging).
                    784:                      */
                    785:                     if (gState != STATE_NORMAL)
                    786:                         break;
                    787: 
                    788:                     /*
                    789:                      * Be sure any outstanding changes get applied
                    790:                      * without errors.
                    791:                      */
                    792:                     if (!StatusApplyChanges())
                    793:                         break;
                    794: 
                    795:                     /*
                    796:                      * Move the control in the specified direction.
                    797:                      */
                    798:                     MoveControl(wParam);
                    799:                     break;
                    800: 
                    801:                 case VK_TAB:
                    802:                     if (GetKeyState(VK_CONTROL) & 0x8000)
                    803:                         break;
                    804: 
                    805:                     /*
                    806:                      * Ignore it if we are not in a normal state
                    807:                      * (don't allow when dragging).
                    808:                      */
                    809:                     if (gState != STATE_NORMAL)
                    810:                         break;
                    811: 
                    812:                     /*
                    813:                      * Be sure any outstanding changes get applied
                    814:                      * without errors.
                    815:                      */
                    816:                     if (!StatusApplyChanges())
                    817:                         break;
                    818: 
                    819:                     /*
                    820:                      * Is the shift key pressed also?
                    821:                      */
                    822:                     if (GetKeyState(VK_SHIFT) & 0x8000)
                    823:                         SelectPrevious();
                    824:                     else
                    825:                         SelectNext();
                    826: 
                    827:                     break;
                    828: 
                    829:                 case VK_ESCAPE:
                    830:                     if ((GetKeyState(VK_SHIFT) & 0x8000) ||
                    831:                             (GetKeyState(VK_CONTROL) & 0x8000))
                    832:                         break;
                    833: 
                    834:                     /*
                    835:                      * Be sure any outstanding changes get applied
                    836:                      * without errors.
                    837:                      */
                    838:                     if (!StatusApplyChanges())
                    839:                         break;
                    840: 
                    841:                     if (gState == STATE_SELECTING)
                    842:                         OutlineSelectCancel();
                    843: 
                    844:                     /*
                    845:                      * Cancel any drag operation they might have been doing.
                    846:                      */
                    847:                     if (gState != STATE_NORMAL)
                    848:                         DragCancel();
                    849: 
                    850:                     break;
                    851: 
                    852:                 case VK_RETURN:
                    853:                     if ((GetKeyState(VK_SHIFT) & 0x8000) ||
                    854:                             (GetKeyState(VK_CONTROL) & 0x8000))
                    855:                         break;
                    856: 
                    857:                     /*
                    858:                      * Be sure any outstanding changes get applied
                    859:                      * without errors.
                    860:                      */
                    861:                     if (!StatusApplyChanges())
                    862:                         break;
                    863: 
                    864:                     switch (gState) {
                    865:                         POINTS mpt;
                    866:                         POINT pt;
                    867:                         DWORD dwPos;
                    868: 
                    869:                         case STATE_SELECTING:
                    870:                             /*
                    871:                              * In outline selection mode.  Map the
                    872:                              * location of the mouse at the time that
                    873:                              * the user pressed Enter into a point
                    874:                              * relative to the dialog client and complete
                    875:                              * the selection operation.
                    876:                              */
                    877:                             dwPos = GetMessagePos();
                    878:                             mpt = (*((POINTS *)&(dwPos)));
                    879:                             ((pt).x = (mpt).x, (pt).y = (mpt).y);
                    880:                             ScreenToClient(gcd.npc->hwnd, &pt);
                    881:                             OutlineSelectEnd(pt.x, pt.y);
                    882: 
                    883:                             break;
                    884: 
                    885:                         case STATE_DRAGGING:
                    886:                         case STATE_DRAGGINGNEW:
                    887:                             /*
                    888:                              * We are dragging something.  Map the
                    889:                              * location of the mouse at the time
                    890:                              * that the user pressed Enter into a
                    891:                              * point relative to the proper window
                    892:                              * and complete the drag operation.
                    893:                              */
                    894:                             dwPos = GetMessagePos();
                    895:                             mpt = (*((POINTS *)&(dwPos)));
                    896:                             ((pt).x = (mpt).x, (pt).y = (mpt).y);
                    897: 
                    898:                             /*
                    899:                              * The point must be changed to be relative to
                    900:                              * the window that the ending mouse up message
                    901:                              * would have come through, which will be the
                    902:                              * capture window for the drag.  This will be
                    903:                              * the dialog if we are adding a new control,
                    904:                              * or it will be the selected control if we are
                    905:                              * dragging an existing control.
                    906:                              */
                    907:                             ScreenToClient((gState == STATE_DRAGGING) ?
                    908:                                     gnpcSel->hwnd : gcd.npc->hwnd, &pt);
                    909: 
                    910:                             /*
                    911:                              * If the dialog is selected, map the points from
                    912:                              * the client area to the window.
                    913:                              */
                    914:                             if (gfDlgSelected)
                    915:                                 MapDlgClientPoint(&pt, TRUE);
                    916: 
                    917:                             DragEnd(pt.x, pt.y);
                    918: 
                    919:                             break;
                    920:                     }
                    921: 
                    922:                     break;
                    923:             }
                    924: 
                    925:             break;
                    926: 
                    927:         case WM_NCCALCSIZE:
                    928:             /*
                    929:              * Save away what is going to be the new window position.
                    930:              */
                    931:             if (!IsIconic(hwnd) && !IsZoomed(hwnd))
                    932:                 grcAppPos = *((LPRECT)lParam);
                    933: 
                    934:             /*
                    935:              * Now let the DefWindowProc calculate the client area normally.
                    936:              */
                    937:             goto DoDefault;
                    938: 
                    939:         case WM_MOVE:
                    940:             if (gfEditingDlg)
                    941:                 RepositionDialog();
                    942: 
                    943:             break;
                    944: 
                    945:         case WM_SIZE:
                    946:             SizeRibbons(hwnd);
                    947: 
                    948:             /*
                    949:              * Did the app start minimized and is it being restored
                    950:              * for the first time?  If so, show the toolbox if
                    951:              * the user has requested it.
                    952:              */
                    953:             if (fStartAsIcon && !IsIconic(hwnd)) {
                    954:                 if (gfShowToolbox)
                    955:                     ToolboxShow(TRUE);
                    956: 
                    957:                 fStartAsIcon = FALSE;
                    958:             }
                    959: 
                    960:             break;
                    961: 
                    962:         case WM_SYSCOLORCHANGE:
                    963:             LoadSysColorBitmaps();
                    964:             break;
                    965: 
                    966:         case WM_CLOSE:
                    967:             if (ghwndTestDlg)
                    968:                 DestroyTestDialog();
                    969: 
                    970:             if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
                    971:                     DoWeSave(FILE_RESOURCE) == IDCANCEL)
                    972:                 break;
                    973: 
                    974:             /*
                    975:              * First destroy the Properties Bar.
                    976:              */
                    977:             DestroyWindow(hwndStatus);
                    978:             hwndStatus = NULL;
                    979: 
                    980:             DestroyWindow(hwnd);
                    981:             break;
                    982: 
                    983:         case WM_QUERYENDSESSION:
                    984:             if (ghwndTestDlg)
                    985:                 DestroyTestDialog();
                    986: 
                    987:             if (DoWeSave(FILE_INCLUDE) == IDCANCEL ||
                    988:                     DoWeSave(FILE_RESOURCE) == IDCANCEL)
                    989:                 return FALSE;
                    990:             else
                    991:                 return TRUE;
                    992: 
                    993:         case WM_DESTROY:
                    994:             /*
                    995:              * Save the position of the app's window.
                    996:              */
                    997:             WriteWindowPos(&grcAppPos, IsZoomed(hwnd), szAppPos);
                    998: 
                    999:             WinHelp(hwnd, gszHelpFile, HELP_QUIT, 0L);
                   1000:             FreeMenuBitmaps();
                   1001:             PostQuitMessage(0);
                   1002:             break;
                   1003: 
                   1004:         default:
                   1005:             /*
                   1006:              * Is this the registered help message from one of the common
                   1007:              * dialogs?  If so, show the help for it.
                   1008:              *
                   1009:              * The check to be sure gmsgHelp is non-zero is just in
                   1010:              * case the call to register the help message failed
                   1011:              * (it will return zero) and there happens to be a zero
                   1012:              * message that gets sent to this window somehow.
                   1013:              */
                   1014:             if (msg == gmsgHelp && gmsgHelp) {
                   1015:                 ShowHelp(FALSE);
                   1016:                 return 0;
                   1017:             }
                   1018: 
                   1019:         DoDefault:
                   1020:             return DefWindowProc(hwnd, msg, wParam, lParam);
                   1021:     }
                   1022: 
                   1023:     return 0;
                   1024: }
                   1025: 
                   1026: 
                   1027: 
                   1028: /************************************************************************
                   1029: * LoadSysColorBitmaps
                   1030: *
                   1031: * This function loads bitmaps that depend on the system window and
                   1032: * highlight colors.  As it loads them, it replaces two special colors
                   1033: * in them with some system colors.
                   1034: * This is used for the control type bitmaps that appear in lines
                   1035: * in the listbox in the Order/Group dialog.
                   1036: *
                   1037: ************************************************************************/
                   1038: 
                   1039: STATICFN VOID LoadSysColorBitmaps(VOID)
                   1040: {
                   1041:     DWORD rgbWindow;
                   1042:     DWORD rgbWindowText;
                   1043:     DWORD rgbHighlight;
                   1044:     DWORD rgbHighlightText;
                   1045:     INT i;
                   1046: 
                   1047:     rgbWindow = GetSysColor(COLOR_WINDOW);
                   1048:     rgbWindowText = GetSysColor(COLOR_WINDOWTEXT);
                   1049:     rgbHighlight = GetSysColor(COLOR_HIGHLIGHT);
                   1050:     rgbHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
                   1051: 
                   1052:     if (hbmTabStop)
                   1053:         DeleteObject(hbmTabStop);
                   1054: 
                   1055:     hbmTabStop = LoadAlterBitmap(IDBM_TABSTOP, rgbWindow, rgbWindowText);
                   1056: 
                   1057:     if (hbmTabStopSel)
                   1058:         DeleteObject(hbmTabStopSel);
                   1059: 
                   1060:     hbmTabStopSel = LoadAlterBitmap(IDBM_TABSTOP,
                   1061:             rgbHighlight, rgbHighlightText);
                   1062: 
                   1063:     for (i = 0; i < CCONTROLS; i++) {
                   1064:         if (awcd[i].hbmCtrlType)
                   1065:             DeleteObject(awcd[i].hbmCtrlType);
                   1066: 
                   1067:         awcd[i].hbmCtrlType = LoadAlterBitmap(
                   1068:                 awcd[i].idbmCtrlType, rgbWindow, rgbWindowText);
                   1069: 
                   1070:         if (awcd[i].hbmCtrlTypeSel)
                   1071:             DeleteObject(awcd[i].hbmCtrlTypeSel);
                   1072: 
                   1073:         awcd[i].hbmCtrlTypeSel = LoadAlterBitmap(
                   1074:                 awcd[i].idbmCtrlType, rgbHighlight, rgbHighlightText);
                   1075:     }
                   1076: 
                   1077:     if (ghbmDragHandle)
                   1078:         DeleteObject(ghbmDragHandle);
                   1079: 
                   1080:     ghbmDragHandle = LoadAlterBitmap(IDBM_DRAGHANDLE,
                   1081:             rgbWindow, rgbHighlight);
                   1082: 
                   1083:     if (ghbmDragHandle2)
                   1084:         DeleteObject(ghbmDragHandle2);
                   1085: 
                   1086:     ghbmDragHandle2 = LoadAlterBitmap(IDBM_DRAGHANDLE2,
                   1087:             rgbWindow, rgbHighlight);
                   1088: }
                   1089: 
                   1090: 
                   1091: 
                   1092: /************************************************************************
                   1093: * LoadAlterBitmap
                   1094: *
                   1095: * This function loads a single bitmap.  As it does, it replaces a
                   1096: * couple special RGB colors (REPLACECOLOR1 and REPLACECOLOR2) with
                   1097: * the passed in RGB colors.
                   1098: *
                   1099: * Arguments:
                   1100: *   INT idbm      - Integer ID of the bitmap to load.
                   1101: *   DWORD rgbNew  - Color to replace the special color with.
                   1102: *   DWORD rgbNew2 - A second color to replace the second special color with.
                   1103: *
                   1104: * Returns:
                   1105: *   The handle to the bitmap, or NULL if an error occurs.
                   1106: *
                   1107: ************************************************************************/
                   1108: 
                   1109: STATICFN HBITMAP LoadAlterBitmap(
                   1110:     INT idbm,
                   1111:     DWORD rgbNew,
                   1112:     DWORD rgbNew2)
                   1113: {
                   1114:     register INT i;
                   1115:     LPBITMAPINFOHEADER lpbihInfo;
                   1116:     HDC hdcScreen;
                   1117:     HANDLE hresLoad;
                   1118:     HANDLE hres;
                   1119:     DWORD FAR *qlng;
                   1120:     LPBYTE lpbBits;
                   1121:     HANDLE hbmp;
                   1122:     DWORD rgbReplace1;
                   1123:     DWORD rgbReplace2;
                   1124: 
                   1125:     hresLoad = FindResource(ghInst, MAKEINTRESOURCE(idbm), RT_BITMAP);
                   1126:     if (!hresLoad)
                   1127:         return NULL;
                   1128: 
                   1129:     hres = LoadResource(ghInst, hresLoad);
                   1130:     if (!hresLoad)
                   1131:         return NULL;
                   1132: 
                   1133:     rgbNew = RGBInvertRGB(rgbNew);
                   1134:     rgbNew2 = RGBInvertRGB(rgbNew2);
                   1135:     rgbReplace1 = RGBInvertRGB(REPLACECOLOR1);
                   1136:     rgbReplace2 = RGBInvertRGB(REPLACECOLOR2);
                   1137:     lpbihInfo = (LPBITMAPINFOHEADER)LockResource(hres);
                   1138:     qlng = (LPDWORD)((PBYTE)(lpbihInfo) + lpbihInfo->biSize);
                   1139: 
                   1140:     for (i = 0; i < (1 << lpbihInfo->biBitCount); i++, qlng++) {
                   1141:         if (*qlng == rgbReplace1)
                   1142:             *qlng = rgbNew;
                   1143:         else if (*qlng == rgbReplace2)
                   1144:             *qlng = rgbNew2;
                   1145:     }
                   1146: 
                   1147:     /*
                   1148:      * First skip over the header structure.
                   1149:      */
                   1150:     lpbBits = (LPBYTE)(lpbihInfo + 1);
                   1151: 
                   1152:     /*
                   1153:      * Skip the color table entries, if any.
                   1154:      */
                   1155:     lpbBits += (1 << (lpbihInfo->biBitCount)) * sizeof(RGBQUAD);
                   1156: 
                   1157:     /*
                   1158:      * Create a color bitmap compatible with the display device.
                   1159:      */
                   1160:     if (hdcScreen = GetDC(NULL)) {
                   1161:         hbmp = CreateDIBitmap(hdcScreen, lpbihInfo, (LONG)CBM_INIT,
                   1162:                 lpbBits, (LPBITMAPINFO)lpbihInfo, DIB_RGB_COLORS);
                   1163:         ReleaseDC(NULL, hdcScreen);
                   1164:     }
                   1165: 
                   1166:     UnlockResource(hres);
                   1167:     FreeResource(hres);
                   1168: 
                   1169:     return hbmp;
                   1170: }
                   1171: 
                   1172: 
                   1173: 
                   1174: /************************************************************************
                   1175: * RGBInvertRGB
                   1176: *
                   1177: * Reverses the RGB order of a color.  This needs to be done to match
                   1178: * the resource file format of the color table.
                   1179: *
                   1180: ************************************************************************/
                   1181: 
                   1182: STATICFN DWORD RGBInvertRGB(
                   1183:     DWORD rgb)
                   1184: {
                   1185:     return (DWORD)RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb));
                   1186: }
                   1187: 
                   1188: 
                   1189: 
                   1190: /************************************************************************
                   1191: * SizeRibbons
                   1192: *
                   1193: * This function positions and sizes the child ribbon and subclient
                   1194: * windows in the dialog editor.  It needs to be called any time the
                   1195: * size of the main windows changes.
                   1196: *
                   1197: * Arguments:
                   1198: *   HWND hwnd - Parent window handle.
                   1199: *
                   1200: ************************************************************************/
                   1201: 
                   1202: STATICFN VOID SizeRibbons(
                   1203:     HWND hwnd)
                   1204: {
                   1205:     RECT rcClient;
                   1206: 
                   1207:     if (hwndStatus && !IsIconic(hwnd)) {
                   1208:         /*
                   1209:          * Get the client area.
                   1210:          */
                   1211:         GetClientRect(hwnd, &rcClient);
                   1212: 
                   1213:         /*
                   1214:          * Size/move the status and subclient window to fit
                   1215:          * the new client area.
                   1216:          */
                   1217:         SetWindowPos(hwndStatus, NULL,
                   1218:                 0, 0,
                   1219:                 rcClient.right - rcClient.left,
                   1220:                 min(rcClient.bottom - rcClient.top, gcyStatus),
                   1221:                 SWP_NOACTIVATE | SWP_NOZORDER);
                   1222: 
                   1223:         SetWindowPos(ghwndSubClient, NULL,
                   1224:                 0, gcyStatus,
                   1225:                 rcClient.right - rcClient.left,
                   1226:                 max((rcClient.bottom - rcClient.top) - gcyStatus, 0),
                   1227:                 SWP_NOACTIVATE | SWP_NOZORDER);
                   1228:     }
                   1229: }
                   1230: 
                   1231: 
                   1232: 
                   1233: /****************************************************************************
                   1234: * DialogTerminate
                   1235: *
                   1236: * This undoes what DialogInit does.  It should be called before terminating
                   1237: * and after a DialogInit.
                   1238: *
                   1239: ****************************************************************************/
                   1240: 
                   1241: STATICFN VOID DialogTerminate(VOID)
                   1242: {
                   1243:     register INT i;
                   1244: 
                   1245:     /*
                   1246:      * Save the Preferences data.
                   1247:      */
                   1248:     WriteEnv();
                   1249: 
                   1250:     if (hbmTabStop)
                   1251:         DeleteObject(hbmTabStop);
                   1252: 
                   1253:     if (hbmTabStopSel)
                   1254:         DeleteObject(hbmTabStopSel);
                   1255: 
                   1256:     if (ghbmDragHandle)
                   1257:         DeleteObject(ghbmDragHandle);
                   1258: 
                   1259:     if (ghbmDragHandle2)
                   1260:         DeleteObject(ghbmDragHandle2);
                   1261: 
                   1262:     if (ghDCMem)
                   1263:         DeleteDC(ghDCMem);
                   1264: 
                   1265:     /*
                   1266:      * Free the control type bitmaps.
                   1267:      */
                   1268:     for (i = 0; i < CCONTROLS; i++) {
                   1269:         if (awcd[i].hbmCtrlType)
                   1270:             DeleteObject(awcd[i].hbmCtrlType);
                   1271: 
                   1272:         if (awcd[i].hbmCtrlTypeSel)
                   1273:             DeleteObject(awcd[i].hbmCtrlTypeSel);
                   1274:     }
                   1275: 
                   1276:     /*
                   1277:      * Free all the custom control links.  This must be done before the
                   1278:      * app exits so that any loaded DLL's get unloaded!
                   1279:      */
                   1280:     while (gpclHead)
                   1281:         RemoveCustomLink(gpclHead);
                   1282: 
                   1283:     if (hpenDarkGray)
                   1284:         DeleteObject(hpenDarkGray);
                   1285: 
                   1286:     if (ghhkMsgFilter)
                   1287:         UnhookWindowsHookEx(ghhkMsgFilter);
                   1288: 
                   1289:     if (lpfnRegisterPenApp)
                   1290:         (*lpfnRegisterPenApp)((WORD)1, FALSE);
                   1291: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.