Windows文本输出

Author: 秋时残叶
Date: 2017.12.29
《windows程序设计》笔记

1.

BOOL InvalidateRect(HWND hwnd, CONST RECT *lpRect, BOOL bErase);   //使矩形失效,以产生WM_PAINT消息

2.

BOOL InvalidateRng(HWND hwnd, HRGN hRgn, BOOL bErase);
BOOL ValidateRect(HWND hwnd, CONST RECT *lpRect);  //使客户区中任意矩形变得有效

4. 获取设备环境句柄
4_1.

HDC BeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint);   //擦去无效区域的背景以便绘图

【使用GDI函数】

EndPaint(HWND hwnd, CONST PAINTSTRUCT *lpPaint);
typedef struct tagPAINTSTRUCT { // ps 
    HDC  hdc; 
    BOOL fErase;    //0  意味window在先前的BeginPaint()中已经擦除了无效区域的背景(若要自定义擦除方式,需要处理WM_ERAEBKGND)
                      画刷是hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH)指定的。
    RECT rcPaint;   //定义了无效矩形的边界 
    BOOL fRestore;  //其它windows内部使用
    BOOL fIncUpdate; 
    BYTE rgbReserved[32]; 
} PAINTSTRUCT; 

4_2.

hdc = GetDC(hwnd);   //获取窗口客户区环境句柄
【使用GDI函数】
ReleaseDC(hwnd, hdc);

注:GetDC不会将无效区域有效化,若要整个客户区有效化,可以用:

ValidateRect(hwnd, NULL);
HDC GetWindowDC(HWND hwnd);  //GetDC返回的是窗口客户区的设备环境句柄,GetWindowDC返回的是整个窗口的设备环境句柄 
//WM_NCPAINT   //非客户区绘制消息

5.

BOOL TextOut(HDC hdc,  //可BeginPaint()返回,也可是GetDC获取的, 环境中的属性决定了文本显示的特性
                int nxStart,    //逻辑坐标, "MM_TEXT"映射属性
                int nyStart, 
                LPCTSTR lpString,  //指向字符串的指针
                int cbString    //字符串中的字符数
);
TextOut(hdc, x, y, psText, iLength);

6.

SYSTEM_FONT   //系统字体, 等宽字体, 标题栏,菜单,对话框中使用

7.

int GetSystemMetrics(int nIndex);   /获取用户界面尺寸,包括键盘,鼠标...等信息

8.

BOOL GetTextMetrics(HDC hdc, LPTEXTMETRIC lptm);    //获取字体尺寸
//字符尺寸结构,仅关心前7个
typedef struct tagTEXTMETRIC { // tm 
    LONG tmHeight;  //tmAscent + tmDescent
    LONG tmAscent;  //基线之上最大高度
    LONG tmDescent; //基线之下最大高度
    LONG tmInternalLeading;  //内部间距
    LONG tmExternalLeading;  //建议在两行文字间留出的空间大小
    LONG tmAveCharWidth;     //小写字母加权平均宽度
    LONG tmMaxCharWidth;     //字体中最宽字符的宽度
    LONG tmWeight; 
    LONG tmOverhang; 
    LONG tmDigitizedAspectX; 
    LONG tmDigitizedAspectY; 
    BCHAR tmFirstChar; 
    BCHAR tmLastChar; 
    BCHAR tmDefaultChar; 
    BCHAR tmBreakChar; 
    BYTE tmItalic; 
    BYTE tmUnderlined; 
    BYTE tmStruckOut; 
    BYTE tmPitchAndFamily; //低位决定字体是否为等宽字体 1:变宽  0:等宽
    BYTE tmCharSet;
} TEXTMETRIC;
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight + tm.tmExternalLeading;

wprintf TextOut组合使用:

TCHAR szBuffer[40];
int iLength;
iLength = wprintf(szBuffer, TEXT("text"));
TextOut(hdc, x, y, szBuffer, iLength);

9.

UINT SetTextAlign(HDC hdc, UINT fMode);  //字符对齐方式

10. 滚动条(旧函数)
10_1.

BOOL SetScrollRange(hwnd, iBar, iMin, iMax, bRedraw);   //设置滚动条范围
//iBar: SB_VERT SB_HORZ  
//bRedraw:需要windows根据新的范围来重绘按钮,bRedraw设为TRUE
//若在调用SetScrollRange后还将调用其它函数来调整滚动条的显示时,设为FALSE以免过多重绘

