Category : Files from Magazines
Archive   : NOV92_1.ZIP
Filename : DIALOG.ASC

 
Output of file : DIALOG.ASC contained in archive : NOV92_1.ZIP
_DYNAMIC DIALOG BOXES IN C++_
by Robert Sardis

[LISTING ONE]

/***** DialogTemplate class ******/

#include
#include
#include
#include
#include

int ErrorMessage(LPSTR);
class DialogTemplate
{
public:
DialogTemplate(void);
~DialogTemplate(void);
void SpecifyDlgBox(long Style, int x, int y, int width, int height,
LPSTR MenuName, LPSTR ClassName, LPSTR CaptionText);
void SpecifyFont(short int PointSize, LPSTR TypeFace);
void AddItem(int x, int y, int width, int height, int ID, long Style,
LPSTR Class, LPSTR Text, BYTE DataBytes, LPBYTE Data);
int DialogBoxIndirect(HANDLE hInstance, HWND hWndParent,
FARPROC lpDialogProc);
int DialogBoxIndirectParam(HANDLE hInstance, HWND hWndParent,
FARPROC lpDialogProc, DWORD dwInitParam);
private:
HANDLE hMem;
int nBytes;
int nItems;
};
typedef struct
{
long Style;
BYTE nItems;
int x;
int y;
int width;
int height;
// char MenuName[];
// char ClassName[];
// char CaptionText[];
} DLGTEMPLATE, FAR *LPDLGTEMPLATE;
typedef struct
{
short int PointSize;
// char TypeFace[];
} FONTINFO, FAR *LPFONTINFO;
typedef struct
{
int x;
int y;
int width;
int height;
int ID;
long Style;
// char Class[];
// char Text[];
// BYTE Info;
// PTR Data;
} DLGITEMTEMPLATE, FAR *LPDLGITEMTEMPLATE;
DialogTemplate::DialogTemplate(void)
{
nBytes = 0;
nItems = 0;
hMem = 0;
}
DialogTemplate::~DialogTemplate(void)
{
GlobalFree(hMem);
}
void DialogTemplate::SpecifyDlgBox(long Style, int x, int y,
int width, int height, LPSTR MenuName, LPSTR ClassName, LPSTR CaptionText)
{
LPDLGTEMPLATE lpDlg;
LPSTR lpText;
int MenuNameBytes = lstrlen(MenuName) + 1; // sizes of strings,
int ClassNameBytes = lstrlen(ClassName) + 1; // including null
int CaptionTextBytes = lstrlen(CaptionText) + 1; // terminator

nBytes = sizeof(DLGTEMPLATE) + MenuNameBytes + ClassNameBytes +
CaptionTextBytes;

nItems = 0;
GlobalFree(hMem);
hMem = GlobalAlloc(GHND, nBytes);
if (hMem == NULL)
{
ErrorMessage("Memory allocation error creating dialog template");
return;
}
lpDlg = (LPDLGTEMPLATE) GlobalLock(hMem); // add the "fixed size"
lpDlg->Style = Style; // fields of the template
lpDlg->nItems = 0;
lpDlg->x = x;
lpDlg->y = y;
lpDlg->width = width;
lpDlg->height = height;

lpText = ((LPSTR) lpDlg) + sizeof (DLGTEMPLATE); // append the three
_fmemcpy(lpText, MenuName, MenuNameBytes); // null-terminated text
lpText += MenuNameBytes; // strings
_fmemcpy(lpText, ClassName, ClassNameBytes);
lpText += ClassNameBytes;
_fmemcpy(lpText, CaptionText, CaptionTextBytes);
GlobalUnlock(hMem);
}
void DialogTemplate::SpecifyFont(short int PointSize, LPSTR TypeFace)
{
LPDLGTEMPLATE lpDlg;
LPFONTINFO lpFont;
LPSTR lpText;
int OldnBytes = nBytes;
int TypeFaceBytes = lstrlen(TypeFace) + 1;

nBytes += sizeof(FONTINFO) + TypeFaceBytes;
hMem = GlobalReAlloc(hMem, nBytes, GHND);
if (hMem == NULL)
{
ErrorMessage("Memory allocation error adding dialog font");
return;
}
// add DS_SETFONT to style to indicate font template is being added
lpDlg = (LPDLGTEMPLATE) GlobalLock(hMem);
lpDlg->Style |= DS_SETFONT;
// append font template to dialog template
lpFont = (LPFONTINFO) (((LPSTR) lpDlg) + OldnBytes);
lpFont->PointSize = PointSize; // append fixed-size field of font info
lpText = ((LPSTR) lpFont) + sizeof(LPFONTINFO); // append null-termi-
_fmemcpy(lpText, TypeFace, TypeFaceBytes); // nated text string
GlobalUnlock(hMem);
}
void DialogTemplate::AddItem(int x, int y, int width, int height,
int ID, long Style, LPSTR Class, LPSTR Text, BYTE DataBytes, LPBYTE Data)
{
LPDLGTEMPLATE lpDlg;
LPDLGITEMTEMPLATE lpItem;
LPSTR lpText;
int OldnBytes = nBytes;
int ClassBytes = lstrlen(Class) + 1;
int TextBytes = lstrlen(Text) + 1;

nBytes += sizeof(DLGITEMTEMPLATE) + ClassBytes + TextBytes + sizeof(BYTE)
+ DataBytes;
hMem = GlobalReAlloc(hMem, nBytes, GHND);
if (hMem == NULL)
{
ErrorMessage("Memory allocation error adding dialog item");
return;
}
nItems++;
lpDlg = (LPDLGTEMPLATE) GlobalLock(hMem);
lpDlg->nItems = nItems; // update # items
// append item template to template block
lpItem = (LPDLGITEMTEMPLATE) (((LPSTR) lpDlg) + OldnBytes);
lpItem->x = x; // append fixed-size
lpItem->y = y; // fields
lpItem->width = width;
lpItem->height = height;
lpItem->ID = ID;
lpItem->Style = Style | WS_CHILD | WS_VISIBLE;

lpText = ((LPSTR) lpItem )+ sizeof(DLGITEMTEMPLATE); // append variable
_fmemcpy(lpText, Class, ClassBytes); // length portion:
lpText += ClassBytes; // two strings,
_fmemcpy(lpText, Text, TextBytes); // one byte, and a
lpText += TextBytes; // data block.
*lpText = DataBytes;
lpText += sizeof(BYTE);
_fmemcpy(lpText, Data, DataBytes);

GlobalUnlock(hMem);
}
int DialogTemplate::DialogBoxIndirect(HANDLE hInstance, HWND hWndParent,
FARPROC lpDialogProc)
{
return ::DialogBoxIndirect(hInstance, hMem, hWndParent, lpDialogProc);
}
int DialogTemplate::DialogBoxIndirectParam(HANDLE hInstance, HWND hWndParent,
FARPROC lpDialogProc, DWORD dwInitParam)
{
return ::DialogBoxIndirectParam(hInstance, hMem, hWndParent,
(FARPROC) lpDialogProc, dwInitParam);
}


