• 06 Windows编程——设备句柄 和 WM_PAINT消息


    windows程序在现实方式上属于图形方式,和文字方式的显示,有显著的不同。

     什么是设备句柄,如何获取

    使用统一的数据结构表示某一设备,这个结构就是设备句柄。

    源码

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TCHAR* str = TEXT("hello");
    52     switch (message)
    53     {
    54         case WM_DESTROY:
    55             PostQuitMessage(0);//发送WM_QUIT消息
    56             return 0;
    57         case WM_PAINT:
    58             hdc = BeginPaint(hwnd, &pt);
    59             TextOut(hdc, 0, 0, str, _tcslen(str));
    60             EndPaint(hwnd, &pt);
    61             return 0;
    62         default:
    63             break;
    64     }
    65 
    66     return DefWindowProc(hwnd, message, wParam, lParam);
    67 }
    View Code

    对WM_PAINT消息的处理几乎总是从调用BeginPaint函数开始:hdc = BeginPaint(hwnd, &pt)

    而以调用EndPaint函数结束:EndPaint(hwnd, &pt);

    在这两个函数调用中,第一个参数均为程序的窗口句柄,而第二个参数均为指向一个类型为PAINTSTRUCT结构的指针。PAINTSTRUCT结构包含一些窗口过程用来对客户区进行绘制的信息。

    BeginPaint 调用将使整个客户区有效,并返回一个“设备环境句柄”。

    如何知道客户区呢?

    该函数的第一个参数是程序的窗口句柄。第二个参数为指向类型为RECT的矩形结构的指针。该结构具有4个类型为LONG的字段,名称分别为left、top、right 和botom。GetclientRect函数将依据窗口尺寸来对这4个字段进行设置。其中,left和top字段总是会被赋为0,这样right和bottom字段就分别表示以像素为单位的客户区的宽度和高度。

    BOOL GetClientRect(
        HWND hWnd, // 窗口句柄
        LPRECT lpRect // 客户区坐标
    );

    也可以这样

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TCHAR* str = TEXT("hello");
    52     switch (message)
    53     {
    54         case WM_DESTROY:
    55             PostQuitMessage(0);//发送WM_QUIT消息
    56             return 0;
    57         case WM_PAINT:
    58             /*hdc = BeginPaint(hwnd, &pt);
    59             TextOut(hdc, 0, 0, str, _tcslen(str));
    60             EndPaint(hwnd, &pt);*/
    61             hdc = GetDC(hwnd);
    62             TextOut(hdc, 0, 0, str, _tcslen(str));
    63             ReleaseDC(hwnd, hdc);
    64             ValidateRect(hwnd, NULL);
    65             return 0;
    66         default:
    67             break;
    68     }
    69 
    70     return DefWindowProc(hwnd, message, wParam, lParam);
    71 }
    View Code

    使用EndPaint,直接就会使pt指向的区域变成有效区域。而ReleaseDC不会,WM_PAINT会一直存在,需要手动调用函数ValidateRect释放无效区。使无效客户区有效。

    第三种做法

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TCHAR* str = TEXT("hello");
    52     switch (message)
    53     {
    54         case WM_DESTROY:
    55             PostQuitMessage(0);//发送WM_QUIT消息
    56             return 0;
    57         case WM_PAINT:
    58             /* 第一种
    59             hdc = BeginPaint(hwnd, &pt);
    60             TextOut(hdc, 0, 0, str, _tcslen(str));
    61             EndPaint(hwnd, &pt);
    62             */
    63 
    64             /* 第二种
    65             hdc = GetDC(hwnd);
    66             TextOut(hdc, 0, 0, str, _tcslen(str));
    67             ReleaseDC(hwnd, hdc);
    68             ValidateRect(hwnd, NULL);
    69             */
    70 
    71             hdc = GetWindowDC(hwnd);
    72             TextOut(hdc, 100, 100, str, _tcslen(str));
    73             ReleaseDC(hwnd, hdc);
    74             ValidateRect(hwnd, NULL);
    75             return 0;
    76         default:
    77             break;
    78     }
    79 
    80     return DefWindowProc(hwnd, message, wParam, lParam);
    81 }
    View Code

    GetWindowDC、ReleaseDC操作窗口句柄,在绘制时不是以有效区作为参考,而是以整个窗口做参考,所以需要在TextOut里面调整输出文字的位置

    代码里TextOut只在pt这个无效区显示输出文字。

    HDC BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint );
    
    hWnd:窗口句柄
    
    lpPaint:包含了用来重画客户区的程序信息
    typedef struct tagPAINTSTRUCT {
    
    HDC hdc;             //用来在客户去画图的设备表
    
    BOOL fErase;      //客户背景区是否需要重绘(stru=是)
    
    RECT rcPaint;     //无效客户区
    
    BOOL fRestore;   //保留
    
    BOOL fIncUpdate;//保留
    
    BYTE rgbReserved[16];//保留
    
    } PAINTSTRUCT;

    前面3段代码主要围绕设备句柄处理WM_PAINT消息。

    如果使用TextOut在输出一段文字,调整不好位置的话容易遮挡之前输出的文字。代码如下

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TCHAR* str = TEXT("hello");
    52     TCHAR* str1 = TEXT("World");
    53     switch (message)
    54     {
    55         case WM_DESTROY:
    56             PostQuitMessage(0);//发送WM_QUIT消息
    57             return 0;
    58         case WM_PAINT:
    59             hdc = BeginPaint(hwnd, &pt);
    60             TextOut(hdc, 0, 0, str, _tcslen(str));
    61             TextOut(hdc, 5, 10, str1, _tcslen(str1));
    62             EndPaint(hwnd, &pt);
    63             
    64             /* 第二种
    65             hdc = GetDC(hwnd);
    66             TextOut(hdc, 0, 0, str, _tcslen(str));
    67             ReleaseDC(hwnd, hdc);
    68             ValidateRect(hwnd, NULL);
    69             */
    70 
    71             /* 第三种
    72             hdc = GetWindowDC(hwnd);
    73             TextOut(hdc, 100, 100, str, _tcslen(str));
    74             ReleaseDC(hwnd, hdc);
    75             ValidateRect(hwnd, NULL);
    76             */
    77 
    78             return 0;
    79         default:
    80             break;
    81     }
    82 
    83     return DefWindowProc(hwnd, message, wParam, lParam);
    84 }
    View Code

    输出结果

    获得字体高度的函数:BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC lptm );

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TEXTMETRIC ts;
    52     TCHAR* str = TEXT("hello");
    53     TCHAR* str1 = TEXT("World");
    54     switch (message)
    55     {
    56         case WM_DESTROY:
    57             PostQuitMessage(0);//发送WM_QUIT消息
    58             return 0;
    59         case WM_PAINT:
    60             hdc = BeginPaint(hwnd, &pt);
    61             TextOut(hdc, 0, 0, str, _tcslen(str));
    62             GetTextMetrics(hdc, &ts);
    63             TextOut(hdc, 0, ts.tmHeight, str1, _tcslen(str1));
    64             EndPaint(hwnd, &pt);
    65             
    66             /* 第二种
    67             hdc = GetDC(hwnd);
    68             TextOut(hdc, 0, 0, str, _tcslen(str));
    69             ReleaseDC(hwnd, hdc);
    70             ValidateRect(hwnd, NULL);
    71             */
    72 
    73             /* 第三种
    74             hdc = GetWindowDC(hwnd);
    75             TextOut(hdc, 100, 100, str, _tcslen(str));
    76             ReleaseDC(hwnd, hdc);
    77             ValidateRect(hwnd, NULL);
    78             */
    79 
    80             return 0;
    81         default:
    82             break;
    83     }
    84 
    85     return DefWindowProc(hwnd, message, wParam, lParam);
    86 }
    View Code

    前面讲到3中获取hdc的方式,第一种 BeginPaint  &  EndPaint,在EndPaint之后,原来的无效区就成为有效区,不在发送WM_PAINT重绘

    而第二三种方法,在ReleaseDC后,并不能使原来的无效区成为有效区,一直是无效区。需要使用ValidateRect(hwnd, NULL);来使原来的无效区变成有效区,但是这种方法效率太低,是整个窗口的重回。可以先获取窗口无效区,在针对这个无效区进行重绘

    BOOL ValidateRect(
        HWND hWnd,          // 窗口的句柄
        CONST RECT *lpRect  // 指向RECT结构的指针
    );

    也就是代码顺序

    GetUpdateRect

    ValidateRect    //让某一个矩形区域变得有效

    如果只用第一种方法,就不必写上面2个函数了。

    获取窗口无效区域: BOOL GetUpdateRect( HWND hWnd, LPRECT lpRect, BOOL bErase );

    bErase :如果不想擦除背景,这个值就为false.

    BOOL GetUpdateRect(
          HWND   hWnd,
          LPRECT lpRect,
          BOOL   bErase
    );

    改变hdc设备句柄中字体颜色

    COLORREF SetTextColor( HDC hdc, COLORREF color );

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg,NULL,0,0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     HDC hdc;
    50     PAINTSTRUCT pt;
    51     TEXTMETRIC ts;
    52     TCHAR* str = TEXT("hello");
    53     TCHAR* str1 = TEXT("World");
    54     switch (message)
    55     {
    56         case WM_DESTROY:
    57             PostQuitMessage(0);//发送WM_QUIT消息
    58             return 0;
    59         case WM_PAINT:
    60             hdc = BeginPaint(hwnd, &pt);
    61             SetTextColor(hdc, RGB(0x0, 0xFF, 0));
    62             TextOut(hdc, 0, 0, str, _tcslen(str));
    63             GetTextMetrics(hdc, &ts);
    64             TextOut(hdc, 0, ts.tmHeight, str1, _tcslen(str1));
    65             EndPaint(hwnd, &pt);
    66             
    67             /* 第二种
    68             hdc = GetDC(hwnd);
    69             TextOut(hdc, 0, 0, str, _tcslen(str));
    70             ReleaseDC(hwnd, hdc);
    71             ValidateRect(hwnd, NULL);
    72             */
    73 
    74             /* 第三种
    75             hdc = GetWindowDC(hwnd);
    76             TextOut(hdc, 100, 100, str, _tcslen(str));
    77             ReleaseDC(hwnd, hdc);
    78             ValidateRect(hwnd, NULL);
    79             */
    80 
    81             return 0;
    82         default:
    83             break;
    84     }
    85 
    86     return DefWindowProc(hwnd, message, wParam, lParam);
    87 }
    View Code

    可以在Win10上选好颜色,然后初始化RGB 

    桌面->右键->个性化->颜色->自定义颜色

    创建画刷函数

    HBRUSH CreateSolidBrush( COLORREF color );

     1 #include<Windows.h>
     2 #include<tchar.h>
     3 #define NUM 1000
     4 
     5 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     6 
     7 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     8 {
     9     WNDCLASS WndClass;
    10     TCHAR* ClassName = TEXT("MyClass");
    11     HWND hwnd;
    12     MSG msg;
    13     HBRUSH hBrush;
    14     hBrush = CreateSolidBrush(RGB(0xFF, 0, 0));
    15 
    16     WndClass.cbClsExtra = 0;
    17     WndClass.cbWndExtra = 0;
    18     WndClass.hbrBackground = hBrush;
    19     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    20     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    21     WndClass.hInstance = hInst;
    22     WndClass.lpfnWndProc = WindProc;
    23     WndClass.lpszClassName = ClassName;
    24     WndClass.lpszMenuName = NULL;
    25     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    26 
    27     if (!RegisterClass(&WndClass))
    28     {
    29         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    30         return 0;
    31     }
    32 
    33     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, 500, 300, NULL, NULL, hInst, NULL);
    34     if (hwnd == NULL)
    35     {
    36         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    37         return 0;
    38     }
    39     ShowWindow(hwnd, nShow);
    40     UpdateWindow(hwnd);
    41 
    42     while (GetMessage(&msg, NULL, 0, 0))
    43     {
    44         TranslateMessage(&msg);
    45         DispatchMessage(&msg);
    46     }
    47 
    48     return 0;
    49 }
    50 
    51 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    52 {
    53     HDC hdc;
    54     PAINTSTRUCT pt;
    55     TEXTMETRIC ts;
    56     TCHAR* str = TEXT("hello");
    57     TCHAR* str1 = TEXT("World");
    58     switch (message)
    59     {
    60     case WM_DESTROY:
    61         PostQuitMessage(0);//发送WM_QUIT消息
    62         return 0;
    63     case WM_PAINT:
    64         hdc = BeginPaint(hwnd, &pt);
    65         SetTextColor(hdc, RGB(0x0, 0xFF, 0));
    66         TextOut(hdc, 0, 0, str, _tcslen(str));
    67         GetTextMetrics(hdc, &ts);
    68         TextOut(hdc, 0, ts.tmHeight, str1, _tcslen(str1));
    69         EndPaint(hwnd, &pt);
    70 
    71         /* 第二种
    72         hdc = GetDC(hwnd);
    73         TextOut(hdc, 0, 0, str, _tcslen(str));
    74         ReleaseDC(hwnd, hdc);
    75         ValidateRect(hwnd, NULL);
    76         */
    77 
    78         /* 第三种
    79         hdc = GetWindowDC(hwnd);
    80         TextOut(hdc, 100, 100, str, _tcslen(str));
    81         ReleaseDC(hwnd, hdc);
    82         ValidateRect(hwnd, NULL);
    83         */
    84 
    85         return 0;
    86     default:
    87         break;
    88     }
    89 
    90     return DefWindowProc(hwnd, message, wParam, lParam);
    91 }
    View Code

    改变字体大小

     1 #include<Windows.h>
     2 
     3 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
     4 
     5 int WinMain(HINSTANCE hInst, HINSTANCE tmp, LPSTR szCmd, int nShow)
     6 {
     7     WNDCLASS WndClass;
     8     TCHAR* ClassName = TEXT("MyClass");
     9     HWND hwnd;
    10     MSG msg;
    11 
    12     WndClass.cbClsExtra = 0;
    13     WndClass.cbWndExtra = 0;
    14     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    15     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    16     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    17     WndClass.hInstance = hInst;
    18     WndClass.lpfnWndProc = WindProc;
    19     WndClass.lpszClassName = ClassName;
    20     WndClass.lpszMenuName = NULL;
    21     WndClass.style = CS_VREDRAW | CS_HREDRAW;
    22 
    23     if (!RegisterClass(&WndClass))
    24     {
    25         MessageBox(NULL, TEXT("Gegister Class Fail!!"), TEXT("error"), MB_OK);
    26         return 0;
    27     }
    28 
    29     hwnd = CreateWindow(ClassName, TEXT("Hello"), WS_OVERLAPPEDWINDOW, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL);
    30     if (hwnd == NULL)
    31     {
    32         MessageBox(NULL, TEXT("Create Window Fail!!"), TEXT("error"), MB_OK);
    33         return 0;
    34     }
    35     ShowWindow(hwnd, nShow);
    36     UpdateWindow(hwnd);
    37 
    38     while (GetMessage(&msg, NULL, 0, 0))
    39     {
    40         TranslateMessage(&msg);
    41         DispatchMessage(&msg);
    42     }
    43 
    44     return 0;
    45 }
    46 
    47 LRESULT CALLBACK WindProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    48 {
    49     TEXTMETRIC ts;
    50     TCHAR* str1 = TEXT("World");
    51     HDC hdc;
    52     PAINTSTRUCT pt;
    53     TCHAR* str = TEXT("hello");
    54     HFONT hFont;
    55     hFont = CreateFont(50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
    56     switch (message)
    57     {
    58     case WM_DESTROY:
    59         PostQuitMessage(0);//发送WM_QUIT消息
    60         return 0;
    61     case WM_PAINT:
    62         hdc = BeginPaint(hwnd, &pt);
    63         SelectObject(hdc, hFont);
    64         SetTextColor(hdc, RGB(0x0, 0xFF, 0));
    65         TextOut(hdc, 0, 0, str, _tcslen(str));
    66         GetTextMetrics(hdc, &ts);
    67         TextOut(hdc, 0, ts.tmHeight, str1, _tcslen(str1));
    68         EndPaint(hwnd, &pt);
    69 
    70         /* 第二种
    71         hdc = GetDC(hwnd);
    72         TextOut(hdc, 0, 0, str, _tcslen(str));
    73         ReleaseDC(hwnd, hdc);
    74         ValidateRect(hwnd, NULL);
    75         */
    76 
    77         /* 第三种
    78         hdc = GetWindowDC(hwnd);
    79         TextOut(hdc, 100, 100, str, _tcslen(str));
    80         ReleaseDC(hwnd, hdc);
    81         ValidateRect(hwnd, NULL);
    82         */
    83 
    84         return 0;
    85     default:
    86         break;
    87     }
    88 
    89     return DefWindowProc(hwnd, message, wParam, lParam);
    90 }
    View Code

    WM_PAINT消息的来源和处理方式

    客户区:客户区是一块应用程序可以自由绘图并向用户传达可视输出的区域。

    WM_PAINT何时产生?

    当窗口的客户区的部分或全部“无效”且必须“更新”时,应用程序将得到此通知。这也就意味着窗口必须被“重绘”。

    何种情况下客户区会变为无效?

    ①当窗口被首次创建时,整个客户区都是无效的,因为此时应用程序尚未在该窗口上绘制任何东西。第一条WM_PAINT消息(通常在应用程序调用WinMain中的UpdateWindow时出现)将指示窗口过程在窗口客户区进行绘制。
    ②在调整窗口的尺寸时,客户区也会变为无效。你可能还记得在前面的程序中,我们将窗口类结构的style字段设为了标记CS_HREDRAW和CSVREDRAW。这就指示Windows当窗口尺寸发生变化时,整个窗口都应宣布无效。在此之后,窗口过程将接收到一条WM_PAINT消息。
    ③如果先最小化窗口,然后再将窗口恢复到原先的尺寸,Windows并不会保存客户区的内容。在图形环境中,这种情况下需要保存的数据太多了。对此,Windows采取的策略是宣布窗口无效。窗口过程接收到WM_PAINT消息后,会自行恢复窗口的内容。
    ④在屏幕中拖动窗口导致窗口之间发生重叠时,Windows并不负责保存被另一个窗口覆盖的区域。当被覆盖的区域在后来不再被遮挡时,窗口被标记为无效。窗口过程会收到一条WM_PAINT消息,并对窗口的内容进行重绘。

    例外情况?

    鼠标滑过窗口,此时不发送WM_PAINT消息。这个重绘,由系统完成。

    强制窗口重绘的函数:InvalidateRect和InvalidateRgn。

    强制制定某一区域无效,需要重绘

    BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

    hWnd:想让哪个窗口的客户区无效

    lpRect:客户无效区域

    bErase:窗口背景是否需要重新绘制,如果是TRUE,那么窗口背景被擦去,需要重新绘制。

    BOOL InvalidateRgn( HWND hWnd, HRGN hRgn, BOOL bErase );

    hWnd:想让哪个窗口的客户区无效

    hRgn:客户无效区域

    bErase:窗口背景是否需要重新绘制,如果是TRUE,那么窗口背景被擦去,需要重新绘制。

    HRGN和RECT之间的相互转换:CreateRectRgnIndirect

    HRGN CreateRectRgnIndirect( CONST RECT *lprect );

     

  • 相关阅读:
    两个服务器上SQLServer实例之间配置Service Broker示例
    处理数据库镜像问题的一个案例
    oracel修改密码
    Oracle报错
    如何创建ORACLE大文件表空间
    创建、删除表空间
    oracle中新建用户和赋予权限
    非常全的VsCode快捷键
    VS Code常用快捷键
    启动Weblogic问题集锦
  • 原文地址:https://www.cnblogs.com/kelamoyujuzhen/p/9302055.html
Copyright © 2020-2023  润新知