API入門系列之六 -自己實現MessageBox

原創文章,轉載請註明作者和出處

 

http://blog.csdn.net/beyondcode

SDK編程羣號:81543028 歡迎加入

 

API入門系列文章的第六篇之自己動手實現MessageBox。

我在第四篇文章:一個相當簡單的SDK程序 中講到了通過調用MessageBoxAPI函數來彈出一個對話框,那你有沒有想過,我們一句簡單的代碼背後所隱藏的細節是怎麼的呢,那時候讓你瞭解這些未免還早了些,不過現在時機到了,通過一些基本的API函數調用來實現一個自己的對話框其實也不是很難,那麼這一篇文章就是這個目的。並順帶介紹一些基本API的應用,由於前面五篇文章的鋪墊,我相信你對SDK的程序的大致結構和相關字符處理都有所瞭解了,所以在這篇文章中的這些知識點,我就不再多說,以免有些人覺得我實在太過囉嗦。實在疑惑的,可以參看前面的文章。

首先我先大概的列出我們爲完成這個任務所要用到的一些API函數他

SetWindowText    設置窗口的標題

GetClientRect 得到窗口客戶區的大小信息

GetWindowLongPtr 通過窗口句柄得到和窗口的相關聯信息

CreateWindowEx 創建窗口

BeginPaint 得到窗口的設備句柄

EndPaint 釋放窗口的設備句柄

DrawText 通過設備句柄在窗口上畫出文字

好了,就這些函數,我們就能自己實現有一個確定按鈕並在確定按鈕正上方顯示提示信息的簡易的對話框了,不過這個對話框可是我們一句一句代碼自己實現的喲~~還是比較有成就感吧~

程序的大體框架呢還是我們上一篇文章中的框架,註冊窗口類,創建一個主窗口,消息循環,窗口消息處理函數。不過要我們需要在窗口消息處理函數中添加一些代碼來完成我們需要的功能。在什麼地方添加呢?  上個程序,我們只處理WM_DESTROY這個消息。對於這個消息我不再做講解,不懂的或者忘記了的可以自己MSDN或者看上一篇文章,這裏我們要添加對兩個消息的處理代碼,首先是WM_CREATE,這個消息會在一個窗口被創建的時候被髮送到窗口消息處理函數,如果一些事情需要在一個窗口剛被創建的時候執行,那麼通過處理WM_CREATE最合適不過啦,代碼如下:

case WM_CREATE:

{

RECT rctClient; //用來存放主窗口客戶區大小信息

const int buttonWidth = 80; //按鈕的寬

const int buttonHeight = 25; /按鈕的高

GetClientRecthwnd, &rctClient ); //得到主窗口客戶區的大小信息

HINSTANCE hInst = (HINSTANCE)GetWindowLongPtrhwndGWLP_HINSTANCE );

HWND hButton = CreateWindowEx( 0L, _T("button"), _T("確定"), WS_VISIBLE | WS_CHILD , rctClient.right/2-buttonWidth/2, rctClient.bottom/2-buttonHeight/2, buttonWidthbuttonHeight, hwnd, (HMENU)2, hInstNULL );

SetWindowTexthwnd_T("自定義對話框") );

break;

}

在WM_CREATE消息的處理中,我們就用到了GetClientRect,它的第一個參數是窗口的句柄,你想要獲取哪個窗口的客戶區大小,你就將傳遞哪個窗口的句柄,第二個參數是一個RECT結構的指針,我上面定義了一個rctClient變量,然後這裏把這個變量的地址傳遞給GetClientRect的第二個參數,讓它將所得到的窗口的大小信息保存到這個變量裏面。這個函數的具體用法,讀者朋友們還可以自己參考MSDN,如果函數調用成功,那麼rctClient這個結構體變量中就存放了這個窗口的大小信息了。

然後,我定義了兩個整形常量buttonWidth, buttonHeight用來保存我們需要創建的按鈕的寬和高。

再然後我調用GetWindowLongPtr這個函數獲取和窗口有關的信息,這裏獲取的是窗口所屬的應用程序實例的句柄,也就是WinMain函數所傳遞進來的第一個參數。在得到這些需要的信息之後,我們就開始着手子窗體的創建了,這裏我們要創建的是一個按鈕,按鈕也是一個窗體,所以也需要窗口類,我們並沒有寫按鈕的窗口類進行註冊,那麼這個窗口類由誰來註冊呢? 其實是有系統創建並註冊了按鈕的窗口類,窗口類的名字是button,所以我們這裏只管用這個窗口類來創建窗口就是了,我們創建主窗口是用的WS_OVERLAPPEDWINDOW這個窗口樣式,如果是創建一個子窗口,那麼我們需要指定WS_CHILD ,如果我們需要創建的窗口能顯示出來,那麼需要指定WS_VISIBLE這個窗口樣式,並且還需要指定創建的窗口所屬的父窗口的句柄,如上代碼所示。其中第五個參數到第八個參數是該按鈕的座標位置和寬度高度的信息,因爲我們需要將該按鈕創建在主窗口的中央,所以有一系列的計算,具體是怎麼計算的,就請各位自己仔細根據上面的代碼進行思考了,如果還是有些疑惑,請與我討論或者加入SDK編程(81543028)羣進行討論交流。