[LISTING TWO]

/****** StringsBox class ******/

#include
#include
#include
#include
#include
#include

int ErrorMessage(LPSTR);
#define max(A,B) ((A) > (B) ? A : B)

#define MakeFarPointer(N,F) \
(sizeof(PSTR)==sizeof(LPSTR) ? (LONG)N : MAKELONG((WORD)N,HIWORD((LONG)F)))
// macro to convert near pointer "N" to far -- "F" is a
// reference far pointer, in the same segment as N. Used for DLLs
struct StringSpec
{
char *Title;
int MaxLength;
};
class StringsBox
{
public:
StringsBox(void);
~StringsBox(void);
void SetUp(LPSTR Caption, struct StringSpec far *Items, int NumItems);
int GetStrings(HANDLE hInstance, HWND hwnd, BOOL InitializedFlag);
friend BOOL FAR PASCAL _export
StringsBox_DlgProc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
HANDLE hStrings;
private:
DialogTemplate *DT;
int nItems;
int *ItemLengths;
static StringsBox *FirstBox; // linked list parameters so the
StringsBox *PrevBox; // function DlgProc() can
StringsBox *NextBox; // determine the StringsBox
HWND hDlg; // corresponding to the handle hDlg
friend StringsBox *GetStringsBox(HWND hDlg);
BOOL InitFlag;
};
StringsBox *StringsBox::FirstBox = NULL; // initialize linked list
StringsBox::StringsBox(void)
{
DT = new DialogTemplate;
ItemLengths = NULL;
nItems = 0;
hStrings = 0;
hDlg = 0;
if (FirstBox == NULL) // insert new object in the linked list--
{ // either at the beginning, if the list
FirstBox = this; // is empty ...
PrevBox = NULL;
NextBox = NULL;
}
else // or else at the end, after the first
{ // StringsBox whose NextBox pointer is
StringsBox *pBox; // NULL
for (pBox = FirstBox; pBox->NextBox != NULL; pBox = pBox->NextBox);
PrevBox = pBox;
pBox->NextBox = this;
NextBox = NULL;
}
}
StringsBox::~StringsBox(void)
{
delete DT;
GlobalDiscard(hStrings);
delete ItemLengths;
if (this == FirstBox) // take object out of linked list
FirstBox = NextBox;
if (PrevBox != NULL)
PrevBox->NextBox = NextBox;
if (NextBox != NULL)
NextBox->PrevBox = PrevBox;
}
#define LINE_HEIGHT 2*cy
#define LINE_TEXT_HEIGHT 1.5*cy
#define HSPACE 2*cx
#define IDD_ITEM(A) A+101
void StringsBox::SetUp(LPSTR Caption,struct StringSpec far *Items,int NumItems)
{
int i, y;
LPSTR lpStringsBlock;
int MaxTitleWidth = 0;
int MaxEditWidth = 0;
int hStringSize = 0;
int cx = 4; // character average width and height,
int cy = 8; // in dialog box units
// get max dimensions of titles and edit windows -- hdc needed for call to
// GetTextExtent(), tm needed to convert return value of GetTextExtent()
// from logical units to dialog box units
HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
TEXTMETRIC tm;
HFONT hFont = GetStockObject(SYSTEM_FONT);
SelectObject(hdc, hFont);
GetTextMetrics(hdc, &tm);

for (i = 0; i < NumItems; i++)
{
MaxTitleWidth = max(MaxTitleWidth, LOWORD(GetTextExtent(hdc,
(LPSTR)MakeFarPointer(Items[i].Title, Items),
lstrlen((LPSTR)MakeFarPointer(Items[i].Title, Items)))));
MaxEditWidth = max(MaxEditWidth, cx*(Items[i].MaxLength+1));
}
// convert MaxTitleWidth from logical units to dialog box units:
// multiply by ratio of (ave char width in dialog box units) to
// (ave char width in logical units), and round up to next integer
MaxTitleWidth = ceil(((double)MaxTitleWidth * (double)cx) /
(double)tm.tmAveCharWidth);
DeleteDC(hdc);
// calculate locations of controls
int ItemTitleX = HSPACE;
int ItemEditX = ItemTitleX + MaxTitleWidth + HSPACE;
int FirstItemY = LINE_HEIGHT;
int ButtonWidth = 10*cx;
int ButtonY = FirstItemY + NumItems*LINE_HEIGHT + LINE_HEIGHT;

int BoxX = 1;
int BoxY = 1;
int BoxWidth =
max(MaxTitleWidth + MaxEditWidth + HSPACE + 2*HSPACE,
2*ButtonWidth + 4*HSPACE);
int BoxHeight = ButtonY + LINE_HEIGHT;
int CenterX = BoxWidth / 2;
// set up dialog template
DT->SpecifyDlgBox(WS_CAPTION | WS_SYSMENU | WS_VISIBLE | WS_POPUP,
BoxX, BoxY, BoxWidth, BoxHeight, "", "", Caption);
// DT->SpecifyFont() not called -- use default font
for (i = 0; i < NumItems; i++)
{
y = FirstItemY + i*LINE_HEIGHT;
// Item title
DT->AddItem(ItemTitleX, y, MaxTitleWidth, LINE_TEXT_HEIGHT,
-1, SS_LEFT | WS_GROUP, "STATIC",
(LPSTR) MakeFarPointer(Items[i].Title, Items), 0, NULL);
// Item edit
DT->AddItem(ItemEditX, y, cx*(Items[i].MaxLength+1), LINE_TEXT_HEIGHT,
IDD_ITEM(i), ES_LEFT | ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, "EDIT",
"", 0, NULL);
}
// 'OK' button
DT->AddItem(CenterX - ButtonWidth - HSPACE, ButtonY, ButtonWidth,
LINE_TEXT_HEIGHT, IDOK, BS_DEFPUSHBUTTON | WS_TABSTOP | WS_GROUP,
"BUTTON", "OK", 0, NULL);
// 'CANCEL' button
DT->AddItem(CenterX + HSPACE, ButtonY, ButtonWidth,
LINE_TEXT_HEIGHT, IDCANCEL, BS_PUSHBUTTON | WS_TABSTOP | WS_GROUP,
"BUTTON", "Cancel", 0, NULL);
// set class parameters
nItems = NumItems;
if (ItemLengths != NULL)
delete ItemLengths;
ItemLengths = new int[nItems];
for (i = 0; i < nItems; i++)
hStringSize += (ItemLengths[i] = Items[i].MaxLength);
// allocate hStrings block and initialize it to nulls
if (hStrings == 0)
hStrings = GlobalAlloc(GHND, hStringSize);
else
hStrings = GlobalReAlloc(hStrings, hStringSize, GHND);
lpStringsBlock = GlobalLock(hStrings);
_fmemset(lpStringsBlock, '\0', hStringSize);
GlobalUnlock(hStrings);
}
int StringsBox::GetStrings(HANDLE hInstance, HWND hwnd, BOOL InitializedFlag)
{
FARPROC lpDialogProc;
int RetVal;
InitFlag = InitializedFlag;

lpDialogProc = MakeProcInstance((FARPROC) StringsBox_DlgProc, hInstance);
// pass "this" pointer so dialog box procedure
// can recover it during WM_INITDIALOG
RetVal = DT->DialogBoxIndirectParam(hInstance, hwnd, (FARPROC)lpDialogProc,
(DWORD) this);
FreeProcInstance(lpDialogProc);
return RetVal;
}
BOOL FAR PASCAL _export
StringsBox_DlgProc(HWND hDlg, WORD msg, WORD wParam, LONG lParam)
{
int i;
LPSTR lpText;
// find "this" pointer of corresponding StringsBox object --
// on WM_INITDIALOG, it is passed as lParam; on subsequent
// calls, use GetStringsBox() to look it up in the linked list
StringsBox *pBox =
(msg == WM_INITDIALOG ? (StringsBox *) lParam : GetStringsBox(hDlg));
switch(msg)
{
case WM_INITDIALOG:
pBox->hDlg = hDlg; // insert "this" pointer in linked list -- set
// Box->hDlg so GetStringsBox() can find it on
// subsequent calls from this dialog procedure
if (pBox->InitFlag)
{
lpText = GlobalLock(pBox->hStrings);
for (i = 0; i < pBox->nItems; i++)
{
SetDlgItemText(hDlg, IDD_ITEM(i), lpText);
lpText += pBox->ItemLengths[i];
}
GlobalUnlock(pBox->hStrings);
}
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
lpText = GlobalLock(pBox->hStrings);
for (i = 0; i < pBox->nItems; i++)
{
GetDlgItemText(hDlg, IDD_ITEM(i), lpText,
pBox->ItemLengths[i]);
lpText += pBox->ItemLengths[i];
}
GlobalUnlock(pBox->hStrings);
pBox->hDlg = 0; // set pBox->hDlg back to
// an invalid value
EndDialog(hDlg, TRUE);
return TRUE;
case IDCANCEL:
pBox->hDlg = 0;
EndDialog(hDlg, FALSE);
return TRUE;
}
break;
}
return FALSE;
}
StringsBox * GetStringsBox(HWND hDlg)
{
StringsBox *pBox;
for (pBox = StringsBox::FirstBox; pBox != NULL; pBox = pBox->NextBox)
{
if (pBox->hDlg == hDlg)
return pBox;
}
return NULL;
}



