文本输出与滚动条
作者:互联网
#include<windows.h> #include"SYSMET.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("SysMets1"); 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.1"), 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) { HDC hdc; PAINTSTRUCT ps; static int cxChar, cxCaps, cyChar, cyClient, iVscrollPos; TEXTMETRIC tm; int i, y; TCHAR szBuffer[10]; 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); 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; } iVscrollPos = max(0, min(iVscrollPos, NUMLINES - 1)); if (iVscrollPos != GetScrollPos(hwnd, SB_VERT)) { SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE); InvalidateRect(hwnd, NULL, TRUE); //使客户区无效,从而发送WM_PAINT进行重绘 } case WM_PAINT: hdc = BeginPaint(hwnd, &ps); for (i = 0; i < NUMLINES; i++) { y = cyChar * (i - iVscrollPos); 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].Index))); SetTextAlign(hdc, TA_LEFT | TA_TOP); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }获取句柄和释放句柄只能在一跳消息中,CreateDC除外 case WM_PAINT: return 0; 这种代码会使windows不停发生WM_PAINT,因为没有使用BeginPaint使无效区域有效化,即一直处于无效状态,所以才会一直发送WM_PAINT。 GetWindowDC返回的是整个窗口的设备环境句柄,GetWindowDC返回的句柄可以在窗口的标题栏进行输出,相应的,程序也要处理WM_NCPAINT(非客户区绘制)消息。 GetDC返回的设备环境句柄中的裁剪矩形是整个客户区,所以可以在客户区任意部分绘制,即使没有无效矩形也没有关系。GetDC不会讲无效区域有效化,如果要使整个客户区有效化,需调用ValidateRect(hwnd, NULL)。而InvalidateRect(hwnd, NULL, TRUE)会是整个客户区无效化,并使其后调用的BeginPaint擦除原有的背景
标签:case,输出,NULL,hwnd,WM,iVscrollPos,滚动条,wndclass,文本 来源: https://www.cnblogs.com/Lu3ky-Athena/p/13626226.html