Annotation of mstools/samples/sdktools/dlgedit/addctrl.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: 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: }

unix.superglobalmegacorp.com

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