正如创建所有其它的窗口一样,创建控件使用CreateWindowEx()这个API.将想要的已注册的类传进去,这里是编辑框控件类,这样就得到一个标准的编辑框控件窗口. 当用对话框来创建控件时,一般要写下要创建的控件的清单,以便在你调用DialogBox()或CreateDialog()的时候系统可以在对话框的资源中读入控件的列表并调用CreateWindowEx()来按照在资源中定义的位置和式样来创建每个.
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL); if(hEdit == NULL) MessageBox(hwnd, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
可以看到这个CreateWindowEx()的调用指定了很多的式样,而且在实际的编程有更多也很常见,尤其是有大堆选项的常用控件. 开始的四个WS_式样应该相当清楚,以窗口的一个子窗口来创建这个控件,使其可见,并且有纵向和水平的滾动条.
三个为编辑框特有的式样(ES_MULTLINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL)指定了这个编辑框应该含有多行文本,并于你在控件的最底部和最右边打字的时候分別自动滾动.
常规的窗口式样(WS_*)列在MSDN中.而扩展的窗口式样(WS_EX_*)在MSDN中对CreateWindowEx()的解释中有说明,那个地方也可以找到对每个控件特有式样说明的链接.(例子中的ES_*就是为编辑框所特有).
以控件指定了作为其父窗口的窗口句柄,并为其实指定了一个为IDC_MAIN_EDIT的标识,以便在后面要在对话框上创建控件时引用该控件.位置和大小参数在这里不是很重要因为马上要响应WM_SIZE消息来动态调整此控件以使它总位于窗口中间并适合其大小.
一般来说如果窗口可以调大小的话,你总是希望写点代码来动态调整你在之中创建的控件的大小以使它们总是分佈合理.
GetClientRect(hwnd, &rcClient); hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT); SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
因为现在只有一个控件,工作相对比较简单.我们用GetClientRect()来获取窗口的客戶区的大小,也就是说不包括边际,菜单和标题栏的那块大(当前为止)地方.这会用值填充我们的RECT结构体,left 和top总是为0,所以你一般可以忽略他们.right和 bottom值会给你客戶区的寛和高.
下一步我们用GetDlgItem()来获取我们控件的句柄,这个API对于对话框和常规的窗口都可以使用,并调用SetWindowPos()去移动和拉伸以填充整个客戶区.当然可以通过更改给SetWindowPos()的值来做些別的事情,比如只填充窗口的一半,让另外一半留下来放別的控件.
套用前面的windows程序的框架,就可以完成。
#include <Windows.h> #define IDC_MAIN_EDIT 101 const char g_szClassName[] = "myWindowClass"; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CREATE: { HWND hEdit; HFONT hDefFont; hEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"Edit","",WS_CHILD|WS_VISIBLE |WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL, 0,0,100,100,hwnd,(HMENU)IDC_MAIN_EDIT,GetModuleHandle(NULL),NULL); if(hEdit == NULL) MessageBox(hwnd,"Create Edit Failed","Error",MB_OK|MB_ICONERROR); hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); SendMessage(hEdit,WM_SETFONT,(WPARAM)hDefFont,MAKELPARAM(FALSE,0)); } break; case WM_SIZE: { HWND hEdit; RECT rect; GetClientRect(hwnd,&rect); hEdit = GetDlgItem(hwnd,IDC_MAIN_EDIT); SetWindowPos(hEdit,NULL,0,0,rect.right,rect.bottom,SWP_NOZORDER); } break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, "Edit", WS_OVERLAPPEDWINDOW, 200, 200, 400, 400, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }