轉帖|其它|編輯:郝浩|2010-11-19 11:43:13.000|閱讀 566 次
概述:本文講述如何定制控件的背景顏色和背景位圖的技巧。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
本文講述如何定制控件的背景顏色和背景位圖的技巧。
首先要說一下控件的繪制過程:當控件的某個區域需要重繪時,都會觸發WM_ERASEBKGND和WM_PAINT消息。比如控件的某個區域被另一個程序的窗口擋住了,而后那個窗口又被移走了,這時控件被擋住的內容就需要重新繪制了。
第一步:系統向控件發送WM_ERASEBKGND消息以實現背景的擦除工作(有時不發送,比如用戶可能調用InvalidateRect(),其參數卻指定不擦除背景,這樣就沒有這個消息);
第二步:系統向控件的窗口過程發送WM_PAINT消息,控件執行處理這個WM_PAINT消息時會有選擇地觸發后面三個步驟的動作;
第三步:對于有些標準控件,如Button、Edit、ListBox、 ScrollBar、Static控件,它還會向父窗口發送WM_CTLCOLORxxx(WM_CTLCOLORBUTTON、 WM_CTLCOLOREDIT、WM_CTLCOLORSTATIC、WM_CTLCOLORLISTBOX、 WM_CTLCOLORSCROLLBAR等)的消息,這些消息返回一個刷子句柄,系統拿這個刷子句柄進一步涂刷自己的背景。另外還發現Trackbar 也會向父窗口發送WM_CTLCOLORSTATIC消息,TreeView在某些情況下也有,不過我沒有看到微軟在什么地方對這一點作說明;我常常發現很多人處理這個消息時,喜歡給系統返回一個NULL_BRUSH的空刷子,以為這樣系統就不會把前面步驟畫好的背景覆蓋掉,其實不一定的,有些控件不覆蓋,有些就有問題,像Trackbar就是如此,要小心。
第四步:對于菜單和許多標準控件,如Button、Edit、ListBox、 Static、ComboBox它可能會向父窗口發送WM_MEASUREITEM和WM_DRAWITEM消息,另外通用控件Tab、 StatusBar、ListView、Header也可能會有WM_DRAWITEM消息;但對于多數通用控件,如TreeView、 ListView、Rebar、Trackbar、Toolbar等,它會向父窗口發送許多其ID為NM_CUSTOMDRAW的WM_NOTIFY消息。對于這兩種消息,實際要求用戶在已經涂刷好的背景之上再執行自己的繪制工作;
第五步:當控件的WM_DRAWITEM或者WM_NOTIFY消息沒有被用戶處理時,系統會親自執行自己的默認繪制工作,把控件畫出來,這一步沒有辦法重載。
知道了這些步驟,大概我們心中已經了然,知道如何定制控件的背景顏色和背景位圖了。一般情況下我們定制第一步、第三步實現自己的特殊背景,定制第四部實現控件本身的特殊繪制。甚至我們可以整個重載控件第一步的WM_ERASEBKGND消息和第二步的WM_PAINT消息,控件背景和控件繪制全部自己搞定,沒人說這樣做不行。不過要注意,當自己實現WM_PAINT消息的重載處理時,后面3個步驟就都不發生了。
定制顏色倒是很簡單,根據控件的類型處理WM_ERASEBKGND、 WM_CTLCOLORxxx、WM_DRAWITEM、WM_NOTIFY消息了,一般情況下,定制WM_ERASEBKGND和 WM_CTLCOLORxxx就可以了;對于背景位圖很多控件卻特別麻煩,像ListBox,你把背景位圖涂刷好,結果因為用戶操作滾動條或鼠標滾輪或按方向鍵,背景位圖也發生滾動,這就不得不重繪位圖,對于背景顏色就沒有這個問題,不管怎么滾動,顏色還是那個顏色,位圖就不行,需要自己重載發生滾動操作的各種消息以實現位圖重繪。微軟似乎并不假設你會修改控件的背景位圖,它沒有對這個情況作準備,總是毫不猶豫的對控件畫布執行Scroll操作。真正實現背景位圖的方法常常迫使我們要攔截那些導致窗口內容發生滾動的各種操作,因此位圖背景的功能實現也總讓人覺得不怎么規范、不那么可信。
最后要說明的是:如果父控件還包含背景透明的子控件,你應當重載父控件的WM_ERASEBKGND消息,否則那些透明背景的子控件可能就沒有正確的背景內容。
上面這些步驟是我個人的理解,不一定對哦!僅供參考。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:博客轉載