创建响应式 Windows winapi c++

Creating Responsive Windows winapi c++

本文关键字:winapi c++ Windows 响应 创建      更新时间:2023-10-16

我只是在学习使用 winapi 创建一个 gui,但我遇到了一个问题。 我可以创建一个这样的窗口

#include "stdafx.h"
#include <windows.h>
int main()
{
    HWND hwnd = CreateWindow(L"STATIC",NULL,WS_VISIBLE|WS_SYSMENU|WS_CAPTION,0,0,600,600,NULL,NULL,NULL,NULL);
    UpdateWindow(hwnd);
    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    _gettch();
}

但是当单击关闭按钮时,窗口不会关闭,并且窗口无法拖动或移动。 我想知道如何启用窗口的这些功能。

静态窗口不适用于普通窗口,您应该尝试查找如何使用 RegisterWindowEx 注册和处理您自己的类,然后使用相同的类名来创建窗口。您必须拥有自己的窗口过程才能处理消息。系统注册的所有窗口类都运行自己的默认窗口程序,据我所知,它们都没有处理WM_CLOSE(即关闭按钮),这就是您无法关闭它的原因。

对于您来说,主窗口始终使用类似WS_OVERLAPPEDWINDOW的东西,因此可以很清楚它是否可以,并从中消除您不需要的标志。

你如何设置它 :

WNDCLASSEX wndcls;
HWND hMainWnd;
// Register your own window class
    ZeroMemory(&wndcls,sizeof(WNDCLASSEX));
    wndcls.cbSize=sizeof(WNDCLASSEX);
    wndcls.style=CS_VREDRAW+CS_HREDRAW;
    wndcls.lpfnWndProc=&appWndFunc;
    wndcls.hInstance=hInstance;
    wndcls.hIcon=hMainIcon;     // or just LoadIcon(hInstance,MAKEINTRESOURCE(IDI_MAIN_ICON))
    wndcls.hIconSm=hMainIcon;
    wndcls.hCursor=LoadCursor((HINSTANCE)NULL,IDC_ARROW);
    wndcls.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE;
    wndcls.lpszClassName="myWndClass";
    if (RegisterClassEx(&wndcls)==0)
    {
        // failed to register class name
        return false;
    }
// Create window with your own class
    hMainWnd=CreateWindowEx(0,
                            "myWndClass","widnow title",
                            WS_OVERLAPPEDWINDOW|WS_VISIBLE,
                            0,
                            0,
                            250,
                            250,
                            hMainWnd,NULL,hInstance,NULL);
    if (hMainWnd==(HWND)NULL)
    {
        // failed to create main window
        return false;
    }

然后你的主循环:

bool bAppMainLoop=false
while(!bAppMainLoop)
{
    WaitMessage();
    while(PeekMessage(&emsg,NULL,0,0,PM_NOREMOVE))
    {
        if(GetMessage(&emsg,NULL,0,0)==0)
        {
            bAppMainLoop=true;
            break;
        }
        TranslateMessage(&emsg);
        DispatchMessage(&emsg);
    }
}

这比通常的设置多一点,所以让我解释一下,为了不烧毁CPU,你用WaitMessage等待一条消息,它会阻塞,直到发生一些事情,比如移动窗口,点击,绘画等。 如果有消息,PeekMessage 将返回 true,因此在 while 循环中调用它将确保它耗尽消息 quene, 如果 GetMessage 返回 0,它将获得消息,这意味着您的应用程序调用了 PostQuitMessage(0),因此在消息循环中找到了到达WM_QUIT,这意味着是时候脱离消息循环了。其余的翻译和调度按照它的名字做。

最后你需要自己的窗口过程:

LRESULT CALLBACK appWndFunc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    if (uMsg==WM_CLOSE)
    {
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

DefWindowProc 对于处理来自系统的所有常见消息至关重要,因此您不需要在此处处理这些消息。您只需响应WM_CLOSE消息,该消息是在您想要关闭窗口时发送的,并将退出消息发布到您将捕获并退出的消息循环中。

附加信息 :不需要释放你的东西,因为 windows 会为你这样做,所以下次启动程序时它不会被锁定,但至少在主循环后取消注册窗口类是一个很好的做法。

顺便说一句,这是错误的主函数:WinMain 这是正确的。另外,为了避免更多的错误,请确保编译Windows GUI应用程序。