windows程式設計(5)使用捲軸

來源:互聯網
上載者:User

本文的程式來自《windows程式設計(第五版)》

設計捲軸的初衷,是因為客戶區需要顯示的東西太多了,在這個標頭檔中,我們包含了一大堆的系統的資訊:

//總行數#define NUMLINES  ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))struct{int Index ;TCHAR* szLabel;TCHAR* szDesc ;}//結構體數組sysmetrics [] =        {        SM_CXSCREEN,TEXT ("SM_CXSCREEN"),TEXT ("Screen width in pixels"),        SM_CYSCREEN,TEXT ("SM_CYSCREEN"),TEXT ("Screen height in pixels"),           SM_CXVSCROLL,TEXT ("SM_CXVSCROLL"),TEXT ("Vertical scroll width"),            SM_CYHSCROLL,TEXT ("SM_CYHSCROLL"),TEXT ("Horizontal scroll height"),            SM_CYCAPTION,TEXT ("SM_CYCAPTION"),TEXT ("Caption bar height"),            SM_CXBORDER,TEXT ("SM_CXBORDER"),TEXT ("Window border width"),            SM_CYBORDER,TEXT ("SM_CYBORDER"),TEXT ("Window border height"),            SM_CXFIXEDFRAME,TEXT ("SM_CXFIXEDFRAME"),TEXT ("Dialog window frame width"),            SM_CYFIXEDFRAME,TEXT ("SM_CYFIXEDFRAME"),TEXT ("Dialog window frame height"),            SM_CYVTHUMB,TEXT ("SM_CYVTHUMB"),TEXT ("Vertical scroll thumb height"),            SM_CXHTHUMB,TEXT ("SM_CXHTHUMB"),TEXT ("Horizontal scroll thumb width"),            SM_CXICON,TEXT ("SM_CXICON"),TEXT ("Icon width"),            SM_CYICON,TEXT ("SM_CYICON"),TEXT ("Icon height"),            SM_CXCURSOR,TEXT ("SM_CXCURSOR"),TEXT ("Cursor width"),            SM_CYCURSOR,TEXT ("SM_CYCURSOR"),TEXT ("Cursor height"),            SM_CYMENU,TEXT ("SM_CYMENU"),TEXT ("Menu bar height"),            SM_CXFULLSCREEN,TEXT ("SM_CXFULLSCREEN"),TEXT ("Full screen client area width"),            SM_CYFULLSCREEN,TEXT ("SM_CYFULLSCREEN"),TEXT ("Full screen client area height"),            SM_CYKANJIWINDOW,TEXT ("SM_CYKANJIWINDOW"),TEXT ("Kanji window height"),            SM_MOUSEPRESENT,TEXT ("SM_MOUSEPRESENT"),TEXT ("Mouse present flag"),            SM_CYVSCROLL,TEXT ("SM_CYVSCROLL"),TEXT ("Vertical scroll arrow height"),            SM_CXHSCROLL,TEXT ("SM_CXHSCROLL"),TEXT ("Horizontal scroll arrow width"),            SM_DEBUG,TEXT ("SM_DEBUG"),TEXT ("Debug version flag"),            SM_SWAPBUTTON,TEXT ("SM_SWAPBUTTON"),TEXT ("Mouse buttons swapped flag"),            SM_CXMIN,TEXT ("SM_CXMIN"),TEXT ("Minimum window width"),            SM_CYMIN,TEXT ("SM_CYMIN"),TEXT ("Minimum window height"),            SM_CXSIZE,TEXT ("SM_CXSIZE"),TEXT ("Min/Max/Close button width"),            SM_CYSIZE,TEXT ("SM_CYSIZE"),TEXT ("Min/Max/Close button height"),            SM_CXSIZEFRAME,TEXT ("SM_CXSIZEFRAME"),TEXT ("Window sizing frame width"),            SM_CYSIZEFRAME,TEXT ("SM_CYSIZEFRAME"),TEXT ("Window sizing frame height"),            SM_CXMINTRACK,TEXT ("SM_CXMINTRACK"),TEXT ("Minimum window tracking width"),            SM_CYMINTRACK,TEXT ("SM_CYMINTRACK"),TEXT ("Minimum window tracking height"),            SM_CXDOUBLECLK,TEXT ("SM_CXDOUBLECLK"),TEXT ("Double click x tolerance"),            SM_CYDOUBLECLK,TEXT ("SM_CYDOUBLECLK"),TEXT ("Double click y tolerance"),            SM_CXICONSPACING,TEXT ("SM_CXICONSPACING"),TEXT ("Horizontal icon spacing"),            SM_CYICONSPACING,TEXT ("SM_CYICONSPACING"),TEXT ("Vertical icon spacing"),            SM_MENUDROPALIGNMENT,TEXT ("SM_MENUDROPALIGNMENT"),TEXT ("Left or right menu drop"),            SM_PENWINDOWS,TEXT ("SM_PENWINDOWS"),TEXT ("Pen extensions installed"),            SM_DBCSENABLED,TEXT ("SM_DBCSENABLED"),TEXT ("Double-Byte Char Set enabled"),            SM_CMOUSEBUTTONS,TEXT ("SM_CMOUSEBUTTONS"),TEXT ("Number of mouse buttons"),           SM_SECURE,TEXT ("SM_SECURE"),TEXT ("Security present flag"),            SM_CXEDGE,TEXT ("SM_CXEDGE"),TEXT ("3-D border width"),            SM_CYEDGE,TEXT ("SM_CYEDGE"),TEXT ("3-D border height"),            SM_CXMINSPACING,TEXT ("SM_CXMINSPACING"),TEXT ("Minimized window spacing width"),            SM_CYMINSPACING,TEXT ("SM_CYMINSPACING"),TEXT ("Minimized window spacing height"),            SM_CXSMICON,TEXT ("SM_CXSMICON"),TEXT ("Small icon width"),           SM_CYSMICON,TEXT ("SM_CYSMICON"),TEXT ("Small icon height"),            SM_CYSMCAPTION,TEXT ("SM_CYSMCAPTION"),TEXT ("Small caption height"),            SM_CXSMSIZE,TEXT ("SM_CXSMSIZE"),TEXT ("Small caption button width"),            SM_CYSMSIZE,TEXT ("SM_CYSMSIZE"),TEXT ("Small caption button height"),            SM_CXMENUSIZE,TEXT ("SM_CXMENUSIZE"),TEXT ("Menu bar button width"),            SM_CYMENUSIZE,TEXT ("SM_CYMENUSIZE"),TEXT ("Menu bar button height"),            SM_ARRANGE,TEXT ("SM_ARRANGE"),TEXT ("How minimized windows arranged"),            SM_CXMINIMIZED,TEXT ("SM_CXMINIMIZED"),TEXT ("Minimized window width"),            SM_CYMINIMIZED,TEXT ("SM_CYMINIMIZED"),TEXT ("Minimized window height"),            SM_CXMAXTRACK,TEXT ("SM_CXMAXTRACK"),TEXT ("Maximum draggable width"),            SM_CYMAXTRACK,TEXT ("SM_CYMAXTRACK"),TEXT ("Maximum draggable height"),            SM_CXMAXIMIZED,TEXT ("SM_CXMAXIMIZED"),TEXT ("Width of maximized window"),            SM_CYMAXIMIZED,TEXT ("SM_CYMAXIMIZED"),TEXT ("Height of maximized window"),            SM_NETWORK,TEXT ("SM_NETWORK"),TEXT ("Network present flag"),            SM_CLEANBOOT,TEXT ("SM_CLEANBOOT"),TEXT ("How system was booted"),            SM_CXDRAG,TEXT ("SM_CXDRAG"),TEXT ("Avoid drag x tolerance"),            SM_CYDRAG,TEXT ("SM_CYDRAG"),TEXT ("Avoid drag y tolerance"),            SM_SHOWSOUNDS,TEXT ("SM_SHOWSOUNDS"),TEXT ("Present sounds visually"),            SM_CXMENUCHECK,TEXT ("SM_CXMENUCHECK"),TEXT ("Menu check-mark width"),            SM_CYMENUCHECK,TEXT ("SM_CYMENUCHECK"),TEXT ("Menu check-mark height"),            SM_SLOWMACHINE,TEXT ("SM_SLOWMACHINE"),TEXT ("Slow processor flag"),            SM_MIDEASTENABLED,TEXT ("SM_MIDEASTENABLED"),TEXT ("Hebrew and Arabic enabled flag"),            SM_MOUSEWHEELPRESENT,TEXT ("SM_MOUSEWHEELPRESENT"),TEXT ("Mouse wheel present flag"),            SM_XVIRTUALSCREEN,TEXT ("SM_XVIRTUALSCREEN"),TEXT ("Virtual screen x origin"),            SM_YVIRTUALSCREEN,TEXT ("SM_YVIRTUALSCREEN"),TEXT ("Virtual screen y origin"),            SM_CXVIRTUALSCREEN,     TEXT ("SM_CXVIRTUALSCREEN"),TEXT ("Virtual screen width"),            SM_CYVIRTUALSCREEN,TEXT ("SM_CYVIRTUALSCREEN"),TEXT ("Virtual screen height"),            SM_CMONITORS,TEXT ("SM_CMONITORS"),TEXT ("Number of monitors"),            SM_SAMEDISPLAYFORMAT,TEXT ("SM_SAMEDISPLAYFORMAT"),TEXT ("Same color format flag")        } ;

