学习windows编程 day2 之滚动条使用
相关函数:
setscrollrange,setscrollpos,getscrollrange,getscrollpos
使用滚动条时我们需要进行的操作:
1.初始化滚动条范围和位置
在窗口创建时WM_CREATE响应时可以完成
SetScrollRange(hwnd, SB_VERT, 0, NUMLINES,FALSE); SetScrollPos(hwnd, SB_VERT, 0, TRUE);
2.处理窗口过程的滚动条消息
在响应WM_VSCROLL时处理
switch(LOWORD(wParam)) { case SB_LINEUP: .... break; case SB_LINEDOWN: .... break; case SB_PAGEUP: .... break; case SB_PAGEDOWN: .... break; case SB_THUMBTRACK: .... break; case SB_THUMBPOSITION: .... break; }
注意在wParam参数中的低十六位中可以获取鼠标在滚动条上的动作使用LOWORD(wParam)
当滚动条动作为SB_THUMBPOSITION或SB_THUMBTRACK时,可以在wParam参数中的高十六位中获取位置HIWORD(wParam)
3.更新滑块位置
SetScrollPos(hwnd, SB_VERT, XXX, TRUE);
4.根据滚动条变化更新客户端内容
可以在处理滚动条消息是设置全局参数,在WM_PAINT响应时做出响应更新
为了及时更新客户端内容
可以使用
InvalidateRect(hwnd, NULL, TRUE);
向消息队列中发送消息WM_PAINT,此消息会放在消息队列后面,知道其他消息处理完毕才会响应
或者使用
UpdateWindow(hwnd);
非队列化消息,跳过消息循环机制直接处理更新窗口
全部代码:
#include <windows.h> #include <strsafe.h> #include "SysMet.h" LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iShowCmd) { static TCHAR szClassName[] = TEXT("MyWindow5"); MSG msg; HWND hwnd; WNDCLASS wndclass; wndclass.cbClsExtra=0; wndclass.cbWndExtra=0; wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.hCursor = LoadCursor(NULL, IDI_APPLICATION); wndclass.hIcon = LoadIcon(NULL, IDC_ARROW); wndclass.hInstance = hInstance; wndclass.lpfnWndProc = WndProc; wndclass.lpszClassName = szClassName; wndclass.lpszMenuName = NULL; wndclass.style = CS_HREDRAW; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("this program must run in win nt!"), TEXT("ERROR"), MB_OK); return 0; } hwnd = CreateWindow(szClassName, TEXT("MyWindowProgram"), WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); ShowWindow(hwnd,iShowCmd); 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) { HDC hdc; PAINTSTRUCT ps; RECT rect; TCHAR szBuffer[100]; TEXTMETRIC tm; static int cxChar, cyChar, cxCaps,iVscrollPos;//大写占1.5倍 size_t st; int y; static int cxClient, cyClient; switch (message) { case WM_CREATE: iVscrollPos = 0; SetScrollRange(hwnd, SB_VERT, 0, NUMLINES,FALSE);//后面代表是否现在重画窗口 SetScrollPos(hwnd, SB_VERT, 0, TRUE); hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmExternalLeading + tm.tmHeight; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2)*cxChar / 2; ReleaseDC(hwnd,hdc); break; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (int i = 0; i < NUMLINES;i++) { y = cyChar*(i - iVscrollPos); //获取的大量数据 StringCchLength(sysmetrics[i].szLabel, 1024, &st); TextOut(hdc, 0, y, sysmetrics[i].szLabel, st); StringCchLength(sysmetrics[i].szDesc, 1024, &st); TextOut(hdc, 40 * cxCaps, y, sysmetrics[i].szDesc, st); SetTextAlign(hdc,TA_RIGHT|TA_TOP); StringCchPrintf(szBuffer, 100, L"%d %d %5d", i + 1,iVscrollPos, GetSystemMetrics(sysmetrics[i].iIndex)); StringCchLength(szBuffer, 100, &st); TextOut(hdc, 40 * cxCaps + 40 * cxChar, y, szBuffer, st); SetTextAlign(hdc, TA_LEFT|TA_TOP); } //获取屏幕分辨率 // cxClient=GetSystemMetrics(SM_CXSCREEN); //水平 // cyClient=GetSystemMetrics(SM_CYSCREEN); //垂直 // StringCchPrintf(szBuffer, 100, L"screen : %d * %d px", cxClient, cyClient); // //在屏幕中心写字 // GetClientRect(hwnd, &rect); // DrawText(hdc, szBuffer, -1, &rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER); EndPaint(hwnd, &ps); break; case WM_VSCROLL: hdc = GetDC(hwnd); GetClientRect(hwnd, &rect); if (LOWORD(wParam) == SB_LINEUP) { iVscrollPos -= 1; } else if (LOWORD(wParam) == SB_LINEDOWN) { iVscrollPos += 1; } else if (LOWORD(wParam) == SB_PAGEUP) { iVscrollPos -= cyClient / cyChar; } else if (LOWORD(wParam) == SB_PAGEDOWN) { iVscrollPos += cyClient / cyChar; } else if (LOWORD(wParam) == SB_THUMBTRACK) { DrawText(hdc, L"Slider.....", -1, &rect, DT_RIGHT | DT_VCENTER); } else if (LOWORD(wParam) == SB_THUMBPOSITION) { iVscrollPos = HIWORD(wParam); } ReleaseDC(hwnd, hdc); iVscrollPos = max(0, min(iVscrollPos, NUMLINES)); if (iVscrollPos != GetScrollPos(hwnd, SB_VERT)) { InvalidateRect(hwnd, NULL, TRUE); SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE); } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_QUIT: break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }