📄 dynamicdialogtemplate.h
字号:
/////////////////////////////////////////////////////////////////////////////
// DynamicDialogTemplate.h - Class used to construct an in-memory dialog
// template, along with controls to go on the dialog
//
// Written by Daniel Bowen (dbowen@es.com)
// Copyright (c) 2003-2004 Daniel Bowen.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever.
//
// If you find bugs, have suggestions for improvements, etc.,
// please contact the author.
//
//
// CDynamicDialogTemplate - Used to construct an in-memory dialog template
// based on DLGTEMPLATE and DLGITEMTEMPLATE
//
// CDynamicDialogExTemplate - Used to construct an in-memory dialog template
// based on DLGTEMPLATEEX and DLGITEMTEMPLATEEX
#ifndef __DynamicDialogTemplate_h__
#define __DynamicDialogTemplate_h__
// To find out more about in-memory dialog templates, see the MSDN library
// for a description of DLGTEMPLATE and DLGITEMTEMPLATE
namespace DynamicDialog {
struct DynamicDialogItemSize
{
public:
short x, y, cx, cy;
DynamicDialogItemSize(short left = 0, short top = 0, short width = 0, short height = 0) :
x(left), y(top), cx(width), cy(height)
{
}
void Set(short left, short top, short width, short height)
{
x=left, y=top, cx=width, cy=height;
}
void Set(RECT rect)
{
x=(short)rect.left;
y=(short)rect.top;
cx=(short)(rect.right - rect.left);
cy=(short)(rect.bottom - rect.top);
}
};
class CDynamicDialogTemplate
{
protected:
HGLOBAL m_hDialogTemplateMemory;
size_t m_bytesAllocated;
size_t m_bytesUsed;
protected:
enum { byteAllocationChunk = 256 };
// See help on DLGITEMTEMPLATE
enum ClassAtom
{
eClassAtom_Button = 0x0080,
eClassAtom_Edit = 0x0081,
eClassAtom_Static = 0x0082,
eClassAtom_ListBox = 0x0083,
eClassAtom_ScrollBar = 0x0084,
eClassAtom_ComboBox = 0x0085,
};
// Constructor/Destructor
public:
CDynamicDialogTemplate() :
m_hDialogTemplateMemory(NULL),
m_bytesAllocated(0),
m_bytesUsed(0)
{
}
virtual ~CDynamicDialogTemplate()
{
this->Destroy();
}
// Operators
public:
operator bool() { return (m_hDialogTemplateMemory != NULL); }
operator HGLOBAL() { return m_hDialogTemplateMemory; }
operator DLGTEMPLATE*() { return this->GetDLGTEMPLATE(); }
HGLOBAL GetHGLOBAL(void)
{
return m_hDialogTemplateMemory;
}
DLGTEMPLATE* GetDLGTEMPLATE(void)
{
DLGTEMPLATE* dialogTemplate = (DLGTEMPLATE*)::GlobalLock(m_hDialogTemplateMemory);
::GlobalUnlock(m_hDialogTemplateMemory);
// This should be valid at least until something causes a GlobalReAlloc.
// No one should call this (explicitly or implictly) until the dialog
// resource has been fully constructed
return dialogTemplate;
}
public:
bool Create(
UINT cxDLU, UINT cyDLU,
UINT style, UINT styleEx,
const wchar_t* dialogTitle,
const wchar_t* fontName = L"MS Sans Serif",
UINT fontSize = 8)
{
if(m_hDialogTemplateMemory)
{
return false;
}
m_hDialogTemplateMemory = ::GlobalAlloc((GMEM_MOVEABLE | GMEM_ZEROINIT), byteAllocationChunk);
if(m_hDialogTemplateMemory)
{
m_bytesAllocated = byteAllocationChunk;
DLGTEMPLATE* pDialogTemplate = (DLGTEMPLATE*) ::GlobalLock(m_hDialogTemplateMemory);
if(pDialogTemplate)
{
// Define dialog template
pDialogTemplate->style = style;
pDialogTemplate->dwExtendedStyle = styleEx;
pDialogTemplate->cdit = 0;
pDialogTemplate->x = 0;
pDialogTemplate->y = 0;
pDialogTemplate->cx = (short)cxDLU;
pDialogTemplate->cy = (short)cyDLU;
// Get a pointer to the WORD after the structure
WORD* pWordPtr = (WORD*)(pDialogTemplate + 1);
// no menu
*pWordPtr++ = 0;
// default dialog box class
*pWordPtr++ = 0;
// Dialog title
if(dialogTitle)
{
wchar_t* unicodeString = (wchar_t*) pWordPtr;
// dialog caption
lstrcpyW(unicodeString, dialogTitle);
pWordPtr += ::lstrlenW(unicodeString);
}
// NUL termination for string
*pWordPtr++ = 0;
if((style & DS_SETFONT) == DS_SETFONT)
{
// font size
*pWordPtr++ = (WORD)fontSize;
if(fontName)
{
wchar_t* unicodeString = (wchar_t*) pWordPtr;
// font name
lstrcpyW(unicodeString, fontName);
pWordPtr += ::lstrlenW(unicodeString);
}
// NUL termination for string
*pWordPtr++ = 0;
}
m_bytesUsed = (size_t)((BYTE*)pWordPtr - (BYTE*)pDialogTemplate);
::GlobalUnlock(m_hDialogTemplateMemory);
}
}
return m_hDialogTemplateMemory ? true : false;
}
void Destroy(void)
{
if(m_hDialogTemplateMemory)
{
::GlobalFree(m_hDialogTemplateMemory);
m_hDialogTemplateMemory = NULL;
m_bytesAllocated = 0;
m_bytesUsed = 0;
}
}
bool AddControl(
DWORD style, DWORD dwExtendedStyle,
short x, short y, short cx, short cy,
WORD id,
const wchar_t* text, size_t textWordCount,
const wchar_t* classStringOrAtom, size_t classStringOrAtomWordCount)
{
if(m_hDialogTemplateMemory == NULL)
{
return false;
}
// padding (class atom, NULL termination, etc.)
const size_t padding = 16;
size_t estimatedBytesNeeded = (size_t)
sizeof(DLGITEMTEMPLATE) +
(textWordCount*sizeof(WORD)) +
(classStringOrAtomWordCount*sizeof(WORD)) +
padding;
if((m_bytesAllocated - m_bytesUsed) < estimatedBytesNeeded)
{
// Align the bytesToAllocate to be a multiple of the chunk size
size_t bytesToAllocate = (((m_bytesUsed + estimatedBytesNeeded) / byteAllocationChunk) * byteAllocationChunk) + byteAllocationChunk;
HGLOBAL hDialogTemplateReallocatedMemory = ::GlobalReAlloc(m_hDialogTemplateMemory, bytesToAllocate, (GMEM_MOVEABLE | GMEM_ZEROINIT));
if(hDialogTemplateReallocatedMemory == NULL)
{
return false;
}
else
{
m_bytesAllocated = bytesToAllocate;
m_hDialogTemplateMemory = hDialogTemplateReallocatedMemory;
}
}
DLGTEMPLATE* pDialogTemplate = (DLGTEMPLATE*) ::GlobalLock(m_hDialogTemplateMemory);
if(pDialogTemplate)
{
// Increment the control count
pDialogTemplate->cdit += 1;
// Get a pointer to the "end"
BYTE* pOffset = (BYTE*)pDialogTemplate + m_bytesUsed;
// Fill out the structure and following bytes for the control.
// DLGITEMTEMPLATE structures should be aligned on DWORD boundaries.
DLGITEMTEMPLATE* pDialogItem = (DLGITEMTEMPLATE*) (((DWORD_PTR)pOffset + 3) & ~3);
pDialogItem->style = style;
pDialogItem->dwExtendedStyle = dwExtendedStyle;
pDialogItem->x = x;
pDialogItem->y = y;
pDialogItem->cx = cx;
pDialogItem->cy = cy;
pDialogItem->id = id;
// Get a pointer to the WORD after the structure
WORD* pWordPtr = (WORD*) (pDialogItem + 1);
// Class Array (string or atom)
if(classStringOrAtom)
{
::CopyMemory(pWordPtr, classStringOrAtom, classStringOrAtomWordCount * sizeof(WORD));
pWordPtr += classStringOrAtomWordCount;
// NOTE! "classStringOrAtomWordCount" should include the
// terminating NUL (if its not an atom value)
}
else
{
// Default to "Static" control if no control class or atom is provided
*pWordPtr++ = 0xFFFF;
*pWordPtr++ = eClassAtom_Static;
}
// Title Array (text or resource id)
if(text)
{
::CopyMemory(pWordPtr, text, textWordCount * sizeof(WORD));
pWordPtr += textWordCount;
// NOTE! "textWordCount" should include the
// terminating NUL (if its not a resource ID value)
}
else
{
// default to 0 length string
*pWordPtr++ = 0;
}
// no creation data
*pWordPtr++ = 0;
m_bytesUsed = (size_t)((BYTE*)pWordPtr - (BYTE*)pDialogTemplate);
::GlobalUnlock(m_hDialogTemplateMemory);
}
return true;
}
bool AddControl(
DWORD style, DWORD dwExtendedStyle,
short x, short y, short cx, short cy,
WORD id, const wchar_t* text,
const wchar_t* classString)
{
return this->AddControl(style, dwExtendedStyle,
x, y, cx, cy,
id,
text, text ? ::lstrlenW(text) + 1 : 0,
classString, classString ? ::lstrlenW(classString) + 1 : 0);
}
bool AddControl(
DWORD style, DWORD dwExtendedStyle,
const DynamicDialogItemSize dialogItemSize,
WORD id, const wchar_t* text,
const wchar_t* classString)
{
return this->AddControl(style, dwExtendedStyle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -