开发者

Porting GCC app, Windows cursor stays on IDC_APPSTARTING

I'm porting an application (which makes use of a launcher stub) to Windows (using MinGW GCC).

Here's a minimal example that I will use as reference to demonstrate the issue.

#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;
}

This launcher stub is compiled as follows:

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

When launcher.exe is run, it correctly executes app.exe and then waits for it to terminate before terminating itself.

The unexpected side effect of this is that the Windows cursor goes i开发者_Go百科nto arrow+hourglass mode for about 5 seconds after launch.exe is spawned.

This does not happen when app.exe is run directly (through the command prompt or by double-clicking it.)

I have already tried adding the following to the app above, with no success (cursor still behaves exactly as before):

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

Interestingly, running launcher.exe from the command prompt (instead of double-clicking in Explorer), causes the cursor to act normally. I.e., it merely flashes to the hourglass and almost instantly returns to normal.

How can the busy cursor be suppressed? Or at least changed back reliably, without having to block?


The SetCursor trick won't work because it will change immediately to the IDC_APPSTARTING, as the system is responding to the WM_SETCURSOR messages.

The APPSTARTING cursor in Windows is more or less documented in the STARTUPINFO struct page (see explanation on STARTF_FORCEONFEEDBACK).

There it says that you can call GetMessage() to get rid of the feedback cursor, but you appear to know that already. Why is that you don't want to use it?

About the different behavior when calling from a console window, it makes sense. Think of when a program is "input idle":

  • If the program is a Windows one: When the first window is created and ready (called GetMessage).
  • If the program is a Console one:
    • If running from double-click: as soon as it creates the console window.
    • If running from another console: immediate.

Update: Try adding the following at the very beginning of main:

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


This is pretty simple and Rodrigo pointed you in the right direction.

Windows displays this cursor to indicate that an app is starting and turns it off when the app begins it's message loop. Your launcher application never starts a message loop so Windows never turns off the cursor.

So, here is what you need:

#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;
}

This posts a quit message to the message queue and then runs the loop which quits immediately. Windows thinks the app is ready to go.

  • Geoffrey
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