Win32程序文本输出 --设备无关的编程基础、滚动条
注:以下内容为学习笔记,多数是从书本、资料中得来,只为加深印象,及日后参考。然而本人表达能力较差,写的不好。因非翻译、非转载,只好选原创,但多数乃摘抄,实为惭愧。但若能帮助一二访客,幸甚!
以下内容摘自Charles Petzold所著《Windows程序设计》
1.WM_PAINT
Windows通过发送WM_PAINT消息来通知窗口过程其可获区需要重绘。
以下任何一个事件发送时,窗口过程都会收到一条WM_PAINT消息:
1)用户移动一个窗口,导致原来被遮盖的部分窗口暴露出来。
2)用户调整窗口大小(当窗口类型设定为CS_HREDRAW和CS_VREDRAW时)
3)程序调用ScrollWindow或ScrollDC函数滚动客户区
4)程序调用InvalidateRect或InvalidateRgn函数显式生成WM_PAINT消息
在某些情况下,当客户区的一部分被临时覆盖时,Windows会试图保存被覆盖的这部分,以便将来恢复。这并不是每次都能成功。以下情形,Windows有时会发送一条WM_PAINT消息:
1)Windows关闭一个覆盖了部分窗口的对话框或消息框
2)下拉菜单被拉下然后收回
3)显式提示信息
在少数情况下,Windows总是会保存被覆盖的部分的显式内容,然后恢复:
1)鼠标指针在客户区移动
2)在客户区内拖到图标
2.有效矩形和无效矩形
尽管窗口过程必须能够在收到WM_PAINT消息时更新整个客户区,但通常它只需要更新其中的一部分,最常见的是更新其中一个矩形区域。
需要重新绘制的部分称为“无效区域”或“更新区域”。在客户区中有一个无效区域将导致Windows在应用程序的消息队列中放置一条WM_PAINT消息。只有当程序客户区的一部分失效时,窗口过程才会接收到WM_PAINT消息。
Windows内部为每个窗口保存了一个“绘制信息结构”这个结构保存着一个可以覆盖该无效区域的最小矩形的坐标和一些其他的信息。这个最小矩形被称为“无效矩形”。
窗口过程可以通过调用InvalidRect强制使自己的客户区中一个矩形失效。
窗口过程在处理WM_PAINT时,调用BeginPaint后,整个客户区会变成有效的。也可以调用ValidateRect使客户区中任意的矩形变得有效。
3.设备环境
绘制一个客户区需要调用Windows的图形设备接口(GDI)函数。
设备环境句柄是程序窗口使用GDI函数的通行证。
设备环境(也被简称为DC)实际上是GDI内部维护的一个数据结构,与特定的显式设备(如显示器或打印机)相关联。
获取设备环境句柄:
1)方法1
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
// ...
EndPaint(hwnd, &ps);
2)方法2
HDC hdc;
hdc = GetDC(hwnd);
//....
ReleaseDC(hwnd, hdc);
从GetDC返回的设备环境句柄中的裁剪矩形是整个客户区。这意味着你可以在客户区的任意部分绘制,而不仅仅是在无效矩形里。GetDC与BeginPaint不同,它不会将无效区域有效化。如果需要将整个客户区有效化,可:
ValidateRect(hwnd, NULL);
与GetDC类似,GetWindowDC返回的是整个窗口的设备环境句柄,可以在窗口的标题栏输出。
4.TextOut
它是显式文本的最重要的GDI函数。
TextOut(hdc, x, y, psText, iLength);
hdc设备环境句柄,它的属性决定了文本显式的特性。
在类似于TextOut的GDI绘图函数的文档中,传给函数的坐标值通常被称为”逻辑坐标“。
设备环境同时定义了一个裁剪区域。GetDC得到的设备环境句柄中,该裁剪区域就是整个客户区;BeginPaint得到的则是无效区域。调用TextOut时,Windows将不会显示字符串落在裁剪区域外的部分。
5.字符尺寸大小
可调用GetSystemMetrics获取用户界面的尺寸,可调用GetTextMetrics获取字体尺寸。
Windows提供了与设备无关的图形界面,但应注意:不要在Windows应用程序中猜测文本的尺寸,不要使用固定的值,应用GetTextMetrics获取这些信息。
6.示例代码(显示Windows中各种图形项的尺寸信息)
/*-----------------------------------------------SYSMETS.H -- System metrics display structure-----------------------------------------------*/#define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))struct
{int iIndex ;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")
} ;
/*-----------------------------------------------------------------------------------SysMets1.cpp -- System Metrics Display Program ver1*----------------------------------------------------------------------------------*/#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("HelloWin32");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, // window class nameTEXT("System Metrics"), // window captionWS_OVERLAPPEDWINDOW, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y positionCW_USEDEFAULT, // initial x sizeCW_USEDEFAULT, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(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)
{// cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度// 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍static int cxChar, cxCaps, cyChar; HDC hdc;int i;PAINTSTRUCT ps;TCHAR szBuffer[10];TEXTMETRIC tm; // switch (message){case WM_CREATE:hdc = GetDC(hwnd);GetTextMetrics(hdc, &tm); // 获取系统默认字体的尺寸cxChar = tm.tmAveCharWidth;// tmPitchAndFamily为1表示变宽字体,为0表示等宽字体cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;cyChar = tm.tmHeight + tm.tmExternalLeading;ReleaseDC(hwnd, hdc);return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);for (i = 0; i < NUMLINES; i++){TextOut(hdc, 0, cyChar*i, sysmetrics[i].szLabel, lstrlen(sysmetrics[i].szLabel));TextOut(hdc, 22*cxCaps, cyChar*i, sysmetrics[i].szDesc, lstrlen(sysmetrics[i].szDesc));SetTextAlign(hdc, TA_RIGHT | TA_TOP);// 第一栏里显示的字符串最长有20个字符TextOut(hdc, 22*cxCaps + 40*cxChar, cyChar*i, 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);
}
7.滚动条
解决上面显示不完全的问题。
每个滚动条都有相应的“范围”和“位置”。默认状态范围为0~100.可用
SetScrollRange(hwnd, iBar, iMin, iMax, bRedraw);
iBar为SB_VERT或SB_HORZ。
若需要Windows根据新的范围来重绘滚动条时,bRedraw设为TRUE。
通过下面函数可设置滑块在滚动条范围中的位置:
SetScrollPos(hwnd, iBar, iPos, bRedraw);
在程序中使用滚动条时,程序需要和Windows共同负责维护滚动条以及滑块在滚动条中的位置。
Windows负责:
1)处理滚动条中的所有鼠标消息
2)当用户单击滚动条时,提供一种反向显示的闪烁
3)当用户拖动滑块时,在滚动条内移动滑块
4)向拥有滚动条的窗口 的窗口过程发送滚动条消息
程序负责:
1)初始化滚动条的范围和位置
2)处理传送给窗口过程的滚动条消息
3)更新滑块的位置
4)根据滚动条的变化更新客户区的内容
滚动条消息:
当用户单击滚动条或拖动滑块时,Windows向窗口过程发送WM_VSCROLL消息(垂直滚动)或WM_HSCROLL(水平滚动)。在滚动条上的任何鼠标动作会至少产生两条消息:一条在鼠标键按下时,另一条在鼠标键松开时。
加入滚动条的SYSMETS代码:
/*-----------------------------------------------------------------------------------SysMets1.cpp -- System Metrics Display Program ver1*----------------------------------------------------------------------------------*/#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("HelloWin32");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, // window class nameTEXT("System Metrics"), // window captionWS_OVERLAPPEDWINDOW | WS_VSCROLL, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y positionCW_USEDEFAULT, // initial x sizeCW_USEDEFAULT, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(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)
{// cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度// 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍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;// tmPitchAndFamily为1表示变宽字体,为0表示等宽字体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));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);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);
}
效果更好的滚动,解决前面程序效率低的问题
使用函数SetScrollInfo和GetScrollInfo:
SetScrollInfo(hwnd, iBar, &si, bRedraw);
GetScrollInfo(hwnd, iBar, &si);
代码:
/*-----------------------------------------------------------------------------------SysMets1.cpp -- System Metrics Display Program ver1*----------------------------------------------------------------------------------*/#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("HelloWin32");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, // window class nameTEXT("System Metrics"), // window captionWS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL, // window styleCW_USEDEFAULT, // initial x positionCW_USEDEFAULT, // initial y positionCW_USEDEFAULT, // initial x sizeCW_USEDEFAULT, // initial y sizeNULL, // parent window handleNULL, // window menu handlehInstance, // program instance handleNULL); // creation parametersShowWindow(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)
{// cxChar平均字符宽度,cyChar字符的总高度(包括外部间距),cxCaps大写字符的平均宽度// 等宽字体中,cxCaps等于cxChar,变宽字体中,cxCaps等于cxChar的1.5倍static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth, iVscrollPos; HDC hdc;int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;PAINTSTRUCT ps;SCROLLINFO si;TCHAR szBuffer[10];TEXTMETRIC tm; switch (message){case WM_CREATE:hdc = GetDC(hwnd);GetTextMetrics(hdc, &tm); // 获取系统默认字体的尺寸cxChar = tm.tmAveCharWidth;// tmPitchAndFamily为1表示变宽字体,为0表示等宽字体cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;cyChar = tm.tmHeight + tm.tmExternalLeading;ReleaseDC(hwnd, hdc);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_VSCROLL:si.cbSize = sizeof(si);si.fMask = SIF_ALL;GetScrollInfo(hwnd, SB_VERT, &si);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_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_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;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 + 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].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);
}
Win32程序文本输出 --设备无关的编程基础、滚动条相关推荐
- Windows下更改C/C++控制台程序文本输出颜色
保存下面的代码放到一个头文件concol.h中 concol.h #include <iostream> using namespace std; #include <windows ...
- 黑马程序员_java总结_网络编程基础
----------- android培训.java培训.java学习型技术博客.期待与您交流! ------------ 现在总结网络编程.在网络通信中,人们把网络通信分为了多个层.为了方便理解,我 ...
- GUI图形界面编程基础知识
文章目录 一.GDI概述 二.OpenGL 三.什么是DirectX? 四.GDI与OpenGL与DirectX之间的区别 五.显卡驱动 1.显卡概述 2.显卡工作原理 六.C++图形化GUI开发框架 ...
- Python编程:从入门到实践+爬虫开发与项目实战+网络编程基础+项目开发实战
给还在苦苦自学Python的小伙伴们分享一波学习教程~有了它们,至少能节省50%的时间,少走一半的弯路. 书不在多,而在于精~ <Python编程:从入门到实践>豆瓣评分9.2 本书是针对 ...
- python语言好不好_《python编程基础》这本书怎么样
<python编程基础>这本书怎么样 发布时间:2020-11-11 12:01:06 来源:亿速云 阅读:73 作者:小新 小编给大家分享一下<python编程基础>这本书怎 ...
- Windows桌面应用程序(1-2-4-7th) DPI和设备无关的像素
要使用Windows图形进行有效编程,您必须了解两个相关的概念: 每英寸点数(DPI) 设备无关像素(DIP). 我们从DPI开始.这将需要短暂的绕行排版.在印刷术中,类型的大小以称为点的单位来测量. ...
- Win32编程基础知识(包括对程序的分析)
管Windows应用程序千变万化,令人眼花缭乱,但,消息机制和窗口过程却始终它们的基础,掌握了这两项技术,也就相当于把握住了问题的关键. 如果你以前是C程序员或是MFC的忠实用户,只要你学习过C语言的 ...
- [Win32]重绘的基本概念以及简单的文本输出文本输出
1. 客户区的完整概念: 即应用程序窗口中没有被标题栏.边框.菜单栏.工具栏.状态栏和滚动条占据的中间的一片区域,用户可以在这片区域内绘制任意信息 注意!我们不能假定它有特定的尺寸或者是它的尺寸不会发 ...
- win32程序启用控制台-- 调试输出
win32程序启用控制台(控制台文件名:conout$,conin$,conerr$) 2010-07-23 13:55:40| 分类: c++|字号 订阅 一个寻找很久,却得来全不费功夫的事情. ...
最新文章
- Unity3D小功能 小技巧 小教程 小原理(持续更新...)
- php base64处理
- 提高ASP性能的最佳选择
- flask-bootstrap-高亮-下划线-删除线-加粗-斜体
- Linux中包的管理与程序安装
- java reader_Java之字符输入流,Reader类的简单介绍
- Nginx的HTTP运行时健康检查
- NLP知识包--语义分析-语义角色标注
- JavaScript 图像延迟加载库 Echo.js的简单使用
- hdu1166------树状数组(板子)
- java 图片md5码_java 对图片进行MD5算法
- 在线旅游中需要上传获取那些信息,对接旅行社护照录入系统
- 高级php工程师需要掌握的知识点
- 高薪程序员面试题精讲系列54之你熟悉B树吗?有哪几种B树?
- 迭代模型(Iterative Model)
- 机器学习笔记09:支持向量机(二)-核函数(Kernels)
- 子元素自动撑开父元素空间
- GitHub Desktop安装与使用教程
- 带你理解交换机基本原理和配置
- 计算机网络之无线与移动网络-移动IP网络与其他典型无线网络
热门文章
- 嵌入式学习代码总结(一)
- php 去掉json外层 方括号,从 JSON 中删除方括号 - WITHOUT_ARRAY_WRAPPER 选项
- python 圆括号和方括号一样吗_Python中用方括号和圆括号括起来的列表有什么区别?...
- 不要因为一时的孤独而去接受一段不属于自己的爱情,也不要因为一段不属于自己的爱情而孤独一生
- dubbo的@Reference注解作用分析
- 边双连通和点双连通(连通性)
- ffmpeg 安装和参数介绍
- 使用REST-Assured对API接口进行自动化测试
- 详解如何安装64位win7系统
- FFT运算的加深理解——栅栏效应、补零、物理分辨率、计算分辨率