При портировании приложения GCC курсор Windows остается на IDC_APPSTARTING - PullRequest
1 голос
/ 23 сентября 2011

Я портирую приложение (использующее заглушку запуска) в 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, а затем ожидает его завершения, прежде чем завершить сам.

Неожиданным побочным эффектом этого является то, что курсор Windows переходит в режим стрелки + песочные часы примерно на 5 секунд после появления launch.exe.

Этого не происходит, когда app.exe запускается напрямую (черезкомандной строки или двойным щелчком по ней.)

Я уже пытался добавить следующее в приложение выше, но безуспешно (курсор по-прежнему работает точно так же, как и раньше):

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

Интересно, что при запуске launcher.exe из командной строки (вместо двойного щелчка в проводнике) курсор работает нормально.То есть он просто мигает в песочных часах и почти мгновенно возвращается в нормальное состояние.

Как можно подавить занятый курсор?Или, по крайней мере, вернулось обратно надежно, без необходимости блокировать?

Ответы [ 2 ]

4 голосов
/ 27 сентября 2011

Трюк SetCursor не будет работать, потому что он немедленно изменится на IDC_APPSTARTING, поскольку система отвечает на сообщения WM_SETCURSOR.

Курсор APPSTARTING в Windows более или менее задокументирован на странице структуры STARTUPINFO (см. Пояснение к STARTF_FORCEONFEEDBACK).

Там написано, что вы можете позвонить GetMessage(), чтобы избавиться от курсора обратной связи, но вы, кажется, уже знаете это. Почему вы не хотите его использовать?

О различном поведении при вызове из окна консоли, это имеет смысл. Подумайте, когда программа находится в режиме ожидания ввода:

  • Если программа для Windows: когда первое окно создано и готово (называется GetMessage).
  • Если программа консольная:
    • При запуске с двойным щелчком мыши: как только оно создает окно консоли.
    • При запуске с другой консоли: немедленно.

Обновление: Попробуйте добавить следующее в самом начале main:

PostMessage(0, 0, 0, 0);
MSG msg;
GetMessage(&msg, 0, 0, 0);
0 голосов
/ 27 сентября 2011

Это довольно просто, и Родриго указал вам правильное направление.

Windows отображает этот курсор, чтобы указать, что приложение запускается, и выключает его, когда приложение начинает цикл обработки сообщений. Ваше приложение launcher никогда не запускает цикл сообщений, поэтому 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 считает, что приложение готово к работе.

  • Geoffrey
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...