轉自:http://blog.csdn.net/xiaodan007/article/details/6197478
WINDOWS 提供了幾個預定義的窗口類以方便我們的使用。大多數時間內,我們把它們用在對話框中,所以我們一般就它們叫做子窗口控件。子窗口控件會自己處理消息,並在自己狀態發生改變時通知父窗口。這樣就大大地減輕了我們的編程工作,所以我們應盡可能地利用它們。本課中我們把這些控件放在窗口中以簡化程序,但是大多數時間內子窗口控件都是放在對話框中的。我們示例中演示的子窗口控件包括:按鈕、下拉菜單、檢查框、單選按鈕、編輯框等。使用子窗口控件時,先調用 CreateWindow 或 CreateWindowEx。在這里由於WINDOWS 已經注冊了這些子控件,所以無須我們再注冊。當然我們不能改變它們的類名稱。譬如:如果您想產生一個按鈕,在調用上述兩個函數時就必須指定類名為"button"。其他必須指定的參數還有父窗口的句柄和將要產生的子控件的ID號。子控件的ID號是用來標識子控件的,故也必須是唯一 的。子控件產生后,當其狀態改變時將會向父窗口發送消息。一般我們應在父窗口的WM_CREATE消息中產生字控件。子控件向父窗口發送的消息是 WM_COMMAND,並在傳遞的參數wPara的底位中包括控件的ID號,消息號在wParam的高位,lParam中則包括了子控件的窗口的句柄。各類控件有不同的消息代碼集,詳情請參見WIN32 API參考手冊。父窗口也可以通過調用函數SendMessage向子控件發送消息,其中第一個參數是子控件的窗口句柄,第二個參數是要發送的消息號,附加的參數可以在wParam和lParam中傳遞,其實只要知道了某個窗口的句柄就可以用該函數向其發送相關消息。所以產生了子窗口后必須處理 WM_COMMAND消息以便可以接收到子控件的消息。
取父窗口的窗口句柄:
hwndParent = GetParent (hwnd) ;
發送消息:
SendMessage (hwndParent, message, wParam, lParam) ;
預定義的控件有:
按鈕、復選框、編輯方塊、清單方塊、下拉式清單方塊、靜態字符串標簽和滾動條。
當使用預定義的控件時,不必為其注冊窗口類,窗口類已經存在於Windows中,並有一個預先定義的名字。
您只需在CreateWindow()的參數中指出窗口類名字。CreateWindow()的窗口樣式參數准確地定義了子窗口
控件的外形和功能。Windows內建了這些控件的窗口消息處理程序。
========================================
按鈕控件
創建子窗口時指定窗口類為"button".
顯示窗口的CreateWindow參數如下:
Class name(類別名稱) TEXT ("button")
Window text(窗口文字) 一個c字符串szText
Window style(窗口樣式) WS_CHILD | WS_VISIBLE | 按鈕樣式(下邊有說明)
x position(x位置)
y position(y位置)
Width(寬度)
Height(高度)
Parent window(父窗口)
Child window ID(子窗口ID) 要轉換為HMENU類型.如(HMENU) i
Instance handle(執行實體句柄) 執行實例句柄
Extra parameters(附加參數) NULL
其中的按鈕樣式為:
BS_PUSHBUTTON
BS_DEFPUSHBUTTON
BS_CHECKBOX (帶有復選框.復選框的狀態要手動發送BM_SETCHECK消息設置)
BS_AUTOCHECKBOX (帶有復選框.復選框的狀態自動設置)
BS_RADIOBUTTON (帶單選按鈕.其狀態要手動發送BM_SETCHECK消息設置)
BS_3STATE
BS_AUTO3STATE
BS_GROUPBOX (分組方塊. 它只是一個標題框. 不處理輸入.)
BS_AUTORADIOBUTTON
BS_OWNERDRAW
按鈕會向父窗口發送WM_COMMAND消息.參數:
LOWORD(wParam) 為子窗口ID.
HIWORD(wParam) 為通知碼.
lParam 為子窗口句柄.
通知碼HIWORD(wParam)有:
BN_CLICKED
BN_PAINT
BN_HILITE or BN_PUSHED
BN_UNHILITE or BN_UNPUSHED
BN_DISABLE
BN_DOUBLECLICKED or BN_DBLCLK
BN_SETFOCUS
BN_KILLFOCUS
父窗口也可以向按鈕發送消息.
BM_GETCHECK (復選框的選定標記)
BM_SETCHECK
BM_GETSTATE ("正常狀態" 還是"按下狀態" )
BM_SETSTATE
BM_SETSTYLE (改變按鈕樣式)
BM_CLICK
BM_GETIMAGE
BM_SETIMAGE
要得到控件ID用
GetDlgCtrlId(hwndChild);
要得到控件的子窗口句柄用
GetDlgItem(hwndParent, id);
改變按鈕的文字用
SetWindowText (hwnd, pszString) ;
取按鈕的當前文字用
iLength = GetWindowText (hwnd, pszBuffer, iMaxLength) ;
======================================
顯示/隱藏子窗口
如果子窗口的窗口類的樣式中沒有WS_VISIBLE. 則在沒有呼叫ShowWindow之前不會顯示窗口.
顯示子窗口用:
ShowWindow (hwndChild, SW_SHOWNORMAL) ;
隱藏子窗口用:
ShowWindow (hwndChild, SW_HIDE) ;
查看子窗口是否可見用:
IsWindowVisible (hwndChild) ;
不可用/啟用 子窗口
要使按鈕不可用(文字變為灰色).用:
EnableWindow (hwndChild, FALSE) ;
恢復為可用:
EnableWindow (hwndChild, TRUE) ;
判斷是否被啟用:
IsWindowEnabled (hwndChild) ;
輸入焦點
用戶使用按鈕時.按鈕獲得輸入焦點而其父窗口失去輸入焦點.這時父窗口先收到WM_KILLFOCUS消
息(wParam參數為獲得輸入焦點的窗口的句柄).然后獲得輸入焦點的窗口(按鈕子窗口)收到一個WM
_SETFOCUS消息(wParam參數為失去輸入焦點的窗口的句柄).
控件與顏色
系統顏色
Windows保留了29種系統顏色以供各種顯示使用(例如:菜單顏色.菜單文字顏色.窗口顏色等等)。您可
以使用GetSysColor和SetSysColors來獲得和設定這些顏色。設定的系統顏色只在目前Windows對
話過程中有效。
要在按鈕中顯示圖標或位圖,您可以用BS_ICON或BS_BITMAP樣式,並用BM_SETIMAGE消息設定位圖。
對於BS_OWNERDRAW樣式的按鈕,它允許完全自由地繪制按鈕。
====================================
靜態控件
創建子窗口時指定窗口類為"static".它既不接收鼠標或鍵盤輸入,也不向父窗口發送WM_COMMAND消息。
設置靜態控件的文字用SetWindowText.
================================
滾動條控件
創建子窗口時指定窗口類為"scrollbar".
它不向父窗口發送WM_COMMAND消息,而是像窗口滾動條那樣發送WM_VSCROLL和WM_HSCROLL消息。
可以通過lParam參數來區分窗口滾動條與滾動條控件。對子窗口滾動條其值為0,對於滾動條控件其值為滾動
條子窗口的句柄。wParam對窗口滾動條和滾動條控件來說含義相同。
設置滾動條控件用的函數和設置窗口滾動條一樣:
SetScrollRange (hwndScroll, SB_CTL, iMin, iMax, bRedraw) ;
SetScrollPos (hwndScroll, SB_CTL, iPos, bRedraw) ;
SetScrollInfo (hwndScroll, SB_CTL, &si, bRedraw) ;
區別是設置滾動條控件時.第一個參數是控件子窗口句柄而不是父窗口句柄.第二個參數是SB_CTL而不是
SB_VERT或SB_HORZ.
===========================
為控件指定窗口函數
控件的窗口函數是windows內部的. 但可以用GWL_WNDPROC做參數通過GetWindowLong函數得到它
的函數地址. 而且可以用SetWindowLong給它重新指定一個新的窗口函數(新的函數也要是callback函數).如:
OldScroll = (WNDPROC) SetWindowLong (hwndScroll, GWL_WNDPROC,
(LONG) ScrollProc)) ; //返回值是原來的窗口函數的地址.
在需要用Tab鍵在控件之間切換輸入焦點時. 由於控件獲得輸入焦點后所有的鍵盤消息都發送給控件的窗口
函數了.而控件原來的窗口函數並不處理Tab鍵按下的消息.這時就可以用上邊的方法給控件重新設定一個窗
口消息處理函數並在其中處理Tab鍵.最后再在新的窗口函數中呼叫原來的窗口函數處理其它消息:
return CallWindowProc (OldScroll, hwnd, message, wParam,lParam) ;
這樣就可以處理Tab鍵了.
就像可以通過SetWindowLong給窗口重新設置窗口函數一樣.可以用SetClassLong來設置某個窗口的窗
口類的一些東西.例如下邊重新設置窗口類的畫刷:
SetClassLong (hwnd, GCL_HBRBACKGROUND,
(LONG)CreateSolidBrush (RGB (color[0], color[1], color[2])));
===============================
編輯控件
創建子窗口時用"edit".如:
hwndEdit = CreateWindow (TEXT ("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
WS_BORDER | ES_LEFT | ES_MULTILINE |
ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 0, 0, hwnd, (HMENU) ID_EDIT,
((LPCREATESTRUCT) lParam) -> hInstance, NULL) ;
編輯控件的樣式:
文字對齊: ES_LEFT、ES_RIGHT和ES_CENTER
多行: ES_MULTILINE (缺省為單行)
在單行樣式中.要文字水平卷動: ES_AUTOHSCROLL
在多行樣式中.要文字水平卷動(不是出現滾動條)(這阻止了自動換行): ES_AUTOHSCROLL
在多行樣式中.要文字垂直卷動(不是出現滾動條): ES_AUTOVSCROLL
在多行樣式中.要顯示滾動條用WS_HSCROLL和WS_VSCROLL
編輯控件缺省時沒有邊框.要顯示邊框用 WS_BORDER
選擇編輯控件的文字時.文字反白顯示.但編輯控件失去焦點后文字將不再加亮顯示.要使失去焦點后
選擇的文字仍然加亮顯示用: ES_NOHIDESEL
編輯控件給父窗口消息處理程序發送WM_COMMAND消息.消息參數為
LOWORD (wParam) 子窗口ID
HIWORD (wParam) 通知碼
lParam 子窗口句柄
其中通知碼為:
EN_SETFOCUS 編輯控件已經獲得輸入焦點
EN_KILLFOCUS 編輯控件已經失去輸入焦點
EN_CHANGE 編輯控件的內容將改變
EN_UPDATE 編輯控件的內容已經改變
EN_ERRSPACE 編輯控件執行已經超出中間
EN_MAXTEXT 編輯控件在插入時執行超出空間
EN_HSCROLL 編輯控件的水平滾動條已經被按下
EN_VSCROLL 編輯控件的垂直滾動條已經被按下
要處理tab鍵切換輸入焦點或處理Enter鍵. 可以給它重新指定一個窗口函數並在其中攔截.
要在編輯區插入文字用:
GetWindowTextLength
GetWindowText
SetWindowText
給編輯控件發送消息:
SendMessage (hwndEdit, WM_CUT, 0, 0) ; //剪貼
SendMessage (hwndEdit, WM_COPY, 0, 0) ; //復制
SendMessage (hwndEdit, WM_CLEAR, 0, 0) ; //刪除選擇文字
SendMessage (hwndEdit, WM_PASTE, 0, 0) ; //粘貼
SendMessage (hwndEdit, EM_GETSEL, (WPARAM) &iStart,(LPARAM) &iEnd) ;
//取得目前選擇的起始位置和末尾位置.(末尾位置是選擇的最后一個文字的位置加1)
SendMessage (hwndEdit, EM_SETSEL, iStart, iEnd) ; //選擇文字
SendMessage (hwndEdit, EM_REPLACESEL, 0, (LPARAM) szString) ;
//用其他文字替換目前選擇的文字
iCount = SendMessage (hwndEdit, EM_GETLINECOUNT, 0, 0) ;
//取得多行編輯控件的行數
iOffset = SendMessage (hwndEdit, EM_LINEINDEX, iLine, 0) ;
//對任何特定的行(從0行開始),您可以取得距離編輯緩沖區文字開頭的偏移量.
//iLine為-1時返回光標所在行的偏移量.
iLength = SendMessage (hwndEdit, EM_LINELENGTH, iLine, 0) ;
//取得第iLine行的長度
iLength = SendMessage (hwndEdit, EM_GETLINE, iLine, (LPARAM) szBuffer) ;
//將第iLine行復制到緩沖區szBuffer中
==========================
列表控件
創建列表子窗口時,用"listbox"作為窗口類.
列表樣式:
LBS_NOTIFY 允許父窗口接收列表的WM_COMMAND消息(缺省時不向父窗口發送WM_COMMAND消息)
LBS_SORT 對列表中的項目排序
LBS_MULTIPLESEL 列表是多選的(缺省時為單選)
LBS_NOREDRAW 防止在向列表增加項目時自動重畫列表
樣式LBS_STANDARD包含了最常用的樣式:(LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
將字符串放入列表:
SendMessage (hwndList, LB_INSERTSTRING, i, (LPARAM) szString) ;
第一個參數是列表控件的窗口句柄.
第二個參數LB_INSERTSTRING表示要插入一個項目.
第三個參數表示要插入的位置.(位置值從0開始.0表示最上邊第一個位置.-1表示插入最后)
第四個參數是要插入的字符串(字符串以0結尾).
函數返回0表示正常完成.
如果列表控件包含LBS_SORT樣式.則插入一個字符串時可以將第2個參數設置為LB_ADDSTRING.這樣
字符串就會被自動插入到一個位置.如:
SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) szString) ;
要在列表控件中刪除一個字符串.只要指定第2個參數為LB_DELETESTRING. 例如:
SendMessage (hwndList, LB_DELETESTRING, iIndex, 0) ;
要刪除所有列表中的內容.則指定第2個參數為LB_RESETCONTENT. 如:
SendMessage (hwndList, LB_RESETCONTENT, 0, 0) ;
在向列表增加或刪除字符串時.列表控件會自動被它的窗口函數重畫.如果你有許多字符串需要增加.
你可能希望在所有字符串增加完成前暫時阻止列表的自動重畫.這要:
SendMessage (hwndList, WM_SETREDRAW, FALSE, 0) ;
在增加完成后再恢復列表控件的自動重畫就可以了:
SendMessage (hwndList, WM_SETREDRAW, TRUE, 0) ;
要取得現在列表控件中的項目數用:
iCount = SendMessage (hwndList, LB_GETCOUNT, 0, 0) ;
在單選列表控件中.要選擇一個項目(它會被加亮顯示)用:
SendMessage (hwndList, LB_SETCURSEL, iIndex, 0) ;
//iIndex參數為要選擇第幾個項目.指定為-1表示取消所有選擇.
在單選列表控件中.也可以根據一個字符串的第一個字母來選擇一個項目.如:
iIndex = SendMessage (hwndList, LB_SELECTSTRING, iIndex,
(LPARAM) szSearchString) ;
表示從第iIndex位置開始搜索.如果哪個項目的開始字母與 szSearchString相同.則選擇該項目.並
返回該項目的位置. 沒有匹配的項目時返回-1.
在單選列表控件中.要取得當前選擇項目的索引.用:
iIndex = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ;
如果沒有被選項目.函數返回LB_ERR(值為-1).
在單選列表控件中.將某個項目復制到一個字符緩沖區.用:
iLength = SendMessage (hwndList, LB_GETTEXT, iIndex, (LPARAM) szBuffer) ;
則將列表控件中索引為iIndex的項目復制到szBuffer. 並返回字符串的長度iLength.
(為了使szBuffer緩沖區足夠大.你可以用LB_GETTEXTLEN做參數先取得該項目的字符串長度.)
對於多選列表控件:
可以使用LB_SETSEL來設定某特定項目的選擇狀態(不會影響其他項目的選擇狀態):
SendMessage (hwndList, LB_SETSEL, wParam, iIndex) ;
參數wParam為0時.取消選擇. 為-1時.選擇/取消所有項目. 為其它值時. 選擇第iIndex個項目.
查看某項目的選擇狀態:
iSelect = SendMessage (hwndList, LB_GETSEL, iIndex, 0) ;
//項目被選擇時返回非0. 否則返回0.
要使清單控件獲得輸入焦點用:
SetFocus (hwndList) ;
清單控件發送給父窗口的消息是WM_COMMAND. 參數如下:
LOWORD (wParam) 子窗口ID
HIWORD (wParam) 通知碼
lParam 子窗口句柄
其中通知碼的值如下:
LBN_ERRSPACE -2 表示已經超出執行空間
LBN_SELCHANGE 1 表示目前選擇已經被改變
LBN_DBLCLK 2 說明某項目已經被鼠標雙擊
LBN_SELCANCEL 3
LBN_SETFOCUS 4
LBN_KILLFOCUS 5
只有清單窗口樣式包括LBS_NOTIFY時,清單控件才會向父窗口發送LBN_SELCHANGE和LBN_DBLCLK。
文件列表
要將文件目錄列表填入清單列表.用:
SendMessage (hwndList, LB_DIR, iAttr, (LPARAM) szFileSpec) ;
//iAttr參數是文件屬性代碼,其低字節是文件屬性代碼:
iAttr 值 屬性
DDL_READWRITE 0x0000 普通文件
DDL_READONLY 0x0001 只讀文件
DDL_HIDDEN 0x0002 隱藏文件
DDL_SYSTEM 0x0004 系統文件
DDL_DIRECTORY 0x0010 子目錄
DDL_ARCHIVE 0x0020 歸檔位設立的檔案
//高字節提供了一些對所要求項目的附加控制:
iAttr 值 屬性
DDL_DRIVES 0x4000 包括磁盤驅動器句柄
DDL_EXCLUSIVE 0x8000 互斥搜索