移植GCC应用程序,Windows光标停留在IDC_APPSTARTING上

我将一个应用程序(使用启动程序存根)移植到Windows(使用MinGW GCC)。

这是一个我将用作参考来展示问题的最简单的例子。

#include <process.h> int main(int argc, char *argv[]) { chdir("C:\appdir"); spawnl(P_WAIT, "C:\appdir\app.exe", "C:\appdir\app.exe", NULL); return 0; } 

这个启动程序存根编译如下:

 gcc -O3 -o launcher.o -c launcher.c gcc -mwindows -o launcher.exe launcher.o 

launcher.exe运行时,它正确执行app.exe ,然后在终止之前等待它终止。

这意想不到的副作用是在生成launch.exe后,Windows光标进入箭头+沙漏模式大约5秒钟。

app.exe直接运行时(通过命令提示符或双击它)不会发生这种情况。

我已经尝试将以下内容添加到上面的应用程序,但没有成功(游标仍然像以前一样):

 #include <windows.h> SetCursor(LoadCursor(NULL, IDC_ARROW)); 

有趣的是,从命令提示符运行launcher.exe (而不是在资源pipe理器中双击)会导致游标正常运行。 也就是说,它只闪烁到沙漏,几乎立即恢复正常。

忙碌的光标如何被抑制? 或者至less可靠地换回, 不必阻止?

SetCursor技巧将无法正常工作,因为它将立即更改为IDC_APPSTARTING,因为系统正在响应WM_SETCURSOR消息。

Windows中的APPSTARTING游标或多或少记录在STARTUPINFO结构页面中(请参阅有关STARTF_FORCEONFEEDBACK的说明)。

在那里它说,你可以调用GetMessage()来摆脱反馈光标,但你似乎已经知道。 为什么你不想使用它?

关于从控制台窗口调用时的不同行为,这是有道理的。 想想程序何时“输入空闲”:

  • 如果程序是Windows的话:当第一个窗口被创建并准备就绪时(称为GetMessage)。
  • 如果该程序是一个控制台之一:
    • 如果从双击运行:一旦它创建控制台窗口。
    • 如果从另一个控制台运行:立即。

更新:尝试在主开头添加以下内容:

 PostMessage(0, 0, 0, 0); MSG msg; GetMessage(&msg, 0, 0, 0); 

这很简单,罗德里格指出你正确的方向。

Windows会显示这个光标,指示应用程序正在启动,并在应用程序启动时将其关闭。 您的启动程序应用程序永远不会启动消息循环,所以Windows永远不会关闭光标。

所以,这里是你需要的:

 #include <process.h> #include <Windows.h> void turn_off_the_starting_cursor() { PostQuitMessage( 0 ); MSG msg; BOOL bRet; while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0) { if (bRet != -1) { TranslateMessage(&msg); DispatchMessage(&msg); } } } int main(int argc, char *argv[]) { turn_off_the_starting_cursor(); chdir("C:\appdir"); spawnl(P_WAIT, "C:\appdir\app.exe", "C:\appdir\app.exe", NULL); return 0; } 

这将一个退出消息发送到消息队列,然后运行立即退出的循环。 Windows认为该应用程序已准备就绪。

  • 杰弗里