創建控件
正如創建所有其它的窗口一樣,創建控件使用CreateWindowEx()這個API.將想要的已注冊的類傳進去,這裡是編輯框控件類,這樣就得到一個標准的編輯框控件窗口. 當用對話框來創建控件時,一般要寫下要創建的控件的清單,以便在你調用DialogBox()或CreateDialog()的時候系統可以在對話框的資源中讀入控件的列表並調用CreateWindowEx()來按照在資源中定義的位置和式樣來創建每個.
[cpp]
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消息來動態調整此控件以使它總位於窗口中間並適合其大小.
動態創建的控件的大小調整
一般來說如果窗口可以調大小的話,你總是希望寫點代碼來動態調整你在之中創建的控件的大小以使它們總是分佈合理.
[cpp]
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程序的框架,就可以完成。
貼代碼了:
[cpp]
#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;
}