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

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /****************************** Module Header *******************************
                     13: * Module Name: 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: }

unix.superglobalmegacorp.com

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