[LISTING THREE]

/***** dboxdemo.cpp -- C++ dynamic dialog box example *****/

#include
#include
#include
#include
#include "wbdialog.hpp" // header file containing DialogTemplate and
// StringsBox class definitions
StringsBox EditBox;
struct StringSpec StringFieldSpec[] = // field spec for EditBox
{
"Name", 20,
"Address", 30,
"Telephone", 15,
};
int NumStrings = sizeof(StringFieldSpec) / sizeof(struct StringSpec);
struct
{
HANDLE hInstance;
} InsGlobs;
struct
{
HWND hwnd;
short cxChar;
short cyChar;
} WndGlobs;
long FAR PASCAL _export WndProc(HWND, WORD, WORD, LONG);
int ErrorMessage(char *msg);
char szAppName[] = "dboxdemo";
int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
if(!hPrevInstance)
{
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName;
RegisterClass(&wndclass);
}
hwnd = CreateWindow(szAppName, "C++ Dynamic Dialog Box Demo",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
WndGlobs.hwnd = hwnd;
InsGlobs.hInstance = hInstance;
ShowWindow(WndGlobs.hwnd, nCmdShow);
UpdateWindow(WndGlobs.hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
long FAR PASCAL _export WndProc(HWND hwnd, WORD message, WORD wParam,
LONG lParam)
{
HDC hdc;
TEXTMETRIC tm;
PAINTSTRUCT ps;
LPSTR lpString;
int i;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
GetTextMetrics(hdc, &tm);
WndGlobs.cxChar = tm.tmAveCharWidth;
WndGlobs.cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hwnd, hdc);
EditBox.SetUp("Edit Fields", StringFieldSpec, NumStrings);
return 0;
case WM_LBUTTONDBLCLK: // display dialog box on double-click
// StringsBox::GetStrings() returns TRUE if
// user selects OK button; in this case,
// cause window to be repainted to display
// latest contents of EditBox.hStrings block
if ((EditBox.GetStrings(InsGlobs.hInstance, WndGlobs.hwnd, TRUE)
== TRUE))
InvalidateRect(WndGlobs.hwnd, NULL, TRUE);
return 0;
case WM_PAINT:
hdc = BeginPaint(WndGlobs.hwnd, &ps);
if (EditBox.hStrings != 0)
{
lpString = GlobalLock(EditBox.hStrings);
for (i = 0; i < NumStrings; i++)
{
TextOut(hdc, 0, i*WndGlobs.cyChar, lpString,
_fstrlen(lpString));
lpString += StringFieldSpec[i].MaxLength;
}
GlobalUnlock(EditBox.hStrings);
}
EndPaint(WndGlobs.hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int ErrorMessage(LPSTR msg)
{
MessageBox(WndGlobs.hwnd, msg, szAppName, MB_ICONINFORMATION|MB_OK);
return 0;
}



  3 Responses to “Category : Files from Magazines
Archive   : NOV92_1.ZIP
Filename : DIALOG.ASC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/