2011-09-22 53 views
1

我將一個應用程序(使用啓動程序存根)移植到Windows(使用MinGW GCC)。移植GCC應用程序,Windows光標停留在IDC_APPSTARTING

這是一個我將用作參考來展示問題的最小示例。

#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,使光標正常起作用。也就是說,它只閃爍到沙漏,幾乎立即恢復正常。

忙碌光標如何被抑制?或者至少可靠地換回,沒有不得不阻止?

回答

4

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); 
+0

整個啓動器被張貼以上。沒有窗戶,也不應該產生一個控制檯。 GetMessage()會引入不需要的阻塞行爲。啓動程序本身充當主可執行程序的包裝。 – Unsigned

+0

您可以通過發佈任何消息避免在「GetMessage」中阻塞。請嘗試更新後的答案中的代碼。 – rodrigo

0

這是非常簡單和Rodrigo指出你在正確的方向。

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認爲該應用程序已準備就緒。

  • 傑弗裏
+0

您的解決方案與rodrigo的效果相同,但顯着更大。爲什麼這樣? – Unsigned

+0

這是因爲他複製了一個完全標準的消息循環,但是之前發佈了一條消息。 PostQuitMessage()會首先調用GetMessage()返回FALSE,然後它會完成。 – rodrigo

+0

@rodrigo:對PostMessage(0,0,0,0)與PostQuitMessage(0)有沒有什麼優點或缺點? – Unsigned

相關問題