Win32 API (C):更改焦点后窗口在运行时永久消失?

问题描述 投票:0回答:1

我正在创建一个窗口应用程序,目前正在用 C 语言处理 Windows 平台层。我希望应用程序更新循环在其窗口未获得焦点时暂停,否则不暂停。

我当前处理事件的方式可以很好地处理

[X]
(关闭)图标和最大化图标(即调整窗口大小)。但是,每当我单击 Windows 生成的应用程序窗口右上角的
[-]
(最小化)图标时,该窗口就会永远消失,并且我无法让它重新出现或将焦点返回到它以通过键绑定退出;我必须从命令行终止该应用程序。每当窗口将焦点更改为背景时,都会发生同样的情况;它消失并且无法再次聚焦。

与窗口焦点更改无关的所有其他事件代码都工作正常:按键事件、鼠标事件、窗口关闭/调整大小等。

最小可重现示例:

#include <stdio.h>
#include <string.h>
#include <windows.h>

typedef _Bool bool;
#define true    ( ( bool ) 1 )
#define false   ( ( bool ) 0 )

bool suspended;
bool running;

void
platform_update
( void )
{
    MSG message;
    while ( PeekMessageA ( &message , 0 , 0 , 0 , PM_REMOVE ) )
    {
        TranslateMessage ( &message );
        DispatchMessageA ( &message );
    }
}

LRESULT CALLBACK
platform_process_message
(   HWND    window
,   UINT    message
,   WPARAM  w_param
,   LPARAM  l_param
)
{
    switch ( message )
    {
        case WM_CLOSE:
        {
            printf ( "Quitting application.\n" );
            running = false;
            return 0;
        }

        case WM_DESTROY:
        {
            PostQuitMessage ( 0 );
            return 0;
        }

        case WM_ACTIVATE:
        {
            if ( running )
            {
                if ( LOWORD ( w_param ) == WA_INACTIVE )
                {
                    printf ( "Suspending application.\n" );
                    suspended = true;
                }
                else
                {
                    printf ( "Resuming application.\n" );
                    suspended = false;
                }
            }
        }
        break;

        case WM_SIZE:
        {
            printf ( "Resized application window.\n" );
        }
        break;
    }
    return DefWindowProcA ( window , message , w_param , l_param );
}

int
main
( void )
{
    HINSTANCE h_instance = GetModuleHandleA ( 0 );

    // Register window class.
    WNDCLASSA class;
    memset ( &class , 0 , sizeof ( class ) );
    class.style = CS_DBLCLKS;
    class.lpfnWndProc = platform_process_message;
    class.cbClsExtra = 0;
    class.cbWndExtra = 0;
    class.hInstance = h_instance;
    class.hIcon = LoadIcon ( h_instance, IDI_APPLICATION );
    class.hCursor = LoadCursor ( 0 , IDC_ARROW );
    class.hbrBackground = 0;
    class.lpszClassName = "test_window";
    if ( !RegisterClassA ( &class ) )
    {
        printf ( "Error: RegisterClassA failed.\n" );
        return 1;
    }

    // Initialize window dimensions.
    int window_x = 100;
    int window_y = 100;
    int window_width = 200;
    int window_height = 200;

    // Initialize window style.
    int window_style = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION
                     | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME
                     ;
    int window_ex_style = WS_EX_APPWINDOW;
    RECT border = { 0 , 0 , 0 , 0 };
    AdjustWindowRectEx ( &border , window_style , 0 , window_ex_style );
    window_x += border.left;
    window_y += border.top;
    window_width += border.right - border.left;
    window_height += border.bottom - border.top;

    // Create the window.
    HWND window = CreateWindowExA ( window_ex_style
                                  , class.lpszClassName
                                  , "Test window"
                                  , window_style
                                  , window_x
                                  , window_y
                                  , window_width
                                  , window_height
                                  , 0
                                  , 0
                                  , h_instance
                                  , 0
                                  );
    if ( !window )
    {
        printf ( "Error: CreateWindowExA failed.\n" );
        return 2;
    }

    // Display the window.
    ShowWindow ( window , SW_SHOW );

    // Update loop.
    running = true;
    suspended = false;
    while ( running )
    {
        if ( suspended )
        {
            continue;
        }
        platform_update ();
        Sleep ( 16 );// Simulates other stuff being done here.
    }
    running = false;

    // Destroy window.
    if ( !DestroyWindow ( window ) )
    {
        printf ( "Error: DestroyWindow failed." );
        return 3;
    }

    return 0;
}
c winapi event-handling
1个回答
0
投票

当窗口变为非活动状态时,您将

suspended
设置为
true
,并阻止主循环再次调用
platform_update()
,因此您的窗口将停止正常工作。您需要继续处理窗口消息,只需暂停代码的 rest 即可,例如:

while ( running )
{
    platform_update (); // <-- move here
    if ( suspended )
    {
        continue;
    }
    Sleep ( 16 );// Simulates other stuff being done here.
}
© www.soinside.com 2019 - 2024. All rights reserved.