50_WM_PAINT消息

作业讲解

  1. 添加计数器,创建新窗口,计数器增加,关闭一个窗口,计数器减少
  2. 保存第一个窗口句柄,每次关闭的时候比较一下

关闭窗口资源释放时

  1. 当一个进程退出的时候,与这个进程有关的一切资源都被释放

背景颜色

  1. WNDCLASS.hbrBackground = (HBRUSH)COLOR + 1; //规定要加1

关键消息

  • WM_PAINT:绘图消息,只告诉程序绘图的时机到了,绘什么图由程序员写
    • DrawText:相当于文本框里面插入文字
      • HDC hDC
        • DC – Device context设备上下文,对于屏幕的抽象
        • BeginPaint:对指定的窗口进行绘制,获取窗口的DC,用完需要释放,不然一直占用gdi
        • EndPaint:用于释放资源
      • LPCTSTR lpString:文本的缓冲区
      • Int nCount:文本字符串长度
      • LPRECT lpRect:矩形
      • UINT uFormat:格式,文本显示格式
    • 客户区与非客户区
      • 非客户区:菜单,标题,滚动条,状态栏所占的区域
      • 客户区:除了非客户区
    • 日志信息
      • OutputDebugString:提示字符串,通过dbgview.exe来查看,release版也能用
    • 画直线
      • MoveToEx:定位起点
      • LineToEx:终点
    • 画矩形:Rectangle
    • 时机,窗口有无效区的才有WM_PAINT消息
      • 最大化
      • 最小化还原的时候
      • 修改窗口尺寸
      • 遮挡的部分被还原(鼠标遮挡被系统优化掉了),这个部分叫做无效区(update region)
      • 创建窗口
    • 当没有无效区的时候需要绘制的时候
      • InvalidateRect:设置无效区
      • GetDC:拿到dc,也需要释放,ReleaseDC
    • BeginPaint与GetDC的区别
      • BeginPaint会清空无效区,但是GetDC不会
      • BeginPaint绘制图像区域不能超过无效区,GetDc无视无效区
    • BeginPaint只能在WM_PAINT消息中使用
    • SPY++获得其它窗口的窗口句柄
      • 拿到屏幕DC
    • GetDc(NULL);
    • 拿到窗口DC:
      • GetWindowDC,使用ReleaseDC释放,可以不在WM_PAINT消息里
      • TextOut也是绘制文字,可以不在WM_PAINT消息里
      • GetClinetRect,获取客户区大小
  • 键盘消息
  • 区分WM_CLOSE消息和WM_DESTROY

作业

  1. 在窗口的中心显示一个40*40的矩形
  2.  //test.cpp
    #include 
    #include 
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    void MyErrorException()
    {
        LPVOID lpMsgBuf;
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            GetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
            (LPTSTR)& lpMsgBuf,
            0,
            NULL
        );
        // Process any inserts in lpMsgBuf.
        // ...
        // Display the string.
        MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), 
            MB_OK | MB_ICONINFORMATION);
        // Free the buffer.
        LocalFree(lpMsgBuf);
    
    }
    
    int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, 
        _In_ LPSTR lpCmdLine, _In_ int nShowCmd
    )
    {
    
        WNDCLASS wnd;
        wnd.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wnd.cbClsExtra = 0;
        wnd.cbWndExtra = 0;
        wnd.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wnd.hCursor = NULL;
        wnd.hIcon = NULL;
        wnd.hInstance = hInstance;
        wnd.lpfnWndProc = (WNDPROC)WndProc;
        wnd.lpszClassName = TEXT("MyWndClass");
        wnd.lpszMenuName = NULL;
    
        ATOM aTom = RegisterClass(&wnd);
    
        if (aTom == 0)
        {
            MyErrorException();
            return 0;
        }
    
        HWND hWnd;
    
        hWnd = CreateWindow(TEXT("MyWndClass"),
            TEXT("窗口"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstance,
            NULL);
        
        if (hWnd == NULL)
        {
            MyErrorException();
            return 0;
        }
    
        ShowWindow(hWnd, nShowCmd);
        UpdateWindow(hWnd);
    
        MSG msg;
        while (GetMessage(&msg, NULL, NULL, NULL))
        {
            DispatchMessage(&msg);
        }
    
        return 0;
    }
    
    LRESULT  CALLBACK WndProc(
        HWND hWnd,              // handle to window
        UINT Msg,               // message
        WPARAM wParam,          // first message parameter
        LPARAM lParam           // second message parameter
    )
    
    {
        switch (Msg)
        {
        case WM_PAINT:
            RECT rect;
            HDC hdc;
            PAINTSTRUCT ps;
            GetClientRect(hWnd, &rect);
            hdc = BeginPaint(hWnd, &ps);
            if (hdc == NULL)
            {
                MyErrorException();
                return 0;
            }
            Rectangle(hdc,
                (rect.right - rect.left) / 2 - 20,
                (rect.bottom - rect.top) / 2 - 20,
                (rect.right - rect.left) / 2 + 20,
                (rect.bottom - rect.top) / 2 + 20
            );
            //Rectangle(hdc, 0, 100, 200, 200);
            EndPaint(hWnd, &ps);
            return 0;
        case WM_CLOSE:
            PostQuitMessage(0);
            return 0;
        default:
            break;
        }
    
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
0 条评论
发表一条评论