234 lines
6.8 KiB
C++
234 lines
6.8 KiB
C++
////////////////////////////////////////////////////////////////
|
|
// MSDN Magazine -- June 2005
|
|
// If this code works, it was written by Paul DiLascia.
|
|
// If not, I don't know who wrote it.
|
|
// Compiles with Visual Studio .NET 2003 (V7.1) on Windows XP. Tab size=3.
|
|
//
|
|
#include "..\stdafx.h"
|
|
#include "InputDlg.h"
|
|
#include <atlconv.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
//////////////////
|
|
// Note: Make sure nBufLen is big enough to hold your entire dialog template!
|
|
//
|
|
CDlgTemplateBuilder::CDlgTemplateBuilder(UINT nBufLen)
|
|
{
|
|
m_pBuffer = new WORD[nBufLen];
|
|
m_pNext = m_pBuffer;
|
|
m_pEndBuf = m_pNext + nBufLen;
|
|
}
|
|
|
|
CDlgTemplateBuilder::~CDlgTemplateBuilder()
|
|
{
|
|
delete [] m_pBuffer;
|
|
}
|
|
|
|
//////////////////
|
|
// Create template (DLGTEMPLATE)
|
|
//
|
|
DLGTEMPLATE* CDlgTemplateBuilder::Begin(DWORD dwStyle, const CRect& rc,
|
|
LPCTSTR text, DWORD dwStyleEx)
|
|
{
|
|
ASSERT(m_pBuffer==m_pNext); // call Begin first and only once!
|
|
|
|
DLGTEMPLATE* hdr = (DLGTEMPLATE*)m_pBuffer;
|
|
hdr->style = dwStyle; // copy style..
|
|
hdr->dwExtendedStyle = dwStyleEx; // ..and extended, too
|
|
hdr->cdit = 0; // number of items: zero
|
|
|
|
// Set dialog rectangle.
|
|
CRect rcDlg = rc;
|
|
hdr->x = (short)rcDlg.left;
|
|
hdr->y = (short)rcDlg.top;
|
|
hdr->cx = (short)rcDlg.Width();
|
|
hdr->cy = (short)rcDlg.Height();
|
|
|
|
// Append trailing items: menu, class, caption. I only use caption.
|
|
m_pNext = (WORD*)(hdr+1);
|
|
*m_pNext++ = 0; // menu (none)
|
|
*m_pNext++ = 0; // dialog class (use standard)
|
|
m_pNext = AddText(m_pNext, text); // append dialog caption
|
|
|
|
ASSERT(m_pNext < m_pEndBuf);
|
|
return hdr;
|
|
}
|
|
|
|
//////////////////
|
|
// Add dialog item (control).
|
|
//
|
|
void CDlgTemplateBuilder::AddItemTemplate(WORD wType, DWORD dwStyle,
|
|
const CRect& rc, WORD nID, DWORD dwStyleEx)
|
|
{
|
|
ASSERT(m_pNext < m_pEndBuf);
|
|
|
|
// initialize DLGITEMTEMPLATE
|
|
DLGITEMTEMPLATE& it = *((DLGITEMTEMPLATE*)AlignDWORD(m_pNext));
|
|
it.style = dwStyle;
|
|
it.dwExtendedStyle = dwStyleEx;
|
|
|
|
CRect rcDlg = rc;
|
|
it.x = (short)rcDlg.left;
|
|
it.y = (short)rcDlg.top;
|
|
it.cx = (short)rcDlg.Width();
|
|
it.cy = (short)rcDlg.Height();
|
|
it.id = nID;
|
|
|
|
// add class (none)
|
|
m_pNext = (WORD*)(&it+1);
|
|
*m_pNext++ = 0xFFFF; // next WORD is atom
|
|
*m_pNext++ = wType; // ..atom identifier
|
|
ASSERT(m_pNext < m_pEndBuf); // check not out of range
|
|
|
|
// increment control/item count
|
|
DLGTEMPLATE* hdr = (DLGTEMPLATE*)m_pBuffer;
|
|
hdr->cdit++;
|
|
}
|
|
|
|
//////////////////
|
|
// Add dialog item (control).
|
|
//
|
|
void CDlgTemplateBuilder::AddItem(WORD wType, DWORD dwStyle,
|
|
const CRect& rc, LPCTSTR text, WORD nID, DWORD dwStyleEx)
|
|
{
|
|
AddItemTemplate(wType, dwStyle, rc, nID, dwStyleEx);
|
|
m_pNext = AddText(m_pNext, text); // append title
|
|
*m_pNext++ = 0; // no creation data
|
|
ASSERT(m_pNext < m_pEndBuf);
|
|
}
|
|
|
|
//////////////////
|
|
// Add dialog item (control).
|
|
//
|
|
void CDlgTemplateBuilder::AddItem(WORD wType, DWORD dwStyle,
|
|
const CRect& rc, WORD wResID, WORD nID, DWORD dwStyleEx)
|
|
{
|
|
AddItemTemplate(wType, dwStyle, rc, nID, dwStyleEx);
|
|
*m_pNext++ = 0xFFFF; // next is resource id
|
|
*m_pNext++ = wResID; // ..here it is
|
|
*m_pNext++ = 0; // no extra stuff
|
|
ASSERT(m_pNext < m_pEndBuf);
|
|
}
|
|
|
|
//////////////////
|
|
// Append text to buffer. Convert to Unicode if necessary.
|
|
// Return pointer to next character after terminating NULL.
|
|
//
|
|
WORD* CDlgTemplateBuilder::AddText(WORD* buf, LPCTSTR text)
|
|
{
|
|
if (text) {
|
|
USES_CONVERSION;
|
|
wcscpy((WCHAR*)buf, T2W((LPTSTR)text));
|
|
buf += wcslen((WCHAR*)buf)+1;
|
|
} else {
|
|
*buf++ = 0;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
//////////////////
|
|
// Create string dialog. If no icon specified, use IDI_QUESTION. Note that
|
|
// the order in which the controls are added is the TAB order.
|
|
//
|
|
BOOL CInputDialog::Init(LPCTSTR caption, LPCTSTR prompt, CWnd* pParent, BOOL bIsOk, CString str, WORD nIDIcon)
|
|
{
|
|
m_str = str;
|
|
const CXDIALOG = 300; // dialog width
|
|
const DLGMARGIN = 7; // margins all around
|
|
const CYSTATIC = 8; // height of static text
|
|
const CYEDIT = 12; // height of edit control
|
|
const CYSPACE = 5; // vertical space between controls
|
|
const CXBUTTON = 40; // button width...
|
|
const CYBUTTON = 15; // ..and height
|
|
|
|
CDlgTemplateBuilder& dtb = m_dtb;
|
|
CRect rc(
|
|
CPoint(0,0),
|
|
CSize(CXDIALOG, CYSTATIC + CYEDIT + CYBUTTON + 2*DLGMARGIN + 2*CYSPACE));
|
|
|
|
// create dialog header
|
|
DLGTEMPLATE* pTempl = dtb.Begin(WS_POPUPWINDOW|DS_MODALFRAME|WS_DLGFRAME,rc,caption);
|
|
|
|
// shrink main rect by margins
|
|
rc.DeflateRect(CSize(DLGMARGIN,DLGMARGIN));
|
|
|
|
// create icon if needed
|
|
if (nIDIcon) {
|
|
if (nIDIcon >= (WORD)IDI_APPLICATION) {
|
|
// if using a system icon, I load it here and set it in OnInitDialog
|
|
// because can't specify system icon in template, only icons from
|
|
// application resource file.
|
|
m_hIcon = ::LoadIcon(NULL, MAKEINTRESOURCE(nIDIcon));
|
|
nIDIcon = 0;
|
|
} else {
|
|
m_hIcon = NULL;
|
|
}
|
|
|
|
// The size is calculated in pixels, but it seems to work OK--???
|
|
CSize sz(GetSystemMetrics(SM_CXICON),GetSystemMetrics(SM_CYICON));
|
|
CRect rcIcon(rc.TopLeft(), sz);
|
|
dtb.AddItem(CDlgTemplateBuilder::STATIC, // add icon
|
|
WS_VISIBLE|WS_CHILD|SS_LEFT|SS_ICON, rc, nIDIcon, IDICON);
|
|
rc.left += sz.cx; // shrink main rect by width of icon
|
|
}
|
|
|
|
// add prompt
|
|
rc.bottom = rc.top + CYSTATIC; // height = height of static
|
|
dtb.AddItem(CDlgTemplateBuilder::STATIC, // add it
|
|
WS_VISIBLE|WS_CHILD|SS_LEFT, rc, prompt);
|
|
|
|
// add edit control
|
|
rc += CPoint(0, rc.Height() + CYSPACE); // move below static
|
|
rc.bottom = rc.top + CYEDIT; // height = height of edit control
|
|
dtb.AddItem(CDlgTemplateBuilder::EDIT, // add it ES_AUTOHSCROLL must be add
|
|
WS_VISIBLE|WS_CHILD|WS_BORDER|WS_TABSTOP|ES_AUTOHSCROLL, rc, m_str, IDEDIT);
|
|
|
|
// add OK button
|
|
rc += CPoint(0, rc.Height() + CYSPACE); // move below edit control
|
|
rc.bottom = rc.top + CYBUTTON; // height = button height
|
|
rc.left = rc.right - CXBUTTON; // width = button width
|
|
rc -= CPoint(CXBUTTON + DLGMARGIN,0); // move left one button width
|
|
dtb.AddItem(CDlgTemplateBuilder::BUTTON, // add it
|
|
WS_VISIBLE|WS_CHILD|WS_TABSTOP|BS_DEFPUSHBUTTON, rc, _T("&OK"), IDOK);
|
|
|
|
// add Cancel button
|
|
rc += CPoint(CXBUTTON + DLGMARGIN,0); // move right again
|
|
dtb.AddItem(CDlgTemplateBuilder::BUTTON, // add Cancel button
|
|
WS_VISIBLE|WS_CHILD|WS_TABSTOP, rc, _T("&Cancel"), IDCANCEL);
|
|
m_bIsOk = bIsOk;
|
|
|
|
return InitModalIndirect(pTempl, pParent);
|
|
}
|
|
|
|
//////////////////
|
|
// Initialize dialog: if I loaded a system icon, set it in static control.
|
|
//
|
|
BOOL CInputDialog::OnInitDialog()
|
|
{
|
|
if (m_hIcon) {
|
|
CStatic* pStatic = (CStatic*)GetDlgItem(IDICON);
|
|
ASSERT(pStatic);
|
|
pStatic->SetIcon(m_hIcon);
|
|
}
|
|
return CDialog::OnInitDialog();
|
|
}
|
|
|
|
/////////////////
|
|
// User pressed OK: check for empty string if required flag is set.
|
|
//
|
|
void CInputDialog::OnOK()
|
|
{
|
|
UpdateData(TRUE);
|
|
if (m_bRequired && m_str.IsEmpty()) {
|
|
if(m_bIsOk)
|
|
{
|
|
MessageBeep(0);
|
|
return; // don't quit dialog!
|
|
}
|
|
}
|
|
CDialog::OnOK();
|
|
}
|