第4章,[标签 Win32] :SysMets3 程序代码
专栏导航
下一篇:第4章,[标签 Win32] :SysMets3 程序讲解01
本节前言
对于本节所讲解的知识,有可能,你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点,请你自行查阅。
我呢,也会提到一部分的参考课节。但是呢,你不应该依赖于我的主动提及。最好呢,你自己能够多去了解和查看本专栏目录。
本节内容,主要来自对佩措尔德原教材的大段抄录。
我们开始本节的学习。
一. 程序说明
本节程序代码,是本章中最终版本的 SysMets 。这个版本的程序,使用了 SetScrollInfo 和 GetScrollInfo 函数,也使用了 ScrollWindow 函数。
对于 ScrollWindow 函数,我们会在讲解本节代码时再来讨论。本节,你主要的任务是浏览代码和将其编译出来。
当然了,应该会有一部分人,不需要我的讲解,就可以自己搞懂 ScrollWindow 函数的功能。
看你自己的了。如果能够自己搞懂本节的全部代码,那最好了。如果不能,那就先浏览代码,等我们讲完了本节代码,讲完了 ScrollWindow 函数时,你再来认真研究本节代码,也是可以的。
二. 本节代码
与之前的 SysMets 一样,代码分为头文件 SysMets.h 和 WinMain.cpp 两部分。
(一)SysMets.h
/*-----------------------------------------------
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 dragable width"),
SM_CYMAXTRACK, TEXT("SM_CYMAXTRACK"),
TEXT("Maximum dragable 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")
};
这个代码,与 SysMets2 和 SysMets1 中的头文件 SysMets.h 是一样的。
(二)WinMain.cpp
/*----------------------------------------------------
SYSMETS3.C -- System Metrics Display Program No. 3
(c) Charles Petzold, 1998
水饺编程改编版,2026
----------------------------------------------------*/
#define WINVER 0x0500
#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("SysMets3");
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("窗口类注册失败。"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Get System Metrics No. 3"),
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 WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth;
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;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2;
cyChar = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hwnd, hdc);
// Save the width of the three columns
iMaxWidth = 40 * cxChar + 22 * cxCaps;
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
// Set vertical scroll bar range and page size
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);
// Set horizontal scroll bar range and page size
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:
// Get all the vertial scroll bar information
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
// Save the position for comparison later on
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;
}
// Set the position and then retrieve it. Due to adjustments
// by Windows it may not be the same as the value set.
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
// If the position has changed, scroll the window and update it
if (si.nPos != iVertPos)
{
ScrollWindow(hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL);
UpdateWindow(hwnd);
}
return 0;
case WM_HSCROLL:
// Get all the vertial scroll bar information
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
// Save the position for comparison later on
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;
}
// Set the position and then retrieve it. Due to adjustments
// by Windows it may not be the same as the value set.
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
GetScrollInfo(hwnd, SB_HORZ, &si);
// If the position has changed, scroll the window
if (si.nPos != iHorzPos)
{
ScrollWindow(hwnd, cxChar * (iHorzPos - si.nPos), 0,
NULL, NULL);
}
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
// Get vertical scroll bar position
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo(hwnd, SB_VERT, &si);
iVertPos = si.nPos;
// Get horizontal scroll bar position
GetScrollInfo(hwnd, SB_HORZ, &si);
iHorzPos = si.nPos;
// Find painting limits
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);
}
到了这里,代码就展示完了。
我们在下面的分节中讲解编译与运行。
三. 代码编译
(一)基本安排
我们用 VS2019 来新建一个解决方案,将解决方案和项目名称都命名为【SysMets3】。然后呢,分别添加本篇文章第一分节中的 SysMets.h 和 WinMain.cpp 代码文件。
然后呢,我们接着往下讲。
(二)项目设置
本节代码项目,需要根据你所使用的 Visual Studio 软件版本,来决定是否可以直接编译。
如果,你使用的软件版本,为 2010 版和 2008 版等等的低版本 Visual Studio 软件,那么,你并不需要进行专门的项目设置。直接去编译,项目就可以获得通过。
如果,你使用的软件版本,为 2017 版和 2019 版等等的高版本 Visual Studio 软件,那么,直接去编译,Visual Studio 会报错。为了让项目编译通过,我们还需要对此项目,进行一番设置。我们需要设置【符合模式】这一项。设置原因与设置方法,详见测试案例3 的分节二与分节三的讲解。
测试案例3 的课节链接如下。
参考课节:第4章,[标签 Win32] :TextOut 测试案例3
设置好了以后,就可以编译程序了。
我这里,程序是编译成功了的。运行结果如下。
结束语
到了这里,本节就要结束了。
下一节,我们来讲解本节代码的逻辑。其中的一个重点,是去讲解本节代码涉及的 ScrollWindow 函数。
专栏导航
更多推荐
所有评论(0)