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