Windows API入门系列之六 -自己实现MessageBox
我在第四篇文章:一個(gè)相當(dāng)簡(jiǎn)單的SDK程序?中講到了通過(guò)調(diào)用MessageBoxAPI函數(shù)來(lái)彈出一個(gè)對(duì)話框,那你有沒有想過(guò),我們一句簡(jiǎn)單的代碼背后所隱藏的細(xì)節(jié)是怎么的呢,那時(shí)候讓你了解這些未免還早了些,不過(guò)現(xiàn)在時(shí)機(jī)到了,通過(guò)一些基本的API函數(shù)調(diào)用來(lái)實(shí)現(xiàn)一個(gè)自己的對(duì)話框其實(shí)也不是很難,那么這一篇文章就是這個(gè)目的。并順帶介紹一些基本API的應(yīng)用,由于前面五篇文章的鋪墊,我相信你對(duì)SDK的程序的大致結(jié)構(gòu)和相關(guān)字符處理都有所了解了,所以在這篇文章中的這些知識(shí)點(diǎn),我就不再多說(shuō),以免有些人覺得我實(shí)在太過(guò)啰嗦。實(shí)在疑惑的,可以參看前面的文章。
首先我先大概的列出我們?yōu)橥瓿蛇@個(gè)任務(wù)所要用到的一些API函數(shù)他
SetWindowText????設(shè)置窗口的標(biāo)題
GetClientRect?得到窗口客戶區(qū)的大小信息
GetWindowLongPtr?通過(guò)窗口句柄得到和窗口的相關(guān)聯(lián)信息
CreateWindowEx?創(chuàng)建窗口
BeginPaint?得到窗口的設(shè)備句柄
EndPaint?釋放窗口的設(shè)備句柄
DrawText?通過(guò)設(shè)備句柄在窗口上畫出文字
好了,就這些函數(shù),我們就能自己實(shí)現(xiàn)有一個(gè)確定按鈕并在確定按鈕正上方顯示提示信息的簡(jiǎn)易的對(duì)話框了,不過(guò)這個(gè)對(duì)話框可是我們一句一句代碼自己實(shí)現(xiàn)的喲~~還是比較有成就感吧~
程序的大體框架呢還是我們上一篇文章中的框架,注冊(cè)窗口類,創(chuàng)建一個(gè)主窗口,消息循環(huán),窗口消息處理函數(shù)。不過(guò)要我們需要在窗口消息處理函數(shù)中添加一些代碼來(lái)完成我們需要的功能。在什么地方添加呢???上個(gè)程序,我們只處理WM_DESTROY這個(gè)消息。對(duì)于這個(gè)消息我不再做講解,不懂的或者忘記了的可以自己MSDN或者看上一篇文章,這里我們要添加對(duì)兩個(gè)消息的處理代碼,首先是WM_CREATE,這個(gè)消息會(huì)在一個(gè)窗口被創(chuàng)建的時(shí)候被發(fā)送到窗口消息處理函數(shù),如果一些事情需要在一個(gè)窗口剛被創(chuàng)建的時(shí)候執(zhí)行,那么通過(guò)處理WM_CREATE最合適不過(guò)啦,代碼如下:
case?WM_CREATE:
{
RECT?rctClient;?//用來(lái)存放主窗口客戶區(qū)大小信息
const?int?buttonWidth?=?80;?//按鈕的寬
const?int?buttonHeight?=?25;?/按鈕的高
GetClientRect(?hwnd,?&rctClient?);?//得到主窗口客戶區(qū)的大小信息
HINSTANCE?hInst?=?(HINSTANCE)GetWindowLongPtr(?hwnd,?GWLP_HINSTANCE?);
HWND?hButton?=?CreateWindowEx(?0L,?_T("button"),?_T("確定"),?WS_VISIBLE?|??WS_CHILD?,?rctClient.right/2-buttonWidth/2,?rctClient.bottom/2-buttonHeight/2,?buttonWidth,??buttonHeight,?hwnd,?(HMENU)2,?hInst,?NULL?);
SetWindowText(?hwnd,?_T("自定義對(duì)話框")?);
break;
}
在WM_CREATE消息的處理中,我們就用到了GetClientRect,它的第一個(gè)參數(shù)是窗口的句柄,你想要獲取哪個(gè)窗口的客戶區(qū)大小,你就將傳遞哪個(gè)窗口的句柄,第二個(gè)參數(shù)是一個(gè)RECT結(jié)構(gòu)的指針,我上面定義了一個(gè)rctClient變量,然后這里把這個(gè)變量的地址傳遞給GetClientRect的第二個(gè)參數(shù),讓它將所得到的窗口的大小信息保存到這個(gè)變量里面。這個(gè)函數(shù)的具體用法,讀者朋友們還可以自己參考MSDN,如果函數(shù)調(diào)用成功,那么rctClient這個(gè)結(jié)構(gòu)體變量中就存放了這個(gè)窗口的大小信息了。
然后,我定義了兩個(gè)整形常量buttonWidth,?buttonHeight用來(lái)保存我們需要?jiǎng)?chuàng)建的按鈕的寬和高。
再然后我調(diào)用GetWindowLongPtr這個(gè)函數(shù)獲取和窗口有關(guān)的信息,這里獲取的是窗口所屬的應(yīng)用程序?qū)嵗木浔?#xff0c;也就是WinMain函數(shù)所傳遞進(jìn)來(lái)的第一個(gè)參數(shù)。在得到這些需要的信息之后,我們就開始著手子窗體的創(chuàng)建了,這里我們要?jiǎng)?chuàng)建的是一個(gè)按鈕,按鈕也是一個(gè)窗體,所以也需要窗口類,我們并沒有寫按鈕的窗口類進(jìn)行注冊(cè),那么這個(gè)窗口類由誰(shuí)來(lái)注冊(cè)呢??其實(shí)是有系統(tǒng)創(chuàng)建并注冊(cè)了按鈕的窗口類,窗口類的名字是button,所以我們這里只管用這個(gè)窗口類來(lái)創(chuàng)建窗口就是了,我們創(chuàng)建主窗口是用的WS_OVERLAPPEDWINDOW這個(gè)窗口樣式,如果是創(chuàng)建一個(gè)子窗口,那么我們需要指定WS_CHILD?,如果我們需要?jiǎng)?chuàng)建的窗口能顯示出來(lái),那么需要指定WS_VISIBLE這個(gè)窗口樣式,并且還需要指定創(chuàng)建的窗口所屬的父窗口的句柄,如上代碼所示。其中第五個(gè)參數(shù)到第八個(gè)參數(shù)是該按鈕的坐標(biāo)位置和寬度高度的信息,因?yàn)槲覀冃枰獙⒃摪粹o創(chuàng)建在主窗口的中央,所以有一系列的計(jì)算,具體是怎么計(jì)算的,就請(qǐng)各位自己仔細(xì)根據(jù)上面的代碼進(jìn)行思考了,如果還是有些疑惑,請(qǐng)與我討論或者加入SDK編程(81543028)群進(jìn)行討論交流。
創(chuàng)建完了按鈕子窗口,我們還需要將我們的主窗口的標(biāo)題設(shè)置為我們想要的,可以通過(guò)SetWindowText這個(gè)API函數(shù)來(lái)完成,第一個(gè)參數(shù)就是要設(shè)置的窗口的句柄,這里為主窗口,所以是我們窗口消息處理函數(shù)傳遞進(jìn)來(lái)的第一個(gè)參數(shù)hwnd,?第二個(gè)參數(shù)就是一個(gè)字符串指針,指向一個(gè)以零結(jié)尾的字符串。這里我們就直接將一個(gè)字符串常量的首地址傳遞給它。就完成了主窗口的標(biāo)題設(shè)置。
經(jīng)過(guò)上面這些步驟,我們已經(jīng)在主窗體的中央顯示了一個(gè)按鈕了,并且把主窗口的標(biāo)題設(shè)置為我們自己需要的,但是還要一個(gè)問(wèn)題需要解決,那就是在按鈕的正上方顯示一串提示文本,怎么來(lái)完成呢,這就是我們下面要講的。
要在主窗口的按鈕的正上方顯示提示文本信息,就需要得到主窗口的設(shè)備句柄,然后通過(guò)該設(shè)備句柄調(diào)用GDI函數(shù)DrawText來(lái)完成。由于該提示文本需要在每次窗口進(jìn)行更新的時(shí)候繪出,所以我們需要處理WM_PAINT消息來(lái)達(dá)到這個(gè)目的。下面還是先看代碼:
case?WM_PAINT:
{
const?int?buttonWidth?=?80;
const?int?buttonHeight?=?25;
const?int?textHeight?=?25;
PAINTSTRUCT?ps;
HDC?hdc?=?BeginPaint(?hwnd,?&ps?);
RECT?rctClient,rctText;
GetClientRect(?hwnd,?&rctClient?);
rctText.left?=?rctClient.left;
rctText.right?=?rctClient.right;
rctText.top?=?rctClient.bottom/2?-?buttonHeight?-textHeight;
rctText.bottom?=?rctClient.bottom/2?-?buttonHeight;
DrawText(?hdc,?_T("Beyondcode"),?_tcslen(?_T("Beyondcode")),?&rctText,?DT_CENTER??|?DT_SINGLELINE?|?DT_VCENTER?);
EndPaint(?hwnd,?&ps?);
break;
}
首先定義了三個(gè)整形常量?buttonWidth,buttonHeight指示剛才創(chuàng)建的按鈕的大小,textHeight指示要顯示在文本的矩形框的高度,矩形框的寬度和主窗口的寬度一直,所以就沒定義了,然后PAINTSTRUCT?是BeginPaint和EndPaint這兩個(gè)函數(shù)會(huì)用到的一個(gè)結(jié)構(gòu)體類型,用它定義了一個(gè)結(jié)構(gòu)體變量ps,并在調(diào)用BeginPaint和EndPaint的時(shí)候?qū)⑺牡刂穫鬟f給他們的第二個(gè)參數(shù)。獲取一些相關(guān)和繪圖有關(guān)的信息。不過(guò)我們這里不會(huì)用到,所以就不做詳細(xì)解釋,可以查看MSDN。
注意,BeginPatin這個(gè)函數(shù)會(huì)返回一個(gè)設(shè)備句柄,然后我們就可以通過(guò)這個(gè)設(shè)備句柄進(jìn)行繪圖,顯示文字也是一種繪圖,在繪圖完畢后,我們需要調(diào)用EndPaint這個(gè)函數(shù)釋放剛才得到的哪個(gè)設(shè)備句柄,也就是是剛才哪個(gè)設(shè)備句柄無(wú)效。而所有的繪圖操作,都必須在BeginPaint和EndPatin這兩個(gè)函數(shù)之間完成。如上面,通過(guò)參數(shù)hdc調(diào)用DrawText這個(gè)函數(shù),因?yàn)楂@取的hdc是通過(guò)hwnd這個(gè)窗口句柄的,所以這里所有的繪圖都會(huì)顯示在hwnd這個(gè)句柄所代表的窗口上,也就是主窗口。rctText是顯示文本的矩形的信息,它的大小和位置是通過(guò)按鈕的大小和當(dāng)前主窗口的大小信息計(jì)算出來(lái)的,具體的計(jì)算代碼中已經(jīng)寫的很清楚了,如有疑惑的可以和我交流交流。?然后還要說(shuō)的一個(gè)就是DT_CENTER?和DT_VCENTER這兩個(gè)標(biāo)志表示在剛才那個(gè)矩形框中的水平中央和垂直中央顯示我們的文本,DT_SINGLELINE就是指示單行顯示。
最后留給大家一個(gè)問(wèn)題,以供大家思考,上面的程序中,當(dāng)你改變窗口的大小的時(shí)候,就會(huì)出現(xiàn)問(wèn)題,按鈕就不會(huì)再位于主窗口的中央了,怎么解決呢??我提示一下吧,處理WM_SIZE這個(gè)消息。好了,留下這個(gè)任務(wù)給大家,試試吧~~讓按鈕隨時(shí)隨地位于主窗口的中央。
更詳細(xì)的注釋的完整源代碼我會(huì)上傳群空間供各位下載。
Ok,這章就到這里,由于這些天有些忙,沒來(lái)得及及時(shí)更新,所以多多抱歉了。SDK編程群(81543028)歡迎各位的加入。
總結(jié)
以上是生活随笔為你收集整理的Windows API入门系列之六 -自己实现MessageBox的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows API入门系列之五 -一
- 下一篇: java string类的方法_Java