10_2.

int SetScrollPos(hwnd, iBar, iPos, bRedraw);   //指定滑块在滚动条范围中的位置

10_3.

BOOL GetScrollRange(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos);   //获取滚动条当前范围

10_4.

int GetScrollPos(HWND hwnd, int nBar);    //获取滚动条当前位置

滚动条消息
WM_VSCROLL WM_HSCROLL都伴随着wParam和lParam消息参数
当滚动条是窗口的一部分时, 可以忽略lParam参数:只用于滚动条是子窗口时,通常在对话框中
wParam低位字:鼠标在滚动条上的动作 "通知码" SB_xxx
含有LEFT,RIGHT的标识符用于水平滚动条中
含有UP,DOWN,TOP,BOTTOM的用于垂直滚动条中

11. Win32新引入滚动条函数
11_1.

int SetScrollInfo(hwnd, iBar, &si, bRedraw);
//iBar:SB_VERT  SB_HORZ SB_CTL(表示一个滚动条控件)
//&si  LPSCROLLINFO
typedef struct tagSCROLLINFO {  // si 
    UINT cbSize;   //sizeof(SCROLLINFO)  
    UINT fMask;    //要设置或获取的值  一个或多个以SIF_xxx的标志
    int  nMin;     //范围的最小值
    int  nMax;     //范围的最大值
    UINT nPage;    //页面大小
    int  nPos;     //当前位置
    int  nTrackPos;    //当前追踪位置
}SCROLLINFO; 
typedef SCROLLINFO FAR *LPSCROLLINFO; 

例子:

SCROLLINFO si;
si.cbSize = sizeof(si);   //先将size设为该结构的大小
//或者:
si.cbSize = sizeof(SCROLLINFO);

注:设置大小是为了以后的windows版本可以扩充结构而同时保持与以前的应用程序兼容

【fMask:】
SetScrollInfo:

SIF_RANGE:必须在nMin和nMax中指定滚动条的位置
SIF_POS:须在nPos字段中指定滚动条的位置
SIF_PAGE: 指定页面大小
SIF_TRACKPOS:只用于set中,只在处理SB_THUMBTRACK或SB_THUMBPOSRION的WM_VSCROLL或WM_HSCROLL时,
函数返回时, nTrackPos将返回当前滑块的位置(32位整数)
SIF_DISABLENOSCROLL:原来让滚动条不显示的设置这里将禁用滚动条  不想隐藏滚动条时调用
SIF_ALL:SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS的组合

GetScrollInfo:

SIF_RANGE:nMin和nMax将返回当前的范围
SIF_POS时: nPos返回滚动条的位置
SIF_PAGE: 获取页面大小

11_2.

GetScrollInfo(hwnd, iBar, &si);  //获取滚动条信息

12.

ScrollWindow(hwnd, x, y, NULL, NULL);    //滚动窗口

实例:SysMets1

//sysmets.h

#pragma once
#include <windows.h>
#define NUMLINES ((int)(sizeof sysmetrics / sizeof sysmetrics[0]))

