49_创建窗口

作业讲解

  1. Z:zero P ZP STR,指针指向零结尾的字符串指针

ZZ:两个零结尾

NZ:不已零结尾的字符数组

     2.MessageBox是C语言的名称粉碎规则,C++会出错,extern “C” {}

创建窗口的六要素

  • 设计注册窗口类(非必须,是用系统预定义的窗口类)
    • 窗口类创建出来的叫做窗口实例,一对多的关系
    • 注册窗口类RegisterClass,指向WNDCLASS结构体
      • UNIT style 风格,宏常量按位存,为了组合方便
        • CS_DBLCLKS,当用户快速按两次表示有双击
        • CS_HREDRAW,当拖动窗口修改窗口尺寸的时候重新绘制窗口
        • CS_VREDRAW,当拖动窗口修改窗口尺寸的时候重新绘制窗口
        • 去掉风格样式,大量使用位运算,&~或者^
  • WNDPROC lpfnWndPro:回调函数
  • Int cbClsExtra:附加,默认给0
  • Int cbWndExtra:附加,默认给0
  • HINSTANCE hInstance:实例句柄或者父实例句柄
  • HICO hIco:图标,可以给NULL
  • HCURSOR hCurso:光标, 可以给NULL
  • HBRUSH:hbrBackground:背景画刷,背景颜色, 可以给NULL
  • LPCTSTR:lpszMenuName:菜单, 可以给NULL
  • LPCTSTR:lpszClassName:窗口类名,TEXT(“WNDCLASSNAME”)
  • 返回值是ATOM,windows内部对窗口类名的hash键值,注册失败返回0,一个窗口类名没释放之前只能注册一次。
  • Windows会把错误码保存起来,是用GetLastError API获取
  1. 工具-错误查找,输入十进制的错误码
  2. @err,hr
  3. *(unsigned long *)(tib+0x34), hr
  4. dwErrCode,hr
  5. 2,hr
  • 错误信息格式化,FormatMessage
  • 创建窗口实例
    • CreateWindow
      • LPCTSTR lpClassName:注册的窗口类
      • LPCTSTR lpwWindowName:窗口标题名
      • DWORD dwSytle:窗口风格
        • WS_CHILD:子窗口
        • WS_OVERLAPPED:重叠窗口,一般由多个子窗口组成
        • WS_POPUP:弹出窗口,一般是对话框
        • WS_OVERLAPPEDWINDOWS:重叠窗口,带很多东西
        • WS_CAPTION:标题菜单
        • WS_SYSMENU:系统菜单
        • WS_VISIBLE:显示窗口
  • Int X:在windows程序设计中x,y左边轴是左上角,可以用CW_USEDEFAULT默认坐标
  • Int Y:Y轴
  • Int nWidth:宽度
  • Int nHeight:高度
  • hWndParent:父窗口指针
  • HMENU hMenu:菜单
  • HINSTANCE hIstance:顶层实例句柄
  • LPVOID lpParam:参数
  • 显示窗口(非必须)
    • ShowWindow
      • HWND hWnd:显示那一个窗口
      • int nCmdShow:显示的状态
  • 更新窗口(非必须:xp上不能注释掉)
    • UpdateWindow
      • HWND hwnd:更新窗口句柄
  • 消息循环
    • 建立消息循环

在饭馆里面客人多,客人进来点餐,菜单给厨师,厨师做完上菜。三个客人进来,三个厨师分配完,此时第四个客人进来,先点菜,把菜单记下来,某个厨师做完接着取菜单

