他人の空似自作物置場

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;
}