struct
{
    int iIndex;
    TCHAR * szLabel;
    TCHAR * szDesc;
}
sysmetrics[] =
{
    SM_CXSCREEN,          L"SM_CXSCREEN",
                          L"Screen width in pixels",
    SM_CYSCREEN,          L"SM_CYSCREEN",
                          L"Screen height in pixels",
    SM_CXVSCROLL,         L"SM_CXVSCROLL",
                          L"Vertical scroll width",
    SM_CYHSCROLL,         L"SM_CYHSCROLL",
                          L"Horizontal scroll height",
    SM_CYCAPTION,         L"SM_CYCAPTION",
                          L"Caption bar height",
    SM_CXBORDER,          L"SM_CXBORDER",
                          L"Window border width",
    SM_CYBORDER,          L"SM_CYBORDER",
                          L"Window border height",
    SM_CXFIXEDFRAME,      L"SM_CXFIXEDFRAME",
                          L"Dialog window frame width",
    SM_CYFIXEDFRAME,      L"SM_CYFIXEDFRAME",
                          L"Dialog window frame height",
    SM_CYVTHUMB,          L"SM_CYVTHUMB",
                          L"Vertical scroll thumb height",
    SM_CXHTHUMB,          L"SM_CXHTHUMB",
                          L"Horizontal scroll thumb width",
    SM_CXICON,            L"SM_CXICON",
                          L"Icon width",
    SM_CYICON,            L"SM_CYICON",
                          L"Icon height",
    SM_CXCURSOR,          L"SM_CXCURSOR",
                          L"Cursor width",
    SM_CYCURSOR,          L"SM_CYCURSOR",
                          L"Cursor height",
    SM_CYMENU,            L"SM_CYMENU",
                          L"Menu bar height",
    SM_CXFULLSCREEN,      L"SM_CXFULLSCREEN",
                          L"Full screen client area width",
    SM_CYFULLSCREEN,      L"SM_CYFULLSCREEN",
                          L"Full screen client area height",
    SM_CYKANJIWINDOW,     L"SM_CYKANJIWINDOW",
                          L"Kanji window height",
    SM_MOUSEPRESENT,      L"SM_MOUSEPRESENT",
                          L"Mouse present flag",
    SM_CYVSCROLL,         L"SM_CYVSCROLL",
                          L"Vertical scroll arrow height",
    SM_CXHSCROLL,         L"SM_CXHSCROLL",
                          L"Horizontal scroll arrow width",
    SM_DEBUG,             L"SM_DEBUG",
                          L"Debug version flas",
    SM_SWAPBUTTON,        L"SM_SWAPBUTTON",
                          L"Mouse buttons swapped flag",
    SM_CXMIN,             L"SM_CXMIN",
                          L"Minimum window width",
    SM_CYMIN,             L"SM_CYMIN",
                          L"Mininmum window height",
    SM_CXSIZE,            L"SM_CXSIZE",
                          L"Min/Max/Close button width",
    SM_CYSIZE,            L"SM_CYSIZE",
                          L"Min/Max/Close button height",
    SM_CXSIZEFRAME,       L"SM_CXSIZEFRAME",
                          L"Window sizing frame width",
    SM_CYSIZEFRAME,       L"SM_CYSIZEFRAME",
                          L"Window sizing frame height",
    SM_CXMINTRACK,        L"SM_CXMINTRACK",
                          L"Minimum window tracking width",
    SM_CYMINTRACK,        L"SM_CYMINTRACK",
                          L"Minimum window tracking height",
    SM_CXDOUBLECLK,       L"SM_CXDOUBLECLK",
                          L"Double click x tolerance",
    SM_CYDOUBLECLK,       L"SM_CYDOUBLECLK",
                          L"Double click y tolerance",
    SM_CXICONSPACING,     L"SM_CXICONSPACING",
                          L"Horizontal icon spacing",
    SM_CYICONSPACING,     L"SM_CYICONSPACING",
                          L"Vertical icon spacing",
    SM_MENUDROPALIGNMENT, L"SM_MENUDROPALIGNMENT",
                          L"Left or right menu drop",
    SM_PENWINDOWS,        L"SM_PENWINDOWS",
                          L"Pen extensions installed",
    SM_DBCSENABLED,       L"SM_DBCSENABLED",
                          L"Double-byte Char Set enabled",
    SM_SECURE,            L"SM_SECURE",
                          L"Security present flag",
    SM_CXEDGE,            L"SM_CXEDGE",
                          L"3 - D border width",
    SM_CYEDGE,            L"SM_CYEDGE",
                          L"3 - D border height",
    SM_CXMINSPACING,      L"SM_CXMINSPACING",
                          L"Minimized window spacing width",
    SM_CYMINSPACING,      L"SM_CYMINSPACING",
                          L"Minimized window spacing height",
    SM_CXSMICON,          L"SM_CXSMICON",
                          L"Small icon width",
    SM_CYSMICON,          L"SM_CYSMICON",
                          L"Small icon height",
    SM_CYSMCAPTION,       L"SM_CYSMCAPTION",
                          L"Small caption height",
    SM_CXSMSIZE,          L"SM_CXSMSIZE",
                          L"Small caption button width",
    SM_CYSMSIZE,          L"SM_CYSMSIZE",
                          L"Small caption button height",
    SM_CXMENUSIZE,        L"SM_CXMENUSIZE",
                          L"Menu bar button width",
    SM_CYMENUSIZE,        L"SM_CYMENUSIZE",
                          L"Menu bar button height",
    SM_ARRANGE,           L"SM_ARRANGE",
                          L"How minimized",
    SM_CXMINIMIZED,       L"SM_CXMINIMIZED",
                          L"Minimized window width",
    SM_CYMINIMIZED,       L"SM_CYMINIMIZED",
                          L"Minimized window height",
    SM_CXMAXTRACK,        L"SM_CXMAXTRACK",
                          L"Maximum draggable width",
    SM_CYMAXTRACK,        L"SM_CYMAXTRACK",
                          L"Maximum draggable height",
    SM_CXMAXIMIZED,       L"SM_CXMAXIMIZED",
                          L"Width of maximized window",
    SM_CYMAXIMIZED,       L"SM_CYMAXIMIZED",
                          L"Height of maximized window",
    SM_NETWORK,           L"SM_NETWORK",
                          L"Network present flag",
    SM_CLEANBOOT,         L"SM_CLEANBOOT",
                          L"How system was booted",
    SM_CXDRAG,            L"SM_CXDRAG",
                          L"Avoid drag x tolerance",
    SM_CYDRAG,            L"SM_CYDRAG",
                          L"Avoid drag y tolerance",
    SM_SHOWSOUNDS,        L"SM_SHOWSOUNDS",
                          L"Present sounds visually",
    SM_CXMENUCHECK,       L"SM_CXMENUCHECK",
                          L"Menu check-mark width",
    SM_CYMENUCHECK,       L"SM_CYMENUCHECK",
                          L"Menu check-mark height",
    SM_SLOWMACHINE,       L"SM_SLOWMACHINE",
                          L"Slow processor flag",
    SM_MIDEASTENABLED,    L"SM_MIDEASTNABLED",
                          L"Hebrew and Arabic enabled flag",
    SM_MOUSEWHEELPRESENT, L"SM_MOUSEWHEELPRESENT",
                          L"Mouse wheel present flag",
    SM_XVIRTUALSCREEN,    L"SM_XVIRTUALSCREEN",
                          L"Virtual screen x origin",
    SM_YVIRTUALSCREEN,    L"SM_YVIRTUALSCREEN",
                          L"Virtual screen y origin",
    SM_CXVIRTUALSCREEN,   L"SM_CXVIRTUALSCREEN",
                          L"Virtual screen width",
    SM_CYVIRTUALSCREEN,   L"SM_VYVIRTUALSCREEN",
                          L"Virtual screen height",
    SM_CMONITORS,         L"SM_CMONITORS",
                          L"Number of monitors",
    SM_SAMEDISPLAYFORMAT, L"SM_SAMEDISPLAYFORMAT",
                          L"Same color format flag"
};
//main.cpp

