窗口的创建

  1. 编写窗口生成器

    1. 注册某个 窗口类 (用字符串作为类名注册)
    2. 利用 窗口类 创建某个窗口
    3. 注意:每个自定义窗口类只能存在一个窗口实例
  2. 编写消息处理器(响应窗口操作)
  3. 循环处理窗口的操作

    1. GetMessage 获取消息
    2. DispatchMessage 派发消息(回调消息处理器)

主体结构

  1. 在程序中通过while配合GetMessage获取窗口的操作
  2. 如果有需要调用 DispatchMessage处理该消息(回调消息处理器)
  3. 再合适的时机 消息处理器 调用PostQuitMessage(0) ,不再处理任何窗口操作

消息处理器

  1. 消息处理器接收窗口的操作并且调用相应的函数
  2. 统一接受用户对窗口的操作参数
  3. 所有窗口的所有 操作/消息 都会调用这个函数

作为一个窗口必须有以下操作

  1. 显示
  2. 刷新
  3. 关闭
  4. ...
LRESULT CALLBACK MainWndProc(HWND hwnd,      // handle to window
    UINT uMsg,      // message identifier 消息码
    WPARAM wParam,  // first message parameter
    LPARAM lParam)   // second message parameter;
{

    switch (uMsg)
    {
        //case WM_NCCREATE:{
        //     return 0;
        //}
        //  break;
    
    case WM_COMMAND:
    {
        if (HIWORD(wParam) == 0) {
            //表示是菜单消息
            if (LOWORD(wParam) == ID_OPEN) {
                //表示打开按钮被点击
                //MessageBox(hwnd, NULL, NULL, NULL);
                //n_windows
                create_window(m_HINSTANCE, 100+ n_windows*10, 200+ n_windows*10, str_cat("test", n_windows));
            }
        }
    
    }
    break;
    
    case WM_CREATE:
        // Initialize the window. 
        return 0;
    
    case WM_PAINT:
        // Paint the window's client area. 
        return 0;
    
    case WM_SIZE:
        // Set the size and position of the window. 
        return 0;
    
    case WM_DESTROY:
        // Clean up window-specific data objects. 
    
        //手动投递WM_QUIT
        //PostMessage(hwnd,
        //            WM_QUIT,
        //            0,
        //            0);
    
        n_windows--;
        if (n_windows == 0) {
            PostQuitMessage(0);
        }
    
    
        return 0;
    
        // 
        // Process other messages. 
        // 
    
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
    
}

窗口生成器

为了简化窗口生成的代码我们通过封装函数来实现窗口的显示

/*
创建窗口
*/
int create_window(HINSTANCE hinstance,int x,int y,char * str_name) {
    //<<----注册窗口类
    WNDCLASSEX wcx;
    memset(&wcx, 0, sizeof(WNDCLASSEX));

    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_HREDRAW |
        CS_VREDRAW;                    // redraw if size changes 
    wcx.lpfnWndProc = MainWndProc;     // points to window procedure 
    wcx.cbClsExtra = 0;                // no extra class memory 
    wcx.cbWndExtra = 0;                // no extra window memory 
    wcx.hInstance = hinstance;         // handle to instance 
    wcx.hIcon = LoadIcon(NULL,
        IDI_APPLICATION);              // predefined app. icon 
    wcx.hCursor = LoadCursor(NULL,
        IDC_ARROW);                    // predefined arrow 
    wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);                  // white background brush 
    wcx.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);    // name of menu resource 
    //wcx.lpszClassName = _T("MainWClass");  // name of window class 
    wcx.lpszClassName = (LPCWSTR)str_name;  // name of window class 
    
    ATOM atom = RegisterClassEx(&wcx);
    
    if (atom == 0) {
        return 0;
    }
    //注册窗口类---->>
    
    //创建窗口
    HWND hWnd = CreateWindowA((LPCSTR)atom,
        str_name,
        WS_OVERLAPPEDWINDOW,//窗口具有的属性,我们这里设置为常规窗口 其他属性参考 https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowa
        x,
        y,
        800,
        600,
        NULL,
        NULL,
        hinstance,
        NULL);
    
    if (hWnd == NULL)
    {
        return 0;
    }
    
    //显示窗口
    ShowWindow(hWnd, SW_SHOW);
    
    //更新
    UpdateWindow(hWnd);
    
    n_windows++;
    return 1;
}

监听操作

主要是通过while配合消息队列来处理

/*
gui的main
*/
int WINAPI _tWinMain(HINSTANCE hinstance, //应用程序实例句柄,模块基址
    HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine,
    int nCmdShow)
{
    m_HINSTANCE = hinstance;
    create_window(hinstance,100,200,"windows0");      
    //create_window(hinstance,200,300,"windows1");
    //消息循环
    //线程拥有消息队列
    MSG msg;
    while (GetMessage(&msg,
        NULL,
        0,
        0) > 0)
    {
        //派发消息
        DispatchMessage(&msg);
    }
    return 0;
}
Last modification:October 26, 2018
如果觉得我的文章对你有用,请随意赞赏