滚动条详解
對(duì)上一天學(xué)習(xí)的回顧:
1>.??TextOut函數(shù)的使用
TextOut函數(shù)的作用是使用系統(tǒng)當(dāng)前選擇的字體、背景顏色以及正文顏色將一個(gè)字符串輸出到指定位置,?函數(shù)原型:
BOOL TextOut(HDC hdc, //設(shè)備環(huán)境句柄int nXStart, //字符串開始輸出的x坐標(biāo)int nYStart, // 字符串開始輸出的y坐標(biāo) LPCTSTR lpString, //需要輸出的字符串int cbString // 字符串的長度);當(dāng)函數(shù)調(diào)用成功時(shí)返回一個(gè)非零的值,?調(diào)用失敗時(shí),?返回值為0。
?
2>.?取得當(dāng)前系統(tǒng)字體信息:
使用GetTextMetrics函數(shù)可以取得當(dāng)前字體信息,?函數(shù)原型如下:
BOOL GetTextMetrics(HDC hdc, // 設(shè)備環(huán)境句柄LPTEXTMETRIC lptm // 指向一個(gè)TEXTMETRIC結(jié)構(gòu)的指針, 該結(jié)構(gòu)用于存放字體信息。 );參數(shù)二LPTEXTMETRIC指向TEXTMETRIC結(jié)構(gòu),?在函數(shù)調(diào)用成功時(shí),?函數(shù)將系統(tǒng)當(dāng)前字體的各種信息復(fù)制到TEXTMETRIC結(jié)構(gòu)中。
?
?
Windows滾動(dòng)條介紹
滾動(dòng)條由滾動(dòng)滑塊以及兩端的滾動(dòng)箭頭組成,?滾動(dòng)條的作用是當(dāng)需要顯示的內(nèi)容超過窗口客戶區(qū)大小時(shí)提供上下/左右的翻頁使用戶能夠完整的閱讀顯示信息,?滾動(dòng)條的圖示:
?
?
滾動(dòng)條理論基礎(chǔ)
1>.?上下滾動(dòng)?
以垂直方向的滾動(dòng)條為例,?當(dāng)用戶向下滾動(dòng)滾動(dòng)條時(shí)目的是想看到下方更多的的信息,?因此我們需要將下方的信息顯示出來,?如何顯示更多的信息?
解決方案:?將不需要被顯示的信息顯示到客戶區(qū)外,?令信息自動(dòng)被Windows截掉,?圖示說明:
?
由圖示看出,?當(dāng)用戶向下翻動(dòng)滾動(dòng)條實(shí)際上我們是將起始輸出部分的y坐標(biāo)設(shè)為負(fù)數(shù),?使已經(jīng)顯示過的信息輸出到客戶區(qū)的上部,?我們知道,?輸出到客戶區(qū)外部的信息會(huì)被Windows自動(dòng)截掉,?所以用戶不會(huì)再次看到已經(jīng)顯示過的信息,?取而代之的就是下方等待顯示的信息,?上翻以及左右翻動(dòng)的顯示思路與下翻相同,?不再介紹。
?
2>.?如何創(chuàng)建一個(gè)帶有滾動(dòng)條的窗口?
創(chuàng)建帶有水平/垂直的滾動(dòng)條的窗口十分簡單,?在CreateWindow函數(shù)中說明下即可,?CreateWindow函數(shù)的原型回顧:
HWND CreateWindow(LPCTSTR lpClassName, //窗口類名稱LPCTSTR lpWindowName, //窗口標(biāo)題DWORD dwStyle, //窗口樣式int x, //窗口初始x坐標(biāo)int y, //窗口初始y坐標(biāo)int nWidth, //窗口初始x方向尺寸int nHeight, //窗口初始y方向尺寸HWND hWndParent, //父窗口句柄HMENU hMenu, //窗口菜單句柄HANDLE hlnstance, //程序?qū)嵗浔鶯PVOID lpParam //創(chuàng)建參數(shù));要窗口帶有滾動(dòng)條的窗口, 只需要在第三個(gè)參數(shù)
DWORD dwStyle, //窗口樣式? 也就是在窗口樣式的屬性中使用位或(?|?)運(yùn)算對(duì)相關(guān)的標(biāo)識(shí)符進(jìn)行組合即可得到一個(gè)帶有垂直/水平滾動(dòng)條的窗口,
WS_HSCROLL //水平滾動(dòng)條的標(biāo)識(shí)符WS_VSCROLL //垂直滾動(dòng)條的標(biāo)識(shí)符例如要?jiǎng)?chuàng)建一個(gè)既含有垂直滾動(dòng)條又含有水平滾動(dòng)條的組合:
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL?
3>.?對(duì)于滾動(dòng)條,?Windows需要做哪些事?
當(dāng)帶有滾動(dòng)條的窗口創(chuàng)建好后,?Windows就會(huì)做一些必要的處理來協(xié)助我們更好的使用滾動(dòng)條,?Windows需要做的事情如下:
1>.?處理滾動(dòng)條中的所有鼠標(biāo)消息;
2>.?當(dāng)用戶單擊滾動(dòng)條時(shí)提供被單擊部分的輕微閃爍;
3>.?當(dāng)用戶拖動(dòng)滑塊時(shí)在滾動(dòng)條內(nèi)移動(dòng)滑塊;
4>.?當(dāng)窗口大小被調(diào)整時(shí),?自動(dòng)調(diào)整滾動(dòng)條的長度;
5>.?向滾動(dòng)條所在的窗口發(fā)送滾動(dòng)條的相關(guān)消息。
?
?
4>.?我們要做的事情:
相對(duì)于系統(tǒng),?我們需要做的事情已經(jīng)較為輕松了,?主要有4項(xiàng)任務(wù):
1>.?初始化滾動(dòng)條的位置和滾動(dòng)條的范圍;
2>.?處理系統(tǒng)發(fā)來的消息;
3>.?根據(jù)發(fā)來的消息重置滑塊的位置;
4>.?根據(jù)滾動(dòng)條消息重繪客戶區(qū)顯示的內(nèi)容。
?
5>.?將會(huì)收到哪些滾動(dòng)條消息?
滾動(dòng)條消息來源同其他消息一樣,?伴隨著wParam與lParam消息機(jī)制,?當(dāng)窗口為父窗口時(shí)消息的來源為wParam,?此時(shí)可忽略lParam的值,?lParam用于子窗口消息。
wParam參數(shù)分為兩部分,?高位字與低位字,?其中高位字代表用戶松開鼠標(biāo)鍵時(shí)滑塊的最終位置,?低位字上代表鼠標(biāo)在滾動(dòng)條上的動(dòng)作,?以一個(gè)值的形式表現(xiàn)出來,?同樣,?為了方便記憶,?有不同的標(biāo)識(shí)符對(duì)這些值進(jìn)行區(qū)分,?這些標(biāo)識(shí)符定義在WINUSER.H頭文件中,?以SB_開頭,?有關(guān)滾動(dòng)條的消息標(biāo)識(shí)符如下:
#define SB_LINEUP 0 //上翻一個(gè)單位 #define SB_LINELEFT 0 //左翻一個(gè)單位 #define SB_LINEDOWN 1 //下翻一個(gè)單位 #define SB_LINERIGHT 1 //右翻一個(gè)單位 #define SB_PAGEUP 2 //上翻一頁 #define SB_PAGELEFT 2 //左翻一頁 #define SB_PAGEDOWN 3 //下翻一頁 #define SB_PAGERIGHT 3 //右翻一頁 #define SB_THUMBPOSITION 4 //當(dāng)鼠標(biāo)放下滑塊時(shí) #define SB_THUMBTRACK 5 //移動(dòng)滑塊時(shí) #define SB_TOP 6 //滑塊到了頂端 #define SB_LEFT 6 //滑塊到了左端 #define SB_BOTTOM 7 //滑塊到了底端 #define SB_RIGHT 7 //滑塊到了右端 #define SB_ENDSCROLL 8 //釋放鼠標(biāo)?
6>.??需要使用到的新函數(shù):
?、??SetScrollRange
SetScrollRange函數(shù)的作用是設(shè)置所指定滾動(dòng)條范圍的最小值和最大值,?其函數(shù)的原型如下:
BOOL SetScrollRange(HWND hWnd, //窗口句柄int nBar, //被設(shè)置的滾動(dòng)條類型int nMinPos, //滾動(dòng)條的最小位置int nMaxPos, //滾動(dòng)條的最大位置BOOL bRedraw //重繪標(biāo)志);參數(shù)二int?nBar為被設(shè)置的滾動(dòng)條類型,?SB_HORZ表示該窗口的水平滾動(dòng)條,?SB_VERT表示垂直滾動(dòng)條;
參數(shù)四BOOL?bRedraw指定滾動(dòng)條是否被重繪以反映變化,?當(dāng)參數(shù)為TRUE,?滾動(dòng)條被重繪,?FALSE則不被重繪。
?
②.?SetScrollPos
SetScrollPos函數(shù)的作用是設(shè)置所指定滾動(dòng)條中的滾動(dòng)按鈕的位置,?函數(shù)原型:
int SetScrollPos(HWND hWnd, //窗體句柄int nBar, //被設(shè)置的滾動(dòng)條類型int nPos, //滾動(dòng)條的新位置BOOL bRedraw //重繪標(biāo)志);?
?
?
實(shí)戰(zhàn)滾動(dòng)條
下面我們嘗試著輸出一些文字,?使其上下、左右均超過客戶區(qū)的尺寸,?這樣我們就可以實(shí)際練習(xí)下水平滾動(dòng)條以及垂直滾動(dòng)條了,??我們準(zhǔn)備了很多行文字,?筆者也不知道到底有多少行,?而且最長的那行文字有多少個(gè)也不知道,?我們把他放在一個(gè)text.h頭文件中,?并計(jì)算他到底有多少行以及最長的那行有多少字,?由于文字行數(shù)較多,?這里將它在代碼框里折疊顯示,?定義的頭文件如下:
View Code - text.h #include<string.h>#define NUMLINES ( (int)(sizeof(statement) / sizeof(statement[0]) ) ) //計(jì)算總行數(shù)
TCHAR *statement[] = {
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運(yùn)?!?,
TEXT(“偉人之所以偉大,是因?yàn)樗c別人共處逆境時(shí),別人失去了信心,他卻下決心實(shí)現(xiàn)自己的目標(biāo)?!?,
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人?!?,
TEXT(“當(dāng)你感到悲哀痛苦時(shí),最好是去學(xué)些什么東西。學(xué)習(xí)會(huì)使你永遠(yuǎn)立于不敗之地?!?,
TEXT(“給自己定目標(biāo),一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運(yùn)。破罐子破摔只能和懦弱做朋友?!?,
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個(gè)方向去實(shí)現(xiàn)。而不是無所事事和做一些無謂的事?!?,
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠(yuǎn)得不到寧靜,直到夢想成為事實(shí)?!?,
TEXT(“夢是一種欲望,想是一種行動(dòng)。夢想是夢與想的結(jié)晶。”),
TEXT(“生氣,就是拿別人的過錯(cuò)來懲罰自己。原諒別人,就是善待自己。”),
TEXT(“一個(gè)實(shí)現(xiàn)夢想的人,就是一個(gè)成功的人?!?,
TEXT(“大事堅(jiān)持原則,小事學(xué)會(huì)變通。”),
TEXT(“一個(gè)人有錢沒錢不一定,但如果這個(gè)人沒有了夢想,這個(gè)人窮定了?!?,
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對(duì)你揣摸猜測。謹(jǐn)慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評(píng)和非議。如果這些決定是以失敗告終,你就會(huì)更加倒霉。”),
TEXT(“平凡樸實(shí)的夢想,我們用那唯一的堅(jiān)持信念去支撐那夢想。”),
TEXT(“不要總談?wù)撟约耗闳艨偸钦務(wù)撟约?#xff0c;那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)?!?,
TEXT(“千萬不要抱怨,抱怨會(huì)使你丟丑。抱怨會(huì)使人對(duì)你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚(yáng)他人。”),
TEXT(“凡事終了時(shí)務(wù)必小心謹(jǐn)慎,順利抽身退出要比順利地進(jìn)入時(shí)更難。”),
TEXT(“很難說什么是辦不到的事情,因?yàn)樽蛱斓膲粝?#xff0c;可以是今天的希望,并且還可以成為明天的現(xiàn)實(shí)。”),
TEXT(“當(dāng)你再也沒有什么可以失去的時(shí)候,就是你開始得到的時(shí)候?!?,
TEXT(“生命猶如一片綠葉,隨著時(shí)間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見。”),
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事?!?,
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌。”),
TEXT(“一個(gè)人想平庸,阻攔者很少;一個(gè)人想出眾,阻攔者很多。不少平庸者與周圍人關(guān)系融洽,不少出眾者與周圍人關(guān)系緊張?!?,
TEXT("“危機(jī)”兩個(gè)字,一個(gè)意味著危險(xiǎn),另外一個(gè)意味著機(jī)會(huì),不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人。”),
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達(dá)。”),
TEXT(“有志者自有千計(jì)萬計(jì),無志者只感千難萬難?!?,
TEXT(“成功與不成功之間有時(shí)距離很短只要后者再向前幾步?!?,
TEXT(“世界會(huì)向那些有目標(biāo)和遠(yuǎn)見的人讓路?!?,
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當(dāng)你的思維以最高速度運(yùn)轉(zhuǎn)時(shí),樂觀歡快的情緒就會(huì)充斥全身。一個(gè)人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的。學(xué)會(huì)讓自己安靜,把思維沉浸下來,慢慢降低對(duì)事物的欲望。把自我經(jīng)常歸零,每天都是新的起點(diǎn),沒有年齡的限制,只要你對(duì)事物的欲望適當(dāng)?shù)慕档?#xff0c;會(huì)贏得更多的求勝機(jī)會(huì)?!?,
TEXT(“學(xué)會(huì)讓自己安靜,把思維沉浸下來,慢慢降低對(duì)事物的欲望。把自我經(jīng)常歸零,每天都是新的起點(diǎn),沒有年齡的限制,只要你對(duì)事物的欲望適當(dāng)?shù)慕档?#xff0c;會(huì)贏得更多的求勝機(jī)會(huì)。”),
TEXT(“楊瀾:年輕時(shí)候應(yīng)該能夠作一些冒險(xiǎn)。年輕時(shí)候最大的財(cái)富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯(cuò)誤的機(jī)會(huì)?!?,
TEXT(“沒有十全十美的東西,沒有十全十美的人,關(guān)鍵是清楚到底想要什么。得到想要的,肯定會(huì)失去另外一部分。如果什么都想要,只會(huì)什么都得不到。”),
TEXT(“做自己的決定。然后準(zhǔn)備好承擔(dān)后果。從一開始就提醒自己,世上沒有后悔藥吃?!?,
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當(dāng)你回首看時(shí),你就會(huì)知道這絕對(duì)是真的。”),
TEXT(“不為模糊不清的未來擔(dān)憂,只為清清楚楚的現(xiàn)在努力?!?,
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運(yùn)?!?,
TEXT(“偉人之所以偉大,是因?yàn)樗c別人共處逆境時(shí),別人失去了信心,他卻下決心實(shí)現(xiàn)自己的目標(biāo)?!?,
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人?!?,
TEXT(“當(dāng)你感到悲哀痛苦時(shí),最好是去學(xué)些什么東西。學(xué)習(xí)會(huì)使你永遠(yuǎn)立于不敗之地。”),
TEXT(“給自己定目標(biāo),一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運(yùn)。破罐子破摔只能和懦弱做朋友?!?,
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個(gè)方向去實(shí)現(xiàn)。而不是無所事事和做一些無謂的事?!?,
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠(yuǎn)得不到寧靜,直到夢想成為事實(shí)。”),
TEXT(“夢是一種欲望,想是一種行動(dòng)。夢想是夢與想的結(jié)晶?!?,
TEXT(“生氣,就是拿別人的過錯(cuò)來懲罰自己。原諒別人,就是善待自己。生氣,就是拿別人的過錯(cuò)來懲罰自己。原諒別人,就是善待自己。生氣,就是拿別人的過錯(cuò)來懲罰自己?!?,
TEXT(“一個(gè)實(shí)現(xiàn)夢想的人,就是一個(gè)成功的人?!?,
TEXT(“大事堅(jiān)持原則,小事學(xué)會(huì)變通?!?,
TEXT(“一個(gè)人有錢沒錢不一定,但如果這個(gè)人沒有了夢想,這個(gè)人窮定了。”),
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對(duì)你揣摸猜測。謹(jǐn)慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評(píng)和非議?!?,
TEXT(“平凡樸實(shí)的夢想,我們用那唯一的堅(jiān)持信念去支撐那夢想?!?,
TEXT(“不要總談?wù)撟约耗闳艨偸钦務(wù)撟约?#xff0c;那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)?!?,
TEXT(“千萬不要抱怨,抱怨會(huì)使你丟丑。抱怨會(huì)使人對(duì)你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚(yáng)他人?!?,
TEXT(“凡事終了時(shí)務(wù)必小心謹(jǐn)慎,順利抽身退出要比順利地進(jìn)入時(shí)更難?!?,
TEXT(“很難說什么是辦不到的事情,因?yàn)樽蛱斓膲粝?#xff0c;可以是今天的希望,并且還可以成為明天的現(xiàn)實(shí)。”),
TEXT(“當(dāng)你再也沒有什么可以失去的時(shí)候,就是你開始得到的時(shí)候?!?,
TEXT(“生命猶如一片綠葉,隨著時(shí)間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見?!?,
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事?!?,
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌?!?,
TEXT(“一個(gè)人想平庸,阻攔者很少;一個(gè)人想出眾,阻攔者很多。不少平庸者與周圍人關(guān)系融洽,不少出眾者與周圍人關(guān)系緊張?!?,
TEXT("“危機(jī)”兩個(gè)字,一個(gè)意味著危險(xiǎn),另外一個(gè)意味著機(jī)會(huì),不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人?!?,
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達(dá)?!?,
TEXT(“有志者自有千計(jì)萬計(jì),無志者只感千難萬難。”),
TEXT(“成功與不成功之間有時(shí)距離很短只要后者再向前幾步?!?,
TEXT(“世界會(huì)向那些有目標(biāo)和遠(yuǎn)見的人讓路?!?,
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當(dāng)你的思維以最高速度運(yùn)轉(zhuǎn)時(shí),樂觀歡快的情緒就會(huì)充斥全身。一個(gè)人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的?!?,
TEXT(“學(xué)會(huì)讓自己安靜,把思維沉浸下來,慢慢降低對(duì)事物的欲望。把自我經(jīng)常歸零,每天都是新的起點(diǎn),沒有年齡的限制,只要你對(duì)事物的欲望適當(dāng)?shù)慕档?#xff0c;會(huì)贏得更多的求勝機(jī)會(huì)?!?,
TEXT(“楊瀾:年輕時(shí)候應(yīng)該能夠作一些冒險(xiǎn)。年輕時(shí)候最大的財(cái)富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯(cuò)誤的機(jī)會(huì)?!?,
TEXT(“沒有十全十美的東西,沒有十全十美的人,關(guān)鍵是清楚到底想要什么。得到想要的,肯定會(huì)失去另外一部分。如果什么都想要,只會(huì)什么都得不到?!?,
TEXT(“做自己的決定。然后準(zhǔn)備好承擔(dān)后果。從一開始就提醒自己,世上沒有后悔藥吃?!?,
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當(dāng)你回首看時(shí),你就會(huì)知道這絕對(duì)是真的。”),
TEXT(“不為模糊不清的未來擔(dān)憂,只為清清楚楚的現(xiàn)在努力?!?,
TEXT(“沒有一種不通過蔑視、忍受和奮斗就可以征服的命運(yùn)?!?,
TEXT(“偉人之所以偉大,是因?yàn)樗c別人共處逆境時(shí),別人失去了信心,他卻下決心實(shí)現(xiàn)自己的目標(biāo)。”),
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人?!?,
TEXT(“當(dāng)你感到悲哀痛苦時(shí),最好是去學(xué)些什么東西。學(xué)習(xí)會(huì)使你永遠(yuǎn)立于不敗之地。”),
TEXT(“給自己定目標(biāo),一年,兩年,五年,也許你出生不如別人好,通過努力,往往可以改變70%的命運(yùn)。破罐子破摔只能和懦弱做朋友。”),
TEXT(“知道自己要干什么,夜深人靜,問問自己,將來的打算,并朝著那個(gè)方向去實(shí)現(xiàn)。而不是無所事事和做一些無謂的事?!?,
TEXT(“夢想無論怎么模糊,它總潛伏在我們心底,使我們的心境永遠(yuǎn)得不到寧靜,直到夢想成為事實(shí)?!?,
TEXT(“夢是一種欲望,想是一種行動(dòng)。夢想是夢與想的結(jié)晶?!?,
TEXT(“生氣,就是拿別人的過錯(cuò)來懲罰自己。原諒別人,就是善待自己?!?,
TEXT(“一個(gè)實(shí)現(xiàn)夢想的人,就是一個(gè)成功的人。”),
TEXT(“大事堅(jiān)持原則,小事學(xué)會(huì)變通。”),
TEXT(“一個(gè)人有錢沒錢不一定,但如果這個(gè)人沒有了夢想,這個(gè)人窮定了?!?,
TEXT(“不要急于表態(tài)不急于表態(tài)或發(fā)表意見,可以使人對(duì)你揣摸猜測。謹(jǐn)慎的沉默是精明人的幫手。一旦表態(tài),你的決定就容易受到批評(píng)和非議。如果這些決定是以失敗告終,你就會(huì)更加倒霉。”),
TEXT(“平凡樸實(shí)的夢想,我們用那唯一的堅(jiān)持信念去支撐那夢想。”),
TEXT(“不要總談?wù)撟约耗闳艨偸钦務(wù)撟约?#xff0c;那么不是吹噓自己,就是貶低自己;前者是虛榮的表現(xiàn),后者是卑微的表現(xiàn)?!?,
TEXT(“千萬不要抱怨,抱怨會(huì)使你丟丑。抱怨會(huì)使人對(duì)你傲慢無禮,并促使別人如你所抱怨的那么做。要贏得別人的幫助,最好的辦法是表揚(yáng)他人。”),
TEXT(“凡事終了時(shí)務(wù)必小心謹(jǐn)慎,順利抽身退出要比順利地進(jìn)入時(shí)更難?!?,
TEXT(“很難說什么是辦不到的事情,因?yàn)樽蛱斓膲粝?#xff0c;可以是今天的希望,并且還可以成為明天的現(xiàn)實(shí)。”),
TEXT(“當(dāng)你再也沒有什么可以失去的時(shí)候,就是你開始得到的時(shí)候?!?,
TEXT(“生命猶如一片綠葉,隨著時(shí)間的流逝,慢慢變的枯黃,但他的葉脈還是那么清晰可見?!?,
TEXT(“我們可以躲開大家,卻躲不開一只蒼蠅。生活中使我們不快樂的常是一些芝麻小事?!?,
TEXT(“人生的意義不在于拿一手好牌,而在于打好一手壞牌?!?,
TEXT(“一個(gè)人想平庸,阻攔者很少;一個(gè)人想出眾,阻攔者很多。不少平庸者與周圍人關(guān)系融洽,不少出眾者與周圍人關(guān)系緊張。”),
TEXT("“危機(jī)”兩個(gè)字,一個(gè)意味著危險(xiǎn),另外一個(gè)意味著機(jī)會(huì),不要放棄任何一次努力。"),
TEXT(“世上沒有絕望的處境,只有對(duì)處境絕望的人?!?,
TEXT(“再長的路,一步步也能走完,再短的路,不邁開雙腳也無法到達(dá)?!?,
TEXT(“有志者自有千計(jì)萬計(jì),無志者只感千難萬難?!?,
TEXT(“成功與不成功之間有時(shí)距離很短只要后者再向前幾步。”),
TEXT(“世界會(huì)向那些有目標(biāo)和遠(yuǎn)見的人讓路?!?,
TEXT(“世界青睞有雄心壯志的人。成功所依靠的惟一條件就是思考。當(dāng)你的思維以最高速度運(yùn)轉(zhuǎn)時(shí),樂觀歡快的情緒就會(huì)充斥全身。一個(gè)人最完美的作品都是在充滿愉快、樂觀、深情的狀態(tài)下完成的。”),
TEXT(“學(xué)會(huì)讓自己安靜,把思維沉浸下來,慢慢降低對(duì)事物的欲望。把自我經(jīng)常歸零,每天都是新的起點(diǎn),沒有年齡的限制,只要你對(duì)事物的欲望適當(dāng)?shù)慕档?#xff0c;會(huì)贏得更多的求勝機(jī)會(huì)?!?,
TEXT(“楊瀾:年輕時(shí)候應(yīng)該能夠作一些冒險(xiǎn)。年輕時(shí)候最大的財(cái)富,不是你的青春,不是你的美貌,也不是你充沛的精力,而是你有犯錯(cuò)誤的機(jī)會(huì)?!?,
TEXT(“沒有十全十美的東西,沒有十全十美的人,關(guān)鍵是清楚到底想要什么。得到想要的,肯定會(huì)失去另外一部分。如果什么都想要,只會(huì)什么都得不到。”),
TEXT(“做自己的決定。然后準(zhǔn)備好承擔(dān)后果。從一開始就提醒自己,世上沒有后悔藥吃?!?,
TEXT(“在你內(nèi)心深處,還有無窮的潛力,有一天當(dāng)你回首看時(shí),你就會(huì)知道這絕對(duì)是真的?!?,
TEXT(“不為模糊不清的未來擔(dān)憂,只為清清楚楚的現(xiàn)在努力?!?
};
//計(jì)算statement所有句子中最長語句的長度
int GetMaxLength()
{
/*
*計(jì)算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 ;
}
?
在這個(gè)頭文件中, 其中有兩句是十分重要的, 一是計(jì)算總行數(shù):
#define NUMLINES ( (int)(sizeof(statement) / sizeof(statement[0]) ) ) //計(jì)算總行數(shù)另一個(gè)是計(jì)算最長串字符個(gè)數(shù)的函數(shù)GetMaxLength, 該函數(shù)的定義如下:
int GetMaxLength() {/**計(jì)算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,?先看一下完整的代碼,?稍后我們?cè)敿?xì)解釋,?代碼如下:
?
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 //注冊(cè)窗口類26 if( !RegisterClass(&wndclass) )27 {28 MessageBox( NULL, TEXT("無法注冊(cè)窗口類!"), TEXT("錯(cuò)誤"), MB_OK | MB_ICONERROR ) ;29 return 0 ;30 }31 32 //創(chuàng)建窗口33 hwnd = CreateWindow(34 szAppName, TEXT("滾動(dòng)條示例"),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: 豎直方向滾動(dòng)條滑塊位置; iHscrollPos: 水平方向滾動(dòng)條滑塊位置60 61 HDC hdc ;62 RECT rect ; //記錄客戶區(qū)RECT結(jié)構(gòu)63 int i, x, y; //i循環(huán)控制, x記錄水平方向坐標(biāo), y豎直方向坐標(biāo)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 ) ; //設(shè)置豎直滾動(dòng)條范圍的最小值和最大值78 SetScrollRange( hwnd, SB_HORZ, 0, GetMaxLength() - 1, FALSE ) ; //設(shè)置水平滾動(dòng)條范圍的最小值和最大值79 SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; //設(shè)置豎直滾動(dòng)條中的滾動(dòng)按鈕的位置80 SetScrollPos( hwnd, SB_HORZ, iHscrollPos, TRUE ) ; //設(shè)置水平定滾動(dòng)條中的滾動(dòng)按鈕的位置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: //處理垂直滾動(dòng)條消息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: //拖動(dòng)滑塊滑塊被放下時(shí) 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) ) //當(dāng)滑塊位置改變時(shí)重置滑塊位置 118 { 119 SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; 120 InvalidateRect( hwnd, NULL, TRUE ) ; //使客戶區(qū)無效等待重繪 121 } 122 return 0 ; 123 124 case WM_HSCROLL: //處理水平滾動(dòng)條消息 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: //拖動(dòng)滑塊滑塊被放下時(shí) 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 }?
編譯運(yùn)行,?看下成果:
?
看起來還算不錯(cuò),?當(dāng)滾動(dòng)條向下翻時(shí)文字就隨著向上滾動(dòng),?使下面的文字能夠顯示出來,?水平的滾動(dòng)條也是這樣,?下面詳細(xì)說說重點(diǎn)部分的代碼:
1>. 創(chuàng)建一個(gè)帶有垂直滾動(dòng)條以及水平滾動(dòng)條的窗口:
hwnd = CreateWindow(szAppName, TEXT("滾動(dòng)條示例"),WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance, NULL) ;
2>.?設(shè)置垂直滾動(dòng)條、水平滾動(dòng)條的范圍以及初始位置:
SetScrollRange( hwnd, SB_VERT, 0, NUMLINES - 1, FALSE ) ; //設(shè)置垂直滾動(dòng)條范圍的最小值和最大值SetScrollRange( hwnd, SB_HORZ, 0, GetMaxLength() - 1, FALSE ) ; //設(shè)置水平滾動(dòng)條范圍的最小值和最大值SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ; //設(shè)置垂直滾動(dòng)條中的滾動(dòng)按鈕的位置SetScrollPos( hwnd, SB_HORZ, iHscrollPos, TRUE ) ; //設(shè)置水平定滾動(dòng)條中的滾動(dòng)按鈕的位置可以看出,?垂直滾動(dòng)條的范圍為0到行數(shù)-1,?這就意味這,?每下翻/上翻一個(gè)單位,?客戶區(qū)顯示的文字就會(huì)向上//向下滾動(dòng)一行;?
水平滾動(dòng)條的范圍為0到最長那行文字的長度-1, 每左翻/右翻一個(gè)單位,?客戶區(qū)顯示的文字就會(huì)向右//向左滾動(dòng)一個(gè)字符的寬度。
?
3>.?當(dāng)窗口大小調(diào)整時(shí)重新獲取客戶區(qū)尺寸數(shù)據(jù):
case WM_SIZE: //處理WM_SIZEGetClientRect( hwnd, &rect ) ;cyClient = rect.bottom ; //得到客戶區(qū)y方向尺寸cxClient = rect.right ; //得到客戶區(qū)x方向尺寸return 0 ;?
4>. 處理滾動(dòng)條消息:
case WM_VSCROLL: //處理水平滾動(dòng)條消息switch( LOWORD(wParam) ){case 滾動(dòng)條消息:[處理滾動(dòng)條消息]}?
5>. 重置滾動(dòng)條滑塊位置:
iVscrollPos = max( 0, min(iVscrollPos, NUMLINES -1) ) ; //確保滾動(dòng)條的位置在設(shè)置的范圍內(nèi)。 <span style="color: #0000ff;">if</span>( iVscrollPos != GetScrollPos(hwnd, SB_VERT) ) <span style="color: #008000;">//</span><span style="color: #008000;">當(dāng)滑塊位置改變時(shí)重置滑塊位置</span> {
SetScrollPos( hwnd, SB_VERT, iVscrollPos, TRUE ) ;
InvalidateRect( hwnd, NULL, TRUE ) ; //使客戶區(qū)無效等待重繪
}
return 0 ;
這一句注釋上已經(jīng)描述的是否清楚了,?當(dāng)滑塊位置改變時(shí)重置滑塊位置并使客戶區(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 ) ;這是計(jì)算從起始輸出的坐標(biāo),?每行對(duì)應(yīng)一個(gè)y值,?當(dāng)滑塊的位置向下滾動(dòng)1時(shí),?y的值就會(huì)減去一個(gè)字符的高度,?使該行顯示到窗口外部,?這樣新的一行就會(huì)被顯示出來,?同樣,?翻動(dòng)一整夜的計(jì)算思路同一行;?x是指水平起始輸出位置,?計(jì)算思路相同。
?
這樣,?一個(gè)簡單的帶有滾動(dòng)條的窗口就完成了! 看起來挺不錯(cuò)的, 不是嗎? 可以先稍微休息一下, 下面我們還有事要做。
?
?
但這還不夠好!
在上面我們使用的滾動(dòng)條中,?雖說能夠滾動(dòng)文字,?但是依然存在許多小問題:
問題一:?滑塊的大小是固定的,?而我見到的應(yīng)用軟件滑塊能夠根據(jù)內(nèi)容的多少自動(dòng)調(diào)整滑塊大小;
問題二:?當(dāng)我拖動(dòng)滑塊時(shí)只有當(dāng)滑塊釋放時(shí)頁面才會(huì)滾動(dòng),?我想要的是當(dāng)滑塊被拖動(dòng)時(shí)頁面也同樣跟著滾動(dòng);
問題三:?當(dāng)滑塊滾動(dòng)到底部時(shí)最后一行顯示到了客戶區(qū)頂部,?下面留有一大片的空白,?而我并不需要保留下面的空白,?也就是說最后一行在滑塊拖動(dòng)到底部后它只顯示在底部就行。
?
幸運(yùn)的是, 我們依然有解決方案:
問題一: 自行設(shè)置滑塊的大小;
?問題二:?根據(jù)SB_THUMBTRACK消息處理頁面的滾動(dòng),?SB_THUMBTRACK消息是當(dāng)滑塊被拖動(dòng)時(shí)就會(huì)源源不斷的發(fā)來;
? ? ?問題三:?重新設(shè)置滾動(dòng)的范圍。
?
?
?
更好的滾動(dòng)條:
在使用更好的滾動(dòng)條之前我們首先要認(rèn)識(shí)三個(gè)新函數(shù):?SetScrollInfo、GetScrollInfo以及ScrollWindow.
1>.?SetScrollInfo
函數(shù)功能:?用于設(shè)置滾動(dòng)條的相關(guān)參數(shù),?包括滾動(dòng)范圍的最大值和最小值,?頁面大小,?滑塊的位置,?函數(shù)的原型:
int SetScrollInfo(HWND hWnd; //窗口句柄int fnBar, //指定被設(shè)定參數(shù)的滾動(dòng)條的類型LPSCROLLINFO lpsi, //指向一個(gè)SCROLLINFO結(jié)構(gòu)BOOL fRedraw //重繪標(biāo)志) ;穿插講述: 什么是SCROLLINFO結(jié)構(gòu)?
SCROLLINFO的成員記錄有關(guān)滾動(dòng)條的信息,?其結(jié)構(gòu)定義如下:
typedef struct tagSCROLLINFO { UINT cbSize ; //設(shè)置為sizeof (SCROLLINFO), 表示該結(jié)構(gòu)的大小UINT fMask ; //要設(shè)置或獲取的值int nMin ; //滾動(dòng)條范圍的最小值int nMax ; //滾動(dòng)條范圍的最大值UINT nPage ; //頁面大小int nPos ; //當(dāng)前位置 int nTrackPos ; //當(dāng)前追蹤位置 }SCROLLINFO;成員一UINT?cbSize?:??該參數(shù)必須在函數(shù)調(diào)用之前設(shè)置,??cbSize表示該結(jié)構(gòu)的大小,?用sizeof?(SCROLLINFO)表示即可。
成員二UINT?fMask:?用于指定指定結(jié)構(gòu)中的哪些成員是有效的,?通過位或運(yùn)算進(jìn)行組合,?可組合的標(biāo)識(shí)符如下:
SIF_ALL //整個(gè)結(jié)構(gòu)都有效SIF_DISABLENOSCROLL //禁用滾動(dòng)條SIF_PAGE //用于指定或獲取頁面的大小, 在SetScrollInfo中用于設(shè)定頁面的大小, 在GetScrollInfo用于獲取頁面的大小
SIF_POS //設(shè)置/取得滾動(dòng)條滑塊當(dāng)前的位置
SIF_RANGE //滾動(dòng)條的范圍SIF_TRACKPOS //僅在GetScrollInfo函數(shù)中使用, 并且僅用在處理SB_THUMBTRACK或者SB_THUMBPOSITION的WM_VSCROLL消息或WM_HSCROLL消息時(shí)使用。取得當(dāng)前滑塊的跟蹤位置。
?? 穿插講述完畢! 繼續(xù)講解第二個(gè)新函數(shù)。
?
2>.?GetScrollInfo
用于取得滾動(dòng)條的相關(guān)參數(shù),?包括滾動(dòng)范圍的最大值和最小值,?頁面大小,?滑塊的位置,?函數(shù)的原型:
BOOL GetScrollInfo( HWND hWnd, //窗口句柄int fnBar, //指定被設(shè)定參數(shù)的滾動(dòng)條的類型LPSCROLLINFO lpsi //指向一個(gè)SCROLLINFO結(jié)構(gòu));?
3>.?ScrollWindow
該函數(shù)的作用是滾動(dòng)所指定的窗口客戶區(qū)域內(nèi)容,?原型如下:
BOOL ScrollWindow(HWND hWnd, //窗口句柄int XAmount, //指定水平滾動(dòng)的距離int YAmount, //指定垂直滾動(dòng)的距離CONST RECT *IpRect, //指向RECT結(jié)構(gòu)的指針, 該結(jié)構(gòu)指定了將要滾動(dòng)的客戶區(qū)范圍。若此參數(shù)為NULL,則整個(gè)客戶區(qū)域?qū)⒈粷L動(dòng)。 CONST RECT *lpClipRect //指向RECT結(jié)構(gòu)的指針, 該結(jié)構(gòu)指定了要滾動(dòng)的裁剪區(qū)域。只有這個(gè)矩形中才會(huì)被滾動(dòng)。 );好了,?說的差不多夠多了,?研究代碼才是更好的溝通方式,?下面我們實(shí)際實(shí)踐一下更好的滾動(dòng)條,?更多的細(xì)節(jié)請(qǐng)?jiān)诖a中體會(huì), 限于篇幅的長度, 這里將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 //注冊(cè)窗口類 26 if( !RegisterClass(&wndclass) ) 27 { 28 MessageBox( NULL, TEXT("無法注冊(cè)窗口類!"), TEXT("錯(cuò)誤"), MB_OK | MB_ICONERROR ) ; 29 return 0 ; 30 } 31 32 //創(chuàng)建窗口 33 hwnd = CreateWindow( 34 szAppName, TEXT("滾動(dòng)條示例"), 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: 豎直方向滾動(dòng)條滑塊位置; iHscrollPos: 水平方向滾動(dòng)條滑塊位置6 HDC hdc ;7 RECT rect ; //記錄客戶區(qū)RECT結(jié)構(gòu)8 int i, x, y; //i循環(huán)控制, x記錄水平方向坐標(biāo), y豎直方向坐標(biāo)9 PAINTSTRUCT ps ;10 TEXTMETRIC tm ;11 SCROLLINFO si ; //SCROLLINFO結(jié)構(gòu)對(duì)象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è)置垂直滾動(dòng)條相關(guān)參數(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è)置水平滾動(dòng)條相關(guān)參數(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: //處理垂直滾動(dòng)條消息52 si.cbSize = sizeof (si) ;53 si.fMask = SIF_ALL ;54 GetScrollInfo(hwnd, SB_VERT, &si) ;55 56 iVscrollPos = si.nPos ; //記錄當(dāng)前滑塊位置57 58 switch( LOWORD(wParam) ) //處理滾動(dòng)條消息59 {60 case SB_TOP: //到達(dá)頂部61 si.nPos = si.nMin ;62 break ;63 64 case SB_BOTTOM: //到達(dá)底部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: //移動(dòng)滑塊時(shí)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) ; //滾動(dòng)內(nèi)容97 UpdateWindow(hwnd) ;98 }99 return 0 ; 100 101 case WM_HSCROLL: //處理水平滾動(dòng)條消息 102 si.cbSize = sizeof (si) ; 103 si.fMask = SIF_ALL ; 104 GetScrollInfo (hwnd, SB_HORZ, &si) ; 105 106 iHscrollPos = si.nPos ; //記錄當(dāng)前滑塊位置 107 switch( LOWORD(wParam) ) 108 { 109 case SB_TOP: //到達(dá)頂部 110 si.nPos = si.nMin ; 111 break ; 112 113 case SB_BOTTOM: //到達(dá)底部 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: //移動(dòng)滑塊時(shí) 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) ; //滾動(dòng)內(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 ; //獲取當(dāng)前垂直滑塊位置 157 158 GetScrollInfo(hwnd, SB_HORZ, &si) ; 159 iHscrollPos = si.nPos ; //獲取當(dāng)前水平滑塊位置 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 }?
看一下成果:
嗯, 這樣看起來就好多了, 如果嫌行間距太擠的話我們可以調(diào)節(jié)字符的高度
使行間距增大些, 這樣看起來會(huì)更舒服。
好了, 到這里,?一個(gè)較為完善的滾動(dòng)條就完成了。
?
--------------------
?
wid, 2012.10.31
?
總結(jié)
- 上一篇: 教你羊肉炒菠菜的做法
- 下一篇: C语言(标识符)