#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[] = L"SysMets1";
    HWND hWnd;
    WNDCLASS wndclass;
    MSG msg;

    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, L"This program requires Windows!", szAppName, MB_ICONERROR);
        return 0;
    }

    hWnd = CreateWindow(szAppName, L"Get System Metrics No. 1",
                        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 uMsg, WPARAM wParam, LPARAM lParam)
{
    static int cxChar, cyChar, cxCaps, cyClient, iVscrollPos;
    HDC hdc;
    int i, y;
    PAINTSTRUCT ps;
    TCHAR szBuffer[10];
    TEXTMETRIC tm;

    switch (uMsg)
    {
    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_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);   //移动后的滚动条位置,新滑块位置就是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, FALSE);   //使整个窗口无效
            //UpdateWindow(hWnd);   //有无效区域, 调用窗口过程 立即更新
        }
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        
        for (i = 0; i < NUMLINES; i++)
        {
            y = cyChar * (i - iVscrollPos);   //显示的y坐标

            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, L"%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, uMsg, wParam, lParam);
}

输出:
25c83371848150e50613f492cb2131e3.png

实例:SysMets3

//sysmets.h

#pragma once
#pragma once
#include <windows.h>
#define NUMLINES ((int)(sizeof sysmetrics / sizeof sysmetrics[0]))

