滚动条详解
對上一天學習的回顧:
1>.??TextOut函數(shù)的使用
TextOut函數(shù)的作用是使用系統(tǒng)當前選擇的字體、背景顏色以及正文顏色將一個字符串輸出到指定位置,?函數(shù)原型:
BOOL TextOut(HDC hdc, //設備環(huán)境句柄int nXStart, //字符串開始輸出的x坐標int nYStart, // 字符串開始輸出的y坐標 LPCTSTR lpString, //需要輸出的字符串int cbString // 字符串的長度);當函數(shù)調用成功時返回一個非零的值,?調用失敗時,?返回值為0。
?
2>.?取得當前系統(tǒng)字體信息:
使用GetTextMetrics函數(shù)可以取得當前字體信息,?函數(shù)原型如下:
BOOL GetTextMetrics(HDC hdc, // 設備環(huán)境句柄LPTEXTMETRIC lptm // 指向一個TEXTMETRIC結構的指針, 該結構用于存放字體信息。 );參數(shù)二LPTEXTMETRIC指向TEXTMETRIC結構,?在函數(shù)調用成功時,?函數(shù)將系統(tǒng)當前字體的各種信息復制到TEXTMETRIC結構中。
?
?
Windows滾動條介紹
滾動條由滾動滑塊以及兩端的滾動箭頭組成,?滾動條的作用是當需要顯示的內(nèi)容超過窗口客戶區(qū)大小時提供上下/左右的翻頁使用戶能夠完整的閱讀顯示信息,?滾動條的圖示:
?
?
滾動條理論基礎
1>.?上下滾動?
以垂直方向的滾動條為例,?當用戶向下滾動滾動條時目的是想看到下方更多的的信息,?因此我們需要將下方的信息顯示出來,?如何顯示更多的信息?
解決方案:?將不需要被顯示的信息顯示到客戶區(qū)外,?令信息自動被Windows截掉,?圖示說明:
?
由圖示看出,?當用戶向下翻動滾動條實際上我們是將起始輸出部分的y坐標設為負數(shù),?使已經(jīng)顯示過的信息輸出到客戶區(qū)的上部,?我們知道,?輸出到客戶區(qū)外部的信息會被Windows自動截掉,?所以用戶不會再次看到已經(jīng)顯示過的信息,?取而代之的就是下方等待顯示的信息,?上翻以及左右翻動的顯示思路與下翻相同,?不再介紹。
?
2>.?如何創(chuàng)建一個帶有滾動條的窗口?
創(chuàng)建帶有水平/垂直的滾動條的窗口十分簡單,?在CreateWindow函數(shù)中說明下即可,?CreateWindow函數(shù)的原型回顧:
HWND CreateWindow(LPCTSTR lpClassName, //窗口類名稱LPCTSTR lpWindowName, //窗口標題DWORD dwStyle, //窗口樣式int x, //窗口初始x坐標int y, //窗口初始y坐標int nWidth, //窗口初始x方向尺寸int nHeight, //窗口初始y方向尺寸HWND hWndParent, //父窗口句柄HMENU hMenu, //窗口菜單句柄HANDLE hlnstance, //程序實例句柄LPVOID lpParam //創(chuàng)建參數(shù));要窗口帶有滾動條的窗口, 只需要在第三個參數(shù)
DWORD dwStyle, //窗口樣式? 也就是在窗口樣式的屬性中使用位或(?|?)運算對相關的標識符進行組合即可得到一個帶有垂直/水平滾動條的窗口,
WS_HSCROLL //水平滾動條的標識符WS_VSCROLL //垂直滾動條的標識符例如要創(chuàng)建一個既含有垂直滾動條又含有水平滾動條的組合:
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL?
3>.?對于滾動條,?Windows需要做哪些事?
當帶有滾動條的窗口創(chuàng)建好后,?Windows就會做一些必要的處理來協(xié)助我們更好的使用滾動條,?Windows需要做的事情如下:
1>.?處理滾動條中的所有鼠標消息;
2>.?當用戶單擊滾動條時提供被單擊部分的輕微閃爍;
3>.?當用戶拖動滑塊時在滾動條內(nèi)移動滑塊;
4>.?當窗口大小被調整時,?自動調整滾動條的長度;
5>.?向滾動條所在的窗口發(fā)送滾動條的相關消息。
?
?
4>.?我們要做的事情:
相對于系統(tǒng),?我們需要做的事情已經(jīng)較為輕松了,?主要有4項任務:
1>.?初始化滾動條的位置和滾動條的范圍;
2>.?處理系統(tǒng)發(fā)來的消息;
3>.?根據(jù)發(fā)來的消息重置滑塊的位置;
4>.?根據(jù)滾動條消息重繪客戶區(qū)顯示的內(nèi)容。
?
5>.?將會收到哪些滾動條消息?
滾動條消息來源同其他消息一樣,?伴隨著wParam與lParam消息機制,?當窗口為父窗口時消息的來源為wParam,?此時可忽略lParam的值,?lParam用于子窗口消息。
wParam參數(shù)分為兩部分,?高位字與低位字,?其中高位字代表用戶松開鼠標鍵時滑塊的最終位置,?低位字上代表鼠標在滾動條上的動作,?以一個值的形式表現(xiàn)出來,?同樣,?為了方便記憶,?有不同的標識符對這些值進行區(qū)分,?這些標識符定義在WINUSER.H頭文件中,?以SB_開頭,?有關滾動條的消息標識符如下:
#define SB_LINEUP 0 //上翻一個單位 #define SB_LINELEFT 0 //左翻一個單位 #define SB_LINEDOWN 1 //下翻一個單位 #define SB_LINERIGHT 1 //右翻一個單位 #define SB_PAGEUP 2 //上翻一頁 #define SB_PAGELEFT 2 //左翻一頁 #define SB_PAGEDOWN 3 //下翻一頁 #define SB_PAGERIGHT 3 //右翻一頁 #define SB_THUMBPOSITION 4 //當鼠標放下滑塊時 #define SB_THUMBTRACK 5 //移動滑塊時 #define SB_TOP 6 //滑塊到了頂端 #define SB_LEFT 6 //滑塊到了左端 #define SB_BOTTOM 7 //滑塊到了底端 #define SB_RIGHT 7 //滑塊到了右端 #define SB_ENDSCROLL 8 //釋放鼠標?
6>.??需要使用到的新函數(shù):
①.?SetScrollRange
SetScrollRange函數(shù)的作用是設置所指定滾動條范圍的最小值和最大值,?其函數(shù)的原型如下:
BOOL SetScrollRange(HWND hWnd, //窗口句柄int nBar, //被設置的滾動條類型int nMinPos, //滾動條的最小位置int nMaxPos, //滾動條的最大位置BOOL bRedraw //重繪標志);參數(shù)二int?nBar為被設置的滾動條類型,?SB_HORZ表示該窗口的水平滾動條,?SB_VERT表示垂直滾動條;
參數(shù)四BOOL?bRedraw指定滾動條是否被重繪以反映變化,?當參數(shù)為TRUE,?滾動條被重繪,?FALSE則不被重繪。
?
②.?SetScrollPos
SetScrollPos函數(shù)的作用是設置所指定滾動條中的滾動按鈕的位置,?函數(shù)原型:
int SetScrollPos(HWND hWnd, //窗體句柄int nBar, //被設置的滾動條類型int nPos, //滾動條的新位置BOOL bRedraw //重繪標志);?
?
?
實戰(zhàn)滾動條
下面我們嘗試著輸出一些文字,?使其上下、左右均超過客戶區(qū)的尺寸,?這樣我們就可以實際練習下水平滾動條以及垂直滾動條了,??我們準備了很多行文字,?筆者也不知道到底有多少行,?而且最長的那行文字有多少個也不知道,?我們把他放在一個text.h頭文件中,?并計算他到底有多少行以及最長的那行有多少字,?由于文字行數(shù)較多,?這里將它在代碼框里折疊顯示,?定義的頭文件如下:
View Code - text.h #include<string.h>#define NUMLINES ( (int)(sizeof(statement) / sizeof(statement[0]) ) ) //計算總行數(shù)
TCHAR *statement[] = {
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運。”),
TEXT(“偉人之所以偉大,是因為他與別人共處逆境時,別人失去了信心,他卻下決心實現(xiàn)自己的目標。”),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“當你感到悲哀痛苦時,最好是去學些什么東西。學習會使你永遠立于不敗之地。”),
TEXT(“給自己定目標,一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運。破罐子破摔只能和懦弱做朋友。”),
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個方向去實現(xiàn)。而不是無所事事和做一些無謂的事。”),
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠得不到寧靜,直到夢想成為事實。”),
TEXT(“夢是一種欲望,想是一種行動。夢想是夢與想的結晶。”),
TEXT(“生氣,就是拿別人的過錯來懲罰自己。原諒別人,就是善待自己。”),
TEXT(“一個實現(xiàn)夢想的人,就是一個成功的人。”),
TEXT(“大事堅持原則,小事學會變通。”),
TEXT(“一個人有錢沒錢不一定,但如果這個人沒有了夢想,這個人窮定了。”),
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對你揣摸猜測。謹慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評和非議。如果這些決定是以失敗告終,你就會更加倒霉。”),
TEXT(“平凡樸實的夢想,我們用那唯一的堅持信念去支撐那夢想。”),
TEXT(“不要總談論自己你若總是談論自己,那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)。”),
TEXT(“千萬不要抱怨,抱怨會使你丟丑。抱怨會使人對你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚他人。”),
TEXT(“凡事終了時務必小心謹慎,順利抽身退出要比順利地進入時更難。”),
TEXT(“很難說什么是辦不到的事情,因為昨天的夢想,可以是今天的希望,并且還可以成為明天的現(xiàn)實。”),
TEXT(“當你再也沒有什么可以失去的時候,就是你開始得到的時候。”),
TEXT(“生命猶如一片綠葉,隨著時間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見。”),
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事。”),
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌。”),
TEXT(“一個人想平庸,阻攔者很少;一個人想出眾,阻攔者很多。不少平庸者與周圍人關系融洽,不少出眾者與周圍人關系緊張。”),
TEXT("“危機”兩個字,一個意味著危險,另外一個意味著機會,不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達。”),
TEXT(“有志者自有千計萬計,無志者只感千難萬難。”),
TEXT(“成功與不成功之間有時距離很短只要后者再向前幾步。”),
TEXT(“世界會向那些有目標和遠見的人讓路。”),
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當你的思維以最高速度運轉時,樂觀歡快的情緒就會充斥全身。一個人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的。學會讓自己安靜,把思維沉浸下來,慢慢降低對事物的欲望。把自我經(jīng)常歸零,每天都是新的起點,沒有年齡的限制,只要你對事物的欲望適當?shù)慕档?#xff0c;會贏得更多的求勝機會。”),
TEXT(“學會讓自己安靜,把思維沉浸下來,慢慢降低對事物的欲望。把自我經(jīng)常歸零,每天都是新的起點,沒有年齡的限制,只要你對事物的欲望適當?shù)慕档?#xff0c;會贏得更多的求勝機會。”),
TEXT(“楊瀾:年輕時候應該能夠作一些冒險。年輕時候最大的財富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯誤的機會。”),
TEXT(“沒有十全十美的東西,沒有十全十美的人,關鍵是清楚到底想要什么。得到想要的,肯定會失去另外一部分。如果什么都想要,只會什么都得不到。”),
TEXT(“做自己的決定。然后準備好承擔后果。從一開始就提醒自己,世上沒有后悔藥吃。”),
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當你回首看時,你就會知道這絕對是真的。”),
TEXT(“不為模糊不清的未來擔憂,只為清清楚楚的現(xiàn)在努力。”),
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運。”),
TEXT(“偉人之所以偉大,是因為他與別人共處逆境時,別人失去了信心,他卻下決心實現(xiàn)自己的目標。”),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“當你感到悲哀痛苦時,最好是去學些什么東西。學習會使你永遠立于不敗之地。”),
TEXT(“給自己定目標,一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運。破罐子破摔只能和懦弱做朋友。”),
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個方向去實現(xiàn)。而不是無所事事和做一些無謂的事。”),
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠得不到寧靜,直到夢想成為事實。”),
TEXT(“夢是一種欲望,想是一種行動。夢想是夢與想的結晶。”),
TEXT(“生氣,就是拿別人的過錯來懲罰自己。原諒別人,就是善待自己。生氣,就是拿別人的過錯來懲罰自己。原諒別人,就是善待自己。生氣,就是拿別人的過錯來懲罰自己。”),
TEXT(“一個實現(xiàn)夢想的人,就是一個成功的人。”),
TEXT(“大事堅持原則,小事學會變通。”),
TEXT(“一個人有錢沒錢不一定,但如果這個人沒有了夢想,這個人窮定了。”),
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對你揣摸猜測。謹慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評和非議。”),
TEXT(“平凡樸實的夢想,我們用那唯一的堅持信念去支撐那夢想。”),
TEXT(“不要總談論自己你若總是談論自己,那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)。”),
TEXT(“千萬不要抱怨,抱怨會使你丟丑。抱怨會使人對你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚他人。”),
TEXT(“凡事終了時務必小心謹慎,順利抽身退出要比順利地進入時更難。”),
TEXT(“很難說什么是辦不到的事情,因為昨天的夢想,可以是今天的希望,并且還可以成為明天的現(xiàn)實。”),
TEXT(“當你再也沒有什么可以失去的時候,就是你開始得到的時候。”),
TEXT(“生命猶如一片綠葉,隨著時間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見。”),
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事。”),
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌。”),
TEXT(“一個人想平庸,阻攔者很少;一個人想出眾,阻攔者很多。不少平庸者與周圍人關系融洽,不少出眾者與周圍人關系緊張。”),
TEXT("“危機”兩個字,一個意味著危險,另外一個意味著機會,不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達。”),
TEXT(“有志者自有千計萬計,無志者只感千難萬難。”),
TEXT(“成功與不成功之間有時距離很短只要后者再向前幾步。”),
TEXT(“世界會向那些有目標和遠見的人讓路。”),
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當你的思維以最高速度運轉時,樂觀歡快的情緒就會充斥全身。一個人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的。”),
TEXT(“學會讓自己安靜,把思維沉浸下來,慢慢降低對事物的欲望。把自我經(jīng)常歸零,每天都是新的起點,沒有年齡的限制,只要你對事物的欲望適當?shù)慕档?#xff0c;會贏得更多的求勝機會。”),
TEXT(“楊瀾:年輕時候應該能夠作一些冒險。年輕時候最大的財富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯誤的機會。”),
TEXT(“沒有十全十美的東西,沒有十全十美的人,關鍵是清楚到底想要什么。得到想要的,肯定會失去另外一部分。如果什么都想要,只會什么都得不到。”),
TEXT(“做自己的決定。然后準備好承擔后果。從一開始就提醒自己,世上沒有后悔藥吃。”),
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當你回首看時,你就會知道這絕對是真的。”),
TEXT(“不為模糊不清的未來擔憂,只為清清楚楚的現(xiàn)在努力。”),
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運。”),
TEXT(“偉人之所以偉大,是因為他與別人共處逆境時,別人失去了信心,他卻下決心實現(xiàn)自己的目標。”),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“當你感到悲哀痛苦時,最好是去學些什么東西。學習會使你永遠立于不敗之地。”),
TEXT(“給自己定目標,一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運。破罐子破摔只能和懦弱做朋友。”),
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個方向去實現(xiàn)。而不是無所事事和做一些無謂的事。”),
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠得不到寧靜,直到夢想成為事實。”),
TEXT(“夢是一種欲望,想是一種行動。夢想是夢與想的結晶。”),
TEXT(“生氣,就是拿別人的過錯來懲罰自己。原諒別人,就是善待自己。”),
TEXT(“一個實現(xiàn)夢想的人,就是一個成功的人。”),
TEXT(“大事堅持原則,小事學會變通。”),
TEXT(“一個人有錢沒錢不一定,但如果這個人沒有了夢想,這個人窮定了。”),
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對你揣摸猜測。謹慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評和非議。如果這些決定是以失敗告終,你就會更加倒霉。”),
TEXT(“平凡樸實的夢想,我們用那唯一的堅持信念去支撐那夢想。”),
TEXT(“不要總談論自己你若總是談論自己,那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)。”),
TEXT(“千萬不要抱怨,抱怨會使你丟丑。抱怨會使人對你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚他人。”),
TEXT(“凡事終了時務必小心謹慎,順利抽身退出要比順利地進入時更難。”),
TEXT(“很難說什么是辦不到的事情,因為昨天的夢想,可以是今天的希望,并且還可以成為明天的現(xiàn)實。”),
TEXT(“當你再也沒有什么可以失去的時候,就是你開始得到的時候。”),
TEXT(“生命猶如一片綠葉,隨著時間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見。”),
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事。”),
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌。”),
TEXT(“一個人想平庸,阻攔者很少;一個人想出眾,阻攔者很多。不少平庸者與周圍人關系融洽,不少出眾者與周圍人關系緊張。”),
TEXT("“危機”兩個字,一個意味著危險,另外一個意味著機會,不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對處境絕望的人。”),
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達。”),
TEXT(“有志者自有千計萬計,無志者只感千難萬難。”),
TEXT(“成功與不成功之間有時距離很短只要后者再向前幾步。”),
TEXT(“世界會向那些有目標和遠見的人讓路。”),
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當你的思維以最高速度運轉時,樂觀歡快的情緒就會充斥全身。一個人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的。”),
TEXT(“學會讓自己安靜,把思維沉浸下來,慢慢降低對事物的欲望。把自我經(jīng)常歸零,每天都是新的起點,沒有年齡的限制,只要你對事物的欲望適當?shù)慕档?#xff0c;會贏得更多的求勝機會。”),
TEXT(“楊瀾:年輕時候應該能夠作一些冒險。年輕時候最大的財富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯誤的機會。”),
TEXT(“沒有十全十美的東西,沒有十全十美的人,關鍵是清楚到底想要什么。得到想要的,肯定會失去另外一部分。如果什么都想要,只會什么都得不到。”),
TEXT(“做自己的決定。然后準備好承擔后果。從一開始就提醒自己,世上沒有后悔藥吃。”),
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當你回首看時,你就會知道這絕對是真的。”),
TEXT(“不為模糊不清的未來擔憂,只為清清楚楚的現(xiàn)在努力。”)
};
//計算statement所有句子中最長語句的長度
int GetMaxLength()
{
/*
*計算statement所有句子中最長語句的長度
返回值: int GetMaxLength(void) -> int
/
int maxLength = 0 ;
int i ;
for( i = 0; i < NUMLINES; i++ )
{
if( wcslen(statement[i]) > maxLength )
maxLength = wcslen(statement[i]) ;
}
return maxLength ;
}
?
在這個頭文件中, 其中有兩句是十分重要的, 一是計算總行數(shù):
#define NUMLINES ( (int)(sizeof(statement) / sizeof(statement[0]) ) ) //計算總行數(shù)另一個是計算最長串字符個數(shù)的函數(shù)GetMaxLength, 該函數(shù)的定義如下:
int GetMaxLength() {/**計算statement所有句子中最長語句的長度*返回值: int GetMaxLength(void) -> int*/int maxLength = 0 ;int i ;for( i = 0; i < NUMLINES; i++ ){if( wcslen(statement[i]) > maxLength )maxLength = wcslen(statement[i]) ;}return maxLength ; }?
下面編寫我們的源文件,?LearnScroll.c,?先看一下完整的代碼,?稍后我們詳細解釋,?代碼如下:
?
1 #include<windows.h>2 #include"text.h"3 4 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //聲明窗口過程函數(shù)5 6 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )7 {8 static TCHAR szAppName[] = TEXT("LearnScroll") ;9 HWND hwnd ;10 MSG msg ;11 WNDCLASS wndclass ;12 13 //窗口類成員屬性14 wndclass.lpfnWndProc = WndProc ;15 wndclass.style = CS_HREDRAW | CS_VREDRAW ;16 wndclass.hInstance = hInstance ;17 wndclass.lpszClassName = szAppName ;18 wndclass.lpszMenuName = NULL ;19 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) ;20 wndclass.hCursor = LoadCursor(NULL, IDI_APPLICATION) ;21 wndclass.hIcon = LoadIcon(NULL, IDC_ARROW) ;22 wndclass.cbClsExtra = 0 ;23 wndclass.cbWndExtra = 0 ;24 25 //注冊窗口類26 if( !RegisterClass(&wndclass) )27 {28 MessageBox( NULL, TEXT("無法注冊窗口類!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ;29 return 0 ;30 }31 32 //創(chuàng)建窗口33 hwnd = CreateWindow(34 szAppName, TEXT("滾動條示例"),35 WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,36 CW_USEDEFAULT, CW_USEDEFAULT,37 CW_USEDEFAULT, CW_USEDEFAULT,38 NULL, NULL, hInstance, NULL39 ) ;40 41 //顯示窗口42 ShowWindow( hwnd, iCmdShow ) ;43 UpdateWindow( hwnd ) ;44 45 //獲取、翻譯、分發(fā)消息46 while( GetMessage( &msg, NULL, 0, 0 ) )47 {48 TranslateMessage( &msg ) ;49 DispatchMessage( &msg ) ;50 }51 52 return msg.wParam ;53 }54 55 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )56 {57 static int cxChar, cxCaps, cyChar, cyClient, cxClient, iVscrollPos, iHscrollPos ;58 //cxChar:平均字符寬度; cxCaps: 大寫字母平均寬度; cyChar: 字符高; cyClient、cxClient: 客戶區(qū)y、x方向尺寸; 59 //iVscrollPos: 豎直方向滾動條滑塊位置; iHscrollPos: 水平方向滾動條滑塊位置60 61 HDC hdc ;62 RECT rect ; //記錄客戶區(qū)RECT結構63 int i, x, y; //i循環(huán)控制, x記錄水平方向坐標, y豎直方向坐標64 PAINTSTRUCT ps ;65 TEXTMETRIC tm ;66 67 switch(message)68 {69 case WM_CREATE: //處理WM_CREATE消息70 hdc = GetDC(hwnd) ;71 GetTextMetrics( hdc, &tm ) ; //獲取系統(tǒng)字體信息72 cxChar = tm.tmAveCharWidth ; //獲取平均寬度73 cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; //大寫字母平均寬度74 cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符高度75 ReleaseDC( hwnd, hdc );76 77 SetScrollRange( hwnd, SB_VERT, 0, NUMLINES - 1, FALSE ) ; //設置豎直滾動條范圍的最小值和最大值78 SetScrollRange( hwnd, SB_HORZ, 0, GetMaxLength() - 1, FALSE ) ; //設置水平滾動條范圍的最小值和最大值79 SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; //設置豎直滾動條中的滾動按鈕的位置80 SetScrollPos( hwnd, SB_HORZ, iHscrollPos, TRUE ) ; //設置水平定滾動條中的滾動按鈕的位置81 82 return 0 ;83 84 case WM_SIZE: //處理WM_SIZE85 GetClientRect( hwnd, &rect ) ;86 cyClient = rect.bottom ; //得到客戶區(qū)y方向尺寸87 cxClient = rect.right ; //得到客戶區(qū)x方向尺寸88 return 0 ;89 90 case WM_VSCROLL: //處理垂直滾動條消息91 switch( LOWORD(wParam) )92 {93 case SB_LINEUP: //上翻一行94 iVscrollPos -= 1 ;95 break ;96 97 case SB_LINEDOWN: //下翻一行98 iVscrollPos += 1 ;99 break ; 100 101 case SB_PAGEUP: //向上翻一整頁 102 iVscrollPos -= cyClient / cyChar ; 103 break ; 104 105 case SB_PAGEDOWN: //向下翻一整頁 106 iVscrollPos += cyClient / cyChar ; 107 break ; 108 109 case SB_THUMBPOSITION: //拖動滑塊滑塊被放下時 110 iVscrollPos = HIWORD(wParam) ; 111 break ; 112 113 default: 114 break; 115 } 116 iVscrollPos = max( 0, min(iVscrollPos, NUMLINES -1) ) ; 117 if( iVscrollPos != GetScrollPos(hwnd, SB_VERT) ) //當滑塊位置改變時重置滑塊位置 118 { 119 SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; 120 InvalidateRect( hwnd, NULL, TRUE ) ; //使客戶區(qū)無效等待重繪 121 } 122 return 0 ; 123 124 case WM_HSCROLL: //處理水平滾動條消息 125 switch( LOWORD(wParam) ) 126 { 127 case SB_LINELEFT: //左翻一行 128 iHscrollPos -= 1 ; 129 break ; 130 131 case SB_LINERIGHT: //右翻一行 132 iHscrollPos += 1 ; 133 break ; 134 135 case SB_PAGELEFT: //左翻一頁 136 iHscrollPos -= cxClient / cxCaps ; 137 break ; 138 139 case SB_PAGERIGHT: //右翻一頁 140 iHscrollPos += cxClient / cxCaps ; 141 break ; 142 143 case SB_THUMBPOSITION: //拖動滑塊滑塊被放下時 144 iHscrollPos = HIWORD(wParam) ; 145 break ; 146 147 default: 148 break ; 149 } 150 iHscrollPos = max( 0, min( iHscrollPos, GetMaxLength() -1 ) ) ; 151 if( iHscrollPos != GetScrollPos( hwnd, SB_HORZ ) ) 152 { 153 SetScrollPos( hwnd, SB_HORZ, iHscrollPos, TRUE ) ; 154 InvalidateRect( hwnd, NULL, TRUE ) ; 155 } 156 return 0 ; 157 158 case WM_PAINT: //處理WM_PAINT消息 159 hdc = BeginPaint( hwnd, &ps ) ; 160 161 for( i= 0; i < NUMLINES; i++ ) 162 { 163 y = cyChar * ( i -iVscrollPos ) ; 164 x = cxCaps * ( 0 - iHscrollPos ) ; 165 TextOut( hdc, x, y, statement[i], lstrlen(statement[i]) ) ; //輸出文字 166 } 167 168 EndPaint( hwnd, &ps ) ; 169 return 0 ; 170 171 case WM_DESTROY: //處理WM_DESTROY消息 172 PostQuitMessage( 0 ) ; 173 return 0 ; 174 } 175 176 return DefWindowProc( hwnd, message, wParam, lParam ) ; 177 }?
編譯運行,?看下成果:
?
看起來還算不錯,?當滾動條向下翻時文字就隨著向上滾動,?使下面的文字能夠顯示出來,?水平的滾動條也是這樣,?下面詳細說說重點部分的代碼:
1>. 創(chuàng)建一個帶有垂直滾動條以及水平滾動條的窗口:
hwnd = CreateWindow(szAppName, TEXT("滾動條示例"),WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL) ;
2>.?設置垂直滾動條、水平滾動條的范圍以及初始位置:
SetScrollRange( hwnd, SB_VERT, 0, NUMLINES - 1, FALSE ) ; //設置垂直滾動條范圍的最小值和最大值SetScrollRange( hwnd, SB_HORZ, 0, GetMaxLength() - 1, FALSE ) ; //設置水平滾動條范圍的最小值和最大值SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; //設置垂直滾動條中的滾動按鈕的位置SetScrollPos( hwnd, SB_HORZ, iHscrollPos, TRUE ) ; //設置水平定滾動條中的滾動按鈕的位置可以看出,?垂直滾動條的范圍為0到行數(shù)-1,?這就意味這,?每下翻/上翻一個單位,?客戶區(qū)顯示的文字就會向上//向下滾動一行;?
水平滾動條的范圍為0到最長那行文字的長度-1, 每左翻/右翻一個單位,?客戶區(qū)顯示的文字就會向右//向左滾動一個字符的寬度。
?
3>.?當窗口大小調整時重新獲取客戶區(qū)尺寸數(shù)據(jù):
case WM_SIZE: //處理WM_SIZEGetClientRect( hwnd, &rect ) ;cyClient = rect.bottom ; //得到客戶區(qū)y方向尺寸cxClient = rect.right ; //得到客戶區(qū)x方向尺寸return 0 ;?
4>. 處理滾動條消息:
case WM_VSCROLL: //處理水平滾動條消息switch( LOWORD(wParam) ){case 滾動條消息:[處理滾動條消息]}?
5>. 重置滾動條滑塊位置:
iVscrollPos = max( 0, min(iVscrollPos, NUMLINES -1) ) ; //確保滾動條的位置在設置的范圍內(nèi)。 <span style="color: #0000ff;">if</span>( iVscrollPos != GetScrollPos(hwnd, SB_VERT) ) <span style="color: #008000;">//</span><span style="color: #008000;">當滑塊位置改變時重置滑塊位置</span> {
SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ;
InvalidateRect( hwnd, NULL, TRUE ) ; //使客戶區(qū)無效等待重繪
}
return 0 ;
這一句注釋上已經(jīng)描述的是否清楚了,?當滑塊位置改變時重置滑塊位置并使客戶區(qū)無效等待重繪。
?
6>. 處理重繪消息:
case WM_PAINT: //處理WM_PAINT消息hdc = BeginPaint( hwnd, &ps ) ; </span><span style="color: #0000ff;">for</span>( i= <span style="color: #800080;">0</span>; i < NUMLINES; i++<span style="color: #000000;"> ){y </span>= cyChar * ( i -<span style="color: #000000;">iVscrollPos ) ;x </span>= cxCaps * ( <span style="color: #800080;">0</span> -<span style="color: #000000;"> iHscrollPos ) ;TextOut( hdc, x, y, statement[i], lstrlen(statement[i]) ) ; </span><span style="color: #008000;">//</span><span style="color: #008000;">輸出文字</span>}
EndPaint( hwnd, </span>&<span style="color: #000000;">ps ) ;</span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span> ;</pre>?
目的是重繪客戶區(qū)內(nèi)容并使其有效,?注意這里的
y = cyChar * ( i -iVscrollPos ) ;x = cxCaps * ( 0 - iHscrollPos ) ;這是計算從起始輸出的坐標,?每行對應一個y值,?當滑塊的位置向下滾動1時,?y的值就會減去一個字符的高度,?使該行顯示到窗口外部,?這樣新的一行就會被顯示出來,?同樣,?翻動一整夜的計算思路同一行;?x是指水平起始輸出位置,?計算思路相同。
?
這樣,?一個簡單的帶有滾動條的窗口就完成了! 看起來挺不錯的, 不是嗎? 可以先稍微休息一下, 下面我們還有事要做。
?
?
但這還不夠好!
在上面我們使用的滾動條中,?雖說能夠滾動文字,?但是依然存在許多小問題:
問題一:?滑塊的大小是固定的,?而我見到的應用軟件滑塊能夠根據(jù)內(nèi)容的多少自動調整滑塊大小;
問題二:?當我拖動滑塊時只有當滑塊釋放時頁面才會滾動,?我想要的是當滑塊被拖動時頁面也同樣跟著滾動;
問題三:?當滑塊滾動到底部時最后一行顯示到了客戶區(qū)頂部,?下面留有一大片的空白,?而我并不需要保留下面的空白,?也就是說最后一行在滑塊拖動到底部后它只顯示在底部就行。
?
幸運的是, 我們依然有解決方案:
問題一: 自行設置滑塊的大小;
?問題二:?根據(jù)SB_THUMBTRACK消息處理頁面的滾動,?SB_THUMBTRACK消息是當滑塊被拖動時就會源源不斷的發(fā)來;
? ? ?問題三:?重新設置滾動的范圍。
?
?
?
更好的滾動條:
在使用更好的滾動條之前我們首先要認識三個新函數(shù):?SetScrollInfo、GetScrollInfo以及ScrollWindow.
1>.?SetScrollInfo
函數(shù)功能:?用于設置滾動條的相關參數(shù),?包括滾動范圍的最大值和最小值,?頁面大小,?滑塊的位置,?函數(shù)的原型:
int SetScrollInfo(HWND hWnd; //窗口句柄int fnBar, //指定被設定參數(shù)的滾動條的類型LPSCROLLINFO lpsi, //指向一個SCROLLINFO結構BOOL fRedraw //重繪標志) ;穿插講述: 什么是SCROLLINFO結構?
SCROLLINFO的成員記錄有關滾動條的信息,?其結構定義如下:
typedef struct tagSCROLLINFO { UINT cbSize ; //設置為sizeof (SCROLLINFO), 表示該結構的大小UINT fMask ; //要設置或獲取的值int nMin ; //滾動條范圍的最小值int nMax ; //滾動條范圍的最大值UINT nPage ; //頁面大小int nPos ; //當前位置 int nTrackPos ; //當前追蹤位置 }SCROLLINFO;成員一UINT?cbSize?:??該參數(shù)必須在函數(shù)調用之前設置,??cbSize表示該結構的大小,?用sizeof?(SCROLLINFO)表示即可。
成員二UINT?fMask:?用于指定指定結構中的哪些成員是有效的,?通過位或運算進行組合,?可組合的標識符如下:
SIF_ALL //整個結構都有效SIF_DISABLENOSCROLL //禁用滾動條SIF_PAGE //用于指定或獲取頁面的大小, 在SetScrollInfo中用于設定頁面的大小, 在GetScrollInfo用于獲取頁面的大小
SIF_POS //設置/取得滾動條滑塊當前的位置
SIF_RANGE //滾動條的范圍SIF_TRACKPOS //僅在GetScrollInfo函數(shù)中使用, 并且僅用在處理SB_THUMBTRACK或者SB_THUMBPOSITION的WM_VSCROLL消息或WM_HSCROLL消息時使用。取得當前滑塊的跟蹤位置。
?? 穿插講述完畢! 繼續(xù)講解第二個新函數(shù)。
?
2>.?GetScrollInfo
用于取得滾動條的相關參數(shù),?包括滾動范圍的最大值和最小值,?頁面大小,?滑塊的位置,?函數(shù)的原型:
BOOL GetScrollInfo( HWND hWnd, //窗口句柄int fnBar, //指定被設定參數(shù)的滾動條的類型LPSCROLLINFO lpsi //指向一個SCROLLINFO結構);?
3>.?ScrollWindow
該函數(shù)的作用是滾動所指定的窗口客戶區(qū)域內(nèi)容,?原型如下:
BOOL ScrollWindow(HWND hWnd, //窗口句柄int XAmount, //指定水平滾動的距離int YAmount, //指定垂直滾動的距離CONST RECT *IpRect, //指向RECT結構的指針, 該結構指定了將要滾動的客戶區(qū)范圍。若此參數(shù)為NULL,則整個客戶區(qū)域將被滾動。 CONST RECT *lpClipRect //指向RECT結構的指針, 該結構指定了要滾動的裁剪區(qū)域。只有這個矩形中才會被滾動。 );好了,?說的差不多夠多了,?研究代碼才是更好的溝通方式,?下面我們實際實踐一下更好的滾動條,?更多的細節(jié)請在代碼中體會, 限于篇幅的長度, 這里將WinMain函數(shù)折疊顯示, 僅將窗口過程函數(shù)部分的代碼全部顯示出來:
View Code - Function - WinMain 1 #include<windows.h>2 #include"text.h"3 4 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //聲明窗口過程函數(shù)5 6 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )7 {8 static TCHAR szAppName[] = TEXT("LearnScroll") ;9 HWND hwnd ; 10 MSG msg ; 11 WNDCLASS wndclass ; 12 13 //窗口類成員屬性 14 wndclass.lpfnWndProc = WndProc ; 15 wndclass.style = CS_HREDRAW | CS_VREDRAW ; 16 wndclass.hInstance = hInstance ; 17 wndclass.lpszClassName = szAppName ; 18 wndclass.lpszMenuName = NULL ; 19 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) ; 20 wndclass.hCursor = LoadCursor(NULL, IDI_APPLICATION) ; 21 wndclass.hIcon = LoadIcon(NULL, IDC_ARROW) ; 22 wndclass.cbClsExtra = 0 ; 23 wndclass.cbWndExtra = 0 ; 24 25 //注冊窗口類 26 if( !RegisterClass(&wndclass) ) 27 { 28 MessageBox( NULL, TEXT("無法注冊窗口類!"), TEXT("錯誤"), MB_OK | MB_ICONERROR ) ; 29 return 0 ; 30 } 31 32 //創(chuàng)建窗口 33 hwnd = CreateWindow( 34 szAppName, TEXT("滾動條示例"), 35 WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, 36 CW_USEDEFAULT, CW_USEDEFAULT, 37 CW_USEDEFAULT, CW_USEDEFAULT, 38 NULL, NULL, hInstance, NULL 39 ) ; 40 41 //顯示窗口 42 ShowWindow( hwnd, iCmdShow ) ; 43 UpdateWindow( hwnd ) ; 44 45 //獲取、翻譯、分發(fā)消息 46 while( GetMessage( &msg, NULL, 0, 0 ) ) 47 { 48 TranslateMessage( &msg ) ; 49 DispatchMessage( &msg ) ; 50 } 51 52 return msg.wParam ; 53 }?
窗口過程部分的代碼:
1 LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )2 {3 static int cxChar, cxCaps, cyChar, cyClient, cxClient, iVscrollPos, iHscrollPos ;4 //cxChar:平均字符寬度; cxCaps: 大寫字母平均寬度; cyChar: 字符高; cyClient、cxClient: 客戶區(qū)y、x方向尺寸; 5 //iVscrollPos: 豎直方向滾動條滑塊位置; iHscrollPos: 水平方向滾動條滑塊位置6 HDC hdc ;7 RECT rect ; //記錄客戶區(qū)RECT結構8 int i, x, y; //i循環(huán)控制, x記錄水平方向坐標, y豎直方向坐標9 PAINTSTRUCT ps ;10 TEXTMETRIC tm ;11 SCROLLINFO si ; //SCROLLINFO結構對象12 int iMaxLength ; //所有語句中的最大長度13 14 iMaxLength = GetMaxLength() ; //取得最大長度15 16 switch(message)17 {18 case WM_CREATE: //處理WM_CREATE消息19 hdc = GetDC(hwnd) ;20 GetTextMetrics( hdc, &tm ) ; //獲取系統(tǒng)字體信息21 cxChar = tm.tmAveCharWidth ; //獲取平均寬度22 cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ; //大寫字母平均寬度23 cyChar = tm.tmHeight + tm.tmExternalLeading ; //字符高度24 ReleaseDC( hwnd, hdc );2526 return 0 ;27 28 case WM_SIZE: //處理WM_SIZE29 GetClientRect( hwnd, &rect ) ;30 cxClient = LOWORD (lParam) ;31 cyClient = HIWORD (lParam) ;32 33 //設置垂直滾動條相關參數(shù)34 si.cbSize = sizeof (si) ;35 si.fMask = SIF_RANGE | SIF_PAGE ;36 si.nMin = 0 ;37 si.nMax = NUMLINES - 1 ;38 si.nPage = cyClient / cyChar ;39 SetScrollInfo(hwnd, SB_VERT, &si, TRUE) ;40 41 //設置水平滾動條相關參數(shù)42 si.cbSize = sizeof (si) ;43 si.fMask = SIF_RANGE | SIF_PAGE ;44 si.nMin = 0 ;45 si.nMax = 2 + iMaxLength ;46 si.nPage = cxClient / cxCaps ;47 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE) ;48 49 return 0 ;50 51 case WM_VSCROLL: //處理垂直滾動條消息52 si.cbSize = sizeof (si) ;53 si.fMask = SIF_ALL ;54 GetScrollInfo(hwnd, SB_VERT, &si) ;55 56 iVscrollPos = si.nPos ; //記錄當前滑塊位置57 58 switch( LOWORD(wParam) ) //處理滾動條消息59 {60 case SB_TOP: //到達頂部61 si.nPos = si.nMin ;62 break ;63 64 case SB_BOTTOM: //到達底部65 si.nPos = si.nMax ;66 break ;67 68 case SB_LINEUP: //上翻一行69 si.nPos -= 1 ;70 break ;71 72 case SB_LINEDOWN: //下翻一行73 si.nPos += 1 ;74 break ;75 76 case SB_PAGEUP: //向上翻一整頁77 si.nPos -= si.nPage ;78 break ;79 80 case SB_PAGEDOWN: //向下翻一整頁81 si.nPos += si.nPage ;82 break ;83 84 case SB_THUMBTRACK: //移動滑塊時85 si.nPos = si.nTrackPos ;86 break ;87 88 default:89 break;90 }91 si.fMask = SIF_POS ;92 SetScrollInfo(hwnd, SB_VERT, &si, TRUE) ; //重置滑塊位置93 GetScrollInfo(hwnd, SB_VERT, &si) ;94 if( si.nPos != iVscrollPos )95 {96 ScrollWindow(hwnd, 0, cyChar * (iVscrollPos - si.nPos), NULL, NULL) ; //滾動內(nèi)容97 UpdateWindow(hwnd) ;98 }99 return 0 ; 100 101 case WM_HSCROLL: //處理水平滾動條消息 102 si.cbSize = sizeof (si) ; 103 si.fMask = SIF_ALL ; 104 GetScrollInfo (hwnd, SB_HORZ, &si) ; 105 106 iHscrollPos = si.nPos ; //記錄當前滑塊位置 107 switch( LOWORD(wParam) ) 108 { 109 case SB_TOP: //到達頂部 110 si.nPos = si.nMin ; 111 break ; 112 113 case SB_BOTTOM: //到達底部 114 si.nPos = si.nMax ; 115 break ; 116 117 case SB_LINELEFT: //左翻一行 118 si.nPos -= 1 ; 119 break ; 120 121 case SB_LINERIGHT: //右翻一行 122 si.nPos += 1 ; 123 break ; 124 125 case SB_PAGELEFT: //左翻一頁 126 si.nPos -= si.nPage ; 127 break ; 128 129 case SB_PAGERIGHT: //右翻一頁 130 si.nPos += si.nPage ; 131 break ; 132 133 case SB_THUMBTRACK: //移動滑塊時 134 si.nPos = si.nTrackPos ; 135 break ; 136 137 default: 138 break ; 139 } 140 si.fMask = SIF_POS ; 141 SetScrollInfo(hwnd, SB_HORZ, &si, TRUE) ; //重置滑塊位置 142 GetScrollInfo(hwnd, SB_HORZ, &si) ; 143 if( si.nPos != iHscrollPos ) 144 { 145 ScrollWindow(hwnd, cxCaps * (iHscrollPos - si.nPos), 0, NULL, NULL) ; //滾動內(nèi)容 146 UpdateWindow(hwnd) ; 147 } 148 return 0 ; 149 150 case WM_PAINT: //處理WM_PAINT消息 151 hdc = BeginPaint( hwnd, &ps ) ; 152 153 si.cbSize = sizeof (si) ; 154 si.fMask = SIF_POS ; 155 GetScrollInfo(hwnd, SB_VERT, &si) ; 156 iVscrollPos = si.nPos ; //獲取當前垂直滑塊位置 157 158 GetScrollInfo(hwnd, SB_HORZ, &si) ; 159 iHscrollPos = si.nPos ; //獲取當前水平滑塊位置 160 161 for( i= 0; i < NUMLINES; i++ ) 162 { 163 y = cyChar * ( i - iVscrollPos ) ; 164 x = cxCaps * ( 0 - iHscrollPos ) ; 165 TextOut( hdc, x, y, statement[i], lstrlen(statement[i]) ) ; //輸出文字 166 } 167 168 EndPaint( hwnd, &ps ) ; 169 return 0 ; 170 171 case WM_DESTROY: //處理WM_DESTROY消息 172 PostQuitMessage( 0 ) ; 173 return 0 ; 174 } 175 176 return DefWindowProc( hwnd, message, wParam, lParam ) ; 177 }?
看一下成果:
嗯, 這樣看起來就好多了, 如果嫌行間距太擠的話我們可以調節(jié)字符的高度
使行間距增大些, 這樣看起來會更舒服。
好了, 到這里,?一個較為完善的滾動條就完成了。
?
--------------------
?
wid, 2012.10.31
?
總結
- 上一篇: 教你羊肉炒菠菜的做法
- 下一篇: C语言(标识符)