头文件
#pragma once #include <Windows.h> #define NUMLINES ((int)(sizeof sysmetrics/sizeof sysmetrics[0])) struct { int Index; char szLabel[100]; //第一列内容 char szDesc[50]; //第二列内容 }sysmetrics[] = { SM_CXSCREEN,"各位同学大家好","官方标准提示数据", SM_CYSCREEN,"C/C++高级工程师","官方标准发布版本" };
NUMLINES 宏定义是为了得到sysmetrics的数量
源文件
#include <Windows.h> #include "systems.h" LRESULT CALLBACK WndProcFun(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("CKDemoTest"); HWND hwnd; MSG msg; WNDCLASS windclass; windclass.style = CS_HREDRAW | CS_VREDRAW; windclass.lpfnWndProc = WndProcFun; windclass.cbClsExtra = 0; windclass.cbWndExtra = 0; windclass.hInstance = hInstance; windclass.hIcon = NULL; windclass.hCursor = LoadCursor(NULL, IDC_ARROW); windclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); windclass.lpszMenuName = NULL; windclass.lpszClassName = szAppName; if (!RegisterClass(&windclass)) { // 提示信息自己完成 return 0; } hwnd = CreateWindow(szAppName, TEXT("第五讲 键盘控制窗口垂直水平滚事件"), WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,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 WndProcFun(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth; HDC hdc; int i, x, y, iVertPos, iHorzPos=0, iPaintBeg, iPaintEnd; PAINTSTRUCT ps; SCROLLINFO si; TCHAR szBuffer[20]; TEXTMETRIC tm; switch (message) { case WM_CREATE: // 应用程序创建一个窗口 hdc = GetDC(hwnd); GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth; cyChar = tm.tmHeight + tm.tmExternalLeading; cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2)*cxChar / 2; ReleaseDC(hwnd, hdc); // 保存三列宽度 iMaxWidth = 40 * cxChar + 22 * cxCaps; return 0; case WM_SIZE: // 改变一个窗口的大小 cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); // 设置垂直滚动条范围 和 页面大小 si.cbSize = sizeof(si); // SIF_RANGE 设置滚动范围值 // SIF_PAGE 设置滚动页码 si.fMask = SIF_RANGE | SIF_PAGE; si.nMin = 0; si.nMax = NUMLINES - 1; si.nPage = cyClient / cyChar; // SB_VERT 设置所给定的窗体上标准垂直滚动条参数 SetScrollInfo(hwnd, SB_VERT, &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; // 查找绘制限制 iPaintBeg = max(0, iVertPos + ps.rcPaint.top / cyChar); iPaintEnd = min(NUMLINES - 1, iVertPos + ps.rcPaint.bottom / cyChar); for (i = iPaintBeg; i <= iPaintEnd; i++) { x = cxChar * (1 - iHorzPos); y = cyChar * (i - iVertPos); TextOut(hdc, x, y, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel)); TextOut(hdc, x+80*cxCaps, y, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc)); SetTextAlign(hdc, TA_RIGHT | TA_TOP); // 指定设备环境设置文字对齐标志 TextOut(hdc, x + 100 * cxCaps + 40 * cxChar, y, szBuffer, wsprintf(szBuffer, TEXT("%d"), GetSystemMetrics(sysmetrics[i].Index))); SetTextAlign(hdc, TA_LEFT | TA_TOP); } EndPaint(hwnd, &ps); return 0; case WM_KEYDOWN: switch (wParam) { case VK_HOME: // Home SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0); // 消息发送到一个或多个窗口 break; case VK_END: // End SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0); break; case VK_PRIOR: // Page Up SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0); break; case VK_NEXT: // Page Down SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); break; case VK_UP: // 箭头向上 SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0); break; case VK_DOWN: // 箭头向下 SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0); break; } return 0; case WM_VSCROLL: // 获取所有垂直滚动条信息 si.cbSize = sizeof(si); si.fMask = SIF_ALL; // 整个结构都有效 GetScrollInfo(hwnd, SB_VERT, &si); // SB_VERT 设置所绽的窗口上标准垂直滚动条参数 iVertPos = si.nPos; 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; break; case SB_PAGEUP: si.nPos -= 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_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
运行结果只能垂直滚动,水平滚动参考即可