第一行定義的,是數組有多少個元素。之後我們定義了結構體數組。元素個數很多,一行顯示不下,那麼如何添加捲軸呢?

我們先看程式:

#include <windows.h>#include "sysmets.h"LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);int WINAPI WinMain(HINSTANCE hInstance,//當前執行個體控制代碼   HINSTANCE hPrevInstance, //先前執行個體控制代碼   LPSTR lpCmdLine,//命令列   int iCmdShow)//顯示狀態{static TCHAR szAppName[] = TEXT("顯示系統內容");//視窗控制代碼HWND hwnd;//訊息MSG msg;//視窗類別WNDCLASS wndclass;//視窗風格:當移動視窗或者改變大小時重繪視窗wndclass.style   =  CS_HREDRAW | CS_VREDRAW;//指明回呼函數wndclass.lpfnWndProc   = WndProc;//額外的位元用來確認下一個視窗類別的位置,暫時不用wndclass.cbClsExtra    = 0;//額外的位元用來確認下一個視窗執行個體的位置,暫時不用wndclass.cbWndExtra    = 0;//執行個體控制代碼wndclass.hInstance     = hInstance;//裝載表徵圖wndclass.hIcon   = LoadIcon(NULL, IDI_APPLICATION);//裝載游標wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);//背景為白色wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);//菜單:暫時沒有wndclass.lpszMenuName  = NULL;//視窗類別名wndclass.lpszClassName = szAppName;//註冊視窗if(!RegisterClass(&wndclass)){return -1;}//建立視窗hwnd = CreateWindow(szAppName,//視窗類別的名稱,必須是已經註冊的TEXT("系統內容"),//視窗標題WS_OVERLAPPEDWINDOW | WS_VSCROLL,//視窗風格,加入垂直捲軸CW_USEDEFAULT,//X座標CW_USEDEFAULT,//Y座標CW_USEDEFAULT,//寬度CW_USEDEFAULT,//高度NULL,//父視窗控制代碼NULL,//菜單視窗控制代碼hInstance,//進階版本的windos忽略NULL);//顯示視窗//ShowWindow(hwnd,SW_SHOWNA);ShowWindow (hwnd, iCmdShow);//更新視窗UpdateWindow(hwnd);//訊息迴圈while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);//將訊息給視窗DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){//字元的寬度,大寫字母寬度,字元高度static int    cxChar, cxCaps, cyChar ;//視窗大小static int cxClient, cyClient ;//捲軸位置static int iVscrollPos; HDC hdc;//該變數用於索引sysmets.h中定義的結構體數組sysmetrics[]的每個元素int i;//輸出文本的垂直位置int y;//繪圖結構PAINTSTRUCT ps;//字串TCHAR szBuffer [10];//字型資訊結構TEXTMETRIC  tm;switch(message){case WM_CREATE:hdc = GetDC(hwnd);//取得內定系統字型的文字大小,存在放在tm裡GetTextMetrics (hdc, &tm);//平均字元寬cxChar = tm.tmAveCharWidth ;//大寫字母的平平均寬度cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;//字元總高度:高度+行間距cyChar = tm.tmHeight + tm.tmExternalLeading ;ReleaseDC(hwnd,hdc);//設定捲軸範圍:參數為:視窗控制代碼,捲軸類型,最小位置,最大位置,是否重繪SetScrollRange (hwnd, SB_VERT, 0, NUMLINES - 1, FALSE);//捲軸的方塊的位置,參數為:視窗控制代碼,捲軸類型,新的位置SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE); return 0;case WM_SIZE:       cxClient = LOWORD (lParam) ;        cyClient = HIWORD (lParam) ;       return 0; case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;for(i = 0;i < NUMLINES;i++ ){//行寬度*變動的行數y =  cyChar * (i - iVscrollPos) ;//輸出字串到指定的地區(使用當前的字型,背景顏色,顏色)//參數為:裝置內容控制代碼,x座標,y座標,帶輸出的字串(與是否/0結尾無關),字元的個數//lstrlen計算字串長度TextOut(hdc,0,y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel));//從22個大寫字母以後的位置輸出,因為第一列最多隻有20個大寫字母TextOut(hdc,22*cxCaps,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc));//最後一列是靠右對齊的SetTextAlign(hdc,TA_RIGHT | TA_TOP);//40*cxChar是第二列及第三列的列寬//wsprintf用來給指定的buffer中格式化並儲存字串(0結尾),傳回值為字串的數目//GetSystemMetrics用來擷取系統參數,傳回值為系統參數TextOut(hdc,22*cxCaps+40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics (sysmetrics[i].Index)));//再把對齊改回去,否則下一次迴圈時也是靠右對齊SetTextAlign(hdc,TA_LEFT | TA_TOP);}EndPaint (hwnd, &ps) ;return 0;//捲軸訊息case WM_VSCROLL://通過捲軸訊息的wParam表明捲軸的操作switch(LOWORD (wParam)){//點一下上箭頭:向下翻一行case SB_LINEUP:iVscrollPos -=1;break;//點一下下箭頭:向上翻一行case SB_LINEDOWN:iVscrollPos +=1;break;//點一下方塊上面:向上翻一頁,每一頁是:(客戶區/一行高度)這麼多行case SB_PAGEUP:iVscrollPos -= cyClient / cyChar ;break;//點一下方塊下面:向下翻一頁case SB_PAGEDOWN:iVscrollPos += cyClient / cyChar ;break;//拖動捲軸:wParam的高位元組表明了捲軸的位置case SB_THUMBPOSITION:iVscrollPos = HIWORD (wParam) ;break;default:break;}//這一句是為了iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ; //如果捲軸位置改變 if (iVscrollPos != GetScrollPos (hwnd, SB_VERT)) {//設定捲軸小方塊的位置SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;//設為無效區,激勵WM_PAINT訊息InvalidateRect (hwnd, NULL, TRUE) ; }return 0;case  WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc (hwnd, message, wParam, lParam) ;}

