|
|
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: restodlg.c ! 14: * ! 15: * Routines that take a dialog resource and create the dialog to edit, or ! 16: * the other way around. ! 17: * ! 18: * Fucntions: ! 19: * SynchDialogResource() ! 20: * AllocDialogResource() ! 21: * ResLinkToDialog() ! 22: * ResToDialog() ! 23: * GetiClass() ! 24: * Duplicate() ! 25: * MakeCopyFromRes() ! 26: * TypeFromClassStyle() ! 27: * ! 28: * Comments: ! 29: * ! 30: ****************************************************************************/ ! 31: ! 32: #include "dlgedit.h" ! 33: #include "dlgfuncs.h" ! 34: #include "dlgextrn.h" ! 35: ! 36: STATICFN INT TypeFromClassStyle(INT iClass, DWORD flStyle); ! 37: ! 38: ! 39: ! 40: /************************************************************************ ! 41: * SynchDialogResource ! 42: * ! 43: * This routine synchronizes the resource buffer with the contents of ! 44: * the current dialog being edited. This may involve deleting the old ! 45: * contents of the current dialog prior to adding the new data. ! 46: * ! 47: * It is ok to call this routine even if there is not an existing dialog ! 48: * being edited (it will just return) and it should be called before any ! 49: * operation that needs the in memory copy of the dialog to accurately ! 50: * reflect the contents of the current dialog, such as just before a ! 51: * save to disk. ! 52: * ! 53: * Returns: ! 54: * TRUE if all goes well (includes the case where nothing was done). ! 55: * FALSE if an error occurs updating the resource. ! 56: * ! 57: ************************************************************************/ ! 58: ! 59: BOOL SynchDialogResource(VOID) ! 60: { ! 61: PRES pRes; ! 62: PRESLINK prl; ! 63: PRESLINK prlNew; ! 64: PRESLINK prlPrev; ! 65: ! 66: if (!gfEditingDlg) ! 67: return TRUE; ! 68: ! 69: /* ! 70: * Allocate a resource for the current dialog. ! 71: */ ! 72: if (!(pRes = AllocDialogResource(FALSE, FALSE))) ! 73: return FALSE; ! 74: ! 75: /* ! 76: * Allocate a new link for it. ! 77: */ ! 78: if (!(prlNew = AllocResLink(pRes))) ! 79: return FALSE; ! 80: ! 81: /* ! 82: * Free the local copy of the dialog resource now that the ! 83: * link has been created (and the resource copied to global ! 84: * memory). ! 85: */ ! 86: MyFree(pRes); ! 87: ! 88: /* ! 89: * Does a link for the dialog already exist? ! 90: */ ! 91: if (gcd.prl) { ! 92: /* ! 93: * Find the existing link and get it's previous link. ! 94: */ ! 95: for (prl = gprlHead, prlPrev = NULL; prl && prl != gcd.prl; ! 96: prlPrev = prl, prl = prl->prlNext) ! 97: ; ! 98: ! 99: /* ! 100: * Start linking it in. ! 101: */ ! 102: prlNew->prlNext = gcd.prl->prlNext; ! 103: ! 104: if (prlPrev) ! 105: prlPrev->prlNext = prlNew; ! 106: else ! 107: gprlHead = prlNew; ! 108: ! 109: /* ! 110: * Delete the old link now that it is replaced. ! 111: */ ! 112: FreeResLink(gcd.prl); ! 113: } ! 114: else { ! 115: /* ! 116: * Search for the end of the list. Get a pointer to the last link. ! 117: */ ! 118: for (prl = gprlHead, prlPrev = NULL; prl; ! 119: prlPrev = prl, prl = prl->prlNext) ! 120: ; ! 121: ! 122: /* ! 123: * Add the new link to the end of the list. ! 124: */ ! 125: if (prlPrev) ! 126: prlPrev->prlNext = prlNew; ! 127: else ! 128: gprlHead = prlNew; ! 129: } ! 130: ! 131: /* ! 132: * Update our global with the new link. Clear the "dialog changed" ! 133: * flag. ! 134: */ ! 135: gcd.prl = prlNew; ! 136: gfDlgChanged = FALSE; ! 137: ! 138: return TRUE; ! 139: } ! 140: ! 141: ! 142: ! 143: /************************************************************************ ! 144: * AllocDialogResource ! 145: * ! 146: * This function allocates memory and builds a resource file format ! 147: * image in it of the current dialog. ! 148: * ! 149: * Arguments: ! 150: * BOOL fTestMode - TRUE if a special test mode version of the current ! 151: * dialog should be created. ! 152: * BOOL fClipboard - If TRUE, only the selected control(s) will be ! 153: * placed in the resource. This is used when putting ! 154: * controls or groups of controls into the clipboard. ! 155: * If the dialog is selected, this flag is ignored, ! 156: * because selecting the dialog implies all the ! 157: * controls will be written out also. ! 158: * ! 159: * Returns: ! 160: * Pointer to the resource buffer. ! 161: * NULL if unable to create the resource. ! 162: * ! 163: ************************************************************************/ ! 164: ! 165: PRES AllocDialogResource( ! 166: BOOL fTestMode, ! 167: BOOL fClipboard) ! 168: { ! 169: NPCTYPE npc; ! 170: INT cControls; ! 171: BOOL fSelectedOnly = FALSE; ! 172: INT cbDlgName; ! 173: INT cbCaption; ! 174: INT cbPointSize; ! 175: INT cbFontName; ! 176: INT cbCD; ! 177: INT cbResHeader; ! 178: INT cbResData; ! 179: INT cbResSize; ! 180: INT cbMenuName; ! 181: INT cbClass; ! 182: INT cbText; ! 183: INT cbAlloc; ! 184: PBYTE pb; ! 185: PRES pResBegin; ! 186: PRES pResBegin2; ! 187: LPTSTR pszClass; ! 188: LPTSTR pszMenu; ! 189: LPTSTR pszText; ! 190: DWORD flStyle; ! 191: PDIALOGBOXHEADER pdbh; ! 192: PCONTROLDATA pcd; ! 193: ORDINAL ordClass; ! 194: ! 195: cControls = cWindows; ! 196: if (fClipboard && !gfDlgSelected) { ! 197: fSelectedOnly = TRUE; ! 198: for (cControls = 0, npc = npcHead; npc; npc = npc->npcNext) ! 199: if (npc->fSelected) ! 200: cControls++; ! 201: } ! 202: ! 203: /* ! 204: * If testing, don't allow a dialog to be created with any ! 205: * special class, or with the real menu. ! 206: */ ! 207: if (fTestMode) { ! 208: pszClass = NULL; ! 209: pszMenu = NULL; ! 210: } ! 211: else { ! 212: pszClass = gcd.di.pszClass; ! 213: pszMenu = gcd.di.pszMenu; ! 214: } ! 215: ! 216: cbDlgName = NameOrdLen(gcd.pszDlgName); ! 217: cbCaption = (gcd.npc->text) ? ! 218: (lstrlen(gcd.npc->text) + 1) * sizeof(TCHAR) : sizeof(TCHAR); ! 219: cbClass = pszClass ? NameOrdLen(pszClass) : sizeof(TCHAR); ! 220: cbMenuName = pszMenu ? NameOrdLen(pszMenu) : sizeof(TCHAR); ! 221: ! 222: if (gcd.fFontSpecified) { ! 223: cbPointSize = sizeof(WORD); ! 224: cbFontName = (lstrlen(gcd.di.szFontName) + 1) * sizeof(TCHAR); ! 225: } ! 226: else { ! 227: cbPointSize = cbFontName = 0; ! 228: } ! 229: ! 230: /* ! 231: * Calculate the size of the resource header. ! 232: */ ! 233: cbResHeader = sizeof(RES) + // The first fixed part. ! 234: sizeof(ORDINAL) + // The RT_DIALOG ordinal. ! 235: cbDlgName; // The dialog's name. ! 236: DWordAlign((PBYTE *)&cbResHeader); // Pad for the dialog's name. ! 237: cbResHeader += sizeof(RES2); // The last fixed part. ! 238: ! 239: /* ! 240: * Calculate the size of the resource data. This will just include ! 241: * the dialog box header right now. ! 242: */ ! 243: cbResData = SIZEOF_DIALOGBOXHEADER + // The first fixed part. ! 244: cbMenuName + // The menu. ! 245: cbClass + // The class. ! 246: cbCaption + // The caption. ! 247: cbPointSize + // The point size. ! 248: cbFontName; // The font name. ! 249: ! 250: /* ! 251: * Allocate some buffer space. Be sure to round this up to a DWORD ! 252: * boundary to allow space for padding if necessary, but don't round ! 253: * cbResData field because it will need to be written into the header ! 254: * later, and the value that is written is an exact size (not rounded ! 255: * up). ! 256: */ ! 257: cbAlloc = cbResSize = cbResHeader + cbResData; ! 258: DWordAlign((PBYTE *)&cbAlloc); ! 259: if (!(pResBegin = (PRES)MyAlloc(cbAlloc))) ! 260: return NULL; ! 261: ! 262: /* ! 263: * Write the resource header. ! 264: */ ! 265: pdbh = (PDIALOGBOXHEADER)WriteResHeader(pResBegin, 0, ORDID_RT_DIALOG, ! 266: gcd.pszDlgName, gcd.di.fResFlags, gcd.di.wLanguage, ! 267: gcd.di.DataVersion, gcd.di.Version, gcd.di.Characteristics); ! 268: ! 269: /* ! 270: * Write out the style. ! 271: */ ! 272: flStyle = gcd.npc->flStyle; ! 273: if (fTestMode) { ! 274: flStyle &= ~awcd[W_DIALOG].flStylesTestBad; ! 275: flStyle |= WS_VISIBLE; ! 276: } ! 277: ! 278: pdbh->lStyle = flStyle; ! 279: pdbh->lExtendedStyle = gcd.npc->flExtStyle; ! 280: pdbh->NumberOfItems = (WORD)cControls; ! 281: ! 282: /* ! 283: * Write the coordinates. ! 284: * ! 285: * If we are allocating a template that only has the selected controls ! 286: * in it, we put the value of CONTROLS_ONLY in the "cx" field of the ! 287: * dialog header. This is what we will check when the user pastes ! 288: * something from the clipboard into a dialog to determine whether ! 289: * to paste the entire dialog, or only the controls within the dialog ! 290: * item array. ! 291: */ ! 292: pdbh->x = (WORD)gcd.npc->rc.left; ! 293: pdbh->y = (WORD)gcd.npc->rc.top; ! 294: ! 295: if (fSelectedOnly) ! 296: pdbh->cx = CONTROLS_ONLY; ! 297: else ! 298: pdbh->cx = (WORD)(gcd.npc->rc.right - gcd.npc->rc.left); ! 299: ! 300: pdbh->cy = (WORD)(gcd.npc->rc.bottom - gcd.npc->rc.top); ! 301: ! 302: pb = (PBYTE)pdbh + SIZEOF_DIALOGBOXHEADER; ! 303: ! 304: /* ! 305: * Write the menu name if there is one (we always write at least a null. ! 306: */ ! 307: pb = NameOrdCpy((LPTSTR)pb, pszMenu ? pszMenu : szEmpty); ! 308: ! 309: /* ! 310: * Write the class if there is one (we always write at least a null. ! 311: */ ! 312: pb = NameOrdCpy((LPTSTR)pb, pszClass ? pszClass : szEmpty); ! 313: ! 314: /* ! 315: * Write the caption if there is one (we always write at least a null). ! 316: */ ! 317: pb = WriteSz((LPTSTR)pb, gcd.npc->text ? gcd.npc->text : szEmpty); ! 318: ! 319: /* ! 320: * Write out the font, if there is one specified. ! 321: */ ! 322: if (gcd.fFontSpecified) { ! 323: *(PWORD)pb = (WORD)gcd.di.nPointSize; ! 324: pb += sizeof(WORD); ! 325: ! 326: pb = WriteSz((LPTSTR)pb, gcd.di.szFontName); ! 327: } ! 328: ! 329: /* ! 330: * Pad to a DWORD boundary. This is ok even if there are no controls ! 331: * that follow, because we were sure to allocate on an even dword ! 332: * boundary above. ! 333: */ ! 334: DWordPad(&pb); ! 335: ! 336: /* ! 337: * Now do dialog items. ! 338: */ ! 339: for (npc = npcHead; npc; npc = npc->npcNext) { ! 340: /* ! 341: * Skip the control if it is NOT selected and we only want the ! 342: * selected controls. ! 343: */ ! 344: if (fSelectedOnly && !npc->fSelected) ! 345: continue; ! 346: ! 347: /* ! 348: * If we are testing, we don't want to really create a control ! 349: * with some funny class because it probably won't be found. ! 350: * We will substitute our custom class emulator instead. ! 351: */ ! 352: if (fTestMode && npc->pwcd->fEmulated) ! 353: pszClass = szCustomClass; ! 354: else ! 355: pszClass = npc->pwcd->pszClass; ! 356: ! 357: /* ! 358: * Get a pointer to the text. If this is an icon control and ! 359: * we are going into test mode, change the text field so that ! 360: * it points to an ordinal for DlgEdit's icon to display, or ! 361: * the icon resource will probably not be found when the dialog ! 362: * is created. ! 363: */ ! 364: pszText = npc->text; ! 365: if (npc->pwcd->iType == W_ICON && fTestMode) ! 366: pszText = (LPTSTR)&gordIcon; ! 367: ! 368: cbText = pszText ? NameOrdLen(pszText) : sizeof(TCHAR); ! 369: cbClass = pszClass ? NameOrdLen(pszClass) : sizeof(ORDINAL); ! 370: ! 371: cbCD = SIZEOF_CONTROLDATA + // The fixed portion. ! 372: cbClass + // The class. ! 373: cbText + // The text. ! 374: sizeof(WORD); // nExtraStuff field. ! 375: ! 376: /* ! 377: * Since we are adding a new control, we dword align the ! 378: * previous size of the resource data to ensure the new ! 379: * control starts on a dword boundary. ! 380: */ ! 381: DWordAlign((PBYTE *)&cbResSize); ! 382: ! 383: /* ! 384: * Allocate room for this control. This includes room for the ! 385: * template structure, class, text and a byte for the cb field ! 386: * for the create struct data. ! 387: */ ! 388: cbAlloc = cbResSize + cbCD; ! 389: DWordAlign((PBYTE *)&cbAlloc); ! 390: pResBegin2 = (PRES)MyRealloc((PBYTE)pResBegin, cbAlloc); ! 391: if (!pResBegin2) { ! 392: MyFree(pResBegin); ! 393: return NULL; ! 394: } ! 395: ! 396: pResBegin = pResBegin2; ! 397: pcd = (PCONTROLDATA)((PBYTE)pResBegin + cbResSize); ! 398: cbResSize += cbCD; ! 399: ! 400: /* ! 401: * Write the style. If testing, remove any styles that can ! 402: * cause problems, such as ownerdraw styles. If testing and ! 403: * this is an emulated custom control, always make it with ! 404: * the default styles no matter what the user has specified. ! 405: */ ! 406: flStyle = npc->flStyle; ! 407: if (fTestMode) { ! 408: if (npc->pwcd->fEmulated) ! 409: flStyle = awcd[W_CUSTOM].flStyles; ! 410: else ! 411: flStyle &= ~npc->pwcd->flStylesTestBad; ! 412: } ! 413: ! 414: pcd->lStyle = flStyle; ! 415: pcd->lExtendedStyle = npc->flExtStyle; ! 416: ! 417: /* ! 418: * Write the coordinates. ! 419: */ ! 420: pcd->x = (WORD)npc->rc.left; ! 421: pcd->y = (WORD)npc->rc.top; ! 422: pcd->cx = (WORD)(npc->rc.right - npc->rc.left); ! 423: pcd->cy = (WORD)(npc->rc.bottom - npc->rc.top); ! 424: ! 425: /* ! 426: * Write the id. ! 427: */ ! 428: pcd->wId = (WORD)npc->id; ! 429: ! 430: pb = (PBYTE)pcd + SIZEOF_CONTROLDATA; ! 431: ! 432: /* ! 433: * Write the class. This will be a string, except for the ! 434: * predefined control classes, which all have an ordinal ! 435: * value defined for them. ! 436: */ ! 437: if (pszClass) { ! 438: pb = NameOrdCpy((LPTSTR)pb, pszClass); ! 439: } ! 440: else { ! 441: WriteOrd(&ordClass, acsd[awcd[npc->pwcd->iType].iClass].idOrd); ! 442: pb = NameOrdCpy((LPTSTR)pb, (LPTSTR)&ordClass); ! 443: } ! 444: ! 445: /* ! 446: * Write the text. ! 447: */ ! 448: pb = NameOrdCpy((LPTSTR)pb, pszText ? pszText : szEmpty); ! 449: ! 450: /* ! 451: * Write out a zero because there are no additional bytes ! 452: * of create struct data. ! 453: */ ! 454: *(PWORD)pb = 0; ! 455: pb += sizeof(WORD); ! 456: ! 457: /* ! 458: * Pad to a DWORD boundary. This is ok even if there are no more ! 459: * controls, because we were sure to allocate on an even dword ! 460: * boundary above. ! 461: */ ! 462: DWordPad(&pb); ! 463: } ! 464: ! 465: /* ! 466: * Now go back and fill in the resource data size field. ! 467: */ ! 468: pResBegin->DataSize = cbResSize - cbResHeader; ! 469: ! 470: return pResBegin; ! 471: } ! 472: ! 473: ! 474: ! 475: /************************************************************************ ! 476: * ResLinkToDialog ! 477: * ! 478: * This function is used to create a dialog out of a dialog resource ! 479: * that has been stored in the resource linked list. ! 480: * ! 481: * Arguments: ! 482: * PRESLINK prl - Points to the link that describes the dialog to ! 483: * create. It is assumed that the resource is a ! 484: * dialog resource. ! 485: * ! 486: ************************************************************************/ ! 487: ! 488: VOID ResLinkToDialog( ! 489: PRESLINK prl) ! 490: { ! 491: PRES pRes; ! 492: ! 493: pRes = (PRES)GlobalLock(prl->hRes); ! 494: ResToDialog(pRes, TRUE); ! 495: GlobalUnlock(prl->hRes); ! 496: ! 497: /* ! 498: * If the dialog was successfully created, remember which res link ! 499: * it was created from. ! 500: */ ! 501: if (gfEditingDlg) ! 502: gcd.prl = prl; ! 503: } ! 504: ! 505: ! 506: ! 507: /************************************************************************ ! 508: * ResToDialog ! 509: * ! 510: * This function creates a dialog box, complete with controls, ! 511: * from a dialog resource template. ! 512: * ! 513: * Arguments: ! 514: * PRES pRes - Pointer to the dialog resource to use. ! 515: * BOOL fDoDialog - TRUE if a new dialog should be created, followed ! 516: * by the controls. If this is FALSE, just the ! 517: * controls will be created and added to the current ! 518: * dialog. ! 519: * ! 520: * Returns: ! 521: * TRUE on success, FALSE if an error occured. ! 522: * ! 523: ************************************************************************/ ! 524: ! 525: BOOL ResToDialog( ! 526: PRES pRes, ! 527: BOOL fDoDialog) ! 528: { ! 529: LPTSTR pszText; ! 530: LPTSTR pszClass; ! 531: INT x; ! 532: INT y; ! 533: INT cx; ! 534: INT cy; ! 535: INT id; ! 536: INT iClass; ! 537: INT cdit; ! 538: INT Type; ! 539: DWORD flStyle; ! 540: DWORD flExtStyle; ! 541: NPCTYPE npc; ! 542: LPTSTR pszMenuName; ! 543: LPTSTR pszFontName; ! 544: INT nPointSize; ! 545: LPTSTR pszDlgName; ! 546: LPTSTR pszCaption; ! 547: PDIALOGBOXHEADER pdbh; ! 548: PCONTROLDATA pcd; ! 549: PWINDOWCLASSDESC pwcd; ! 550: PCUSTLINK pcl; ! 551: PRES2 pRes2; ! 552: DIALOGINFO di; ! 553: CCINFO cci; ! 554: ! 555: /* ! 556: * First check that the pointer is ok. ! 557: */ ! 558: if (!pRes) ! 559: return FALSE; ! 560: ! 561: pRes2 = ResourcePart2(pRes); ! 562: pdbh = (PDIALOGBOXHEADER)SkipResHeader(pRes); ! 563: ! 564: /* ! 565: * Parse out the dialog box header. ! 566: * After this point, pcd is pointing to the first dialog control item. ! 567: */ ! 568: pcd = ParseDialogBoxHeader(pdbh, ! 569: &flStyle, &flExtStyle, &cdit, &x, &y, &cx, &cy, ! 570: &pszMenuName, &pszClass, &pszCaption, ! 571: &nPointSize, &pszFontName); ! 572: ! 573: /* ! 574: * Are we pasting the entire dialog? ! 575: */ ! 576: if (fDoDialog) { ! 577: pszDlgName = ResourceName(pRes); ! 578: ! 579: /* ! 580: * Determine the best base id for the dialog. ! 581: */ ! 582: if (IsOrd(pszDlgName)) ! 583: id = OrdID(pszDlgName); ! 584: else ! 585: id = NextID(NEXTID_DIALOG, plInclude, 0); ! 586: ! 587: di.fResFlags = pRes2->MemoryFlags; ! 588: di.wLanguage = pRes2->LanguageId; ! 589: di.pszClass = pszClass; ! 590: di.pszMenu = pszMenuName; ! 591: di.DataVersion = pRes2->DataVersion; ! 592: di.Version = pRes2->Version; ! 593: di.Characteristics = pRes2->Characteristics; ! 594: di.nPointSize = nPointSize; ! 595: lstrcpy(di.szFontName, pszFontName ? pszFontName : szEmpty); ! 596: ! 597: /* ! 598: * Create the dialog. ! 599: */ ! 600: if (!AddControl(&awcd[W_DIALOG], pszCaption, flStyle, flExtStyle, id, ! 601: x, y, cx, cy, pszDlgName, &di)) ! 602: return FALSE; ! 603: } ! 604: ! 605: while (cdit--) { ! 606: pcd = ParseControlData(pcd, &flStyle, &flExtStyle, &x, &y, &cx, &cy, ! 607: &id, &pszClass, &pszText); ! 608: ! 609: /* ! 610: * If we are not creating a new dialog, and the id in ! 611: * the resource is already in use, we will use the next ! 612: * available one instead. ! 613: */ ! 614: if (!fDoDialog && !IsUniqueID(id)) ! 615: id = NextID(NEXTID_CONTROL, plInclude, 0); ! 616: ! 617: /* ! 618: * Fix up the class. If the class is a predefined ordinal type, ! 619: * we will null out pszClass so it doesn't confuse AddControl ! 620: * into thinking that there is a string class for this control. ! 621: */ ! 622: iClass = GetiClass(pszClass); ! 623: Type = TypeFromClassStyle(iClass, flStyle); ! 624: if (IsOrd(pszClass)) ! 625: pszClass = NULL; ! 626: ! 627: if (Type == W_CUSTOM) { ! 628: /* ! 629: * Search the list of installed custom controls for one ! 630: * that matches the class. ! 631: */ ! 632: for (pcl = gpclHead; ! 633: pcl && lstrcmpi(pcl->pwcd->pszClass, pszClass) != 0; ! 634: pcl = pcl->pclNext) ! 635: ; ! 636: ! 637: /* ! 638: * Was a match found? ! 639: */ ! 640: if (pcl) { ! 641: pwcd = pcl->pwcd; ! 642: } ! 643: else { ! 644: /* ! 645: * An existing custom control link for this class was ! 646: * not found. We will add an emulated custom control ! 647: * to support it. We assume the default style and size ! 648: * should be what this control has. ! 649: */ ! 650: lstrcpy(cci.szClass, pszClass); ! 651: cci.flOptions = 0; ! 652: *cci.szDesc = TEXT('\0'); ! 653: cci.cxDefault = cx; ! 654: cci.cyDefault = cy; ! 655: cci.flStyleDefault = flStyle; ! 656: cci.flExtStyleDefault = flExtStyle; ! 657: *cci.szTextDefault = TEXT('\0'); ! 658: cci.cStyleFlags = 0; ! 659: cci.aStyleFlags = NULL; ! 660: cci.lpfnStyle = NULL; ! 661: cci.lpfnSizeToText = NULL; ! 662: cci.dwReserved1 = 0; ! 663: cci.dwReserved2 = 0; ! 664: ! 665: if (pcl = AddCustomLink(&cci, TRUE, FALSE, NULL, NULL)) ! 666: pwcd = pcl->pwcd; ! 667: else ! 668: /* ! 669: * Skip this control and continue creating the ! 670: * rest of the dialog. ! 671: */ ! 672: continue; ! 673: } ! 674: } ! 675: else { ! 676: pwcd = &awcd[Type]; ! 677: } ! 678: ! 679: /* ! 680: * If we are not creating the entire dialog (we allow existing ! 681: * resource files to be a little messed up), and this control ! 682: * is a default pushbutton, we will then loop through all the ! 683: * existing controls checking for another default pushbutton. ! 684: * If one is found, we convert the default pushbutton being ! 685: * created into a normal pushbutton instead. It is not allowed ! 686: * to have more than one default pushbuttons in the same dialog. ! 687: */ ! 688: if (!fDoDialog && Type == W_PUSHBUTTON && ! 689: (flStyle & BS_ALL) == BS_DEFPUSHBUTTON) { ! 690: for (npc = npcHead; npc; npc = npc->npcNext) { ! 691: if (npc->pwcd->iType == W_PUSHBUTTON && ! 692: (npc->flStyle & BS_ALL) == BS_DEFPUSHBUTTON) { ! 693: flStyle = (flStyle & ~BS_ALL) | BS_PUSHBUTTON; ! 694: break; ! 695: } ! 696: } ! 697: } ! 698: ! 699: npc = AddControl(pwcd, pszText, flStyle, flExtStyle, id, ! 700: x, y, cx, cy, NULL, NULL); ! 701: ! 702: /* ! 703: * If the control creation succeeded, and we are just adding ! 704: * controls (not creating a whole new dialog), select the ! 705: * controls as they are added, but don't do any drawing yet. ! 706: */ ! 707: if (!fDoDialog && npc) ! 708: SelectControl2(npc, TRUE); ! 709: } ! 710: ! 711: /* ! 712: * Update the selected rectangle. This is normally done by ! 713: * SelectControl2 but we told it not to so that the selection ! 714: * could be done faster. We also select the first control here. ! 715: */ ! 716: if (!fDoDialog) { ! 717: SetAnchorToFirstSel(TRUE); ! 718: CalcSelectedRect(); ! 719: } ! 720: ! 721: ShowWindow(gcd.npc->hwnd, SW_SHOWNA); ! 722: ToolboxOnTop(); ! 723: ! 724: return TRUE; ! 725: } ! 726: ! 727: ! 728: ! 729: /************************************************************************ ! 730: * TypeFromClassStyle ! 731: * ! 732: * This function returns the type of a control (one of the W_ constants) ! 733: * based on the class in iClass and the style in flStyle. ! 734: * ! 735: * Arguments: ! 736: * INT iClass = The class of the control, as an IC_* defined constant. ! 737: * DWORD flStyle = The style of the control. ! 738: * ! 739: * Returns: ! 740: * The type of the control (W_* constant). ! 741: * W_NOTHING is the error return. ! 742: * ! 743: ************************************************************************/ ! 744: ! 745: STATICFN INT TypeFromClassStyle( ! 746: INT iClass, ! 747: DWORD flStyle) ! 748: { ! 749: switch (iClass) { ! 750: case IC_BUTTON: ! 751: return rgmpiClsBtnType[flStyle & BS_ALL]; ! 752: ! 753: case IC_EDIT: ! 754: return W_EDIT; ! 755: ! 756: case IC_SCROLLBAR: ! 757: return (flStyle & SBS_VERT) ? W_VERTSCROLL : W_HORZSCROLL; ! 758: ! 759: case IC_STATIC: ! 760: return rgmpiClsStcType[flStyle & SS_ALL]; ! 761: ! 762: case IC_LISTBOX: ! 763: return W_LISTBOX; ! 764: ! 765: case IC_COMBOBOX: ! 766: return W_COMBOBOX; ! 767: ! 768: case IC_CUSTOM: ! 769: return W_CUSTOM; ! 770: ! 771: case IC_DIALOG: ! 772: return W_DIALOG; ! 773: ! 774: default: ! 775: return W_NOTHING; ! 776: } ! 777: } ! 778: ! 779: ! 780: ! 781: /************************************************************************ ! 782: * GetiClass ! 783: * ! 784: * This function returns the class identifier number for the ! 785: * window class of the control, given the class string from the ! 786: * dialog template. ! 787: * ! 788: * An ordinal class is a special ordinal that is used to identify ! 789: * each of the standard control classes. It is used in the ! 790: * dialog template to save space. The class string passed in ! 791: * can be an ordinal and if so, it will be checked against these ! 792: * predefined ordinal class values for a match. ! 793: * ! 794: * Arguments: ! 795: * LPTSTR pszClass - The class string or ordinal. ! 796: * ! 797: * Returns: ! 798: * The class identifier, one of the IC_* symbols in dlgedit.h. ! 799: * If the class cannot be determined, it assumes it is a custom ! 800: * class and returns IC_CUSTOM. ! 801: * ! 802: ************************************************************************/ ! 803: ! 804: INT GetiClass( ! 805: LPTSTR pszClass) ! 806: { ! 807: INT i; ! 808: WORD idOrd; ! 809: ! 810: if (IsOrd(pszClass)) { ! 811: idOrd = OrdID(pszClass); ! 812: for (i = 0; i < IC_DIALOG; i++) { ! 813: if (acsd[i].idOrd == idOrd) ! 814: return i; ! 815: } ! 816: } ! 817: else { ! 818: for (i = 0; i < IC_DIALOG; i++) { ! 819: if (lstrcmpi(ids(acsd[i].idsClass), pszClass) == 0) ! 820: return i; ! 821: } ! 822: } ! 823: ! 824: /* ! 825: * Not found. Assume it is a user defined class. ! 826: */ ! 827: return IC_CUSTOM; ! 828: } ! 829: ! 830: ! 831: ! 832: /************************************************************************ ! 833: * Duplicate ! 834: * ! 835: * This routine duplicates the current selection. ! 836: * ! 837: ************************************************************************/ ! 838: ! 839: VOID Duplicate(VOID) ! 840: { ! 841: PRES pRes; ! 842: ! 843: if (gcSelected) { ! 844: /* ! 845: * Store the current selection in a dialog resource. ! 846: */ ! 847: if (!(pRes = AllocDialogResource(FALSE, TRUE))) ! 848: return; ! 849: ! 850: MakeCopyFromRes(pRes); ! 851: } ! 852: } ! 853: ! 854: ! 855: ! 856: /************************************************************************ ! 857: * MakeCopyFromRes ! 858: * ! 859: * This function uses the given dialog template to either add a new ! 860: * dialog to the current resource file, or drop controls from the ! 861: * template into the current dialog. If copying a dialog, it is created ! 862: * right away. If copying controls, an operation is begun to start ! 863: * tracking them to their final destination in the current dialog. ! 864: * ! 865: * The caller of this function should NOT free pRes. This will ! 866: * be done either before the function returns, or after the drag ! 867: * operation is complete. ! 868: * ! 869: * Arguments: ! 870: * PRES pRes - Points to the dialog resource that contains ! 871: * the dialog or controls to make a copy of. ! 872: * ! 873: ************************************************************************/ ! 874: ! 875: VOID MakeCopyFromRes( ! 876: PRES pRes) ! 877: { ! 878: PDIALOGBOXHEADER pdbh; ! 879: PCONTROLDATA pcd; ! 880: INT cControls; ! 881: INT i; ! 882: BOOL fFreeData = TRUE; ! 883: INT iType; ! 884: INT iClass; ! 885: INT nBottom; ! 886: INT nBottomLowest; ! 887: ! 888: gpResCopy = pRes; ! 889: pdbh = (PDIALOGBOXHEADER)SkipResHeader(gpResCopy); ! 890: ! 891: /* ! 892: * If cx is CONTROLS_ONLY, then we know that we only ! 893: * want to copy the controls in the template, not ! 894: * the entire dialog plus controls. ! 895: */ ! 896: if (pdbh->cx == CONTROLS_ONLY) { ! 897: /* ! 898: * Begin copying in new controls into the current dialog. ! 899: */ ! 900: cControls = pdbh->NumberOfItems; ! 901: if (cControls) { ! 902: /* ! 903: * Seed the rectangle with impossible values. ! 904: */ ! 905: SetRect(&grcCopy, 32000, 32000, -32000, -32000); ! 906: nBottomLowest = 0; ! 907: ! 908: /* ! 909: * Loop through all the controls, expanding the rectangle ! 910: * to fit around all of them. ! 911: */ ! 912: pcd = SkipDialogBoxHeader(pdbh); ! 913: for (i = 0; i < cControls; i++) { ! 914: iClass = GetiClass((LPTSTR)((PBYTE)pcd + SIZEOF_CONTROLDATA)); ! 915: iType = TypeFromClassStyle(iClass, pcd->lStyle); ! 916: ! 917: if (grcCopy.left > (INT)pcd->x) ! 918: grcCopy.left = (INT)pcd->x; ! 919: ! 920: if (grcCopy.top > (INT)pcd->y) ! 921: grcCopy.top = (INT)pcd->y; ! 922: ! 923: if (grcCopy.right < (INT)pcd->x + (INT)pcd->cx) ! 924: grcCopy.right = (INT)pcd->x + (INT)pcd->cx; ! 925: ! 926: nBottom = ((INT)pcd->y + (INT)pcd->cy) - ! 927: GetOverHang(iType, (INT)pcd->cy); ! 928: if (nBottom > nBottomLowest) ! 929: nBottomLowest = nBottom; ! 930: ! 931: if (grcCopy.bottom < (INT)pcd->y + (INT)pcd->cy) ! 932: grcCopy.bottom = (INT)pcd->y + (INT)pcd->cy; ! 933: ! 934: pcd = SkipControlData(pcd); ! 935: } ! 936: ! 937: /* ! 938: * Begin dragging the new control(s). Set a flag so that ! 939: * the resource data is NOT free'd until after the drag ! 940: * is finished. ! 941: */ ! 942: DragNewBegin(grcCopy.right - grcCopy.left, ! 943: grcCopy.bottom - grcCopy.top, ! 944: grcCopy.bottom - nBottomLowest); ! 945: fFreeData = FALSE; ! 946: } ! 947: } ! 948: else { ! 949: /* ! 950: * Begin copying in a new dialog, complete with controls. ! 951: */ ! 952: if (SynchDialogResource()) { ! 953: /* ! 954: * Remove any existing dialog. ! 955: */ ! 956: if (gfEditingDlg) ! 957: DeleteDialog(FALSE); ! 958: ! 959: if (ResToDialog(gpResCopy, TRUE)) { ! 960: SelectControl(gcd.npc, FALSE); ! 961: gfResChged = TRUE; ! 962: ShowFileStatus(FALSE); ! 963: } ! 964: } ! 965: } ! 966: ! 967: if (fFreeData) { ! 968: MyFree(gpResCopy); ! 969: gpResCopy = NULL; ! 970: } ! 971: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.