home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
vos2-121.zip
/
v
/
srcos2
/
vcmdprnt.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1999-02-20
|
35KB
|
947 lines
//===============================================================
// vcmdprnt.cxx - vCmdParent Class - Windows
//
// Copyright (C) 1995,1996,1997,1998 Bruce E. Wampler
//
// This file is part of the V C++ GUI Framework, and is covered
// under the terms of the GNU Library General Public License,
// Version 2. This library has NO WARRANTY. See the source file
// vapp.cxx for more complete information about license terms.
//===============================================================
#include <v/vos2.h> // for OS/22 stuff
#include <v/vapp.h> // need the codepage
#include <v/vcmdprnt.h> // our include
#include <v/vbtncmd.h> // ButtonCmd
#include <v/vlabelc.h> // LabelCmd
#include <v/vframec.h> // FrameCmd
#include <v/vchkboxc.h> // CheckBoxCmd
#include <v/vradioc.h> // RadioButtonCmd
#include <v/vtextinc.h> // TextInCmd
#include <v/vtextc.h> // TextCmd
#include <v/vlistc.h> // ListCmd
#include <v/vcomboc.h> // ComboBoxCmd
#include <v/vspinc.h> // SpinnerCmd
#include <v/vsliderc.h> // SliderCmd
#include <v/vprogrsc.h> // ProgressCmd
#include <v/vboxlblc.h> // BoxedLabel
// ---------------------------------------------------------------------
// Dynamic Dialog Building Support
// ---------------------------------------------------------------------
// this is an attempt to consolidate all the different margin
// variables that are lying around, but alas all seem to be doing pretty
// much the same thing. We will stick with StdMargin in vcmd.h as the
// master margin variable.
const int _CtrlSpacing = StdMargin;
//======================>>> vCmdParent::vCmdParent <<<========================
// In this tricky little function, the address of the pointer variable used
// in the calling function to track the next free byte at the end of the
// dialog template variable data region is accessed (*inp).
// The function automatically increments this pointer so that after copying
// the *src string to the end of the data region, the original pointer in
// the calling function now points to the new end of the data region.
static void CopyStringToDialog (PSZ *inp, PCSZ src)
{
char *in = (char * )(*inp); // in assigned the address of *inp
do
{
*in++ = (char) *src;
} while (*src++);
*inp = (char *)in; // *inp reset to the new end of data
}
//======================>>> vCmdParent::vCmdParent <<<==========================
vCmdParent::vCmdParent(PaneType pt)
{
_cmdList = 0;
maxX = 0; // minimum size for a dialog
maxY = 0;
if (pt == P_Status)
{
maxX = 4; // give some room at left for drawing box
maxY = 4;
}
_callbackID = -1; // no call back id
_pt = pt;
}
//======================>>> vCmdParent::~vCmdParent <<<============================
vCmdParent::~vCmdParent()
{
SysDebug(Destructor,"vCmdParent::~vCmdParent() destructor\n")
// need to delete everything we added
DlgCmdList* tmp;
if (_hTemplate != 0)
{
DosFreeMem(_hTemplate);
_hTemplate = 0;
}
for (DlgCmdList* cc = _cmdList ; cc != 0 ; )
{
delete cc->cmdP; // delete the cmd object
tmp = cc; // don't forget where we were
cc = cc->nextDCL; // for next time
delete tmp; // delete the list cell
}
}
//======================>>> vCmdParent::AddCmd <<<============================
vCmd* vCmdParent::AddCmd(CommandObject* cmd)
{
// Private method to add a single command to a dialog object.
SysDebug2(Build,"vCmdParent::AddCmd() - %s(id:%d)\n",cmd->title,cmd->cmdId)
vCmd* cmdPtr;
switch (cmd->cmdType) // depends on type
{
case C_IconButton: // a command button Icon
case C_ToggleButton: // a toggle icon button
case C_ToggleIconButton: // a toggle icon button
case C_Button: // Button
case C_ColorButton: // ColorButton
{
cmdPtr = new vButtonCmd(this, cmd);
break;
}
case C_CheckBox: // Checked Item
{
cmdPtr = new vCheckBoxCmd(this, cmd);
break;
}
case C_ComboBox: // Popup combo list
{
cmdPtr = new vComboBoxCmd(this, cmd);
break;
}
case C_Frame: // General purpose frame
case C_ToggleFrame: // A toggle frame
{
cmdPtr = new vFrameCmd(this, cmd);
break;
}
case C_Icon: // a static icon
case C_Blank: // to help RightOfs, Belows work
case C_Label: // Regular text label
case C_ColorLabel: // Color text label
{
cmdPtr = new vLabelCmd(this, cmd);
break;
}
case C_List: // List of items (scrollable)
{
cmdPtr = new vListCmd(this, cmd);
break;
}
case C_ProgressBar: // Progress bar
{
cmdPtr = new vProgressCmd(this, cmd);
break;
}
case C_RadioButton: // radio button
{
cmdPtr = new vRadioButtonCmd(this, cmd);
break;
}
case C_Slider: // slider
{
cmdPtr = new vSliderCmd(this, cmd);
break;
}
case C_BoxedLabel:
{
cmdPtr = new vBoxedLabelCmd(this, cmd);
break;
}
case C_Text: // Text output field
{
cmdPtr = new vTextCmd(this, cmd);
break;
}
case C_TextIn: // Text input field
{
cmdPtr = new vTextInCmd(this, cmd);
break;
}
case C_Spinner: // Value Box list
{
cmdPtr = new vSpinnerCmd(this, cmd);
break;
}
default: // unknown!
{
SysDebug2(BadVals,"vCmdParent::AddCmd(id:%d, title:%s) ** Unknown DialogCommand\n",
cmd->cmdId,cmd->title);
cmd->title = "?? Bad CommandObject ??";
cmdPtr = new vLabelCmd(this, cmd);
break;
}
}
return cmdPtr;
}
//====================>>> vCmdParent::HasId <<<=========================
int vCmdParent::HasId(ItemVal id) VCONST
{
// We need this one for panes to work correctly
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if (((cc->cmdP)->dlgCmd)->cmdId == id)
{
return 1;
}
}
return 0;
}
//====================>>> vCmdParent::GetValue <<<=========================
int vCmdParent::GetValue(ItemVal id) VCONST
{
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if (((cc->cmdP)->dlgCmd)->cmdId == id)
{
return (cc->cmdP)->GetCmdValue(id); // return the value
}
}
return 0;
}
//====================>>> vCmdParent::SetFrameChildren <<<======================
void vCmdParent::SetFrameChildren(ItemVal frameId, int frameVal)
{
// Set all children of given frame to hidden or not hidden
// Do this recursively to be sure to get them all.
// Scan list, setting all children that use this frame
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL) // Find the frame
{
CommandObject* cop = (cc->cmdP)->dlgCmd;
if (cop->cFrame == frameId) // A child of ours
{
// Hide control if not turning on (frameVal is opposite of Hidden)
SetValue(cop->cmdId, !frameVal, Hidden);
if (cop->cmdType == C_Frame || cop->cmdType == C_ToggleFrame)
SetFrameChildren(cop->cmdId, frameVal); // Get other chilren
}
}
}
//====================>>> vCmdParent::GetTextIn <<<=========================
int vCmdParent::GetTextIn(ItemVal id, char* strout, int maxlen)
{
// recover the string from TextIn id, up to maxlen
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if (((cc->cmdP)->dlgCmd)->cmdId == id)
{
// need to cast to a vTextInCmd so we can use getstr
vTextInCmd* tip = (vTextInCmd*) cc->cmdP;
return tip->GetTextIn(id, strout, maxlen); // return the value
}
}
*strout = 0;
return 0;
}
//====================>>> vCmdParent::getParent <<<=======================
HWND vCmdParent::getParent(void) VCONST
{
// Return parent's HWND
return _wDialog;
}
//==================>>> vCmdParent::getThisFromId <<<=======================
vCmd* vCmdParent::getThisFromId(ItemVal find_id)
{
// search the list of cmds for id, return its this
DlgCmdList* cc;
// search the list
for (cc = _cmdList; cc != NULL ; cc = cc->nextDCL)
{
if (cc->cmdP == NULL || (cc->cmdP)->dlgCmd == NULL)
return 0;
if (((cc->cmdP)->dlgCmd)->cmdId == find_id)
{
return cc->cmdP;
}
}
return 0; // failed to find it
}
//====================>>> vCmdParent::SetPosition <<<=========================
void vCmdParent::SetPosition(int& x, int& y, int w, int h, ItemVal frame,
ItemVal rightOf, ItemVal below, int isSpinner)
{
// This method is responsible for controlling the layout of controls in
// a dialog. All positions of controls are set relative to other controls,
// which must have been previously defined (i.e., you start with the upper
// left control and work to the lower right corner). It must dynamically
// set the size of frames, and track the maximum x and y of the whole
// dialog.
//
// note: As far as I can tell, the isSpinner variable is never used
// and is always 0 so I deleted all the isSpinner code
int margin = _CtrlSpacing; // spacing between controls
int FrameMargin = _CtrlSpacing*2; // spacing between controls and frame edge
vCmd* frameCmd = 0;
x = y = margin; // start out with standard spacing
if (frame != 0) // in a frame?
{
// refresher: DlgCmdList is a linked list of pointers to vCmd's
// _cmdList is the list of vCmd's (controls) for this dialog
// dlgCmd is a pointer to the vCmd static definition
//
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
continue;
// search for the vCmd of our frame
if (((cc->cmdP)->dlgCmd)->cmdId == frame)
{
frameCmd = cc->cmdP; // remember our frame
if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
FrameMargin = 0;
// position the control relative to the frame based on the specified
// position data
if (rightOf == 0)
{
x = (cc->cmdP)->_x + FrameMargin; // add to right of frame
if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
++x; // adjust for right side BEW 1.21
}
else
x = FrameMargin;
if (below == 0)
{
y = (cc->cmdP)->_y + FrameMargin;
if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
++y; // adjust for bottom BEW 1.21
}
else
y = FrameMargin;
}
}
} // end of frame procedure
// check if its a command bar and not in a frame
if (_dialogType == aCmdBar && frame == 0)
{
x = maxX + margin; // put the control at the end of the bar + margin
y = margin; // bars are linear in x (no y control allowed)
}
// check if its a status bar and not in a frame
else if (_dialogType == aStatBar && frame == 0)
{
x = maxX + margin; // put the control at the end of the bar + margin
// y = margin + 1; // adjust in y to center better
y = margin; // bars are linear in x (no y control allowed)
}
// else, its a regular dialog with full 2d positioning
else
{
// refresher: DlgCmdList is a linked list of pointers to vCmd's
// _cmdList is the list of vCmd's (controls) for this dialog
// dlgCmd is a pointer to the vCmd static definition
//
// cycle through all the controls in the dialog
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
// we skip the partially added current control
if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
continue;
// set the control's x posn right of the 'rightof' control
if (((cc->cmdP)->dlgCmd)->cmdId == rightOf)
{
x += ((cc->cmdP)->_x) + ((cc->cmdP)->_w); // position to right of the 'rightOf'
}
// set the control's y posn below the 'below' control
if (((cc->cmdP)->dlgCmd)->cmdId == below)
{
y += ((cc->cmdP)->_y) + ((cc->cmdP)->_h); // position below the 'below'
}
}
}
// now we adjust the overall dialog size to enclose the
// control we just added
int cxr = x + w; // right x of control
int cyb = y + h; // bottom y of control
if (maxX < cxr) // track size of the dialog
maxX = cxr;
if (maxY < cyb)
maxY = cyb;
// if a frame was used, then we need to also adjust the
// overall frame size to enclose the control we just added
if (frameCmd) // need to fixup frame
{
FixFrame(cxr, cyb, FrameMargin, frameCmd); // fixup frames
}
}
//====================>>> vCmdParent::FixFrame <<<=======================
// After a vCmd (control) is added to a frame, we need to readjust the
// overall frame size to make sure it encloses the control we just added
//
// cxr is the controls rightmost extent
// cyb is the controls bottommost extent
void vCmdParent::FixFrame(int cxr, int cyb, int FrameMargin, vCmd* frameCmd)
{
int fxr = frameCmd->_x + frameCmd->_w; // right x of frame
int fyb = frameCmd->_y + frameCmd->_h; // bottom y of frame
if (fxr < cxr + FrameMargin) // need to make frame wider
{
frameCmd->_w = (cxr + FrameMargin) - frameCmd->_x;
if (FrameMargin == 0)
++(frameCmd->_w); // make nospace look right BEW 1.21
}
if (fyb < cyb + FrameMargin) // need to make frame taller
{
frameCmd->_h = (cyb + FrameMargin) - frameCmd->_y;
if (FrameMargin == 0)
++(frameCmd->_h); // make nospace look right BEW 1.21
}
// Check if we need fixup the overall dialog size
if (maxX < frameCmd->_x + frameCmd->_w)
maxX = frameCmd->_x + frameCmd->_w;
if (maxY < frameCmd->_y + frameCmd->_h)
maxY = frameCmd->_y + frameCmd->_h;
// Now fixup the dialog template
// The dialog template item for the frame control is already created
// We need to update the template item size parameters with the new
// values for the frame size
if (frameCmd->_CtrlOffset != 0)
{
ULONG *wNumBytes;
PDLGTITEM pDlgTItem;
// wNumBytes points to beginning of DLGTEMPLATE memory block.
wNumBytes = (ULONG *) _hTemplate;
// pDlgTItem points to start of new DLGTITEM.
pDlgTItem = (PDLGTITEM) (((PSZ) wNumBytes) + frameCmd->_CtrlOffset);
// Fix the width
pDlgTItem->cx = frameCmd->_w;
pDlgTItem->cy = frameCmd->_h;
}
// Now, fixup surrounding frames!
int frame = (frameCmd->dlgCmd)->cFrame;
if (frame != 0) // Have to fix frame's frame
{
// refresher: DlgCmdList is a linked list of pointers to vCmd's
// _cmdList is the list of vCmd's (controls) for this dialog
// dlgCmd is a pointer to the vCmd static definition
//
// cycle through all the controls in the dialog
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
continue;
if (((cc->cmdP)->dlgCmd)->cmdId == frame)
{
vCmd* fCmd = cc->cmdP; // remember frame's frame
fxr = frameCmd->_x + frameCmd->_w; // right x of frame
fyb = frameCmd->_y + frameCmd->_h; // bottom y of frame
FixFrame(fxr, fyb, FrameMargin, fCmd);
break;
}
}
}
}
//====================>>> vCmdParent::SetValue <<<=======================
void vCmdParent::SetValue(ItemVal id, ItemVal val, ItemSetType setType)
{
SysDebug2(Misc,"vCmdParent::SetValue(id:%d, val:%d)\n",id,val)
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if (((cc->cmdP)->dlgCmd)->cmdId == id)
{
(cc->cmdP)->SetCmdVal(val,setType); // return the value
return;
}
}
}
//====================>>> vCmdParent::SetString <<<=======================
void vCmdParent::SetString(ItemVal id, char* str) VCONST
{
char trunc[80];
SysDebug2(Misc,"vCmdParent::SetString(id:%d, str:%s)\n",id, strncpy(trunc, str, 60) )
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
if (((cc->cmdP)->dlgCmd)->cmdId == id)
{
(cc->cmdP)->SetCmdStr(str); // return the value
return;
}
}
}
//====================>>> vCmdParent::CreateDlgTemplate <<<==================
// Creates a Dialog Template in memory. Avoids needing a resource file
// to build up the dialog controls.
int vCmdParent::CreateDlgTemplate(
ULONG dtCtlData, // dialog control data (FCF_*, etc)
ULONG dtStyle, // dialog style (WS_* and FS_*)
SHORT dtX, // location, In dialog-box units
SHORT dtY,
SHORT dtCX, // size, in dialog-box units
SHORT dtCY,
SHORT dtID, // V doesn't assign an ID to the frame
PSZ dtMenuName, // "" if no menu (not Implemented)
PSZ dtClassName, // "" if standard dialog box class (not implemented)
PSZ dtCaption, // caption text for dialog
PPRESPARAMS pPP) // Presentation Parameters
{
ULONG wBlockLen;
ULONG wBaseMem, wItemMem;
ULONG wCaptionLen, PPLen;
PSZ szDlgTemplate, szDlgTypeFace;
PDLGTEMPLATE pDlgTemplate;
// Calculate number of bytes required by following fields:
// Block must be large enough to contain the following:
// # bytes: fixed part DLGTEMPLATE and one DLGTITEM
// # bytes: dialog box caption.
// # bytes: presentation parameters.
wCaptionLen = (1 + strlen(dtCaption));
wBlockLen = sizeof(DLGTEMPLATE) + sizeof(dtCtlData) + wCaptionLen;
if (pPP)
{
// Dialog box has Presentation Parameters
// Calculate # of bytes required for PRESPARAM structure
// cb gives the byte count of the aparam[] array, need to add
// extra 4 bytes for pPP->cb count
PPLen = pPP->cb + sizeof(ULONG);
wBlockLen += PPLen; // # bytes for PRESPARAM value (font typeface)
}
else
{
// Dialog box uses the System font.
// Block length does not change.
PPLen = 0;
}
// Allocate global block of memory for Dialog template.
DosAllocMem ((PPVOID) &_hTemplate, wBlockLen, fALLOC);
if (_hTemplate == NULL)
return 0; // memory alloc failed!
// pDlgTemplate points to start of DLGTEMPLATE in block.
pDlgTemplate = _hTemplate;
// Set the members of the DLGTEMPLATE structure.
pDlgTemplate->cbTemplate = wBlockLen;
pDlgTemplate->type = 0; // not used
pDlgTemplate->codepage = theApp->AppCP();
wBaseMem = (ULONG) pDlgTemplate;
wItemMem = (ULONG) pDlgTemplate->adlgti;
pDlgTemplate->offadlgti = (SHORT) wItemMem - wBaseMem;
pDlgTemplate->fsTemplateStatus = 1; // not used (docs say 0 but debug says 1)
pDlgTemplate->iItemFocus = (USHORT) -1; // no focus specified
pDlgTemplate->coffPresParams = 0; // never used!
// Set the members of the frame DLGTITEM structure.
// the first item is always the frame window class (WC_FRAME)
pDlgTemplate->adlgti[0].fsItemStatus = 0; // not used
// no controls yet, Incremented with calls to AddDlgControl.
pDlgTemplate->adlgti[0].cChildren = 0;
pDlgTemplate->adlgti[0].cchClassName = 0; // use PM classes
pDlgTemplate->adlgti[0].offClassName = SHORT1FROMMP((MPARAM) WC_FRAME); // PM class
pDlgTemplate->adlgti[0].cchText = wCaptionLen-1; // strip null from string
pDlgTemplate->adlgti[0].flStyle = dtStyle;
pDlgTemplate->adlgti[0].x = dtX;
pDlgTemplate->adlgti[0].y = dtY;
pDlgTemplate->adlgti[0].cx = dtCX;
pDlgTemplate->adlgti[0].cy = dtCY;
pDlgTemplate->adlgti[0].id = dtID; // V doesn't seem to need this
// szDlgTemplate points to start of variable part of DLGTEMPLATE.
szDlgTemplate = (PSZ) (pDlgTemplate + 1);
// store variable length caption
// we compute the offset from here to start of DLGTEMPLATE and save
wItemMem = (ULONG) szDlgTemplate;
pDlgTemplate->adlgti[0].offText = (SHORT) (wItemMem - wBaseMem);
CopyStringToDialog(&szDlgTemplate, dtCaption);
// store ULONG control data here
wItemMem = (ULONG) szDlgTemplate;
pDlgTemplate->adlgti[0].offCtlData = (SHORT) wItemMem - wBaseMem;
memcpy(szDlgTemplate, &dtCtlData, 4);
szDlgTemplate += 4;
// add the PRESPARAMS info
if (pPP)
{
wItemMem = (ULONG) szDlgTemplate;
pDlgTemplate->adlgti[0].offPresParams = (SHORT) wItemMem - wBaseMem;
memcpy(szDlgTemplate, pPP, PPLen);
szDlgTemplate += PPLen;
DosFreeMem (pPP); // destroy pPP structure after use
}
else // no PPs!
pDlgTemplate->adlgti[0].offPresParams = (USHORT) -1;
return 1; // success
}
//====================>>> vCmdParent::AddDlgControl <<<=====================
int AddDlgControl (SHORT dtilX, SHORT dtilY, SHORT dtilCX, SHORT dtilCY,
USHORT dtilID, ULONG dtilStyle, PCSZ dtilClass, PCSZ dtilText,
PPRESPARAMS dtipPP, ULONG dtilCtlLen, PVOID dtilCtlData);
int vCmdParent::AddDlgControl (
SHORT dtilX, SHORT dtilY, // In dialog-box units.
SHORT dtilCX, SHORT dtilCY, // In dialog-box units.
USHORT dtilID,
ULONG dtilStyle, // WS_* BS_* etc.
PCSZ dtilClass, // Class name WC_*
PCSZ dtilText, // label
PPRESPARAMS dtipPP, // Pointer to presentation parameters
ULONG dtilCtlLen, // Control Data length (bytes)
PVOID dtilCtlData) // Pointer to control data
{
ULONG wBlockLen, wTextLen, wBaseMem, wItemMem;
ULONG PPLen;
USHORT *wCtlLen;
PDLGTEMPLATE pOldDlgTemplate, pDlgTemplate;
PDLGTITEM pDlgTItem;
PSZ pszOldData, pszData;
int i, numControls = 0; // number of controls in dialog
// Calculate number of bytes required by following fields:
wTextLen = (1 + strlen(dtilText)) * sizeof (char);
// Block must be increased by the following amount:
wBlockLen =
sizeof(DLGTITEM) + // # bytes for fixed part of DLGTITEM.
wTextLen + // # bytes for control text.
dtilCtlLen; // # bytes for extra CTRL data.
if (dtipPP)
{
// Dialog box has Presentation Parameters
// Calculate # of bytes required for PRESPARAM structure
// cb gives the byte count of the aparam[] array, need to add
// extra (ULONG) bytes for dtipPP->cb member
PPLen = dtipPP->cb + sizeof(ULONG);
// Block must be large enough to include PP information.
wBlockLen += PPLen; // # bytes for PRESPARAM value (font typeface)
}
else
{
// Dialog box uses the System font.
// Block length does not change.
PPLen = 0;
}
// Add to number of bytes currently in the memory block.
wBlockLen += _hTemplate->cbTemplate;
// pOldDlgTemplate points to start of old DLGTEMPLATE in block.
pOldDlgTemplate = _hTemplate;
// Allocate new larger global block of memory for Dialog template.
// this is probably really inefficient but what else is there to do?
DosAllocMem ((PPVOID) &pDlgTemplate, wBlockLen, fALLOC);
if (pDlgTemplate == NULL)
return 0; // memory alloc failed!
_hTemplate = pDlgTemplate;
wBaseMem = (ULONG) pDlgTemplate; // used for offset calcs
// copy over the old template data to the new structure
// we will fix up the offsets and variable data area later
memcpy(pDlgTemplate, pOldDlgTemplate, pOldDlgTemplate->cbTemplate);
// save the total size of the new template
pDlgTemplate->cbTemplate = wBlockLen;
// Increment the number of controls in the WC_FRAME template item.
numControls = ++pDlgTemplate->adlgti[0].cChildren;
// set pDlgTItem to point to the start of new DLGTITEM.
// This is near the end of the memory block.
pDlgTItem = &pDlgTemplate->adlgti[numControls];
// Set the members of the DLGTITEM structure.
pDlgTItem->fsItemStatus = 0; // not used
pDlgTItem->cChildren = 0; // only WC_FRAME has children
pDlgTItem->cchClassName = 0; // use PM classes
pDlgTItem->offClassName = SHORT1FROMMP((MPARAM) dtilClass); // WC_*
pDlgTItem->cchText = wTextLen-1; // label length (drop null at end)
pDlgTItem->flStyle = dtilStyle; // WS_* BS_*, MLE_* etc.
pDlgTItem->x = dtilX;
pDlgTItem->y = dtilY;
pDlgTItem->cx = dtilCX;
// We have to handle comboboxes specially because the
// height needed here is the combobox PLUS its list, while
// the height we want to use internally is the height WITHOUT the list
if (dtilClass == WC_COMBOBOX ) // Combo?
pDlgTItem->cy = dtilCY + 8*6;
else
pDlgTItem->cy = dtilCY;
pDlgTItem->id = dtilID;
pDlgTItem->offPresParams = (USHORT) -1; // default
// now we need to fix up the variable data area
// pszData points to start of variable data part of the template
pszData = (PSZ) (pDlgTItem + 1);
for (i=0; i<numControls; i++)
{
// store text label and compute offset to start of DLGTEMPLATE
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offText = (USHORT) (wItemMem - wBaseMem);
pszOldData = (PSZ) pOldDlgTemplate; // base of old template
pszOldData += pOldDlgTemplate->adlgti[i].offText; // pointer to old text
CopyStringToDialog(&pszData, pszOldData);
// store PRESPARAMS and compute offset to start of DLGTEMPLATE
// if offset = -1 then no data
if (pOldDlgTemplate->adlgti[i].offPresParams == (USHORT) -1)
pDlgTemplate->adlgti[i].offPresParams = (USHORT) -1;
else // else copy over data
{
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offPresParams = (USHORT) wItemMem - wBaseMem;
pszOldData = (PSZ) pOldDlgTemplate; // base of old template
pszOldData += pOldDlgTemplate->adlgti[i].offPresParams; // pointer to old CtlData
// get the data length in bytes (first 4 bytes of data)
PPLen = (ULONG) *pszOldData;
memcpy(pszData, pszOldData, PPLen + sizeof(ULONG));
pszData += PPLen + sizeof(ULONG);
}
// store CTLDATA and compute offset to start of DLGTEMPLATE
// if offset = -1 then no data
if (pOldDlgTemplate->adlgti[i].offCtlData == (USHORT) -1)
pDlgTemplate->adlgti[i].offCtlData = (USHORT) -1;
else // else copy over data
{
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offCtlData = (USHORT) wItemMem - wBaseMem;
pszOldData = (PSZ) pOldDlgTemplate; // base of old template
pszOldData += pOldDlgTemplate->adlgti[i].offCtlData; // pointer to old CtlData
// get the data length in bytes (first 4 bytes of data)
// Note: WC_FRAME class is non-conforming. It expects a 4 byte
// ULONG in the data area with no size info
if ( pOldDlgTemplate->adlgti[i].offClassName == SHORT1FROMMP((MPARAM) WC_FRAME))
{
memcpy(pszData, pszOldData, 4); // non-conforming
pszData += 4;
}
else
{
wCtlLen = (USHORT*) pszOldData; // conforming
memcpy(pszData, pszOldData, *wCtlLen);
pszData += *wCtlLen;
}
}
}
// now we finish off by storing the current control's data
// store control label and compute offset to start of DLGTEMPLATE
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offText = (USHORT) (wItemMem - wBaseMem);
CopyStringToDialog(&pszData, dtilText);
// store PRESPARAMS and compute offset to start of DLGTEMPLATE
if (dtipPP == 0) // if no data set offset to -1
pDlgTemplate->adlgti[i].offPresParams = (USHORT) -1;
else
{
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offPresParams = (USHORT) wItemMem - wBaseMem;
memcpy(pszData, dtipPP, dtipPP->cb + sizeof(ULONG));
pszData += dtipPP->cb + sizeof(ULONG);
DosFreeMem (dtipPP); // don't forget to clean up afterwards
}
// store CTLDATA and compute offset to start of DLGTEMPLATE
if (dtilCtlLen == 0) // if no data set offset to -1
pDlgTemplate->adlgti[i].offCtlData = (USHORT) -1;
else
{
wItemMem = (ULONG) pszData;
pDlgTemplate->adlgti[i].offCtlData = (USHORT) wItemMem - wBaseMem;
memcpy(pszData, dtilCtlData, dtilCtlLen);
pszData += dtilCtlLen;
}
// now destroy the old template
DosFreeMem(pOldDlgTemplate);
// offset to start of last control
return (int) &pDlgTemplate->adlgti[i] - wBaseMem;
}
//==================>>> vCmdParent::DoneAddingControls <<<===================
void vCmdParent::DoneAddingControls(void)
{
PDLGTEMPLATE pDlgTemplate;
// set pDlgTemplate to start of DLGTEMPLATE in block.
pDlgTemplate = _hTemplate;
// Fixup size
maxX = pDlgTemplate->adlgti[0].cx = maxX + _CtrlSpacing;
maxY = pDlgTemplate->adlgti[0].cy = maxY + _CtrlSpacing;
// we need to transform all control y-dimensions since V uses upper left as
// origin and OS/2 assumes lower left
ULONG *wNumBytes;
PDLGTITEM pDlgTItem;
// set wNumBytes to beginning of DLGTEMPLATE memory block.
wNumBytes = (ULONG *) _hTemplate;
for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
{
// transform the y coord in the dialog template
if ( (cc->cmdP)->_CtrlOffset != 0)
{
// set pDlgTItem to start of current control DLGTITEM.
pDlgTItem = (PDLGTITEM) (((PSZ) wNumBytes) + (cc->cmdP)->_CtrlOffset);
// invert and shift y coord
if ( (((cc->cmdP)->dlgCmd)->cmdType) == C_ComboBox ) // Combo?
pDlgTItem->y = maxY - (cc->cmdP)->_y - (cc->cmdP)->_h - 8*6;
else
pDlgTItem->y = maxY - (cc->cmdP)->_y - (cc->cmdP)->_h;
}
}
}
//================>>> vCmdParent::ChangeDlgTButtonColor <<<=====================
// routine to change the color button color in the dialog template
// after the template is assembled in memory
//
void vCmdParent::ChangeDlgTButtonColor(int CtrlOffset, USHORT cmdId, ULONG newColor )
{
PDLGTITEM pDlgTItem;
// set pDlgTItem to start of current control DLGTITEM.
pDlgTItem = (PDLGTITEM) (((PSZ) _hTemplate) + CtrlOffset);
// a sanity check
if (pDlgTItem->id != cmdId)
{
// something's gone wrong, better punt!
return;
}
// find the button color pres params word in the template...
// this is a bit dangerous since we assume that the button
// color pres param order is fixed, but since we create the template
// we do have control over this so it shouldn't break later
// and it makes life simpler this way
ULONG *buttonColor;
buttonColor = (ULONG *) (((PSZ) _hTemplate) + pDlgTItem->offPresParams);
// button color is 3rd ULONG in from start of Pres Params
buttonColor += 3;
*buttonColor = newColor;
}
//====================>>> vCmdParent::AssyPresParams <<<=====================
//----- routine to assemble an arbitrary size PP structure
PPRESPARAMS vCmdParent::AssyPresParams(PPElement *PPel)
{
ULONG PPlen;
int i;
PPARAM ixPP;
PPRESPARAMS pPP;
// first compute necessary storage space for PPs
PPlen = sizeof(ULONG); // pp.cb
for (i=0; PPel[i].PPtype; i++)
{
if (PPel[i].PPtype == PP_FONTNAMESIZE)
// its a font PP
PPlen += sizeof(PARAM)-1 + strlen(PPel[i].PPval.font)+1;
else
// its a color PP
PPlen += sizeof(PARAM)-1 + sizeof(ULONG);
}
// now we build up the PRESPARAM structure
DosAllocMem ((PPVOID) &pPP, PPlen, fALLOC);
// Danger: PRESPARAMS is so braindead that it is unworkable
// as designed. It uses a PARAM as an indexed array
// internally, but PARAM is variable length so that
// the indexing fails after the first element!
pPP->cb = PPlen - sizeof(ULONG);
ixPP = pPP->aparam;
for (i=0; PPel[i].PPtype; i++)
{
ixPP->id = PPel[i].PPtype;
if (PPel[i].PPtype == PP_FONTNAMESIZE)
{ // its a font PP
ixPP->cb = strlen(PPel[i].PPval.font)+1;
strcpy(ixPP->ab, PPel[i].PPval.font);
}
else
{ // its a color PP
ixPP->cb = sizeof(ULONG);
memcpy(ixPP->ab, &PPel[i].PPval.color, sizeof(ULONG));
}
// now we set the index to the next PARAM element in the PRESPARAM structure
// Here, we temporarily set ixPP to a PSZ so we can do byte size pointer
// arithmetic
ixPP = (PPARAM) (((PSZ) ixPP) + sizeof(PARAM)-1 + ixPP->cb);
}
return(pPP);
}
// ---------------------------------------------------------------------