程式的思路是這樣的:在建立視窗時,就要告訴系統你要加一個捲軸(垂直的),在WM_CREATE訊息中,就要對捲軸進行一些基本的設定。WM_VSCROLL對捲軸做出相應,可以分為3部分:第一部分接收捲軸的訊息;第二部分是讓捲軸的那個小方塊滾動到特定的位置,第三部分是頁面的文字出現“滾動”的效果。

先看第一部分:捲軸的作用是什麼:當點擊一下向上或者向下的按鈕時,會滾動一行文字;當點擊滾動的小方塊的上面或者下面時,會滾動一頁文字;而拖著捲軸走,能滾動到指定的地方。到底是這幾種操作的哪一種,是通過WM_VSCROLL訊息的wParam的低位元組傳過來的。在程式中,使用iVscrollPos這個全域變數來記錄滾動的位置,每一次對捲軸都會改變位置。

iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;是為了不讓捲軸的位置超出一定為範圍,大家可以把它屏蔽之後,將捲軸向上或者向下滾,就可以理解結果了。
而通過SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;就將捲軸的方塊放到了可定位位置。而第三部分讓頁面滾動,則是WM_PAINT的作用了:其實當你看到第二行顯示在原來第一行為位置上時,其實並不是系統沒有輸出第一行,而是第一行輸出的位置已經到了客戶區的上面,所以你看不到!第二行緊跟在第一行下面,剛好就放到了開始的位置。