創建完了按鈕子窗口,我們還需要將我們的主窗口的標題設置爲我們想要的,可以通過SetWindowText這個API函數來完成,第一個參數就是要設置的窗口的句柄,這裏爲主窗口,所以是我們窗口消息處理函數傳遞進來的第一個參數hwnd, 第二個參數就是一個字符串指針,指向一個以零結尾的字符串。這裏我們就直接將一個字符串常量的首地址傳遞給它。就完成了主窗口的標題設置。

經過上面這些步驟,我們已經在主窗體的中央顯示了一個按鈕了,並且把主窗口的標題設置爲我們自己需要的,但是還要一個問題需要解決,那就是在按鈕的正上方顯示一串提示文本,怎麼來完成呢,這就是我們下面要講的。

要在主窗口的按鈕的正上方顯示提示文本信息,就需要得到主窗口的設備句柄,然後通過該設備句柄調用GDI函數DrawText來完成。由於該提示文本需要在每次窗口進行更新的時候繪出,所以我們需要處理WM_PAINT消息來達到這個目的。下面還是先看代碼:

case WM_PAINT:

{

const int buttonWidth = 80;

const int buttonHeight = 25;

const int textHeight = 25;

PAINTSTRUCT ps;

HDC hdc = BeginPainthwnd, &ps );

RECT rctClient,rctText;

GetClientRecthwnd, &rctClient );

rctText.left = rctClient.left;

rctText.right = rctClient.right;

rctText.top = rctClient.bottom/2 - buttonHeight -textHeight;

rctText.bottom = rctClient.bottom/2 - buttonHeight;

DrawTexthdc_T("Beyondcode"), _tcslen_T("Beyondcode")), &rctTextDT_CENTER  | DT_SINGLELINE | DT_VCENTER );

EndPainthwnd, &ps );

break;

}

首先定義了三個整形常量 buttonWidth,buttonHeight指示剛纔創建的按鈕的大小,textHeight指示要顯示在文本的矩形框的高度,矩形框的寬度和主窗口的寬度一直,所以就沒定義了,然後PAINTSTRUCT 是BeginPaint和EndPaint這兩個函數會用到的一個結構體類型,用它定義了一個結構體變量ps,並在調用BeginPaint和EndPaint的時候將它的地址傳遞給他們的第二個參數。獲取一些相關和繪圖有關的信息。不過我們這裏不會用到,所以就不做詳細解釋,可以查看MSDN。

注意,BeginPatin這個函數會返回一個設備句柄,然後我們就可以通過這個設備句柄進行繪圖,顯示文字也是一種繪圖,在繪圖完畢後,我們需要調用EndPaint這個函數釋放剛纔得到的哪個設備句柄,也就是是剛纔哪個設備句柄無效。而所有的繪圖操作,都必須在BeginPaint和EndPatin這兩個函數之間完成。如上面,通過參數hdc調用DrawText這個函數,因爲獲取的hdc是通過hwnd這個窗口句柄的,所以這裏所有的繪圖都會顯示在hwnd這個句柄所代表的窗口上,也就是主窗口。rctText是顯示文本的矩形的信息,它的大小和位置是通過按鈕的大小和當前主窗口的大小信息計算出來的,具體的計算代碼中已經寫的很清楚了,如有疑惑的可以和我交流交流。 然後還要說的一個就是DT_CENTER 和DT_VCENTER這兩個標誌表示在剛纔那個矩形框中的水平中央和垂直中央顯示我們的文本,DT_SINGLELINE就是指示單行顯示。

最後留給大家一個問題,以供大家思考,上面的程序中,當你改變窗口的大小的時候,就會出現問題,按鈕就不會再位於主窗口的中央了,怎麼解決呢? 我提示一下吧,處理WM_SIZE這個消息。好了,留下這個任務給大家,試試吧~~讓按鈕隨時隨地位於主窗口的中央。

更詳細的註釋的完整源代碼我會上傳羣空間供各位下載。

Ok,這章就到這裏,由於這些天有些忙,沒來得及及時更新,所以多多抱歉了。SDK編程羣(81543028)歡迎各位的加入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章