//============================================================================= //MEMORY TEMPLATE DIALOG - Copyright © 2000,2005 Ken Fitlike //============================================================================= //API functions used: DialogBoxIndirect,EndDialog,GetLastError,HIWORD, //LoadImage,LOWORD,MAKEWORD,MessageBox,PostMessage,SendMessage,WinMain, //wsprintf. //============================================================================= //This demonstrates the creation of a modal dialog box from a memory template. //This technique should not be used for the routine creation of dialog boxes; //use resource scripts instead. // //Notes: (1) All strings used by the memory template must be wide character // strings. // (2) Controls must be aligned on WORD boundaries and not DWORD // boundaries as described by msdn. //For more information refer to windows documentation regarding DLGTEMPLATE, //DLGTEMPLATEEX and DLGITEMTEMPLATEEX structures //============================================================================= #include <windows.h> //include all the basics #include <tchar.h> //string and other mapping macros #include <string> #include <vector> //define an unicode string type alias typedef std::basic_string<TCHAR> ustring; //============================================================================= //message processing function declarations INT_PTR CALLBACK DlgProc(HWND,UINT,WPARAM,LPARAM); void OnCommand(const HWND,int,int,const HWND); INT_PTR OnInitDlg(const HWND,LPARAM); //non-message function declarations void AddControl(std::vector<WORD>&,DWORD,DWORD,short,short,short,short,DWORD, const std::wstring&,const std::wstring&,DWORD helpID=0, DWORD extradata=0); void AddString(std::vector<WORD>&,const std::wstring&); inline int ErrMsg(const ustring&); void WordAlign(std::vector<WORD>&); //============================================================================= int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int) { std::vector<WORD> memdlg; //setup the dialog template memdlg.push_back(1); memdlg.push_back(0xffff); DWORD helpID=0; memdlg.push_back(LOWORD(helpID)); memdlg.push_back(HIWORD(helpID)); DWORD exStyle=0; memdlg.push_back(LOWORD(exStyle)); memdlg.push_back(HIWORD(exStyle)); DWORD style=DS_CENTER|WS_OVERLAPPEDWINDOW|WS_POPUP|WS_VISIBLE|DS_SETFONT; memdlg.push_back(LOWORD(style)); memdlg.push_back(HIWORD(style)); memdlg.push_back(3); //number of controls memdlg.push_back(0); //left memdlg.push_back(0); //top memdlg.push_back(186); //width memdlg.push_back(93); //height memdlg.push_back(0); //no menu memdlg.push_back(0); //standard system dialog box class //add dialogbox title AddString(memdlg,L"Dialog: Memory Template"); //set font but only if DS_SETFONT or DS_SHELLFONT styles are set DWORD dwTest=style; if (dwTest & DS_SETFONT) { //this is for simplicity; it would probably be better to obtain and use the //respective properties of the default gui or system fonts memdlg.push_back(8); //pointsize memdlg.push_back(FW_NORMAL); //weight memdlg.push_back(MAKEWORD(0,DEFAULT_CHARSET)); //italic,charset AddString(memdlg,L"MS Sans Serif"); } //add 'ok' button AddControl(memdlg, 0, WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON|WS_TABSTOP, 22,62,50,14, IDOK, L"button", L"Ok"); //add 'cancel' button AddControl(memdlg, 0, WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|WS_TABSTOP, 111,62,50,14, IDCANCEL, L"button", L"Cancel"); //add an edit control AddControl(memdlg, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE|WS_TABSTOP, 10,10,100,14, 200, L"edit", L"single line edit control"); //create the dialog DLGTEMPLATE *pdt=reinterpret_cast<DLGTEMPLATE*>(&memdlg[0]); INT_PTR success=DialogBoxIndirect(hInst,pdt,0,DlgProc); if (success==-1) { ErrMsg(_T("DialogBoxIndirect failed")); } return 0; } //============================================================================= //message processing functions //============================================================================= INT_PTR CALLBACK DlgProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch (uMsg) { case WM_COMMAND: { OnCommand(hwnd,LOWORD(wParam),HIWORD(wParam), reinterpret_cast<HWND>(lParam)); return 0; } case WM_INITDIALOG: { return OnInitDlg(hwnd,lParam); } default: return FALSE; //let system deal with msg } } //============================================================================= void OnCommand(const HWND hwnd,int id,int notifycode,const HWND hCntrl) { //handles WM_COMMAND message of the modal dialogbox switch (id) { case IDOK: //RETURN key pressed or 'ok' button selected case IDCANCEL: //ESC key pressed or 'cancel' button selected EndDialog(hwnd,id); } } //============================================================================= INT_PTR OnInitDlg(const HWND hwnd,LPARAM lParam) { //set the small icon for the dialog. IDI_APPLICATION icon is set by default //for winxp SendMessage(hwnd,WM_SETICON,ICON_SMALL, reinterpret_cast<LPARAM>(LoadImage(0,IDI_APPLICATION,IMAGE_ICON, 0,0,LR_SHARED))); //ensure focus rectangle is properly drawn around control with focus PostMessage(hwnd,WM_KEYDOWN,VK_TAB,0); return TRUE; } //============================================================================= //non-message processing functions //============================================================================= void AddControl(std::vector<WORD>& v,DWORD exStyle,DWORD style,short x,short y, short cx,short cy,DWORD id,const std::wstring& classname, const std::wstring& caption,DWORD helpID,DWORD extradata) { //add a control. defaults: helpID=0,extradata=0. Note there is no capability //in this function for dealing with non-zero values of extradata. WordAlign(v); v.push_back(LOWORD(helpID)); v.push_back(HIWORD(helpID)); v.push_back(LOWORD(exStyle)); v.push_back(HIWORD(exStyle)); v.push_back(LOWORD(style)); v.push_back(HIWORD(style)); v.push_back(x); //left v.push_back(y); //top v.push_back(cx); //width v.push_back(cy); //height //msdn docs are incorrect - the id is a DWORD value and not a WORD v.push_back(LOWORD(id)); v.push_back(HIWORD(id)); //there are only a few class atoms defined for standard (user) controls //so it's arguably better to use string class names than ordinals. AddString(v,classname.c_str()); AddString(v,caption.c_str()); v.push_back(0); //no creation data } //============================================================================= void AddString(std::vector<WORD>& v,const std::wstring& s) { //add a string to the array (eg. dialog title, control caption etc.) std::wstring::const_iterator iter; for (iter=s.begin();iter!=s.end();++iter) { v.push_back(*iter); } v.push_back(L'\0'); } //============================================================================= inline int ErrMsg(const ustring& s) { return MessageBox(0,s.c_str(),_T("ERROR"),MB_OK|MB_ICONEXCLAMATION); } //============================================================================= void WordAlign(std::vector<WORD>& v) { //msdn states that controls must be added at dword boundary. This is incorrect; //controls must be WORD aligned. std::size_t size=v.size()%2; for (unsigned int i=0;i<size;++i) { v.push_back(0); //padding } } //=============================================================================