• Windos编程中窗口的尺寸cxClient和cyClient初始化的问题


    前言

    学习小甲鱼的画(sin)函数的例子,发现最开始创建窗口时cxClient和cyClient不能很好的赋值

    WM_SIZE和WM_PAINT

    经过我的实践发现:在刚刚创建窗口时WM_SIZE和WM_PAINT消息的调用顺序是随机的
    调试下面的代码片段

     case WM_SIZE:
            OutputDebugString(TEXT("调试size消息
    "));
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            OutputDebugString(TEXT("调试paint消息
    "));
            hdc = BeginPaint(hwnd, &ps);//获得设备句柄
            LineTo(hdc, cxClient, cyClient);
            EndPaint(hwnd, &ps);// 函数标记指定窗口的绘画过程结束
            return 0;
    

    输出结果1(我电脑的多数情况):

    调试paint消息
    调试size消息
    

    输出结果2:

    调试size消息
    调试paint消息
    

    如果cxClient和cyClient需要经过WM_SIZE来初始化,并且WM_PAINT消息处理中需要使用这两个变量,那么第一次的WM_PAINT可能会不正常
    这个时候可以选择手动调整一下窗口的大小或者刷新一下客户区,但是用户体验肯定是很差的,因为我需要程序一运行就出现画面

    一种解决方案

    由于WM_CREATE消息肯定优先于WM_PAINT处理,那么我们可以在处理WM_CREAT时初始化cxClient和cyClient
    利用GetClientRect获取当前的矩形结构

    case WM_CREATE:
            GetClientRect(hwnd, &rect);
            cxClient = rect.right-rect.left ;
            cyClient = rect.bottom- rect.top ;
            return 0;
    

    (sin)函数代码

    /* -------------------------------------------------------------------
                        MyWindows.c -- 基本窗口模型
                                    《Windows 程序设计(SDK)》视频教程
    --------------------------------------------------------------------*/
    
    #include <Windows.h>
    #include <tchar.h>
    #include <math.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
    
    
        static TCHAR szAppName[] = TEXT("MyWindows");
        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("这个程序需要在 Windows NT 才能执行!"), szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,//类名
            TEXT("鱼C工作室"),//标题
            WS_OVERLAPPEDWINDOW,//风格
            CW_USEDEFAULT,//初始x坐标
            CW_USEDEFAULT,//初始y坐标
            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 cxClient, cyClient;
        HDC hdc;//设备环境句柄
        PAINTSTRUCT ps;//绘制结构
        RECT rect;//矩形结构
        //int stx = 0, sty =0;
        POINT apt[1000];
        int num = 1000;
        switch (message)
        {
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_CREATE:
            GetClientRect(hwnd, &rect);
            cxClient = rect.right-rect.left ;
            cyClient = rect.bottom- rect.top ;
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);//获得设备句柄
    
            LineTo(hdc, cxClient, cyClient);
            for (int i = 0; i < num; i++) {
                apt[i].x = i * cxClient / num;
                apt[i].y = (long)(cyClient / 2 * sin(i * 3.1415926 * 2.0 / num)) + cyClient / 2;
            }
            Polyline(hdc, apt, num);
            EndPaint(hwnd, &ps);// 函数标记指定窗口的绘画过程结束
      
             return 0;
    
        case WM_DESTROY://窗口关闭
            PostQuitMessage(0);
            return 0;
        }
    
        return DefWindowProc(hwnd, message, wParam, lParam);//交给windows去处理
    }
    
  • 相关阅读:
    WERKZEUG之WSGI阅读笔记
    Express4+Mongodb超简单入门实例
    git 命令小结
    GreenSock Animation Platform
    Nodejs开发框架Express3.0开发手记–从零开始
    交互设计实用指南系列(1) – 操作入口明确
    交互设计实用指南系列(4)—简洁清晰,自然易懂
    交互设计实用指南系列(5) – 突出重点,一目了然
    交互设计实用指南系列(6) –标签明晰、有效
    交互设计实用指南系列(8)—深广度平衡
  • 原文地址:https://www.cnblogs.com/carcar/p/12689000.html
Copyright © 2020-2023  润新知