消息队列:当有消息进来排队,轮到它处理的时候再处理

    • GetMessage:如果没有消息,一直等,无返回
      • LPMSG lpMsg:传出的消息
        • HWND hwnd:给那一个句柄的
        • UINT message:消息种类,消息id
        • WPARAM wParam
        • LPARAM lParam
        • DWORD time:时间
        • POINT pt:指针
      • HWND hWnd:窗口句柄,给某个窗口,如果为NULL,不属于这个窗口的也获取
      • UINT wMsgFileterMin:消息取值最小范围,给0全取
      • UINT wMsgFileterMax:消息取值最大范围,给0全取
    • DispatchMessage:派发消息,找到对应的窗口来处理消息
  • 实现窗口回调函数(非必须):用来处理消息
    • LRESULT CALLBACK WNDPROC(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    • DefWIndowProc:让系统处理消息
    • PostQuitMessage:退出消息循环,在处理消息WN_CLOSE的时候
      • Int nExitCode:退出码
  • WM_LBUTTONDOWN:鼠标左键单击消息
    • wParam:键盘按键
    • lParam:光标坐标
  • wsprintf:唯一一个C调用约定,谁调用谁平衡栈
  • DesrotyWindow:摧毁一个窗口

作业

  1. 鼠标左键按下,弹出一个新窗口,点击关闭按钮,关闭窗口,当只剩下一个窗口的时候,退出程序
  2.  //test1.cpp
    #include 
    
    LRESULT WINAPI WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
    INT g_nHWNDNumber = 0; //记录窗口数量
    
    void MyErrorExcepation()
    {
        LPVOID lpMsgBuf;
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            GetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)& lpMsgBuf,
            0,
            NULL
        );
    
        MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
    
        LocalFree(lpMsgBuf);
    }
    
    int WINAPI WinMain(HINSTANCE hInstacne, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
    
        WNDCLASS wc;
        wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = (WNDPROC)WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstacne;
        wc.hIcon = NULL;
        wc.hCursor = NULL;
        wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        wc.lpszMenuName = NULL;
        wc.lpszClassName = TEXT("MyHWND");
    
        //注册窗口类
        ATOM aResult = RegisterClass(&wc);
        //检测是否注册成功
        if (aResult == 0)
        {
            MyErrorExcepation();
            return 0;
        }
    
        //创建窗口
        //在CreateWindow创建窗口时,系统回调窗口过程,需要窗口过程返回非0值,CreateWindow才能创建成功。
        HWND hWnd = CreateWindow
        (
            TEXT("MyHWND"),
            TEXT("我的父窗口"),
            WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstacne,
            NULL
        );
        //检查
        if (hWnd == NULL)
        {
            MyErrorExcepation();
            return 0;
        }
        g_nHWNDNumber++;
        //显示
        ShowWindow(hWnd, nCmdShow);
        //更新
        UpdateWindow(hWnd);
        //消息循环
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            //派发消息
            DispatchMessage(&msg);
        }
    
        return 0;
    }
    
    LRESULT WINAPI WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_CLOSE:
            if (g_nHWNDNumber > 1)
            {
                DestroyWindow(hwnd);
                g_nHWNDNumber--;
            }
            else if (g_nHWNDNumber == 1)
            {
                PostQuitMessage(0);
                g_nHWNDNumber--;
            }
            return 0;
        case WM_LBUTTONDOWN://鼠标左键单击
            CreateWindow
            (
                TEXT("MyHWND"),
                TEXT("我的子窗口"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                NULL,
                NULL
            );
            g_nHWNDNumber++;
            return 0;
        case WM_RBUTTONDOWN:
            MessageBox(NULL, TEXT("右键"), TEXT("提示"),
                MB_OKCANCEL | MB_ICONINFORMATION);
            return 0;
        default:
            break;
        }
    
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    
  3. 鼠标左键按下,弹出一个新窗口,点击关闭按钮,关闭窗口,当关闭第一个窗口的时候,其他窗口都关闭,并退出程序
  4.  //test2.cpp 
    #include 
    
    LRESULT WINAPI WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
    HINSTANCE g_hTopInstacne = NULL;
    HWND* pParenthWnd = NULL;
    
    void MyErrorExcepation()
    {
        LPVOID lpMsgBuf;
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            GetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR)& lpMsgBuf,
            0,
            NULL
        );
    
        MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION);
    
        LocalFree(lpMsgBuf);
    }
    
    int WINAPI WinMain(HINSTANCE hInstacne, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
        g_hTopInstacne = hInstacne;
        WNDCLASS wc;
        wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = (WNDPROC)WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstacne;
        wc.hIcon = NULL;
        wc.hCursor = NULL;
        wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
        wc.lpszMenuName = NULL;
        wc.lpszClassName = TEXT("MyHWND");
    
        //注册窗口类
        ATOM aResult = RegisterClass(&wc);
        //检测是否注册成功
        if (aResult == 0)
        {
            MyErrorExcepation();
            return 0;
        }
    
        //创建窗口
        //在CreateWindow创建窗口时,系统回调窗口过程,需要窗口过程返回非0值,CreateWindow才能创建成功。
        HWND hWnd = CreateWindow
        (
            TEXT("MyHWND"),
            TEXT("我的父窗口"),
            WS_OVERLAPPEDWINDOW | WS_VISIBLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstacne,
            NULL
        );
        //检查
        if (hWnd == NULL)
        {
            MyErrorExcepation();
            return 0;
        }
        pParenthWnd = &hWnd;
        //显示
        ShowWindow(hWnd, nCmdShow);
        //更新
        UpdateWindow(hWnd);
        //消息循环
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            //派发消息
            DispatchMessage(&msg);
        }
    
        return 0;
    }
    
    LRESULT WINAPI WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_CLOSE:
            if (hwnd != *pParenthWnd)
            {
                DestroyWindow(hwnd);
            }
            else
            {
                PostQuitMessage(0);
            }
            return 0;
        case WM_LBUTTONDOWN://鼠标左键单击
            CreateWindow
            (
                TEXT("MyHWND"),
                TEXT("我的子窗口"),
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                *pParenthWnd,
                NULL,
                NULL,
                NULL
            );
            return 0;
        case WM_RBUTTONDOWN:
            MessageBox(NULL, TEXT("右键"), TEXT("提示"), 
                MB_OKCANCEL | MB_ICONINFORMATION);
            return 0;
        default:
            break;
        }
    
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    
0 条评论
发表一条评论