【问题标题】:Winapi Window in c not respondingc中的Winapi窗口没有​​响应
【发布时间】:2020-12-10 16:11:18
【问题描述】:

我一直在尝试使用 WinAPI 制作一个简单的窗口,它会编译并链接一些警告,当我打开程序时会显示该窗口,但是当我尝试与之交互时,会播放 Windows 警告声音并且它不允许我使用窗口,甚至不能关闭它,我必须使用任务管理器。

为了编译它,我在命令行中使用了微软的“cl.exe”:

cl /c window.c

警告是:

window.c(39): warning C4133: 'function': incompatible types, from 'LPSTR' to 'HINSTANCE'
window.c(40): warning C4133: 'function': incompatible types, from 'LPSTR' to 'HINSTANCE'
window.c(41): warning C4047: '=': 'HBRUSH' differs in levels of indirection from 'int'

要链接我使用crinkler 和命令行:

crinkler /NODEFAULTLIB /ENTRY:main /SUSBYSTEM:WINDOWS /TINYHEADER /TINYIMPORT /OUT:c.exe window.obj kernel32.lib user32.lib

警告是:

: warning LNK: Entry point not at start of section, jump necessary

我使用的代码是:

#include <windows.h>

#define WINDOW_STYLE        WS_VISIBLE+WS_OVERLAPPEDWINDOW-WS_THICKFRAME-WS_MAXIMIZE
#define WINDOW_WIDTH        640
#define WINDOW_HEIGHT       480

static const char* window_name = "My Window";
RECT window_rect = {0, 0, WINDOW_HEIGHT, WINDOW_WIDTH};

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_CLOSE:
        PostQuitMessage(0);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

int main()
{
    int ret = 0;
    HMODULE instance = GetModuleHandleA(NULL);

    AdjustWindowRect(&window_rect, WINDOW_STYLE, FALSE);

    WNDCLASSEXA window_class;
    window_class.cbSize = 48;
    window_class.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
    window_class.lpfnWndProc = WindowProc;
    window_class.cbClsExtra = 0;
    window_class.cbWndExtra = 0;
    window_class.hInstance = instance;
    window_class.hIcon = LoadIconA(IDI_APPLICATION, 0);
    window_class.hCursor = LoadCursorA(IDI_APPLICATION, 0);
    window_class.hbrBackground = COLOR_WINDOW;
    window_class.lpszMenuName = 0;
    window_class.lpszClassName = window_name;
    window_class.hIconSm = 0;

    if (RegisterClassExA(&window_class)) {

        HWND window = CreateWindowExA(
            0,
            window_name,
            window_name,
            WINDOW_STYLE,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            window_rect.right - window_rect.left,
            window_rect.bottom - window_rect.top,
            0,
            0,
            instance,
            NULL);

        ShowWindow(window, SW_SHOW);
        UpdateWindow(window);

        MSG msg;

        while(1)
        {
            if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
                if (msg.message == WM_QUIT) {
                    ExitProcess(0);
                    break;
                } else {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
        }
    } else {
        ret = 1;
    }

    ExitProcess(0);

    return ret;
}

有人知道怎么解决吗?谢谢。

【问题讨论】:

  • 您的消息循环应该使用GetMessage() 而不是PeekMessage()。当您的应用程序没有消息要处理时,您正在运行一个繁忙的循环占用 CPU 周期。使用GetMessage() 将允许应用程序在无事可做时进入睡眠状态。另外,不要使用"magic numbers" - 在设置window_class.cbSize 时使用sizeof(window_class)。并且您收到 HBRUSH 警告,因为您错误地设置了 window_class.hbrBackground。根据文档使用window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  • 这里是handling WM_CLOSE 的一个例子,网上还有很多其他例子可以说明你想做的事情
  • @use 这没用。 OP 没有使用 CRT,因此他们不能依赖它来执行进程关闭。如果没有 CRT,触发进程关闭的责任已转移到客户端代码。提供的代码就是这样做的。

标签: c windows winapi window cl


【解决方案1】:

下面这行并不像你认为的那样:

#define WINDOW_STYLE WS_VISIBLE+WS_OVERLAPPEDWINDOW-WS_THICKFRAME-WS_MAXIMIZE

虽然有些常见,有时甚至会产生正确的值,但它是实现位操作的一种非常脆弱的方法。在这种特殊情况下,表达式扩展为:

0x10000000L + 0x00CF0000L - 0x00040000L - 0x01000000L

这会产生值0xFFCB0000L1(由于意外使用了WS_MAXIMIZE 而不是WS_MAXIMIZEBOX)。这将转换为具有以下样式的窗口:

  • WS_POPUP
  • WS_CHILD(注意,这已经和WS_POPUP互斥)
  • WS_ICONIC
  • WS_VISIBLE
  • WS_DISABLED
  • ...

作为documented:

WS_DISABLED: 窗口最初被禁用。 禁用的窗口无法接收来自用户的输入。要在创建窗口后更改此设置,请使用 EnableWindow 函数。

这就解释了为什么你不能与你的窗口进行交互。解决方法很简单:使用位运算符而不是算术运算符:

#define WINDOW_STYLE (WS_VISIBLE | WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZE)

1撇开这个事实,有符号溢出的行为是未定义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-16
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多