|
|
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: addctrl.c ! 14: * ! 15: * Contains routines for adding (creating) and deleting controls. ! 16: * ! 17: * Functions: ! 18: * ! 19: * AddNewDialog() ! 20: * DropControl() ! 21: * AddControl() ! 22: * CreateControl() ! 23: * CreateDlgFont() ! 24: * MyGetCharDimensions() ! 25: * AdjustDefaultSizes() ! 26: * DeleteControl() ! 27: * DeleteDialog() ! 28: * DeleteControl2() ! 29: * FreeCTYPE() ! 30: * ! 31: * Comments: ! 32: * ! 33: ****************************************************************************/ ! 34: ! 35: #include "dlgedit.h" ! 36: #include "dlgfuncs.h" ! 37: #include "dlgextrn.h" ! 38: #include "dialogs.h" ! 39: ! 40: #include <stdlib.h> ! 41: #include <string.h> ! 42: ! 43: STATICFN HFONT CreateDlgFont(HWND hwnd, LPTSTR pszFontName, ! 44: INT nPointSize); ! 45: STATICFN INT MyGetCharDimensions(HWND hwnd, HFONT hFont, ! 46: PTEXTMETRIC ptm); ! 47: STATICFN VOID AdjustDefaultSizes(VOID); ! 48: STATICFN VOID DeleteControl2(NPCTYPE npcDel); ! 49: STATICFN VOID FreeCTYPE(NPCTYPE npc); ! 50: ! 51: ! 52: ! 53: /************************************************************************ ! 54: * AddNewDialog ! 55: * ! 56: * High level function to add a new dialog to the current resource. ! 57: * Any existing dialog will be saved away in the resource buffer. ! 58: * The dialog is created at a default position and size with default ! 59: * styles. ! 60: * ! 61: ************************************************************************/ ! 62: ! 63: VOID AddNewDialog(VOID) ! 64: { ! 65: RECT rc; ! 66: ! 67: if (gfEditingDlg) { ! 68: if (!SynchDialogResource()) ! 69: return; ! 70: ! 71: DeleteDialog(FALSE); ! 72: } ! 73: ! 74: /* ! 75: * Now drop a new dialog window. ! 76: */ ! 77: SetRect(&rc, DEFDIALOGXPOS, DEFDIALOGYPOS, ! 78: DEFDIALOGXPOS + awcd[W_DIALOG].cxDefault, ! 79: DEFDIALOGYPOS + awcd[W_DIALOG].cyDefault); ! 80: DropControl(&awcd[W_DIALOG], &rc); ! 81: } ! 82: ! 83: ! 84: ! 85: /************************************************************************ ! 86: * DropControl ! 87: * ! 88: * This function drops a new control of Type at the specified ! 89: * location. The default style and text of the control is ! 90: * determined from the awcd table based on its type. The control ! 91: * is selected after being dropped. This function changes the status ! 92: * window to reflect the selected control. ! 93: * ! 94: * Arguments: ! 95: * PWINDOWCLASSDESC pwcd - Describes the type of new control. ! 96: * PRECT prc - Rectangle of the new control (in dialog units). ! 97: * ! 98: ************************************************************************/ ! 99: ! 100: VOID DropControl( ! 101: PWINDOWCLASSDESC pwcd, ! 102: PRECT prc) ! 103: { ! 104: ORDINAL ordIcon; ! 105: ORDINAL ordDlg; ! 106: LPTSTR pszText; ! 107: NPCTYPE npcNew; ! 108: INT idCtrl; ! 109: DIALOGINFO di; ! 110: ! 111: /* ! 112: * Get the next available id to use for the new control. ! 113: */ ! 114: idCtrl = NextID((pwcd->iType == W_DIALOG) ? NEXTID_DIALOG : NEXTID_CONTROL, ! 115: plInclude, 0); ! 116: ! 117: if (pwcd->iType == W_ICON) { ! 118: /* ! 119: * For icon controls, the text is really an ordinal or name ! 120: * of the icon resource to display. We get the next available ! 121: * id (skipping the id we just got for the control itself) to ! 122: * use as an ordinal. ! 123: */ ! 124: WriteOrd(&ordIcon, NextID(NEXTID_CONTROL, plInclude, idCtrl)); ! 125: pszText = (LPTSTR)&ordIcon; ! 126: } ! 127: else { ! 128: pszText = pwcd->pszTextDefault; ! 129: } ! 130: ! 131: /* ! 132: * Make the control. ! 133: */ ! 134: if (pwcd->iType == W_DIALOG) { ! 135: /* ! 136: * Pick a default name for the dialog. ! 137: */ ! 138: WriteOrd(&ordDlg, NextID(NEXTID_DIALOG, plInclude, 0)); ! 139: ! 140: di.fResFlags = DEFDLGMEMFLAGS; ! 141: di.wLanguage = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); ! 142: di.pszClass = NULL; ! 143: di.pszMenu = NULL; ! 144: di.DataVersion = 0; ! 145: di.Version = 0; ! 146: di.Characteristics = 0; ! 147: di.nPointSize = DEFPOINTSIZE; ! 148: lstrcpy(di.szFontName, ids(IDS_DEFFONTNAME)); ! 149: ! 150: npcNew = AddControl(pwcd, pszText, ! 151: pwcd->flStyles, pwcd->flExtStyle, idCtrl, ! 152: prc->left, prc->top, ! 153: prc->right - prc->left, prc->bottom - prc->top, ! 154: (LPTSTR)&ordDlg, &di); ! 155: } ! 156: else { ! 157: npcNew = AddControl(pwcd, pszText, ! 158: pwcd->flStyles, pwcd->flExtStyle, idCtrl, ! 159: prc->left, prc->top, ! 160: prc->right - prc->left, prc->bottom - prc->top, ! 161: NULL, NULL); ! 162: } ! 163: ! 164: if (!npcNew) ! 165: return; ! 166: ! 167: /* ! 168: * If we just dropped a dialog, we need to now show it. ! 169: * It it was some other control, mark the dialog as having ! 170: * been changed. ! 171: */ ! 172: if (pwcd->iType == W_DIALOG) { ! 173: ShowWindow(npcNew->hwnd, SW_SHOWNA); ! 174: ToolboxOnTop(); ! 175: } ! 176: else { ! 177: gfDlgChanged = TRUE; ! 178: } ! 179: ! 180: SelectControl(npcNew, FALSE); ! 181: ! 182: gfResChged = TRUE; ! 183: ShowFileStatus(FALSE); ! 184: ! 185: /* ! 186: * Now we determine if one of the fields in the status ribbon ! 187: * should be given the focus initially. The assumption is that ! 188: * there are some things that a user will always want to change ! 189: * when dropping a new control, such as the text in a push ! 190: * button, for example. ! 191: */ ! 192: idCtrl = 0; ! 193: switch (pwcd->iType) { ! 194: case W_ICON: ! 195: /* ! 196: * For icons, the first thing the user will ! 197: * probably want to do is to change the name. ! 198: */ ! 199: idCtrl = DID_STATUSNAME; ! 200: break; ! 201: ! 202: default: ! 203: /* ! 204: * If this control has text, they will probably want ! 205: * to change it. This includes the caption if the ! 206: * control is a dialog. ! 207: */ ! 208: if (pwcd->fHasText) ! 209: idCtrl = DID_STATUSTEXT; ! 210: ! 211: break; ! 212: } ! 213: ! 214: if (idCtrl) { ! 215: SendDlgItemMessage(hwndStatus, idCtrl, ! 216: EM_SETSEL, (WPARAM)(0), (LONG)(-1)); ! 217: SetFocus(GetDlgItem(hwndStatus, idCtrl)); ! 218: } ! 219: } ! 220: ! 221: ! 222: ! 223: /************************************************************************ ! 224: * AddControl ! 225: * ! 226: * This function is used to add a new control. CreateControl() does ! 227: * half the work. ! 228: * ! 229: * Arguments: ! 230: * PWINDOWCLASSDESC pwcd - Window class structure. Describes the ! 231: * type of control to add. ! 232: * LPTSTR pszText - Text for the new control. ! 233: * DWORD style - Style of the new control. ! 234: * DWORD flExtStyle - Extended style of the new control. ! 235: * INT id - ID for the new control. ! 236: * INT x - X location of the new control. ! 237: * INT y - Y location of the new control. ! 238: * INT cx - Width of the new control. ! 239: * INT cy - Height of the new control. ! 240: * LPTSTR pszDlgName - For dialogs, has dialog name. ! 241: * PDIALOGINFO pdi - Ptr to additional dialog info (NULL for controls). ! 242: * ! 243: * Returns: ! 244: * A pointer to the CTYPE structure for the new control. ! 245: * NULL if it couldn't create the control. ! 246: * ! 247: ************************************************************************/ ! 248: ! 249: NPCTYPE AddControl( ! 250: PWINDOWCLASSDESC pwcd, ! 251: LPTSTR pszText, ! 252: DWORD style, ! 253: DWORD flExtStyle, ! 254: INT id, ! 255: INT x, ! 256: INT y, ! 257: INT cx, ! 258: INT cy, ! 259: LPTSTR pszDlgName, ! 260: PDIALOGINFO pdi) ! 261: { ! 262: NPCTYPE npcNew; ! 263: NPCTYPE npcT; ! 264: NPCTYPE *npnpcLast; ! 265: HWND hwndBehind; ! 266: ! 267: if (!(npcNew = (NPCTYPE)MyAlloc(sizeof(CTYPE)))) ! 268: return NULL; ! 269: ! 270: /* ! 271: * These are checked later if a failure occurs, ! 272: * so we null them out now. ! 273: */ ! 274: npcNew->hwnd = NULL; ! 275: npcNew->hwndDrag = NULL; ! 276: npcNew->text = NULL; ! 277: ! 278: /* ! 279: * Set up some fields and create the control. ! 280: */ ! 281: npcNew->npcNext = NULL; ! 282: npcNew->pwcd = pwcd; ! 283: npcNew->fSelected = FALSE; ! 284: SetRect(&npcNew->rc, x, y, x + cx, y + cy); ! 285: ! 286: if (pwcd->iType == W_DIALOG) ! 287: hwndBehind = (HWND)NULL; ! 288: else ! 289: hwndBehind = (HWND)1; ! 290: ! 291: if (!CreateControl(npcNew, pszText, style, flExtStyle, id, &npcNew->rc, ! 292: hwndBehind, pdi)) ! 293: goto CreateFailed; ! 294: ! 295: /* ! 296: * Create the drag window, unless this is the dialog. ! 297: */ ! 298: if (pwcd->iType != W_DIALOG) { ! 299: npcNew->hwndDrag = CreateWindow( ! 300: szDragClass, ! 301: NULL, ! 302: WS_CHILD, ! 303: 0, 0, 0, 0, ! 304: gcd.npc->hwnd, ! 305: NULL, ! 306: ghInst, ! 307: NULL); ! 308: ! 309: /* ! 310: * Store the CTYPE pointer into the control's drag window. ! 311: * This will be used by PCFROMHWND later. ! 312: */ ! 313: SETPCINTOHWND(npcNew->hwndDrag, npcNew); ! 314: ! 315: /* ! 316: * Move the drag window to the top of the Z-Order. ! 317: */ ! 318: SetWindowPos(npcNew->hwndDrag, NULL, 0, 0, 0, 0, ! 319: SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW); ! 320: ! 321: SizeDragToControl(npcNew); ! 322: } ! 323: ! 324: /* ! 325: * Did we just create a dialog? ! 326: */ ! 327: if (pwcd->iType == W_DIALOG) { ! 328: /* ! 329: * First, copy the new name (it can be an ordinal!). ! 330: */ ! 331: if (!(gcd.pszDlgName = MyAlloc(NameOrdLen(pszDlgName)))) ! 332: goto CreateFailed; ! 333: ! 334: NameOrdCpy(gcd.pszDlgName, pszDlgName); ! 335: ! 336: /* ! 337: * Now, setup some other globals. We clear the gcd.prl pointer, ! 338: * because we are assuming that this dialog was not created ! 339: * from a res link (it was dropped instead). The routines ! 340: * that call AddControl when creating a dialog from a res ! 341: * link are responsible for setting this global later. ! 342: */ ! 343: gcd.prl = NULL; ! 344: gcd.npc = npcNew; ! 345: gfEditingDlg = TRUE; ! 346: } ! 347: else { ! 348: /* ! 349: * Search for the last control in the list. ! 350: */ ! 351: npnpcLast = &npcHead; ! 352: for (npcT = npcHead; npcT; npcT = npcT->npcNext) ! 353: npnpcLast = &npcT->npcNext; ! 354: ! 355: /* ! 356: * Link in the new control at the end of the list. ! 357: */ ! 358: *npnpcLast = npcNew; ! 359: cWindows++; ! 360: } ! 361: ! 362: return npcNew; ! 363: ! 364: CreateFailed: ! 365: FreeCTYPE(npcNew); ! 366: return NULL; ! 367: } ! 368: ! 369: ! 370: ! 371: /************************************************************************ ! 372: * CreateControl ! 373: * ! 374: * Creates a control. Some styles may be masked off of the actual ! 375: * control created. This function can also create the dialog box. ! 376: * ! 377: * If the control created is the dialog box, it will not be made visible. ! 378: * This must be done by the caller. This allows the caller to first add ! 379: * all the controls to the dialog before showing it. ! 380: * ! 381: * The x, y, cx and cy coordinates are all in dialog units. For a ! 382: * type of W_DIALOG, this will be relative to the apps client. For a ! 383: * control, this will be relative to the "client" area of the dialog. ! 384: * ! 385: * Arguments: ! 386: * NPCTYPE npc - The CTYPE pointer to the new control. The hwnd ! 387: * fields of the npc will be set. ! 388: * LPTSTR pszText - The window text. ! 389: * DWORD flStyle - The style to use. ! 390: * DWORD flExtStyle - Extended style of the new control. ! 391: * INT id - ID for the control. ! 392: * PRECT prc - The size and location of the new control. ! 393: * HWND hwndBehind - Put new control behind this hwnd in Z-order. ! 394: * PDIALOGINFO pdi - Pointer to additional dialog info (NULL for controls). ! 395: * ! 396: * Returns: ! 397: * Handle of the control created. ! 398: * NULL if control was not created. ! 399: * ! 400: ************************************************************************/ ! 401: ! 402: HWND CreateControl( ! 403: NPCTYPE npc, ! 404: LPTSTR pszText, ! 405: DWORD flStyle, ! 406: DWORD flExtStyle, ! 407: INT id, ! 408: PRECT prc, ! 409: HWND hwndBehind, ! 410: PDIALOGINFO pdi) ! 411: { ! 412: HWND hwnd; ! 413: HWND hwndChild; ! 414: WNDPROC lpfnChild; ! 415: RECT rcT; ! 416: TEXTMETRIC tm; ! 417: LPTSTR pszCreateClass; ! 418: LPTSTR pszTextOld; ! 419: INT iType = npc->pwcd->iType; ! 420: ! 421: /* ! 422: * Set the text field. Remember that it can be an ordinal ! 423: * (for icon controls). ! 424: */ ! 425: pszTextOld = npc->text; ! 426: if (pszText && *pszText) { ! 427: if (!(npc->text = MyAlloc(NameOrdLen(pszText)))) ! 428: return NULL; ! 429: ! 430: NameOrdCpy(npc->text, pszText); ! 431: } ! 432: else { ! 433: npc->text = NULL; ! 434: } ! 435: ! 436: /* ! 437: * If there was text before on this control, free it now. ! 438: * This should be done after the new text is allocated and ! 439: * copied, because it is common to pass this routine the same ! 440: * pointer, and we don't want to free the text before we have ! 441: * copied it! ! 442: */ ! 443: if (pszTextOld) ! 444: MyFree(pszTextOld); ! 445: ! 446: /* ! 447: * Also set some other values in the CTYPE structure. ! 448: */ ! 449: npc->id = id; ! 450: npc->flStyle = flStyle; ! 451: npc->flExtStyle = flExtStyle; ! 452: ! 453: /* ! 454: * If this is a dialog and it has the WS_CHILD style, remove ! 455: * it and make it WS_POPUP instead. This prevents some problems ! 456: * when editing the dialog. ! 457: */ ! 458: if (iType == W_DIALOG && (flStyle & WS_CHILD)) { ! 459: flStyle &= ~WS_CHILD; ! 460: flStyle |= WS_POPUP; ! 461: } ! 462: ! 463: /* ! 464: * If this is an emulated custom control, we always make it with the ! 465: * default styles no matter what the user has specified. If not, ! 466: * remove any styles that can cause problems for a control of this ! 467: * type, such as OWNERDRAW styles. ! 468: */ ! 469: if (npc->pwcd->fEmulated) ! 470: flStyle = awcd[W_CUSTOM].flStyles; ! 471: else ! 472: flStyle &= ~npc->pwcd->flStylesBad; ! 473: ! 474: if (iType == W_DIALOG) { ! 475: /* ! 476: * If the style includes the DS_MODALFRAME bit, set the appropriate ! 477: * extended style bit. ! 478: */ ! 479: if (flStyle & DS_MODALFRAME) ! 480: flExtStyle |= WS_EX_DLGMODALFRAME; ! 481: ! 482: /* ! 483: * Create the dialog, but don't show it yet. ! 484: */ ! 485: hwnd = CreateWindowEx( ! 486: flExtStyle, ! 487: MAKEINTRESOURCE(DIALOGCLASS), ! 488: npc->text, ! 489: flStyle & ~WS_VISIBLE, ! 490: 0, 0, 0, 0, ! 491: ghwndSubClient, ! 492: 0, ! 493: ghInst, ! 494: NULL); ! 495: } ! 496: else { ! 497: /* ! 498: * Get the size of the control. ! 499: */ ! 500: rcT = *prc; ! 501: ! 502: /* ! 503: * Map the dialog unit rectangle to window coords. ! 504: */ ! 505: DUToWinRect(&rcT); ! 506: ! 507: /* ! 508: * If this is an icon, the text field is actually going ! 509: * to be an ordinal that has the resource id. We must map this to ! 510: * an id of our own or when we create the control it will cause a ! 511: * "Resource not found" error. ! 512: */ ! 513: if (iType == W_ICON) ! 514: pszText = (LPTSTR)&gordIcon; ! 515: else ! 516: pszText = npc->text; ! 517: ! 518: /* ! 519: * Get the class name to use. In the case of custom controls, ! 520: * if the control is emulated, use the special emulator class. ! 521: * Otherwise, it is an installed custom control, and we can use ! 522: * it's real class string. ! 523: */ ! 524: if (iType == W_CUSTOM) { ! 525: if (npc->pwcd->fEmulated) ! 526: pszCreateClass = szCustomClass; ! 527: else ! 528: pszCreateClass = npc->pwcd->pszClass; ! 529: } ! 530: else { ! 531: pszCreateClass = ids(acsd[awcd[iType].iClass].idsClass); ! 532: } ! 533: ! 534: /* ! 535: * Create the control. We always create it visible in work mode, ! 536: * even if the style says it isn't. ! 537: */ ! 538: hwnd = CreateWindowEx( ! 539: flExtStyle, ! 540: pszCreateClass, ! 541: pszText, ! 542: flStyle | WS_VISIBLE, ! 543: rcT.left, rcT.top, ! 544: rcT.right - rcT.left, ! 545: rcT.bottom - rcT.top, ! 546: gcd.npc->hwnd, ! 547: 0, ! 548: ghInst, ! 549: NULL); ! 550: } ! 551: ! 552: if (!hwnd) { ! 553: Message(MSG_CREATECTRLERROR, pszCreateClass); ! 554: return NULL; ! 555: } ! 556: ! 557: if (iType == W_DIALOG) { ! 558: /* ! 559: * Did they specify a font? ! 560: */ ! 561: if (*pdi->szFontName) { ! 562: gcd.hFont = CreateDlgFont(hwnd, pdi->szFontName, pdi->nPointSize); ! 563: lstrcpy(gcd.di.szFontName, pdi->szFontName); ! 564: gcd.di.nPointSize = pdi->nPointSize; ! 565: gcd.fFontSpecified = TRUE; ! 566: } ! 567: else { ! 568: gcd.hFont = NULL; ! 569: *gcd.di.szFontName = CHAR_NULL; ! 570: gcd.di.nPointSize = 0; ! 571: gcd.fFontSpecified = FALSE; ! 572: } ! 573: ! 574: /* ! 575: * Get the dimensions of the font. It is a possible case that ! 576: * they specified a font but it could not be created, so in ! 577: * that case we use the system font as well as if they didn't ! 578: * specify a font at all. ! 579: */ ! 580: if (gcd.hFont) { ! 581: gcd.cxChar = MyGetCharDimensions(hwnd, gcd.hFont, &tm); ! 582: gcd.cyChar = tm.tmHeight; ! 583: } ! 584: else { ! 585: gcd.cxChar = gcxSysChar; ! 586: gcd.cyChar = gcySysChar; ! 587: } ! 588: ! 589: /* ! 590: * Now that we know what font we are using, adjust some entries ! 591: * in the awcd (array of window class data) table for default ! 592: * sizing of controls. ! 593: */ ! 594: AdjustDefaultSizes(); ! 595: } ! 596: ! 597: /* ! 598: * If there is a valid user specified font, inform the control ! 599: * of it. Once the font has been set into the dialog, it ! 600: * must not be destroyed, because the dialog window will ! 601: * clean it up when it is destroyed. ! 602: */ ! 603: if (gcd.hFont) ! 604: SendMessage(hwnd, WM_SETFONT, (WPARAM)gcd.hFont, 0L); ! 605: ! 606: /* ! 607: * Move the window into the requested Z-Order. ! 608: */ ! 609: SetWindowPos(hwnd, hwndBehind, 0, 0, 0, 0, ! 610: SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW); ! 611: ! 612: /* ! 613: * Store the CTYPE pointer into the control's hwnd. ! 614: * This will be used by PCFROMHWND later. ! 615: */ ! 616: SETPCINTOHWND(hwnd, npc); ! 617: ! 618: /* ! 619: * Subclass the control. ! 620: */ ! 621: npc->pwcd->pfnOldWndProc = ! 622: (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, ! 623: (iType == W_DIALOG) ? (DWORD)DialogCtrlWndProc : ! 624: (DWORD)CtrlWndProc); ! 625: ! 626: /* ! 627: * Be sure double-clicks are enabled for this control. ! 628: */ ! 629: (UINT)SetClassLong((hwnd), GCL_STYLE, (LONG)((UINT)GetClassLong((hwnd), GCL_STYLE) | CS_DBLCLKS)); ! 630: ! 631: /* ! 632: * Subclass any children this control may have. ! 633: */ ! 634: for (hwndChild = GetTopWindow(hwnd); hwndChild; ! 635: hwndChild = GetNextWindow(hwndChild, GW_HWNDNEXT)) { ! 636: lpfnChild = (WNDPROC)SetWindowLong(hwndChild, ! 637: GWL_WNDPROC, (DWORD)ChildWndProc); ! 638: SETCHILDPROC(hwndChild, lpfnChild); ! 639: } ! 640: ! 641: /* ! 642: * Did we just create a dialog? ! 643: */ ! 644: if (iType == W_DIALOG) { ! 645: /* ! 646: * Now that the dialog is created, we can figure out how to ! 647: * size it. We start by mapping the dialog units to window ! 648: * coordinates, ! 649: */ ! 650: rcT = *prc; ! 651: DUToWinRect(&rcT); ! 652: ! 653: /* ! 654: * We now have the rectangle for the client area. Expand it ! 655: * to account for the frame controls. ! 656: */ ! 657: AdjustWindowRectEx(&rcT, flStyle, FALSE, flExtStyle); ! 658: ! 659: /* ! 660: * Now we can map the rect from the apps client area ! 661: * to the desktop, then we set the dialogs position. ! 662: */ ! 663: ClientToScreenRect(ghwndSubClient, &rcT); ! 664: SetWindowPos(hwnd, NULL, ! 665: rcT.left, rcT.top, ! 666: rcT.right - rcT.left, rcT.bottom - rcT.top, ! 667: SWP_NOZORDER | SWP_NOACTIVATE); ! 668: ! 669: SaveDlgClientRect(hwnd); ! 670: ! 671: /* ! 672: * Save the class name, if any. ! 673: */ ! 674: if (pdi->pszClass && *pdi->pszClass) { ! 675: if (!(gcd.di.pszClass = MyAlloc(NameOrdLen(pdi->pszClass)))) { ! 676: DestroyWindow(hwnd); ! 677: return (HWND)NULL; ! 678: } ! 679: ! 680: NameOrdCpy(gcd.di.pszClass, pdi->pszClass); ! 681: } ! 682: else { ! 683: gcd.di.pszClass = NULL; ! 684: } ! 685: ! 686: /* ! 687: * Save the menu name, if any. ! 688: */ ! 689: if (pdi->pszMenu && *pdi->pszMenu) { ! 690: if (!(gcd.di.pszMenu = MyAlloc(NameOrdLen(pdi->pszMenu)))) { ! 691: DestroyWindow(hwnd); ! 692: return (HWND)NULL; ! 693: } ! 694: ! 695: NameOrdCpy(gcd.di.pszMenu, pdi->pszMenu); ! 696: } ! 697: else { ! 698: gcd.di.pszMenu = NULL; ! 699: } ! 700: ! 701: /* ! 702: * Set some other fields in the additional dialog info structure. ! 703: */ ! 704: gcd.di.fResFlags = pdi->fResFlags; ! 705: gcd.di.wLanguage = pdi->wLanguage; ! 706: gcd.di.DataVersion = pdi->DataVersion; ! 707: gcd.di.Version = pdi->Version; ! 708: gcd.di.Characteristics = pdi->Characteristics; ! 709: } ! 710: ! 711: npc->hwnd = hwnd; ! 712: return hwnd; ! 713: } ! 714: ! 715: ! 716: ! 717: /************************************************************************ ! 718: * CreateDlgFont ! 719: * ! 720: * This function creates a font with the given face name and point size ! 721: * and returns a handle to it. ! 722: * ! 723: * Arguments: ! 724: * HWND hwnd - Dialog window handle. ! 725: * LPTSTR pszFontName - Name of the font (for example: "Helv"). ! 726: * INT nPointSize - Point size of the font (for example: 8 or 12). ! 727: * ! 728: * Returns: ! 729: * A handle to the created font, or NULL if it could not be created. ! 730: * ! 731: ************************************************************************/ ! 732: ! 733: STATICFN HFONT CreateDlgFont( ! 734: HWND hwnd, ! 735: LPTSTR pszFontName, ! 736: INT nPointSize) ! 737: { ! 738: HFONT hFont; ! 739: HFONT hFontOld; ! 740: HDC hDC; ! 741: LOGFONT lf; ! 742: TCHAR szFaceName[LF_FACESIZE]; ! 743: ! 744: /* ! 745: * Initialize the logical font structure. Note that filling the ! 746: * structure with zeros gives it all the default settings. ! 747: */ ! 748: memset(&lf, 0, sizeof(LOGFONT)); ! 749: lf.lfHeight = (SHORT)-PointSizeToPixels(nPointSize); ! 750: lf.lfWeight = FW_BOLD; ! 751: lstrcpy(lf.lfFaceName, pszFontName); ! 752: ! 753: if (!(hFont = CreateFontIndirect(&lf))) ! 754: return NULL; ! 755: ! 756: /* ! 757: * If we didn't get the face name that was requested, delete the ! 758: * new font and return NULL. This will effectively select the ! 759: * system font for this dialog. ! 760: */ ! 761: hDC = GetDC(hwnd); ! 762: if (hFontOld = SelectObject(hDC, hFont)) { ! 763: GetTextFace(hDC, LF_FACESIZE, szFaceName); ! 764: SelectObject(hDC, hFontOld); ! 765: ! 766: if (lstrcmpi(szFaceName, pszFontName) != 0) { ! 767: DeleteObject(hFont); ! 768: hFont = NULL; ! 769: } ! 770: } ! 771: else { ! 772: DeleteObject(hFont); ! 773: hFont = NULL; ! 774: } ! 775: ! 776: ReleaseDC(hwnd, hDC); ! 777: ! 778: return hFont; ! 779: } ! 780: ! 781: ! 782: ! 783: /************************************************************************ ! 784: * MyGetCharDimensions ! 785: * ! 786: * This function calculates the average character width of the given ! 787: * font for the given window. This must be used instead of ! 788: * simply using the tmAveCharWidth field of the text metrics, because ! 789: * this value is not correct for proportional fonts. ! 790: * ! 791: * Arguments: ! 792: * HWND hwnd - The window handle. ! 793: * HFONT hFont - The font handle. ! 794: * PTEXTMETRIC ptm - Where to return the text metrics. ! 795: * ! 796: * Returns: ! 797: * The average character width. The text metrics are returned in ! 798: * the TEXTMETRIC structure pointed to by ptm. ! 799: * ! 800: ************************************************************************/ ! 801: ! 802: STATICFN INT MyGetCharDimensions( ! 803: HWND hwnd, ! 804: HFONT hFont, ! 805: PTEXTMETRIC ptm) ! 806: { ! 807: register INT i; ! 808: HDC hDC; ! 809: SIZE size; ! 810: INT iWidth; ! 811: TCHAR szAveCharWidth[52]; ! 812: HFONT hFontOld; ! 813: ! 814: hDC = GetDC(hwnd); ! 815: hFontOld = SelectObject(hDC, hFont); ! 816: ! 817: GetTextMetrics(hDC, ptm); ! 818: ! 819: /* ! 820: * Is this a variable pitch font? ! 821: */ ! 822: if (ptm->tmPitchAndFamily & 0x01) { ! 823: for (i = 0; i < 26; i++) ! 824: szAveCharWidth[i] = (TCHAR)(i + CHAR_A); ! 825: ! 826: for (i = 0; i < 26; i++) ! 827: szAveCharWidth[i + 26] = (TCHAR)(i + CHAR_CAP_A); ! 828: ! 829: GetTextExtentPoint(hDC, szAveCharWidth, 52, &size); ! 830: iWidth = (INT)size.cx / 26; ! 831: ! 832: // ! 833: // Round it up. ! 834: // ! 835: iWidth = (iWidth + 1) / 2; ! 836: } ! 837: else { ! 838: iWidth = ptm->tmAveCharWidth; ! 839: } ! 840: ! 841: SelectObject(hDC, hFontOld); ! 842: ReleaseDC(hwnd, hDC); ! 843: ! 844: return iWidth; ! 845: } ! 846: ! 847: ! 848: ! 849: /************************************************************************ ! 850: * AdjustDefaultSizes ! 851: * ! 852: * This functions adjusts some default size entries in the awcd (array of ! 853: * window class data) table. ! 854: * This must be done at run time, because the actual values depend on the ! 855: * system that dlgedit is being run on and the font of the current dialog. ! 856: * ! 857: * This function should be called any time that a dialog is created, ! 858: * or its font is changed. ! 859: * ! 860: ************************************************************************/ ! 861: ! 862: STATICFN VOID AdjustDefaultSizes(VOID) ! 863: { ! 864: awcd[W_ICON].cxDefault = ! 865: (((GetSystemMetrics(SM_CXICON) * 4) * 2) + gcd.cxChar) ! 866: / (gcd.cxChar * 2); ! 867: ! 868: awcd[W_ICON].cyDefault = ! 869: (((GetSystemMetrics(SM_CYICON) * 8) * 2) + gcd.cyChar) ! 870: / (gcd.cyChar * 2); ! 871: ! 872: awcd[W_VERTSCROLL].cxDefault = ! 873: (((GetSystemMetrics(SM_CXVSCROLL) * 4) * 2) + gcd.cxChar) ! 874: / (gcd.cxChar * 2); ! 875: ! 876: awcd[W_HORZSCROLL].cyDefault = ! 877: (((GetSystemMetrics(SM_CYHSCROLL) * 8) * 2) + gcd.cyChar) ! 878: / (gcd.cyChar * 2); ! 879: } ! 880: ! 881: ! 882: ! 883: /************************************************************************ ! 884: * DeleteControl ! 885: * ! 886: * This deletes all selected controls from the dialog being edited ! 887: * (or the dialog itself, if it is selected). ! 888: * ! 889: ************************************************************************/ ! 890: ! 891: VOID DeleteControl(VOID) ! 892: { ! 893: if (gfDlgSelected) { ! 894: if (Message(MSG_DELETEDIALOG) == IDYES) ! 895: /* ! 896: * Delete the dialog, including the resource for it. ! 897: */ ! 898: DeleteDialog(TRUE); ! 899: } ! 900: else { ! 901: while (gnpcSel) ! 902: DeleteControl2(gnpcSel); ! 903: ! 904: gfDlgChanged = TRUE; ! 905: } ! 906: ! 907: gfResChged = TRUE; ! 908: ShowFileStatus(FALSE); ! 909: StatusUpdate(); ! 910: StatusSetEnable(); ! 911: } ! 912: ! 913: ! 914: ! 915: /************************************************************************ ! 916: * DeleteControl2 ! 917: * ! 918: * This deletes a control by destroying its window and removing it ! 919: * from the linked list of controls associated with the dialog box. ! 920: * The control is destroyed and the window is unlinked and the CTYPE free'd. ! 921: * ! 922: ************************************************************************/ ! 923: ! 924: STATICFN VOID DeleteControl2( ! 925: NPCTYPE npcDel) ! 926: { ! 927: register NPCTYPE npcT; ! 928: register NPCTYPE *npnpcLast; ! 929: ! 930: UnSelectControl(npcDel); ! 931: ! 932: /* ! 933: * Search for the control, unlink it from the list and free it. ! 934: */ ! 935: npcT = npcHead; ! 936: npnpcLast = &npcHead; ! 937: while (npcT) { ! 938: if (npcT == npcDel) { ! 939: *npnpcLast = npcT->npcNext; ! 940: FreeCTYPE(npcT); ! 941: cWindows--; ! 942: break; ! 943: } ! 944: ! 945: npnpcLast = &npcT->npcNext; ! 946: npcT = npcT->npcNext; ! 947: } ! 948: } ! 949: ! 950: ! 951: ! 952: /************************************************************************ ! 953: * DeleteDialog ! 954: * ! 955: * This deletes the dialog box being worked on and sets globals ! 956: * and the Status Window appropriately. All CTYPEs are freed, the ! 957: * status window is updated and the dialog window is destroyed. ! 958: * ! 959: * Arguments: ! 960: * BOOL fResAlso - If TRUE, delete the dialog resource also. ! 961: * ! 962: ************************************************************************/ ! 963: ! 964: VOID DeleteDialog( ! 965: BOOL fResAlso) ! 966: { ! 967: register NPCTYPE npcT; ! 968: register NPCTYPE npcNext; ! 969: ! 970: CancelSelection(FALSE); ! 971: ! 972: /* ! 973: * If they requested that the dialog resource be deleted also, ! 974: * do it first while some globals are still set. ! 975: */ ! 976: if (fResAlso) ! 977: DeleteDialogResource(); ! 978: ! 979: /* ! 980: * Hide the window for better painting speed. ! 981: */ ! 982: ShowWindow(gcd.npc->hwnd, SW_HIDE); ! 983: ! 984: /* ! 985: * Free all the controls. ! 986: */ ! 987: npcT = npcHead; ! 988: while (npcT) { ! 989: npcNext = npcT->npcNext; ! 990: FreeCTYPE(npcT); ! 991: npcT = npcNext; ! 992: } ! 993: npcHead = NULL; ! 994: cWindows = 0; ! 995: ! 996: /* ! 997: * Free the dialog itself. ! 998: */ ! 999: FreeCTYPE(gcd.npc); ! 1000: ! 1001: if (gcd.pszDlgName) { ! 1002: MyFree(gcd.pszDlgName); ! 1003: gcd.pszDlgName = NULL; ! 1004: } ! 1005: ! 1006: if (gcd.di.pszClass) { ! 1007: MyFree(gcd.di.pszClass); ! 1008: gcd.di.pszClass = NULL; ! 1009: } ! 1010: ! 1011: if (gcd.di.pszMenu) { ! 1012: MyFree(gcd.di.pszMenu); ! 1013: gcd.di.pszMenu = NULL; ! 1014: } ! 1015: ! 1016: if (gcd.hFont) { ! 1017: DeleteObject(gcd.hFont); ! 1018: gcd.hFont = NULL; ! 1019: } ! 1020: ! 1021: gcd.fFontSpecified = FALSE; ! 1022: *gcd.di.szFontName = CHAR_NULL; ! 1023: ! 1024: /* ! 1025: * Set these globals back to the system font values so that ! 1026: * workers like WinToDUPoint will still work. ! 1027: */ ! 1028: gcd.cxChar = gcxSysChar; ! 1029: gcd.cyChar = gcySysChar; ! 1030: ! 1031: gcd.prl = NULL; ! 1032: ! 1033: gcd.npc = NULL; ! 1034: gfEditingDlg = FALSE; ! 1035: gfDlgChanged = FALSE; ! 1036: ! 1037: ToolboxSelectTool(W_NOTHING, FALSE); ! 1038: StatusUpdate(); ! 1039: StatusSetEnable(); ! 1040: } ! 1041: ! 1042: ! 1043: ! 1044: /************************************************************************ ! 1045: * FreeCTYPE ! 1046: * ! 1047: * This function frees an allocated CTYPE. The associated control or ! 1048: * dialog window is destroyed, and memory for the text and/or class ! 1049: * is freed, followed by freeing the actual CTYPE structure itself. ! 1050: * ! 1051: * If the hwnd in the CTYPE is NULL, only the text (if not NULL) is ! 1052: * assumed to be valid and will be freed, followed by the CTYPE structure ! 1053: * itself. This allows FreeCTYPE to be called when the CTYPE is only ! 1054: * partially initialized. This is a little dependant on the order that ! 1055: * a CTYPE is allocated and initialized in AddControl(). ! 1056: * ! 1057: * Arguments: ! 1058: * NPCTYPE npc = The CTYPE to free. ! 1059: * ! 1060: ************************************************************************/ ! 1061: ! 1062: STATICFN VOID FreeCTYPE( ! 1063: NPCTYPE npc) ! 1064: { ! 1065: if (npc->hwnd) ! 1066: DestroyWindow(npc->hwnd); ! 1067: ! 1068: if (npc->hwndDrag) ! 1069: DestroyWindow(npc->hwndDrag); ! 1070: ! 1071: if (npc->text) ! 1072: MyFree(npc->text); ! 1073: ! 1074: MyFree(npc); ! 1075: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.