input_dialog.zip/input_dialog.cpp
#include <windows.h>
#include <stdio.h>
#include <vector>
#include <locale.h>
#ifndef ASSERT
#define ASSERT(a) if(!(a)){printf("ASSERT %s:%d\n%s\n",__FILE__ ,__LINE__,#a);getchar();exit(1);}
#endif
class DlgBase {
protected:
wchar_t *cls_str;
unsigned short cls_id;
wchar_t *text;
public:
DlgBase() {
cls_str = NULL;
text = NULL;
cls_id = 0;
}
DlgBase(const DlgBase &obj) {
if(obj.cls_str) {
this->cls_str = wcscpy(new wchar_t[wcslen(obj.cls_str) + 1], obj.cls_str);
} else {
this->cls_str = NULL;
}
if(obj.text) {
this->text = wcscpy(new wchar_t[wcslen(obj.text) + 1], obj.text);
} else {
this->text = NULL;
}
this->cls_id = obj.cls_id;
}
~DlgBase() {
if(cls_str != NULL) {
delete cls_str;
cls_str = NULL;
}
if(text != NULL) {
delete text;
text = NULL;
}
}
void setWindowClass(const wchar_t * const str) {
ASSERT(str != NULL);
if(cls_str) {
delete cls_str;
cls_str = NULL;
}
cls_str = new wchar_t[wcslen(str)+1];
wcscpy(cls_str, str);
}
void setWindowClass(const char * const str) {
ASSERT(str != NULL);
if(cls_str) {
delete cls_str;
cls_str = NULL;
}
const unsigned int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
cls_str = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, str, -1, cls_str, len);
}
void setWindowClass(const unsigned short id) {
ASSERT(id == 0 || (0x80 <= id && id <= 0x85) );
if(cls_str) {
delete cls_str;
cls_str = NULL;
}
cls_id = id;
}
void setWindowText(const wchar_t * const str) {
ASSERT(str != NULL);
if(text) {
delete text;
text = NULL;
}
text = new wchar_t[wcslen(str)+1];
wcscpy(text, str);
}
void setWindowText(const char * const str) {
ASSERT(str != NULL);
if(text) {
delete text;
text = NULL;
}
const unsigned int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
text = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, str, -1, text, len);
}
protected:
virtual unsigned char *getWindowClassAddr(unsigned char * const data) const = 0;
bool putWindowClass(unsigned char * const out) const {
ASSERT(out != NULL);
if(cls_str != NULL) {
wcscpy((wchar_t*)out, cls_str);
} else {
ASSERT(0x80 <= cls_id && cls_id <= 0x85);
*(unsigned short*)&out[0] = 0xFFFF;
*(unsigned short*)&out[2] = cls_id;
}
return true;
}
unsigned char *getWindowTextAddr(unsigned char * const data) const {
ASSERT(data != NULL);
unsigned char * const p = getWindowClassAddr(data);
unsigned char *result;
if(*(unsigned short*)p == 0xFFFF) {
ASSERT(0x80 <= *(unsigned short*)&p[2] && *(unsigned short*)&p[2] <= 0x85);
result = &p[4];
} else {
result = &p[(wcslen((wchar_t*)p) + 1) * sizeof(wchar_t)];
}
return result;
}
bool putWindowText(unsigned char * const out) const {
wcscpy((wchar_t*)out, text);
return true;
}
};
class DlgItemEx : public DlgBase {
protected:
std::vector<unsigned char> custom;
public:
unsigned int style;
unsigned int ex;
short x;
short y;
short cx;
short cy;
unsigned int id;
DlgItemEx(const unsigned int id, const unsigned int style, const unsigned int ex, const short x, const short y, const short cx, const short cy) {
this->id = id;
this->ex = ex;
this->style = style;
this->x = x;
this->y = y;
this->cx = cx;
this->cy = cy;
}
DlgItemEx(const DlgItemEx &obj) :
DlgBase(obj)
{
this->id = obj.id;
this->ex = obj.ex;
this->style = obj.style;
this->x = obj.x;
this->y = obj.y;
this->cx = obj.cx;
this->cy = obj.cy;
}
bool put(unsigned char * const out) const {
*(unsigned int*)&out[0] = 0;//HelpID
*(unsigned int*)&out[4] = ex;
*(unsigned int*)&out[8] = style;
*(short*)&out[12] = x;
*(short*)&out[14] = y;
*(short*)&out[16] = cx;
*(short*)&out[18] = cy;
*(unsigned int*)&out[20] = id;
ASSERT(putWindowClass(getWindowClassAddr(out)));
ASSERT(putWindowText(getWindowTextAddr(out)));
ASSERT(putCustomData(getCustomDataAddr(out)));
return true;
}
unsigned int size() const {
unsigned int result = 24;
if(cls_str == NULL) {
result += 4;
} else {
result += (wcslen(cls_str) + 1) * sizeof(wchar_t);
}
result += (wcslen(text) + 1) * sizeof(wchar_t);
result += 2 + custom.size();
if((result % 4) > 0) {
result = (result / 4 + 1) * 4;
}
return result;
}
protected:
unsigned char *getWindowClassAddr(unsigned char * const data) const {
return &data[24];
}
unsigned char *getCustomDataAddr(unsigned char * const data) const {
ASSERT(data != NULL);
unsigned char * const p = getWindowTextAddr(data);
return &p[(wcslen((wchar_t*)p) + 1) * sizeof(wchar_t)];
}
bool putCustomData(unsigned char * const out) const {
ASSERT(custom.size() < 0x10000);
*(unsigned short *)&out[0] = custom.size();
ASSERT(out != NULL);
if(custom.size() > 0) {
memcpy(out, &custom.front(), custom.size());
}
return true;
}
};
class DlgItemButton : public DlgItemEx {
public:
DlgItemButton(const unsigned int id, const unsigned int style, const unsigned int ex, const short x, const short y, const short cx, const short cy) :
DlgItemEx(id, style, ex, x, y, cx, cy)
{
setWindowClass(0x0080);
}
};
class DlgItemEdit : public DlgItemEx {
public:
DlgItemEdit(const unsigned int id, const unsigned int style, const unsigned int ex, const short x, const short y, const short cx, const short cy) :
DlgItemEx(id, style, ex, x, y, cx, cy)
{
setWindowClass(0x0081);
}
};
class DlgEx : public DlgBase {
protected:
struct {
unsigned short size;
unsigned short weight;
bool italic;
unsigned char charset;
wchar_t *name;
} font;
public:
static const unsigned short dlgVer = 1;
static const unsigned short signature = 0xFFFF;
unsigned int style;
unsigned int ex;
short x;
short y;
short cx;
short cy;
std::vector<DlgItemEx> items;
DlgEx(unsigned int style, unsigned int ex, short x, short y, short cx, short cy) {
setWindowClass("");
this->style = style;
this->ex = ex;
this->x = x;
this->y = y;
this->cx = cx;
this->cy = cy;
font.name = NULL;
setFont(9, FW_NORMAL, false, DEFAULT_CHARSET, "MS ゴシック");
}
DlgEx(const DlgEx &obj) :
DlgBase(obj)
{
this->style = obj.style;
this->ex = obj.ex;
this->x = obj.x;
this->y = obj.y;
this->cx = obj.cx;
this->cy = obj.cy;
font.name = NULL;
setFont(obj.font.size, obj.font.weight, obj.font.italic, obj.font.charset, obj.font.name);
items = obj.items;
}
~DlgEx() {
if(font.name != NULL) {
delete font.name;
font.name = NULL;
}
}
void setFont(const unsigned char size, const unsigned short weight, const bool italic, const unsigned char charset, const wchar_t * const name) {
font.size = size;
font.weight = weight;
font.italic = italic;
font.charset = charset;
if(font.name) {
delete font.name;
font.name = NULL;
}
font.name = new wchar_t[wcslen(name)+1];
wcscpy(font.name, name);
}
void setFont(const unsigned char size, const unsigned short weight, const bool italic, const unsigned char charset, const char * const name) {
const unsigned int len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
wchar_t * const str = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, name, -1, str, len);
setFont(size, weight, italic, charset, str);
delete str;
}
bool put(unsigned char * const out) const {
putBody(out);
unsigned char * data = &out[bodySize()];
for(std::vector<DlgItemEx>::const_iterator p = items.begin(); p != items.end(); ++p) {
if(!p->put(data)) {
return false;
}
data += p->size();
}
return true;
}
unsigned int size(void) const {
unsigned int result = bodySize();
for(std::vector<DlgItemEx>::const_iterator p = items.begin(); p != items.end(); ++p) {
result += p->size();
}
return result;
}
int doModal(HINSTANCE hInst, HWND owner, DLGPROC proc) {
unsigned char *data = new unsigned char[size()];
ASSERT(put(data));
const int result = DialogBoxIndirect(hInst, (LPCDLGTEMPLATE)data, owner, proc);
delete data;
return result;
}
protected:
bool putBody(unsigned char * const out) const {
*(unsigned short *)&out[0] = dlgVer;
*(unsigned short *)&out[2] = signature;
*(unsigned int *)&out[4] = 0;//helpID
*(unsigned int *)&out[8] = ex;
*(unsigned int *)&out[12] = style;
*(unsigned short *)&out[16] = items.size();
*(short *)&out[18] = x;
*(short *)&out[20] = y;
*(short *)&out[22] = cx;
*(short *)&out[24] = cy;
*(unsigned short *)&out[26] = 0;//MenuID
ASSERT(putWindowClass(getWindowClassAddr(out)));
ASSERT(putWindowText(getWindowTextAddr(out)));
ASSERT(putFontData(getFontDataAddr(out)));
return true;
}
unsigned char *getWindowClassAddr(unsigned char * const data) const {
return &data[28];
}
unsigned char *getFontDataAddr(unsigned char * const data) const {
ASSERT(data != NULL);
unsigned char * const p = getWindowTextAddr(data);
return &p[(wcslen((wchar_t*)p) + 1) * sizeof(wchar_t)];
}
bool putFontData(unsigned char * const out) const {
*(unsigned short *)&out[0] = font.size;
*(unsigned short *)&out[2] = font.weight;
*(unsigned char *)&out[4] = (font.italic ? TRUE : FALSE);
*(unsigned char *)&out[5] = font.charset;
ASSERT(putFontName(&out[6]));
return true;
}
bool putFontName(unsigned char * const out) const {
wcscpy((wchar_t*)out, font.name);
return true;
}
unsigned int bodySize(void) const {
unsigned int result = 28;
if(cls_str == NULL) {
result += 4;
} else {
result += (wcslen(cls_str) + 1) * sizeof(wchar_t);
}
result += (wcslen(text) + 1) * sizeof(wchar_t);
result += 6;//font
result += (wcslen(font.name) + 1) * sizeof(wchar_t);
if((result % 4) > 0) {
result = (result / 4 + 1) * 4;
}
return result;
}
};
#define EDIT1 (11)
BOOL CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
static wchar_t result[1024];
int id;
switch (msg) {
case WM_CLOSE:
EndDialog(hwnd , NULL);
break;
case WM_COMMAND:
switch(LOWORD(wp)) {
case IDOK:
GetWindowTextW(GetDlgItem(hwnd, EDIT1), result, sizeof(result));
EndDialog(hwnd, (int)result);
break;
case IDCANCEL:
EndDialog(hwnd, NULL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
const wchar_t *callInputDialog(const wchar_t * const title) {
DlgEx dlg(WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_BORDER | DS_MODALFRAME | DS_SETFONT,
WS_EX_TOPMOST | WS_EX_DLGMODALFRAME,
10,10,160,44);
dlg.setWindowText(title);
dlg.setFont(9, FW_NORMAL, false, DEFAULT_CHARSET, "MS Pゴシック");
{
DlgItemEdit edit(EDIT1, WS_CHILD | WS_VISIBLE | WS_TABSTOP, WS_EX_CLIENTEDGE, 5,5,150,14);
edit.setWindowText("");
dlg.items.push_back(edit);
}
{
DlgItemButton btn(IDOK, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0, 50,24,50,15);
btn.setWindowText("OK");
dlg.items.push_back(btn);
}
{
DlgItemButton btn(IDCANCEL, WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 105,24,50,15);
btn.setWindowText("キャンセル");
dlg.items.push_back(btn);
}
return (wchar_t*)dlg.doModal(GetModuleHandle(NULL), NULL, WndProc);
}
const char *callInputDialog(const char * const title) {
static char result[1024];
const unsigned int w_len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
wchar_t * const str = new wchar_t[w_len];
MultiByteToWideChar(CP_ACP, 0, title, -1, str, w_len);
const wchar_t * const wide = callInputDialog(str);
delete str;
WideCharToMultiByte(CP_ACP, 0, wide, -1, result, sizeof(result), "?", NULL);
return result;
}