|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.