//总行数 #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 | 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是为了不是太“顶格”,你也可以把它设置大一点,结果就很明显了。
typedef struct tagSCROLLINFO { UINT cbSize ;// set to sizeof (SCROLLINFO) UINT fMask ; // values to set or get,要设置或获取的值 int nMin ; // minimum range value,范围最小值 int nMax ; // maximum range value,范围最大值 UINT nPage ; // page size,页面大小 int nPos ; // current position,当前位置 int nTrackPos ;// current tracking position,当前追踪位置 } SCROLLINFO, * PSCROLLINFO ;
ScrollWindow:
函数原型:BOOL ScrollWindow(HWND hWnd, int XAmount, int YAmount, CONST RECT *IpRect, CONST RECT *lpClipRect);
参数:
1.按照MSDN提供的方法来使用
调用完ScrollWindow后 ,立即调用UpdateWindow发送一个不进队的WM_PAINT消息。在WM_PAINT消息中可以按照滚动时的逻辑,整个区域都绘制但是利用重绘 区域自动将多余的绘制剪切掉,只绘制未被滚动操作覆盖的一行;但是更高明的做法无疑是只绘制未被滚动操作覆盖的一行,加快绘制速度。
2.在调用ScrollWindow的非WM_PAINT消息中绘制
在调用按ScrollWindow后获得窗口DC,自己绘制未被滚动操作覆盖的一行,然后将整个滚动剪切区域设为有效,禁止其产生WM_PAINT消息,这样也可加快绘制速度。