home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- \******************************************************************************/
-
- /****************************** Module Header *******************************
- * Module Name: restodlg.c
- *
- * Routines that take a dialog resource and create the dialog to edit, or
- * the other way around.
- *
- * Fucntions:
- * SynchDialogResource()
- * AllocDialogResource()
- * ResLinkToDialog()
- * ResToDialog()
- * GetiClass()
- * Duplicate()
- * MakeCopyFromRes()
- * TypeFromClassStyle()
- *
- * Comments:
- *
- ****************************************************************************/
-
- #include "dlgedit.h"
- #include "dlgfuncs.h"
- #include "dlgextrn.h"
-
- STATICFN INT TypeFromClassStyle(INT iClass, DWORD flStyle);
-
-
-
- /************************************************************************
- * SynchDialogResource
- *
- * This routine synchronizes the resource buffer with the contents of
- * the current dialog being edited. This may involve deleting the old
- * contents of the current dialog prior to adding the new data.
- *
- * It is ok to call this routine even if there is not an existing dialog
- * being edited (it will just return) and it should be called before any
- * operation that needs the in memory copy of the dialog to accurately
- * reflect the contents of the current dialog, such as just before a
- * save to disk.
- *
- * Returns:
- * TRUE if all goes well (includes the case where nothing was done).
- * FALSE if an error occurs updating the resource.
- *
- ************************************************************************/
-
- BOOL SynchDialogResource(VOID)
- {
- PRES pRes;
- PRESLINK prl;
- PRESLINK prlNew;
- PRESLINK prlPrev;
-
- if (!gfEditingDlg)
- return TRUE;
-
- /*
- * Allocate a resource for the current dialog.
- */
- if (!(pRes = AllocDialogResource(FALSE, FALSE)))
- return FALSE;
-
- /*
- * Allocate a new link for it.
- */
- if (!(prlNew = AllocResLink(pRes)))
- return FALSE;
-
- /*
- * Free the local copy of the dialog resource now that the
- * link has been created (and the resource copied to global
- * memory).
- */
- MyFree(pRes);
-
- /*
- * Does a link for the dialog already exist?
- */
- if (gcd.prl) {
- /*
- * Find the existing link and get it's previous link.
- */
- for (prl = gprlHead, prlPrev = NULL; prl && prl != gcd.prl;
- prlPrev = prl, prl = prl->prlNext)
- ;
-
- /*
- * Start linking it in.
- */
- prlNew->prlNext = gcd.prl->prlNext;
-
- if (prlPrev)
- prlPrev->prlNext = prlNew;
- else
- gprlHead = prlNew;
-
- /*
- * Delete the old link now that it is replaced.
- */
- FreeResLink(gcd.prl);
- }
- else {
- /*
- * Search for the end of the list. Get a pointer to the last link.
- */
- for (prl = gprlHead, prlPrev = NULL; prl;
- prlPrev = prl, prl = prl->prlNext)
- ;
-
- /*
- * Add the new link to the end of the list.
- */
- if (prlPrev)
- prlPrev->prlNext = prlNew;
- else
- gprlHead = prlNew;
- }
-
- /*
- * Update our global with the new link. Clear the "dialog changed"
- * flag.
- */
- gcd.prl = prlNew;
- gfDlgChanged = FALSE;
-
- return TRUE;
- }
-
-
-
- /************************************************************************
- * AllocDialogResource
- *
- * This function allocates memory and builds a resource file format
- * image in it of the current dialog.
- *
- * Arguments:
- * BOOL fTestMode - TRUE if a special test mode version of the current
- * dialog should be created.
- * BOOL fClipboard - If TRUE, only the selected control(s) will be
- * placed in the resource. This is used when putting
- * controls or groups of controls into the clipboard.
- * If the dialog is selected, this flag is ignored,
- * because selecting the dialog implies all the
- * controls will be written out also.
- *
- * Returns:
- * Pointer to the resource buffer.
- * NULL if unable to create the resource.
- *
- ************************************************************************/
-
- PRES AllocDialogResource(
- BOOL fTestMode,
- BOOL fClipboard)
- {
- NPCTYPE npc;
- INT cControls;
- BOOL fSelectedOnly = FALSE;
- INT cbDlgName;
- INT cbCaption;
- INT cbPointSize;
- INT cbFontName;
- INT cbCD;
- INT cbResHeader;
- INT cbResData;
- INT cbResSize;
- INT cbMenuName;
- INT cbClass;
- INT cbText;
- INT cbAlloc;
- PBYTE pb;
- PRES pResBegin;
- PRES pResBegin2;
- LPTSTR pszClass;
- LPTSTR pszMenu;
- LPTSTR pszText;
- DWORD flStyle;
- PDIALOGBOXHEADER pdbh;
- PCONTROLDATA pcd;
- ORDINAL ordClass;
-
- cControls = cWindows;
- if (fClipboard && !gfDlgSelected) {
- fSelectedOnly = TRUE;
- for (cControls = 0, npc = npcHead; npc; npc = npc->npcNext)
- if (npc->fSelected)
- cControls++;
- }
-
- /*
- * If testing, don't allow a dialog to be created with any
- * special class, or with the real menu.
- */
- if (fTestMode) {
- pszClass = NULL;
- pszMenu = NULL;
- }
- else {
- pszClass = gcd.di.pszClass;
- pszMenu = gcd.di.pszMenu;
- }
-
- cbDlgName = NameOrdLen(gcd.pszDlgName);
- cbCaption = (gcd.npc->text) ?
- (lstrlen(gcd.npc->text) + 1) * sizeof(TCHAR) : sizeof(TCHAR);
- cbClass = pszClass ? NameOrdLen(pszClass) : sizeof(TCHAR);
- cbMenuName = pszMenu ? NameOrdLen(pszMenu) : sizeof(TCHAR);
-
- if (gcd.fFontSpecified) {
- cbPointSize = sizeof(WORD);
- cbFontName = (lstrlen(gcd.di.szFontName) + 1) * sizeof(TCHAR);
- }
- else {
- cbPointSize = cbFontName = 0;
- }
-
- /*
- * Calculate the size of the resource header.
- */
- cbResHeader = sizeof(RES) + // The first fixed part.
- sizeof(ORDINAL) + // The RT_DIALOG ordinal.
- cbDlgName; // The dialog's name.
- DWordAlign((PBYTE *)&cbResHeader); // Pad for the dialog's name.
- cbResHeader += sizeof(RES2); // The last fixed part.
-
- /*
- * Calculate the size of the resource data. This will just include
- * the dialog box header right now.
- */
- cbResData = SIZEOF_DIALOGBOXHEADER + // The first fixed part.
- cbMenuName + // The menu.
- cbClass + // The class.
- cbCaption + // The caption.
- cbPointSize + // The point size.
- cbFontName; // The font name.
-
- /*
- * Allocate some buffer space. Be sure to round this up to a DWORD
- * boundary to allow space for padding if necessary, but don't round
- * cbResData field because it will need to be written into the header
- * later, and the value that is written is an exact size (not rounded
- * up).
- */
- cbAlloc = cbResSize = cbResHeader + cbResData;
- DWordAlign((PBYTE *)&cbAlloc);
- if (!(pResBegin = (PRES)MyAlloc(cbAlloc)))
- return NULL;
-
- /*
- * Write the resource header.
- */
- pdbh = (PDIALOGBOXHEADER)WriteResHeader(pResBegin, 0, ORDID_RT_DIALOG,
- gcd.pszDlgName, gcd.di.fResFlags, gcd.di.wLanguage,
- gcd.di.DataVersion, gcd.di.Version, gcd.di.Characteristics);
-
- /*
- * Write out the style.
- */
- flStyle = gcd.npc->flStyle;
- if (fTestMode) {
- flStyle &= ~awcd[W_DIALOG].flStylesTestBad;
- flStyle |= WS_VISIBLE;
- }
-
- pdbh->lStyle = flStyle;
- pdbh->lExtendedStyle = gcd.npc->flExtStyle;
- pdbh->NumberOfItems = (WORD)cControls;
-
- /*
- * Write the coordinates.
- *
- * If we are allocating a template that only has the selected controls
- * in it, we put the value of CONTROLS_ONLY in the "cx" field of the
- * dialog header. This is what we will check when the user pastes
- * something from the clipboard into a dialog to determine whether
- * to paste the entire dialog, or only the controls within the dialog
- * item array.
- */
- pdbh->x = (WORD)gcd.npc->rc.left;
- pdbh->y = (WORD)gcd.npc->rc.top;
-
- if (fSelectedOnly)
- pdbh->cx = CONTROLS_ONLY;
- else
- pdbh->cx = (WORD)(gcd.npc->rc.right - gcd.npc->rc.left);
-
- pdbh->cy = (WORD)(gcd.npc->rc.bottom - gcd.npc->rc.top);
-
- pb = (PBYTE)pdbh + SIZEOF_DIALOGBOXHEADER;
-
- /*
- * Write the menu name if there is one (we always write at least a null.
- */
- pb = NameOrdCpy((LPTSTR)pb, pszMenu ? pszMenu : szEmpty);
-
- /*
- * Write the class if there is one (we always write at least a null.
- */
- pb = NameOrdCpy((LPTSTR)pb, pszClass ? pszClass : szEmpty);
-
- /*
- * Write the caption if there is one (we always write at least a null).
- */
- pb = WriteSz((LPTSTR)pb, gcd.npc->text ? gcd.npc->text : szEmpty);
-
- /*
- * Write out the font, if there is one specified.
- */
- if (gcd.fFontSpecified) {
- *(PWORD)pb = (WORD)gcd.di.nPointSize;
- pb += sizeof(WORD);
-
- pb = WriteSz((LPTSTR)pb, gcd.di.szFontName);
- }
-
- /*
- * Pad to a DWORD boundary. This is ok even if there are no controls
- * that follow, because we were sure to allocate on an even dword
- * boundary above.
- */
- DWordPad(&pb);
-
- /*
- * Now do dialog items.
- */
- for (npc = npcHead; npc; npc = npc->npcNext) {
- /*
- * Skip the control if it is NOT selected and we only want the
- * selected controls.
- */
- if (fSelectedOnly && !npc->fSelected)
- continue;
-
- /*
- * If we are testing, we don't want to really create a control
- * with some funny class because it probably won't be found.
- * We will substitute our custom class emulator instead.
- */
- if (fTestMode && npc->pwcd->fEmulated)
- pszClass = szCustomClass;
- else
- pszClass = npc->pwcd->pszClass;
-
- /*
- * Get a pointer to the text. If this is an icon control and
- * we are going into test mode, change the text field so that
- * it points to an ordinal for DlgEdit's icon to display, or
- * the icon resource will probably not be found when the dialog
- * is created.
- */
- pszText = npc->text;
- if (npc->pwcd->iType == W_ICON && fTestMode)
- pszText = (LPTSTR)&gordIcon;
-
- cbText = pszText ? NameOrdLen(pszText) : sizeof(TCHAR);
- cbClass = pszClass ? NameOrdLen(pszClass) : sizeof(ORDINAL);
-
- cbCD = SIZEOF_CONTROLDATA + // The fixed portion.
- cbClass + // The class.
- cbText + // The text.
- sizeof(WORD); // nExtraStuff field.
-
- /*
- * Since we are adding a new control, we dword align the
- * previous size of the resource data to ensure the new
- * control starts on a dword boundary.
- */
- DWordAlign((PBYTE *)&cbResSize);
-
- /*
- * Allocate room for this control. This includes room for the
- * template structure, class, text and a byte for the cb field
- * for the create struct data.
- */
- cbAlloc = cbResSize + cbCD;
- DWordAlign((PBYTE *)&cbAlloc);
- pResBegin2 = (PRES)MyRealloc((PBYTE)pResBegin, cbAlloc);
- if (!pResBegin2) {
- MyFree(pResBegin);
- return NULL;
- }
-
- pResBegin = pResBegin2;
- pcd = (PCONTROLDATA)((PBYTE)pResBegin + cbResSize);
- cbResSize += cbCD;
-
- /*
- * Write the style. If testing, remove any styles that can
- * cause problems, such as ownerdraw styles. If testing and
- * this is an emulated custom control, always make it with
- * the default styles no matter what the user has specified.
- */
- flStyle = npc->flStyle;
- if (fTestMode) {
- if (npc->pwcd->fEmulated)
- flStyle = awcd[W_CUSTOM].flStyles;
- else
- flStyle &= ~npc->pwcd->flStylesTestBad;
- }
-
- pcd->lStyle = flStyle;
- pcd->lExtendedStyle = npc->flExtStyle;
-
- /*
- * Write the coordinates.
- */
- pcd->x = (WORD)npc->rc.left;
- pcd->y = (WORD)npc->rc.top;
- pcd->cx = (WORD)(npc->rc.right - npc->rc.left);
- pcd->cy = (WORD)(npc->rc.bottom - npc->rc.top);
-
- /*
- * Write the id.
- */
- pcd->wId = (WORD)npc->id;
-
- pb = (PBYTE)pcd + SIZEOF_CONTROLDATA;
-
- /*
- * Write the class. This will be a string, except for the
- * predefined control classes, which all have an ordinal
- * value defined for them.
- */
- if (pszClass) {
- pb = NameOrdCpy((LPTSTR)pb, pszClass);
- }
- else {
- WriteOrd(&ordClass, acsd[awcd[npc->pwcd->iType].iClass].idOrd);
- pb = NameOrdCpy((LPTSTR)pb, (LPTSTR)&ordClass);
- }
-
- /*
- * Write the text.
- */
- pb = NameOrdCpy((LPTSTR)pb, pszText ? pszText : szEmpty);
-
- /*
- * Write out a zero because there are no additional bytes
- * of create struct data.
- */
- *(PWORD)pb = 0;
- pb += sizeof(WORD);
-
- /*
- * Pad to a DWORD boundary. This is ok even if there are no more
- * controls, because we were sure to allocate on an even dword
- * boundary above.
- */
- DWordPad(&pb);
- }
-
- /*
- * Now go back and fill in the resource data size field.
- */
- pResBegin->DataSize = cbResSize - cbResHeader;
-
- return pResBegin;
- }
-
-
-
- /************************************************************************
- * ResLinkToDialog
- *
- * This function is used to create a dialog out of a dialog resource
- * that has been stored in the resource linked list.
- *
- * Arguments:
- * PRESLINK prl - Points to the link that describes the dialog to
- * create. It is assumed that the resource is a
- * dialog resource.
- *
- ************************************************************************/
-
- VOID ResLinkToDialog(
- PRESLINK prl)
- {
- PRES pRes;
-
- pRes = (PRES)GlobalLock(prl->hRes);
- ResToDialog(pRes, TRUE);
- GlobalUnlock(prl->hRes);
-
- /*
- * If the dialog was successfully created, remember which res link
- * it was created from.
- */
- if (gfEditingDlg)
- gcd.prl = prl;
- }
-
-
-
- /************************************************************************
- * ResToDialog
- *
- * This function creates a dialog box, complete with controls,
- * from a dialog resource template.
- *
- * Arguments:
- * PRES pRes - Pointer to the dialog resource to use.
- * BOOL fDoDialog - TRUE if a new dialog should be created, followed
- * by the controls. If this is FALSE, just the
- * controls will be created and added to the current
- * dialog.
- *
- * Returns:
- * TRUE on success, FALSE if an error occured.
- *
- ************************************************************************/
-
- BOOL ResToDialog(
- PRES pRes,
- BOOL fDoDialog)
- {
- LPTSTR pszText;
- LPTSTR pszClass;
- INT x;
- INT y;
- INT cx;
- INT cy;
- INT id;
- INT iClass;
- INT cdit;
- INT Type;
- DWORD flStyle;
- DWORD flExtStyle;
- NPCTYPE npc;
- LPTSTR pszMenuName;
- LPTSTR pszFontName;
- INT nPointSize;
- LPTSTR pszDlgName;
- LPTSTR pszCaption;
- PDIALOGBOXHEADER pdbh;
- PCONTROLDATA pcd;
- PWINDOWCLASSDESC pwcd;
- PCUSTLINK pcl;
- PRES2 pRes2;
- DIALOGINFO di;
- CCINFO cci;
-
- /*
- * First check that the pointer is ok.
- */
- if (!pRes)
- return FALSE;
-
- pRes2 = ResourcePart2(pRes);
- pdbh = (PDIALOGBOXHEADER)SkipResHeader(pRes);
-
- /*
- * Parse out the dialog box header.
- * After this point, pcd is pointing to the first dialog control item.
- */
- pcd = ParseDialogBoxHeader(pdbh,
- &flStyle, &flExtStyle, &cdit, &x, &y, &cx, &cy,
- &pszMenuName, &pszClass, &pszCaption,
- &nPointSize, &pszFontName);
-
- /*
- * Are we pasting the entire dialog?
- */
- if (fDoDialog) {
- pszDlgName = ResourceName(pRes);
-
- /*
- * Determine the best base id for the dialog.
- */
- if (IsOrd(pszDlgName))
- id = OrdID(pszDlgName);
- else
- id = NextID(NEXTID_DIALOG, plInclude, 0);
-
- di.fResFlags = pRes2->MemoryFlags;
- di.wLanguage = pRes2->LanguageId;
- di.pszClass = pszClass;
- di.pszMenu = pszMenuName;
- di.DataVersion = pRes2->DataVersion;
- di.Version = pRes2->Version;
- di.Characteristics = pRes2->Characteristics;
- di.nPointSize = nPointSize;
- lstrcpy(di.szFontName, pszFontName ? pszFontName : szEmpty);
-
- /*
- * Create the dialog.
- */
- if (!AddControl(&awcd[W_DIALOG], pszCaption, flStyle, flExtStyle, id,
- x, y, cx, cy, pszDlgName, &di))
- return FALSE;
- }
-
- while (cdit--) {
- pcd = ParseControlData(pcd, &flStyle, &flExtStyle, &x, &y, &cx, &cy,
- &id, &pszClass, &pszText);
-
- /*
- * If we are not creating a new dialog, and the id in
- * the resource is already in use, we will use the next
- * available one instead.
- */
- if (!fDoDialog && !IsUniqueID(id))
- id = NextID(NEXTID_CONTROL, plInclude, 0);
-
- /*
- * Fix up the class. If the class is a predefined ordinal type,
- * we will null out pszClass so it doesn't confuse AddControl
- * into thinking that there is a string class for this control.
- */
- iClass = GetiClass(pszClass);
- Type = TypeFromClassStyle(iClass, flStyle);
- if (IsOrd(pszClass))
- pszClass = NULL;
-
- if (Type == W_CUSTOM) {
- /*
- * Search the list of installed custom controls for one
- * that matches the class.
- */
- for (pcl = gpclHead;
- pcl && lstrcmpi(pcl->pwcd->pszClass, pszClass) != 0;
- pcl = pcl->pclNext)
- ;
-
- /*
- * Was a match found?
- */
- if (pcl) {
- pwcd = pcl->pwcd;
- }
- else {
- /*
- * An existing custom control link for this class was
- * not found. We will add an emulated custom control
- * to support it. We assume the default style and size
- * should be what this control has.
- */
- lstrcpy(cci.szClass, pszClass);
- cci.flOptions = 0;
- *cci.szDesc = TEXT('\0');
- cci.cxDefault = cx;
- cci.cyDefault = cy;
- cci.flStyleDefault = flStyle;
- cci.flExtStyleDefault = flExtStyle;
- *cci.szTextDefault = TEXT('\0');
- cci.cStyleFlags = 0;
- cci.aStyleFlags = NULL;
- cci.lpfnStyle = NULL;
- cci.lpfnSizeToText = NULL;
- cci.dwReserved1 = 0;
- cci.dwReserved2 = 0;
-
- if (pcl = AddCustomLink(&cci, TRUE, FALSE, NULL, NULL))
- pwcd = pcl->pwcd;
- else
- /*
- * Skip this control and continue creating the
- * rest of the dialog.
- */
- continue;
- }
- }
- else {
- pwcd = &awcd[Type];
- }
-
- /*
- * If we are not creating the entire dialog (we allow existing
- * resource files to be a little messed up), and this control
- * is a default pushbutton, we will then loop through all the
- * existing controls checking for another default pushbutton.
- * If one is found, we convert the default pushbutton being
- * created into a normal pushbutton instead. It is not allowed
- * to have more than one default pushbuttons in the same dialog.
- */
- if (!fDoDialog && Type == W_PUSHBUTTON &&
- (flStyle & BS_ALL) == BS_DEFPUSHBUTTON) {
- for (npc = npcHead; npc; npc = npc->npcNext) {
- if (npc->pwcd->iType == W_PUSHBUTTON &&
- (npc->flStyle & BS_ALL) == BS_DEFPUSHBUTTON) {
- flStyle = (flStyle & ~BS_ALL) | BS_PUSHBUTTON;
- break;
- }
- }
- }
-
- npc = AddControl(pwcd, pszText, flStyle, flExtStyle, id,
- x, y, cx, cy, NULL, NULL);
-
- /*
- * If the control creation succeeded, and we are just adding
- * controls (not creating a whole new dialog), select the
- * controls as they are added, but don't do any drawing yet.
- */
- if (!fDoDialog && npc)
- SelectControl2(npc, TRUE);
- }
-
- /*
- * Update the selected rectangle. This is normally done by
- * SelectControl2 but we told it not to so that the selection
- * could be done faster. We also select the first control here.
- */
- if (!fDoDialog) {
- SetAnchorToFirstSel(TRUE);
- CalcSelectedRect();
- }
-
- ShowWindow(gcd.npc->hwnd, SW_SHOWNA);
- ToolboxOnTop();
-
- return TRUE;
- }
-
-
-
- /************************************************************************
- * TypeFromClassStyle
- *
- * This function returns the type of a control (one of the W_ constants)
- * based on the class in iClass and the style in flStyle.
- *
- * Arguments:
- * INT iClass = The class of the control, as an IC_* defined constant.
- * DWORD flStyle = The style of the control.
- *
- * Returns:
- * The type of the control (W_* constant).
- * W_NOTHING is the error return.
- *
- ************************************************************************/
-
- STATICFN INT TypeFromClassStyle(
- INT iClass,
- DWORD flStyle)
- {
- switch (iClass) {
- case IC_BUTTON:
- return rgmpiClsBtnType[flStyle & BS_ALL];
-
- case IC_EDIT:
- return W_EDIT;
-
- case IC_SCROLLBAR:
- return (flStyle & SBS_VERT) ? W_VERTSCROLL : W_HORZSCROLL;
-
- case IC_STATIC:
- return rgmpiClsStcType[flStyle & SS_ALL];
-
- case IC_LISTBOX:
- return W_LISTBOX;
-
- case IC_COMBOBOX:
- return W_COMBOBOX;
-
- case IC_CUSTOM:
- return W_CUSTOM;
-
- case IC_DIALOG:
- return W_DIALOG;
-
- default:
- return W_NOTHING;
- }
- }
-
-
-
- /************************************************************************
- * GetiClass
- *
- * This function returns the class identifier number for the
- * window class of the control, given the class string from the
- * dialog template.
- *
- * An ordinal class is a special ordinal that is used to identify
- * each of the standard control classes. It is used in the
- * dialog template to save space. The class string passed in
- * can be an ordinal and if so, it will be checked against these
- * predefined ordinal class values for a match.
- *
- * Arguments:
- * LPTSTR pszClass - The class string or ordinal.
- *
- * Returns:
- * The class identifier, one of the IC_* symbols in dlgedit.h.
- * If the class cannot be determined, it assumes it is a custom
- * class and returns IC_CUSTOM.
- *
- ************************************************************************/
-
- INT GetiClass(
- LPTSTR pszClass)
- {
- INT i;
- WORD idOrd;
-
- if (IsOrd(pszClass)) {
- idOrd = OrdID(pszClass);
- for (i = 0; i < IC_DIALOG; i++) {
- if (acsd[i].idOrd == idOrd)
- return i;
- }
- }
- else {
- for (i = 0; i < IC_DIALOG; i++) {
- if (lstrcmpi(ids(acsd[i].idsClass), pszClass) == 0)
- return i;
- }
- }
-
- /*
- * Not found. Assume it is a user defined class.
- */
- return IC_CUSTOM;
- }
-
-
-
- /************************************************************************
- * Duplicate
- *
- * This routine duplicates the current selection.
- *
- ************************************************************************/
-
- VOID Duplicate(VOID)
- {
- PRES pRes;
-
- if (gcSelected) {
- /*
- * Store the current selection in a dialog resource.
- */
- if (!(pRes = AllocDialogResource(FALSE, TRUE)))
- return;
-
- MakeCopyFromRes(pRes);
- }
- }
-
-
-
- /************************************************************************
- * MakeCopyFromRes
- *
- * This function uses the given dialog template to either add a new
- * dialog to the current resource file, or drop controls from the
- * template into the current dialog. If copying a dialog, it is created
- * right away. If copying controls, an operation is begun to start
- * tracking them to their final destination in the current dialog.
- *
- * The caller of this function should NOT free pRes. This will
- * be done either before the function returns, or after the drag
- * operation is complete.
- *
- * Arguments:
- * PRES pRes - Points to the dialog resource that contains
- * the dialog or controls to make a copy of.
- *
- ************************************************************************/
-
- VOID MakeCopyFromRes(
- PRES pRes)
- {
- PDIALOGBOXHEADER pdbh;
- PCONTROLDATA pcd;
- INT cControls;
- INT i;
- BOOL fFreeData = TRUE;
- INT iType;
- INT iClass;
- INT nBottom;
- INT nBottomLowest;
-
- gpResCopy = pRes;
- pdbh = (PDIALOGBOXHEADER)SkipResHeader(gpResCopy);
-
- /*
- * If cx is CONTROLS_ONLY, then we know that we only
- * want to copy the controls in the template, not
- * the entire dialog plus controls.
- */
- if (pdbh->cx == CONTROLS_ONLY) {
- /*
- * Begin copying in new controls into the current dialog.
- */
- cControls = pdbh->NumberOfItems;
- if (cControls) {
- /*
- * Seed the rectangle with impossible values.
- */
- SetRect(&grcCopy, 32000, 32000, -32000, -32000);
- nBottomLowest = 0;
-
- /*
- * Loop through all the controls, expanding the rectangle
- * to fit around all of them.
- */
- pcd = SkipDialogBoxHeader(pdbh);
- for (i = 0; i < cControls; i++) {
- iClass = GetiClass((LPTSTR)((PBYTE)pcd + SIZEOF_CONTROLDATA));
- iType = TypeFromClassStyle(iClass, pcd->lStyle);
-
- if (grcCopy.left > (INT)pcd->x)
- grcCopy.left = (INT)pcd->x;
-
- if (grcCopy.top > (INT)pcd->y)
- grcCopy.top = (INT)pcd->y;
-
- if (grcCopy.right < (INT)pcd->x + (INT)pcd->cx)
- grcCopy.right = (INT)pcd->x + (INT)pcd->cx;
-
- nBottom = ((INT)pcd->y + (INT)pcd->cy) -
- GetOverHang(iType, (INT)pcd->cy);
- if (nBottom > nBottomLowest)
- nBottomLowest = nBottom;
-
- if (grcCopy.bottom < (INT)pcd->y + (INT)pcd->cy)
- grcCopy.bottom = (INT)pcd->y + (INT)pcd->cy;
-
- pcd = SkipControlData(pcd);
- }
-
- /*
- * Begin dragging the new control(s). Set a flag so that
- * the resource data is NOT free'd until after the drag
- * is finished.
- */
- DragNewBegin(grcCopy.right - grcCopy.left,
- grcCopy.bottom - grcCopy.top,
- grcCopy.bottom - nBottomLowest);
- fFreeData = FALSE;
- }
- }
- else {
- /*
- * Begin copying in a new dialog, complete with controls.
- */
- if (SynchDialogResource()) {
- /*
- * Remove any existing dialog.
- */
- if (gfEditingDlg)
- DeleteDialog(FALSE);
-
- if (ResToDialog(gpResCopy, TRUE)) {
- SelectControl(gcd.npc, FALSE);
- gfResChged = TRUE;
- ShowFileStatus(FALSE);
- }
- }
- }
-
- if (fFreeData) {
- MyFree(gpResCopy);
- gpResCopy = NULL;
- }
- }
-