我正在创建一个窗口应用程序,目前正在用 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;
}
当窗口变为非活动状态时,您将
suspended
设置为 true
,并阻止主循环再次调用 platform_update()
,因此您的窗口将停止正常工作。您需要继续处理窗口消息,只需暂停代码的 rest 即可,例如:
while ( running )
{
platform_update (); // <-- move here
if ( suspended )
{
continue;
}
Sleep ( 16 );// Simulates other stuff being done here.
}