解說Win32的視窗子類化

來源:互聯網
上載者:User

代碼下載:subclass(請點擊進入論壇回複以後下載)

也許你需要一個特殊的Edit來限制浮點數的輸入,但是現有的Edit卻並不能完成這項工作――因為它只能夠單純的限制大小寫或者純數字。當你在論壇上求救的時候,某個網友告訴你:“用子類化。”你也許會在看到一線曙光的同時多出了一連串的問題:何為子類化?子類化的原理是什嗎?如何?子類化?下面就讓我從一個簡單的C++程式開始,一步步解開你的疑團吧。 
 首先,我為你列出以下這個C++程式:

01. #include <iostream> 02. using  namespace  std; 03. class  Parent 04. { 05. public : 06. void  func( void ) { cout <<  "func of Parent"  << endl; } 07. }; 08. class  Child :  public  Parent 09. { 10. public : 11. void  func( void ) { cout <<  "func of Child"  << endl; } 12. }; 13. void  main() 14. { 15. Parent p; 16. Child c; 17. p.func(); 18. c.func(); 19. }</iostream>

現在我來解說一下。這段代碼中我定義了兩個C++類:父類和子類,並且子類是繼承自父類的;它們有一個具有相同名稱的成員函數func。在main函數中,我分別構造了父類和子類的對象,並調用了它們各自的成員函數func。結果如下:

1. func of Parent 2. func of Child

簡單說來,這段代碼就是子類根據自己的需要改寫了func成員函數。而Win32的子類化的原理也與此類似,只不過子類化實際上並沒有像C++一樣重載哪個函數,而是靠攔截Windows系統中的某些訊息來自己進行處理罷了。舉例來說,請大家看以下這段簡單的視窗回調過程:

01. LRESULT  CALLBACK ProcMain( HWND  hDlg,  UINT  Msg,  WPARAM  wParam,  LPARAM lParam) 02. { 03. switch  (Msg) 04. { 05. case  WM_CLOSE: 06. EndDialog(hDlg, 0); 07. break ; 08. case  WM_DESTROY: 09. PostQuitMessage(0); 10. break ; 11. } 12. return  0; 13. }

在這個回調之中,我手動處理了兩個訊息:在單擊了“關閉”按鈕(WM_CLOSE)的時候,我將對話方塊關閉(EndDialog);在對話方塊銷毀(WM_DESTROY)的時候,我向系統訊息佇列中發送了退出的訊息來完成結束工作(PostQuitMessage)。也就是說,如果把WM_CLOSE的響應代碼改成:

1. case  WM_CLOSE: 2. ShowWindow(hDlg, SW_MINIMIZE); 3. break ;

這樣一來,這個對話方塊就會和MSN一樣,在單擊了“關閉”之後,就會完成最小化的工作了。那麼,對於視窗過程已定義好的系統控制項,將如何手動響應它的訊息呢? 
   我們可以用函數指標的辦法,將我們感興趣的訊息攔截下來,處理完之後再讓預定義的視窗過程處理。這個過程大致如下:

1. WNDPROC OldProc; 2.   OldProc = (WNDPROC)SetWindowsLong(hWnd, GWL_WNDPROC, ( LONG )NewProc);

當然,這裡的新視窗過程NewProc是預先由你實現好的。上述代碼執行以後,系統在處理hWnd的視窗訊息時,就會先進入你實現的NewProc回調過程,然後在處理過你感興趣的訊息之後,通過CallWindowProc函數和你預先儲存的OldProc再次回到原來的回調過程中完成剩餘的工作。 
   以上就是視窗子類化的原理分析,下面我通過一個執行個體來實際解說如何對視窗進行子類化。

這個例子的介面如下:

 

介面上方的編輯框是用來限制浮點輸入的,下面則是一個普通的超級連結。 
   好了,下面我開始按步驟完成對這兩個視窗的子類化: 
   第一步,在主視窗對話方塊初始化的時候,儲存原有的視窗過程,並設定新的視窗過程。代碼如下:

1. case  WM_INITDIALOG: 2. EditProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_EDIT), GWL_WNDPROC, ( LONG )ProcFloat); 3. StaticProc = (WNDPROC)SetWindowLong(GetDlgItem(hDlg, IDC_ST_HOMEPAGE), GWL_WNDPROC, ( LONG )ProcLink); 4. break ;

第二步,實現浮點編輯框的視窗過程:

01. LRESULT  CALLBACK ProcFloat( HWND  hWnd,  UINT  Msg,  WPARAM  wParam,  LPARAM lParam) 02. { 03. if  (Msg == WM_CHAR && wParam !=  '' . ''  && (wParam <=  '' 0 ''  || wParam >=  '' 9 '' ) && wParam != VK_BACK) 04. { 05. MessageBeep(MB_OK); 06. return  0; 07. } 08. else 09. return  CallWindowProc(EditProc, hWnd, Msg, wParam, lParam); 10. }

這裡需要解釋的是,由於控制項本身的需求,所以只需要攔截一個訊息,就是接收字元的WM_CHAR。當使用者輸入的字元不是小數點、0~9以及退格鍵(注意不要少了退格鍵,否則你將會發現你的編輯框無法刪除輸入錯誤的數字)的時候,就發出一聲聲音以提示輸入錯誤。至於其它的訊息,則調用原有的回呼函數進行處理。 
   第三步,實現超級連結的視窗過程:

01. LRESULT  CALLBACK ProcLink( HWND  hWnd,  UINT  Msg,  WPARAM  wParam,  LPARAM lParam) 02. { 03. switch  (Msg) 04. { 05. case  WM_SETCURSOR: 06. SetCursor(LoadCursor(NULL, IDC_HAND)); 07. break ; 08. case  WM_LBUTTONDOWN: 09. ShellExecute(NULL,  "open" "http://home.ncust.edu.cn/~titilima" , NULL, NULL, SW_SHOWNORMAL); 10. break ; 11. default : 12. return  CallWindowProc(StaticProc, hWnd, Msg, wParam, lParam); 13. } 14. return  0; 15. }

這段代碼很容易明白:它完成了兩件事,其一是設定游標指標為手形(注意:對於較早的Windows系統,是沒有預定義的IDC_HAND指標的,這個時候你需要在EXE的資源中自己畫一個手形指標,比如Delphi之中的手形指標就是自己畫的),其二是當單擊了滑鼠左鍵的時候開啟你想開啟的網頁連結。 
   其實對於超級連結,它更主要的東西是在子類化之外實現的――就是它的字型顏色(注意這段代碼是在主視窗對話方塊的回調過程中實現的):

1. case  WM_CTLCOLORSTATIC: 2. if  (GetDlgItem(hDlg, IDC_ST_HOMEPAGE) == ( HWND )lParam) 3. { 4. SetTextColor(( HDC )wParam, 0xff0000); 5. SetBkMode(( HDC )wParam, TRANSPARENT); 6. return  ( LRESULT )CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); 7. } 8. break ;

還有幾點要說明的是:
1、你的這個Static超連結必須擁有一個唯一的資源ID,比如我的這個就是IDC_ST_HOMEPAGE,這樣才能用GetDlgItem獲得它的控制代碼來完成子類化;
2、你必須為它設定SS_NOTIFY樣式,以保證在單擊它的時候它能夠通知父視窗對話方塊;
3、單擊它開啟網頁的處理也可以放在子類化之外,處理主視窗對話方塊的WM_COMMAND訊息也可以實現這一功能。

  關於Win32的視窗子類化就介紹到這裡了,你可以 點這裡下載本文的配套原始碼 ,代碼中有詳細的注釋。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.