struct
{
    int iIndex;
    TCHAR * szLabel;
    TCHAR * szDesc;
}
sysmetrics[] =
{
    SM_CXSCREEN,          L"SM_CXSCREEN",
    L"Screen width in pixels",
    SM_CYSCREEN,          L"SM_CYSCREEN",
    L"Screen height in pixels",
    SM_CXVSCROLL,         L"SM_CXVSCROLL",
    L"Vertical scroll width",
    SM_CYHSCROLL,         L"SM_CYHSCROLL",
    L"Horizontal scroll height",
    SM_CYCAPTION,         L"SM_CYCAPTION",
    L"Caption bar height",
    SM_CXBORDER,          L"SM_CXBORDER",
    L"Window border width",
    SM_CYBORDER,          L"SM_CYBORDER",
    L"Window border height",
    SM_CXFIXEDFRAME,      L"SM_CXFIXEDFRAME",
    L"Dialog window frame width",
    SM_CYFIXEDFRAME,      L"SM_CYFIXEDFRAME",
    L"Dialog window frame height",
    SM_CYVTHUMB,          L"SM_CYVTHUMB",
    L"Vertical scroll thumb height",
    SM_CXHTHUMB,          L"SM_CXHTHUMB",
    L"Horizontal scroll thumb width",
    SM_CXICON,            L"SM_CXICON",
    L"Icon width",
    SM_CYICON,            L"SM_CYICON",
    L"Icon height",
    SM_CXCURSOR,          L"SM_CXCURSOR",
    L"Cursor width",
    SM_CYCURSOR,          L"SM_CYCURSOR",
    L"Cursor height",
    SM_CYMENU,            L"SM_CYMENU",
    L"Menu bar height",
    SM_CXFULLSCREEN,      L"SM_CXFULLSCREEN",
    L"Full screen client area width",
    SM_CYFULLSCREEN,      L"SM_CYFULLSCREEN",
    L"Full screen client area height",
    SM_CYKANJIWINDOW,     L"SM_CYKANJIWINDOW",
    L"Kanji window height",
    SM_MOUSEPRESENT,      L"SM_MOUSEPRESENT",
    L"Mouse present flag",
    SM_CYVSCROLL,         L"SM_CYVSCROLL",
    L"Vertical scroll arrow height",
    SM_CXHSCROLL,         L"SM_CXHSCROLL",
    L"Horizontal scroll arrow width",
    SM_DEBUG,             L"SM_DEBUG",
    L"Debug version flas",
    SM_SWAPBUTTON,        L"SM_SWAPBUTTON",
    L"Mouse buttons swapped flag",
    SM_CXMIN,             L"SM_CXMIN",
    L"Minimum window width",
    SM_CYMIN,             L"SM_CYMIN",
    L"Mininmum window height",
    SM_CXSIZE,            L"SM_CXSIZE",
    L"Min/Max/Close button width",
    SM_CYSIZE,            L"SM_CYSIZE",
    L"Min/Max/Close button height",
    SM_CXSIZEFRAME,       L"SM_CXSIZEFRAME",
    L"Window sizing frame width",
    SM_CYSIZEFRAME,       L"SM_CYSIZEFRAME",
    L"Window sizing frame height",
    SM_CXMINTRACK,        L"SM_CXMINTRACK",
    L"Minimum window tracking width",
    SM_CYMINTRACK,        L"SM_CYMINTRACK",
    L"Minimum window tracking height",
    SM_CXDOUBLECLK,       L"SM_CXDOUBLECLK",
    L"Double click x tolerance",
    SM_CYDOUBLECLK,       L"SM_CYDOUBLECLK",
    L"Double click y tolerance",
    SM_CXICONSPACING,     L"SM_CXICONSPACING",
    L"Horizontal icon spacing",
    SM_CYICONSPACING,     L"SM_CYICONSPACING",
    L"Vertical icon spacing",
    SM_MENUDROPALIGNMENT, L"SM_MENUDROPALIGNMENT",
    L"Left or right menu drop",
    SM_PENWINDOWS,        L"SM_PENWINDOWS",
    L"Pen extensions installed",
    SM_DBCSENABLED,       L"SM_DBCSENABLED",
    L"Double-byte Char Set enabled",
    SM_SECURE,            L"SM_SECURE",
    L"Security present flag",
    SM_CXEDGE,            L"SM_CXEDGE",
    L"3 - D border width",
    SM_CYEDGE,            L"SM_CYEDGE",
    L"3 - D border height",
    SM_CXMINSPACING,      L"SM_CXMINSPACING",
    L"Minimized window spacing width",
    SM_CYMINSPACING,      L"SM_CYMINSPACING",
    L"Minimized window spacing height",
    SM_CXSMICON,          L"SM_CXSMICON",
    L"Small icon width",
    SM_CYSMICON,          L"SM_CYSMICON",
    L"Small icon height",
    SM_CYSMCAPTION,       L"SM_CYSMCAPTION",
    L"Small caption height",
    SM_CXSMSIZE,          L"SM_CXSMSIZE",
    L"Small caption button width",
    SM_CYSMSIZE,          L"SM_CYSMSIZE",
    L"Small caption button height",
    SM_CXMENUSIZE,        L"SM_CXMENUSIZE",
    L"Menu bar button width",
    SM_CYMENUSIZE,        L"SM_CYMENUSIZE",
    L"Menu bar button height",
    SM_ARRANGE,           L"SM_ARRANGE",
    L"How minimized",
    SM_CXMINIMIZED,       L"SM_CXMINIMIZED",
    L"Minimized window width",
    SM_CYMINIMIZED,       L"SM_CYMINIMIZED",
    L"Minimized window height",
    SM_CXMAXTRACK,        L"SM_CXMAXTRACK",
    L"Maximum draggable width",
    SM_CYMAXTRACK,        L"SM_CYMAXTRACK",
    L"Maximum draggable height",
    SM_CXMAXIMIZED,       L"SM_CXMAXIMIZED",
    L"Width of maximized window",
    SM_CYMAXIMIZED,       L"SM_CYMAXIMIZED",
    L"Height of maximized window",
    SM_NETWORK,           L"SM_NETWORK",
    L"Network present flag",
    SM_CLEANBOOT,         L"SM_CLEANBOOT",
    L"How system was booted",
    SM_CXDRAG,            L"SM_CXDRAG",
    L"Avoid drag x tolerance",
    SM_CYDRAG,            L"SM_CYDRAG",
    L"Avoid drag y tolerance",
    SM_SHOWSOUNDS,        L"SM_SHOWSOUNDS",
    L"Present sounds visually",
    SM_CXMENUCHECK,       L"SM_CXMENUCHECK",
    L"Menu check-mark width",
    SM_CYMENUCHECK,       L"SM_CYMENUCHECK",
    L"Menu check-mark height",
    SM_SLOWMACHINE,       L"SM_SLOWMACHINE",
    L"Slow processor flag",
    SM_MIDEASTENABLED,    L"SM_MIDEASTNABLED",
    L"Hebrew and Arabic enabled flag",
    SM_MOUSEWHEELPRESENT, L"SM_MOUSEWHEELPRESENT",
    L"Mouse wheel present flag",
    SM_XVIRTUALSCREEN,    L"SM_XVIRTUALSCREEN",
    L"Virtual screen x origin",
    SM_YVIRTUALSCREEN,    L"SM_YVIRTUALSCREEN",
    L"Virtual screen y origin",
    SM_CXVIRTUALSCREEN,   L"SM_CXVIRTUALSCREEN",
    L"Virtual screen width",
    SM_CYVIRTUALSCREEN,   L"SM_VYVIRTUALSCREEN",
    L"Virtual screen height",
    SM_CMONITORS,         L"SM_CMONITORS",
    L"Number of monitors",
    SM_SAMEDISPLAYFORMAT, L"SM_SAMEDISPLAYFORMAT",
    L"Same color format flag"
};
//main.cpp

#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[] = L"SysMets1";
    HWND hWnd;
    WNDCLASS wndclass;
    MSG msg;

    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, L"This program requires Windows!", szAppName, MB_ICONERROR);
        return 0;
    }

    hWnd = CreateWindow(szAppName, L"Get System Metrics No. 1",
        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 uMsg, WPARAM wParam, LPARAM lParam)
{
    static int cxChar, cyChar, cxCaps, cyClient, cxClient, iMaxWidth;
    HDC hdc;
    int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd;
    PAINTSTRUCT ps;
    SCROLLINFO si;
    TCHAR szBuffer[10];
    TEXTMETRIC tm;

    switch (uMsg)
    {
    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);   //设定初始位置
        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;
        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);
        }
        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 = 0; i < NUMLINES; 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 + 32 * cxCaps + 40 * cxChar, y, szBuffer,
                wsprintf(szBuffer, L"%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, uMsg, wParam, lParam);
}

输出:
ca6252fbe4c80eac7397fdef07e533f0.png

转载于:https://www.cnblogs.com/coolcpp/p/windows-text-input.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值