MFC DLEdit 設計屬於自己的編輯框


起因

  無意間看到了大牛們寫的自定義編輯框控件,於是找了個時間自己寫了一個,加深了對MFC消息機制和一些功能的了解。

分析

  先來看一張QQ2011的登錄窗口,發現當鼠標懸停在編輯框上的時候,會有懸停邊框高亮,這樣給用戶一種很絢麗的視覺享受,但我相信大家每天都上q,從而都忽略了這些美麗,細心分析一下,QQ的每一個器官甚至一根毛都是經過精心設計的。當編輯框失去輸入焦點,而編輯框內文本為空的時候,會有灰色提示文本,提示用戶輸入。 

 

  還可以有好多的自定編輯框功能,美化我們的編輯框。

具體實現和細節

  在之前《MFC自動隱藏》這篇文章中的技術細節有與DLEdit相似的地方,那就是鼠標懸停的判斷。 當鼠標懸停的時候,DLEdit要繪上編輯框“懸停框條”,因此什么時候“鼠標是懸停狀態”的判斷很重要,為了不造成文章的累贅,點這里《MFC 鼠標去留》。在程序當中要有一BOOL變量m_bHover來標志鼠標是否懸停在控件上面。這樣一來只要m_bHover為true,就可以在WM_ERASEBKGND的處理函數當中來繪絢麗的“懸停框條”。

  沒錯,幾乎所有的繪圖都在WM_ERASEBKGND的處理函數當中進行,CEdit沒有SS_OWNERDRAW風格,因此也沒有DrawItem來對自身進行繪制,所以要用WM_ERASEBKGND的處理函數中繪制編輯框的背景,自定義美化的工作很大一部分落在其上。

  其實DLEdit作為控件,很多的消息是不能夠接受並處理的,相反的,它們要發送給主窗口(parentWnd),從而交給主窗口來處理。就比如WM_DRAWITEM消息,控件窗口(假設它具有*S_OWNERDRAW風格)根本就不會接受到它,更不會去調用DrawItem函數來自繪;它是被發送到主窗口,調用主窗口的afx_msg void OnDrawItem(int nIDCtl,LPDRAWITEMSTRUCT lpDrawItemStruct )函數,其內部實現會根據nIDCtl控件ID來繪控件;當然可以在OnDrawItem中實現所有控件的繪制,但是對於控件很多的窗口來說,OnDrawItem會倍感壓力,所以控件本身的DrawItem有了施展身手的機會。在win32 sdk純C的編程中,所有的控件的自繪都在“case WM_DRAWITEM:”后面得到實現,但是MFC為了更好結合面向對象思想,所以控件窗口有自己的DrawItem,並由OnDrawItem來調用。同樣,WM_CTLCOLOR消息也是一樣的。

   細心的人都會發現,如果在控件類(或者說是子類)中添加WM_CTLCOLOR或者通知碼處理消息,在消息映射表中,我們都會發現:

ON_CONTROL_REFLECT(EN_CHANGE,&CDLEdit::OnEnChange)
ON_WM_CTLCOLOR_REFLECT()

 

在宏的最后都有REFLECT字眼,就是映射的意思。以ON_CONTROL_REFLECT為例,MFC中定義如下:

#define ON_WM_CTLCOLOR_REFLECT() \
    { WM_CTLCOLOR+WM_REFLECT_BASE,  000, AfxSig_hDw, \
        (AFX_PMSG)(AFX_PMSGW) \
        (static_cast< HBRUSH (AFX_MSG_CALL CWnd::*)(CDC*, UINT) > ( &ThisClass :: CtlColor)) },

有這種映射,就把WM_CTLCOLOR和CtlColor函數在控件類里對應起來了。在主窗口中添加WM_CTLCOLOR消息響應函數,里面有我們很熟悉的一句話:

HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

這一句就是根據子窗口(或者子控件,nCtlColor來指定)是否有CtlColor,來決定是否執行子窗口的CtlColor,不信你可以一步一步調試下去。另外在CSDN里嘮叨一篇好文章,思路很清晰,《WM_DRAWITEM與DrawItem()的討論》。

來看看自定義的編輯框:

說明:

  • 懸停邊框:鼠標懸停才繪制的邊框;
  • 默認邊框:編輯框外圍的一個實線框,與懸停邊框緊貼;
  • 編輯框框條:緊貼編輯框的框條,一般選擇淡色為好。

  在編輯框的CtlColor函數中,pDC->SetBkColor(clr),的clr是指文本顏色的背景色,而CtlColor函數的返回值是編輯框的畫刷句柄(return hbr),所以,如果你不能保證clr和返回畫刷的顏色一致,那么編輯框就會出現兩種顏色,上面是文本的背景色,而下面是編輯框的背景色,兩者是不同的。

功能圖示

看看與普通的編輯框有什么不同:

 
邊框框條就不同,接着有灰色字體提示輸入。

 


具備輸入焦點后,底色改變。

 

具備輸入焦點后,字體變粗。

 

具備輸入焦點后,有陰影。總之上面四個編輯框比起下面的兩個會更個性化。

關於編輯框圓角功能

  還有很多的功能可以自定義,比如自定義背景圖案等等,拋磚引玉,拋磚引玉。如果大家有好建議,歡迎拍磚討論。看了網上大牛們的代碼,有“圓角編輯框”的功能,這只要將代碼中的pDC->Rectangle(rct)變pDC->RoundRect(..)就可以了。

收獲與疑問

  看着自己也能寫出這樣的東西,還是有點欣慰的。有着大牛們的引導,相信很多的東西都可以輕車熟路。我認為,學習最忌諱的就是走彎路,在看似時髦但又百無聊賴的技術上浪費大量的時間,基礎課程很重要,這才是一成不變的東西,學有余力可以接觸具體的技術。有一個疑問,不知道花時間在諸如這些雞毛蒜皮的技術上,到以后會不會產生價值,我會不會在浪費時間?

附件下載:DLEdit 工程

 

搗亂小子  2012年2月4日星期六

出處:http://www.cnblogs.com/daoluanxiaozi/archive/2012/02/04/2337016.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM