c++ - 创建响应式 Windows winapi c++

标签 c++ windows user-interface hwnd

我刚开始学习使用 winapi 创建图形用户界面,但我遇到了一个问题。我可以创建一个这样的窗口

#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 循环中调用它会确保它耗尽消息队列,如果返回 0,GetMessage 将获取消息,这意味着您的应用程序调用了 PostQuitMessage(0),因此找到了 WM_QUIT在消息循环中,这意味着是时候从消息循环中跳出来了。其余的 Translate 和 Dispatch 按照其名称进行操作。

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

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 应用程序。

关于c++ - 创建响应式 Windows winapi c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19607944/

相关文章:

c++ - 当飞行中出现多个异常时会发生什么,如何捕捉它们?

c++ - 纯虚函数可能没有内联定义。为什么?

python - 如何使用 setuptools 安装可写共享和用户特定数据文件?

python - 将小部件添加到第三页会导致 Frames 调整大小

c++ - 使用 scons 管理版本的最佳实践?

c++ - 从USB存储器中检索序列号(Windows环境c++)

windows - 安排 Powershell 和批处理作业同步运行

c++ - SMBIOS 枚举值。文档错误?

c++ - 制作工作台类型界面的想法

windows - 鼠标移动后 SetCursor 恢复