這個捲軸有一個明顯的缺點,就是他並不是我們希望看到的那樣:捲軸的長度反應的當前頁面占顯示的內容總的內容的百分比,具體的說,就是:

頁面方塊的大小/滾動的長度=頁面大小/整個範圍=顯示檔案的數量/整個檔案的數量

別看這隻是一點小小的改動,但是他的實現方法卻與上面的差別很大。總體上來說,他需要使用SCROLLINFO結構來記錄捲軸的資訊,然後使用GetScrollInfo擷取資訊,通過SetScrollInfo設定資訊。在對捲軸的響應訊息中,通過ScrollWindow來實現內容的滾動(而不像前面那個程式,在WM_PAINT訊息下實現)。

我們在看看程式:

#include <windows.h>#include "sysmets.h"LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM);int WINAPI WinMain(HINSTANCE hInstance,//當前執行個體控制代碼   HINSTANCE hPrevInstance, //先前執行個體控制代碼   LPSTR lpCmdLine,//命令列   int iCmdShow)//顯示狀態{static TCHAR szAppName[] = TEXT("顯示系統內容");//視窗控制代碼HWND hwnd;//訊息MSG msg;//視窗類別WNDCLASS wndclass;//視窗風格:當移動視窗或者改變大小時重繪視窗wndclass.style   =  CS_HREDRAW | CS_VREDRAW;//指明回呼函數wndclass.lpfnWndProc   = WndProc;//額外的位元用來確認下一個視窗類別的位置,暫時不用wndclass.cbClsExtra    = 0;//額外的位元用來確認下一個視窗執行個體的位置,暫時不用wndclass.cbWndExtra    = 0;//執行個體控制代碼wndclass.hInstance     = hInstance;//裝載表徵圖wndclass.hIcon   = LoadIcon(NULL, IDI_APPLICATION);//裝載游標wndclass.hCursor       = LoadCursor(NULL,IDC_ARROW);//背景為白色wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);//菜單:暫時沒有wndclass.lpszMenuName  = NULL;//視窗類別名wndclass.lpszClassName = szAppName;//註冊視窗if(!RegisterClass(&wndclass)){return -1;}//建立視窗hwnd = CreateWindow(szAppName,//視窗類別的名稱,必須是已經註冊的TEXT("系統內容"),//視窗標題WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,//視窗風格,加入捲軸CW_USEDEFAULT,//X座標CW_USEDEFAULT,//Y座標CW_USEDEFAULT,//寬度CW_USEDEFAULT,//高度NULL,//父視窗控制代碼NULL,//菜單視窗控制代碼hInstance,//進階版本的windos忽略NULL);//顯示視窗//ShowWindow(hwnd,SW_SHOWNA);ShowWindow (hwnd, iCmdShow);//更新視窗UpdateWindow(hwnd);//訊息迴圈while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);//將訊息給視窗DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){//字元的寬度,大寫字母寬度,字元高度static int    cxChar, cxCaps, cyChar ;//視窗大小static int cxClient, cyClient ;//最大寬度static int iMaxWidth;//捲軸位置static int iVertPos,iHorzPos,iPaintBeg,iPaintEnd;HDC hdc;//該變數用於索引sysmets.h中定義的結構體數組sysmetrics[]的每個元素int i;//輸出文本的位置int x,y;//繪圖結構PAINTSTRUCT ps;//這個結構包含了捲軸的資訊//通過SetScrollInfo函數設定資訊,通過 GetScrollInfo 函數擷取資訊SCROLLINFO si;//字串TCHAR szBuffer [10];//字型資訊結構TEXTMETRIC  tm;switch(message){case WM_CREATE:hdc = GetDC(hwnd);//取得內定系統字型的文字大小,存在放在tm裡GetTextMetrics (hdc, &tm);//平均字元寬cxChar = tm.tmAveCharWidth ;//大寫字母的平均寬度cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;//字元總高度:高度+行間距cyChar = tm.tmHeight + tm.tmExternalLeading ;ReleaseDC(hwnd,hdc);//最大跨度 = 40個字元+22個大寫字母iMaxWidth = 40*cxChar+22*cxCaps;return 0;case WM_SIZE:cxClient = LOWORD (lParam) ;        cyClient = HIWORD (lParam) ;   //設定垂直捲軸資訊//結構體的大小si.cbSize  = sizeof(si);//指明將要設定和擷取的參數:這裡是最大最小值組成的範圍和頁面的大小si.fMask = SIF_RANGE | SIF_PAGE ;//捲軸位置的最小值si.nMin = 0;//捲軸位置的最大值si.nMax = NUMLINES - 1 ;//頁面大小si.nPage = cyClient / cyChar ;//設定捲軸的參數SetScrollInfo(hwnd, SB_VERT,&si,TRUE);//設定水平捲軸資訊si.cbSize  = sizeof(si);si.fMask = SIF_RANGE | SIF_PAGE ;si.nMin = 0;si.nMax = 2+ iMaxWidth/cxChar ;si.nPage = cxClient / cxChar ;SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;return 0; case WM_PAINT:hdc = BeginPaint (hwnd, &ps) ;si.cbSize = sizeof(si);si.fMask = SIF_POS;GetScrollInfo(hwnd,SB_VERT,&si);iVertPos = si.nPos;GetScrollInfo(hwnd,SB_HORZ,&si);iHorzPos = si.nPos;//max(0,當前位置+需要繪圖的矩形區的最高點/字元的高度)//iPaintBeg = max(0,iVertPos+ps.rcPaint.top/cyChar);iPaintBeg = max(0,iVertPos);//繪圖結束的地方 = 當前位置+繪製去取的高度iPaintEnd = min(NUMLINES -1,iVertPos+ps.rcPaint.bottom/cyChar);for(i = iPaintBeg; i <= iPaintEnd;i++){//繪圖的x起始位置:1是自己設定的,設定越大離左邊越寬x = cxChar * (1 - iHorzPos) ;//繪圖的y起始位置。y = cyChar * (i - iVertPos) ;TextOut(hdc,x, y,sysmetrics[i].szLabel,lstrlen(sysmetrics[i].szLabel));  //從22個大寫字母以後的位置輸出,因為第一列最多隻有20個大寫字母  TextOut(hdc,x+22*cxCaps,y,sysmetrics[i].szDesc,lstrlen(sysmetrics[i].szDesc));  SetTextAlign(hdc,TA_RIGHT | TA_TOP);TextOut(hdc,x+22*cxCaps+40*cxChar,y,szBuffer,wsprintf(szBuffer,TEXT("%5d"),GetSystemMetrics (sysmetrics[i].Index))); SetTextAlign(hdc,TA_LEFT | TA_TOP);  }EndPaint (hwnd, &ps) ;return 0;//垂直捲軸訊息case WM_VSCROLL://擷取垂直捲軸資訊si.cbSize = sizeof(si);//所有參數si.fMask = SIF_ALL;GetScrollInfo(hwnd,SB_VERT,&si);//垂直位置iVertPos = si.nPos ;//通過捲軸訊息的wParam表明捲軸的操作switch(LOWORD (wParam)){case SB_TOP:si.nPos = si.nMin;break;case SB_BOTTOM:si.nPos = si.nMax;break;case SB_LINEUP:si.nPos -= 1;break;case SB_LINEDOWN:si.nPos +=1;case SB_PAGEUP:si.nPage -= si.nPage;break;case SB_PAGEDOWN:si.nPos +=si.nPage;break;case SB_THUMBTRACK:si.nPos = si.nTrackPos;break;default:break;}si.fMask = SIF_POS;SetScrollInfo(hwnd,SB_VERT,&si,TRUE);GetScrollInfo(hwnd,SB_VERT,&si);if(si.nPos != iVertPos){//滾動指定視窗的內容ScrollWindow(hwnd,0,cyChar*(iVertPos-si.nPos),NULL,NULL);UpdateWindow(hwnd);}return 0;//水平捲軸訊息case WM_HSCROLL:si.cbSize = sizeof(si);si.fMask = SIF_ALL;GetScrollInfo(hwnd,SB_HORZ,&si);iHorzPos = si.nPos;switch(LOWORD(wParam)){case SB_LINELEFT:si.nPos -= 1;break;case SB_LINERIGHT:si.nPos +=1;break;case SB_PAGELEFT:si.nPos -= si.nPage;break;case SB_PAGERIGHT:si.nPos += si.nPage;break;case SB_THUMBPOSITION:si.nPos = si.nTrackPos;break;default:break;}si.fMask = SIF_POS;SetScrollInfo(hwnd,SB_HORZ,&si,TRUE);GetScrollInfo(hwnd,SB_HORZ,&si);if(si.nPos != iHorzPos){ScrollWindow(hwnd,cxChar*(iHorzPos-si.nPos),0,NULL,NULL);//UpdateWindow (hwnd) ;}return 0;case  WM_DESTROY:PostQuitMessage(0);return 0;}return DefWindowProc (hwnd, message, wParam, lParam) ;}

 

程式中有幾點需要注意:

1.程式中設定了垂直捲軸和水平捲軸。在WM_SIZE訊息中,隨著視窗的變化,捲軸的那個小方塊的大小也在變化。

2.在每次使用GetScrollInfo或者SetScrollInfo之前,都必須有si.cbSize  = sizeof(si);這是因為相容的緣故。而且還得指明操作的是SCROLLINFO中的哪些內容,這通過fMask來控制。

3.程式中有幾行代碼很費解:

iPaintBeg = max(0,iVertPos+ps.rcPaint.top/cyChar);實際上,由於ps.rcPaint.top=0,這行代碼也可以寫為:iPaintBeg = max(0,iVertPos);

iPaintEnd = min(NUMLINES -1,iVertPos+ps.rcPaint.bottom/cyChar);畫圖的結束位置=捲軸當前的位置+繪製的行數,而行數=客戶區寬度/每一行的寬度;

x = cxChar * (1 - iHorzPos) ;繪圖的x座標,那個1是為了不是太“頂格”,你也可以把它設定大一點,結果就很明顯了。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.