您的位置:首页 > 其它

《Windows程序设计》读书笔记------------->>基本滚动条<<

2007-07-09 10:43 513 查看
一、滚动条的建立:
在CreateWindow的第三个参数中包括窗口样式(WS)标识符WS_VSCROLL(垂直卷动)和/或WS_HSCROLL(水平卷动)即可。

二、需要做的:

Windows对滚动条的处理:

处理所有滚动条鼠标事件
 

当使用者在滚动条内单击鼠标时,提供一种「反相显示」的闪烁
 

当使用者在滚动条内拖动卷动方块时,移动卷动方块
 

为包含滚动条窗口的窗口消息处理程序发送滚动条消息
 

程序写作者应该完成的工作:

初始化滚动条的范围和位置

1、范围

SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ;

参数iBar为SB_VERT或者SB_HORZ,iMin和iMax分别是范围的最小值和最大值。如果想要Windows根据新范围重画滚动条,则设置bRedraw为TRUE(如果在呼叫SetScrollRange后,呼叫了影响滚动条位置的其它函数,则应该将bRedraw设定为FALSE以避免过多的重画)。
一般情况下,最小值和最大值应该是与文本紧密关联的内容,以方便操作。

2、位置

SetScrollPos (hwnd, iBar, iPos, bRedraw) ;

参数iPos是新位置,它必须在iMin至iMax的范围内。Windows提供了类似的函数(GetScrollRange和GetScrollPos)来取得滚动条的目前范围和位置。
 

处理窗口消息处理程序的滚动条消息

在用鼠标单击滚动条或者拖动卷动方块时,Windows给窗口消息处理程序发送WM_VSCROLL(供上下移动)和WM_HSCROLL(供左右移动)消息。在滚动条上的每个鼠标动作都至少产生两个消息,一条在按下鼠标按钮时产生,一条在释放按钮时产生。

和所有的消息一样,WM_VSCROLL和WM_HSCROLL也带有wParam和lParam消息参数。wParam消息参数被分为一个低字组和一个高字组。wParam的低字组是一个数值,它指出了鼠标对滚动条进行的操作。

这些操作有:

#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

在wParam的低字组是SB_THUMBTRACK时,wParam的高字组是使用者在拖动卷动方块时的目前位置。

PS:取得低字组的方法是使用LOWORD(wParam),取得高字组的方法是使用HIWORD(wParam)。

更新滚动条内卷动方块的位置

Windows不会去改变卷动方块的位置,而您可以在程序中呼叫SetScrollPos来改变卷动方块的位置。
 

更改显示区域的内容以响应对滚动条的更改(看注释)




/**//*------------------------------------------------------------------




SYSMETS2.C -- System Metrics Display Program No. 2




(c) Charles Petzold, 1998




------------------------------------------------------------------*/




#include <windows.h>




#include "sysmets.h"




LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;




int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,




PSTR szCmdLine, int iCmdShow)






...{




static TCHAR szAppName[] = TEXT ("SysMets2") ;




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))






...{




MessageBox (NULL, TEXT ("This program requires Windows NT!"),




szAppName, MB_ICONERROR) ;




return 0 ;




}






hwnd = CreateWindow (szAppName, TEXT ("Get System Metrics No. 2"),




WS_OVERLAPPEDWINDOW | WS_VSCROLL, //建立竖直滚动条




CW_USEDEFAULT, CW_USEDEFAULT,




CW_USEDEFAULT, CW_USEDEFAULT,




NULL, NULL, hInstance, NULL) ;




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, cyClient, iVscrollPos ;




HDC hdc ;




int i, y ;




PAINTSTRUCT ps ;




TCHAR szBuffer[10] ;




TEXTMETRIC tm ;




switch (message)






...{




case WM_CREATE:




hdc = GetDC (hwnd) ;




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:




cyClient = HIWORD (lParam) ; //取得窗口大小




return 0 ;






//滚动条处理函数


case WM_VSCROLL:




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 ;








case SB_THUMBPOSITION:




iVscrollPos = HIWORD (wParam) ;




break ;








default :




break ;




}






iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;//非常精彩的宏!控制了iVscrollPos不会超过ScrollRange




if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))






...{




SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;




InvalidateRect (hwnd, NULL, TRUE) ;//将窗口设置为无效,使之重画




}




return 0 ;




case WM_PAINT:




hdc = BeginPaint (hwnd, &ps) ;




for (i = 0 ; i < NUMLINES ; i++)






...{




y = cyChar * (i - iVscrollPos) ;//iVscrollPos中记录了偏移的大小,所以y需要重新计算




TextOut (hdc, 0, y,




sysmetrics[i].szLabel,




lstrlen (sysmetrics[i].szLabel)) ;








TextOut (hdc, 22 * cxCaps, y,




sysmetrics[i].szDesc,




lstrlen (sysmetrics[i].szDesc)) ;








SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;




TextOut (hdc, 22 * cxCaps + 40 * cxChar, y, szBuffer,




wsprintf (szBuffer, TEXT ("%5d"),




GetSystemMetrics (sysmetrics[i].iIndex))) ;




SetTextAlign (hdc, TA_LEFT | TA_TOP) ;




}




EndPaint (hwnd, &ps) ;




return 0 ;






case WM_DESTROY:




PostQuitMessage (0) ;




return 0 ;




}




return DefWindowProc (hwnd, message, wParam, lParam) ;




}



如果仔细看了这些代码,会发现很多是一种经验的积累,它的处理方式清晰简洁,也是学习的一种方法呢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