建立子視窗
btnlook
定義了乙個叫做button的結構,它包括了按鈕視窗樣式和描述性字串,它們對應於10個按鈕型態,所有按鈕視窗樣式都以字母「bs」開頭,它表示「按鈕樣式」。10個按鈕子視窗是在wndproc中處理wm_create訊息的過程中使用乙個for迴圈建立的。createwindow呼叫使用下面這些引數:
class name
(類別名稱)
window text
(視窗文字)
window style
(視窗樣式)
x position
(x位置)
y position
(y位置)
width
(寬度)
height
(高度)
parent window
(父視窗)
child window id
(子視窗id)
instance handle
(執行實體控制代碼)
extra parameters
(附加引數)
text ("button")
button[i].sztext
ws_child | ws_visible | button[i].istyle
cxchar
cychar * (1 + 2 * i)
20 * xchar
7 * ychar / 4
hwnd
(hmenu) i
((lpcreatestruct) lparam) -> hinstance
null
類別名稱引數是預先定義的名字。視窗樣式使用ws_child、ws_visible以及在button結構中定義的10個按鈕樣式之一(bs_pushbutton、bs_defpushbutton等等)。視窗文字引數(對於普通視窗來說,它是顯示在標題列中的文字)將在每個按鈕上顯示出來。我簡單地使用標識按鈕樣式文字的x位置和y位置引數,說明子視窗左上角相對于父視窗顯示區域左上角的位置。寬度和高度引數規定了每個子視窗的寬度和高度。請注意,我用的是getdialogbaseunits函式來獲得內定字型字元的寬度和高度。這是對話方塊用來獲得文字尺寸的函式。此函式傳回乙個32位的值,其中低字組表示寬度,高字組表示高度。由於getdialogbaseunits傳回的值與從gettextmetrics獲得的值大致上相同,但getdialogbaseunits有時使用起來會更方便些,而且能夠與對話方塊控制項更好地保持一致。
對每個子視窗,它的子視窗id引數應該各不相同。在處理來自子視窗的wm_command訊息時,id幫助您的視窗訊息處理程式識別出相應的子視窗。注意子視窗id是作為createwindow的乙個引數傳遞的,該引數通常用於指定程式的選單,因此子視窗id必須被強制轉換為hmenu。
createwindow
呼叫的執行實體控制代碼看起來有點奇怪,但是它利用了如下的事實,亦即在處理wm_create訊息的過程中,lparam實際上是指向createstruct (「建立結構」)結構的指標,該結構有乙個hinstance成員。所以將lparam轉換成指向createstruct結構的乙個指標,並取出hinstance。
(有些windows程式使用名為hinst的整體變數,使視窗訊息處理程式能訪問winmain中的執行實體控制代碼。在winmain中,您只需在建立主視窗之前設定:
hinst = hinstance ;
可以用getwindowlong取得執行實體控制代碼:
getwindowlong (hwnd, gwl_hinstance)
這幾種方法都是正確的。)
在呼叫createwindow之後,我們不必再為這些子視窗做任何事情,由windows中的按鈕視窗訊息處理程式負責維護它們,並處理所有的重畫工作(bs_ownerdraw樣式的按鈕例外,它要求程式繪製它,這些將在後面加以討論)。在程式終止時,如果父視窗已經被清除,那麼windows將清除這些子視窗。
子視窗向父視窗發訊息
當您執行btnlook時,將看到在顯示區域的左邊會顯示出不同的按鈕型態。我在前面已經提到過,用滑鼠單擊按鈕時,子視窗控制項就向其父視窗傳送乙個wm_command訊息。btnlook攔截wm_command訊息並顯示wparam和lparam的值,它們的含義如下:
loword (wparam)
hiword (wparam)
lparam
子視窗id
通知碼子視窗控制代碼
如果您正在移植16位windows程式,那麼要注意改變這些訊息引數以容納32位的控制代碼。
子視窗id是在建立子視窗時傳遞給createwindow的值。在btnlook中,這些id被顯示在顯示區域中,並使用0到9分別標識10個按鈕。子視窗控制代碼是windows從createwindow傳回的值。
通知碼更詳細表示了訊息的含義。按鈕通知碼的可能值在windows表頭檔案中定義如下:
表9-1
按鈕通知碼識別符號
值
bn_clicked
0
bn_paint
1
bn_hilite or bn_pushed
2
bn_unhilite or bn_unpushed
3
bn_disable
4
bn_doubleclicked or bn_dblclk
5
bn_setfocus
6
bn_killfocus
7
實際上,您不會看到這些按鈕值中的大多數。從1到4的通知碼是用於一種叫做bs_userbutton的已不再使用的按鈕的(它已經由bs_ownerdraw和另一種不同的通知方式所替換)。通知碼6到7只有當按鈕樣式包括標識bs_notify才傳送。通知碼5只對bs_radiobutton、bs_autoradiobutton和bs_ownerdraw按鈕傳送,或者當按鈕樣式中包括bs_notify時,也為其它按鈕傳送。
您會注意到,在用滑鼠單擊按鈕時,該按鈕文字的周圍會有虛線。這表示該按鈕擁有了輸入焦點,所有鍵盤輸入都將傳送給子視窗按鈕控制項,而不是傳送給主視窗。但是,當該按鈕控制項擁有輸入焦點時,它將忽略所有的鍵盤輸入,除了spacebar鍵例外,此時spacebar鍵與滑鼠具有相同的效果。
父視窗向子視窗傳送訊息
雖然btnlook中沒有顯示這一事實,但是父視窗訊息處理程式也能向子視窗控制項傳送訊息。這些訊息包括以字首wm開頭的許多訊息。另外,在winuser.h中還定義了8個按鈕說明訊息;字首bm表示「按鈕訊息」。這些按鈕訊息如下表所示:
表9-2
按鈕訊息
值
bm_getcheck
0x00f0
bm_setcheck
0x00f1
bm_getstate
0x00f2
bm_setstate
0x00f3
bm_setstyle
0x00f4
bm_click
0x00f5
bm_getimage
0x00f6
bm_setimage
0x00f7
bm_getcheck
和bm_setcheck訊息由父視窗傳送給子視窗控制項,以取得或者設定核取方塊和單選按鈕的選中標記。bm_getstate和bm_setstate訊息表示按鈕處於正常狀態還是(滑鼠或spacebar鍵按下時的)「按下」狀態。我們將在討論按鈕的每種型態時,看到這些訊息是如何起作用的。bm_setstyle訊息允許您在按鈕建立之後改變按鈕樣式。
每個子視窗控制項都具有乙個在其兄弟中唯一的視窗控制代碼和id值。對於控制代碼和id這兩者,知道其中的乙個您就可以獲得另乙個。如果您知道子視窗控制項的視窗控制代碼,那麼您可以用下面的敘述來獲得id:
id = getwindowlong (hwndchild, gwl_id) ;
用此函式(與setwindowlong一起)來維護註冊視窗類別時保留的特殊區域的資料。在建立子視窗時,windows保留了gwl_id識別符號訪問的資料。您也可以使用:
id = getdlgctrlid (hwndchild) ;
雖然函式中的「dlg」部分指的是對話方塊,但實際上這是乙個通用的函式。
知道id和父視窗控制代碼,您就能獲得子視窗控制代碼:
hwndchild = getdlgitem (hwndparent, id) ;
C 中如何處理父視窗及其子視窗標題
因為在例子程式中 mainwindow 是唯一乙個訪問該字串的類,所以沒有必要使用屬性機制。有了這兩個新的資料成員,你要做的只是 改寫 wm gettext 處理例程,返回子視窗最大化狀態以及常態時的標題文字。那麼如何改寫 wm gettext 處理例程呢?windows.forms 提供了一些 處...
子視窗呼叫父視窗
相信學計算機的大學生都碰過這樣的程式設計作業吧 程式執行後主視窗隱藏,然後彈出登入框,輸入賬號密碼登陸成功後再關閉登陸框,然後讓之前隱藏的主視窗重新顯示。沒錯,我當時就是這麼笨,怎麼都想不到好的解決辦法 當時的同學都是不管之前隱藏的主視窗,而是直接新建了乙個主視窗 剛好昨晚在做專案時碰到類似的情況,...
Flink的滾動視窗 會話視窗 滑動視窗及其應用
flink作業中的視窗 是指一種對無限資料流設定有限資料集,從而實現了處理無線資料流的機制。視窗本身只是個劃分資料集的依據,它並不儲存資料。當我們需要在時間視窗維度上對資料進行聚合時,視窗是流處理應用中經常需要解決的問題。flink的視窗運算元為我們提供了方便易用的api,我們可以將資料流切分成乙個...