Skip to content

Instantly share code, notes, and snippets.

@mxpv
Last active December 17, 2015 04:19
Show Gist options
  • Save mxpv/5549872 to your computer and use it in GitHub Desktop.
Save mxpv/5549872 to your computer and use it in GitHub Desktop.
Small helper class for generating dynamic dialog templates in memory and handling all alignment stuff. (see http://msdn.microsoft.com/en-us/library/windows/desktop/ff468828(v=vs.85).aspx)
DialogTemplate::DialogTemplate(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height)
: _size(0)
{
Header header = { 0 };
header.dlg.style = DS_SETFONT | DS_CENTER | WS_POPUP | WS_CAPTION;
header.dlg.dwExtendedStyle = 0;
header.dlg.x = x;
header.dlg.y = y;
header.dlg.cx = width;
header.dlg.cy = height;
header.dlg.cdit = 0;
header.menu = 0x0000;
header.className = 0x0000;
append(header);
appendString(caption);
wchar_t font[] = L"Tahoma";
WORD fontSize = 8;
append(fontSize);
appendString(font);
}
void DialogTemplate::button(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id)
{
add(Button, caption, WS_TABSTOP | WS_CHILD | WS_VISIBLE, 0, x, y, width, height, id);
}
void DialogTemplate::groupbox(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id)
{
add(Button, caption, BS_GROUPBOX | WS_TABSTOP | WS_CHILD | WS_VISIBLE, 0, x, y, width, height, id);
}
void DialogTemplate::editboxro(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id)
{
add(Edit, caption, ES_AUTOHSCROLL | ES_READONLY | ES_LEFT | WS_BORDER | WS_CHILD | WS_VISIBLE, 0, x, y, width, height, id);
}
void DialogTemplate::text(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id)
{
add(Static, caption, ES_LEFT | WS_CHILD | WS_VISIBLE, 0, x, y, width, height, id);
}
void DialogTemplate::add(WORD type, const wchar_t * caption, DWORD style, DWORD styleEx, u32 x, u32 y, u32 width, u32 height, WORD id)
{
Item item = { 0 };
item.tpl.id = id;
item.tpl.style = style;
item.tpl.dwExtendedStyle = styleEx;
item.tpl.x = x;
item.tpl.y = y;
item.tpl.cx = width;
item.tpl.cy = height;
item.preType = 0xFFFF;
item.type = type;
align(sizeof(DWORD));
append(item);
appendString(caption);
WORD dummy = 0;
append(dummy);
Header * hdr = (Header *)&_buffer;
hdr->dlg.cdit++;
}
void DialogTemplate::align(uint size)
{
u32 pad = _size % size;
if (0 != pad)
{
_size += pad;
}
}
bool DialogTemplate::appendString(const wchar_t * str)
{
size_t len = (::wcslen(str) + 1) * sizeof(wchar_t);
return append(str, len);
}
template<class T>
bool DialogTemplate::append(const T & data)
{
return append(&data, sizeof(T));
}
bool DialogTemplate::append(const void * data, uint len)
{
bool result = 0 == ::memcpy_s(&_buffer[_size], BufferSize, data, len);
_size += len;
return result;
}
DLGTEMPLATE * DialogTemplate::get() const
{
return (DLGTEMPLATE *)&_buffer;
}
class DialogTemplate
{
public:
enum
{
BufferSize = 4096 * 16,
};
DialogTemplate(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height);
DLGTEMPLATE * get() const;
void button(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id);
void groupbox(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id);
void editboxro(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id);
void text(const wchar_t * caption, u32 x, u32 y, u32 width, u32 height, WORD id);
private:
enum
{
Button = 0x0080,
Edit = 0x0081,
Static = 0x0082,
ListBox = 0x0083,
ScrollBar = 0x0084,
ComboBox = 0x0085,
};
struct Header
{
DLGTEMPLATE dlg;
WORD menu;
WORD className;
};
struct Item
{
DLGITEMTEMPLATE tpl;
WORD preType;
WORD type;
};
void add(
WORD type,
const wchar_t * caption,
DWORD style,
DWORD styleEx,
u32 x, u32 y,
u32 width, u32 height,
WORD id);
void align(uint size);
bool appendString(const wchar_t * str);
template<class T>
bool append(const T & data);
bool append(const void * data, uint len);
private:
u8 _buffer[BufferSize];
uint _size;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment