main WinMain入口函數比較

本文是轉載,原文地址http://blog.csdn.net/jackalfly/article/details/8235225

C/C++語言中的main函數, 經常帶有參數argc, argv, 如下:
int main(int argc, char** argv)
int main(int argc, char* argv[]) //也可以是wchar_t 或 tchar
argc 是指命令行輸入參數的個數, argv存儲了所有的命令行參數. 在命令行下, 每兩個argv[n]之間以空格分隔.
如在命令行下輸入 test.exe a b
argc 爲 3
argv[0] 爲 "test.exe"
argv[1] 爲 "a"
argv[2] 爲 "b"

以下一個簡單的程序可以幫你看看argc, argv具體代表什麼.
#include <stdio.h>

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; i++)
    {
        printf("%s\n", argv[i]);//通過處理argv[0]可以獲得當前可執行程序所在的路徑哦。
    }
    return 0;
}

另外, vc環境下向程序傳遞參數可以在 Debugging -> command argument 下設置. (下面說的WinMain也一樣)

在VS2008下,右鍵要調試的項目—>Properties—>Debugging—>Command Arguments—>輸入你要輸入的參數即可。
WinMain函數的原型聲明如下:
int WINAPI WinMain(
                HINSTANCE hInstance,     // handle to current instance
                HINSTANCE hPrevInstance, // handle to previous instance
                LPSTR lpCmdLine,         // command line
                int nCmdShow             // show state
);

WinMain函數接收4個參數, 這些參數都是在系統調用WinMain函數時, 傳遞給應用程序的.
第一個參數hInstance表示該程序當前運行的實例的句柄, 這是一個數值. 當程序在Windows下運行時, 它唯一標識運行中的實例(注意, 只有運行中的程序實例, 纔有實例句柄). 一個應用程序可以運行多個實例, 每運行一個實例, 系統都會給該實例分配一個句柄值, 並通過hInstance參數傳遞給WinMain函數.
第二個參數hPrevInstance (MSDN)在Win32環境下, 這個參數不起作用,歷史遺留,hPrevInstance=NULL;
第三個參數lpCmdLine是一個以空('\0')終止的字符串, 指定傳遞給應用程序的命令行參數.
注: 運行參數,例如在命令行鍵入:test.exe /install,那麼程序入口WinMain處,其參數lpCmdLine就接收到了/install參數。但是,至於你用這個參數做什麼,那是用代碼實現,你即時對/INSTALL參數做了一個"uninstall"的處理,也是可以的。而實現安裝,這需要根據你的需求加入代碼,和命令行參數無關。

這個跟命令行的int main(int argc, char* argv[])不同
如上文test.exe a b
      lpCmdLine 爲 "a b"

第四個參數nCmdShow指定程序的窗口應該如何顯示, 例如最大化、最小化、隱藏等. 這個參數的值由該程序的調用者所指定, 應用程序通常不需要去理會這個參數的值.

注意:C語言的Windows API編程,並不一定需要使用WinMain入口函數。
    如果不使用WinMain的四個參數,那麼直接使用main代替WinMain就完全可以了。
    如果程序中使用了WinManin的某個參數,那麼也可以用main替代,但是需要增加WinMain的四個參數作爲變量,如下所示:
    main()
   {
         ....   
         HINSTANCE hInstance;    
         int iCmdShow;    
         LPTSTR szCmdLine;    
         hInstance=GetModuleHandle(NULL);  //獲取程序本身的實例句柄    
         iCmdShow=SW_SHOWNORMAL;//定義窗口顯示模式    
         szCmdLine=GetCommandLine();//獲取命令行字符串   
        (hPrevInstance=NULL;一般程序用不到這個參數)
         ....
    }   
   不過有一點要說明的就是GetCommandLine()函數返回的命令行參數帶有執行程序本身的名字,而WinMain的參數LPSTR lpCmdLine是不包含執行程序的名字本身的。
   用main代替WinMain除了命令行參數是否包含程序本身名字這一點外,其他未發現不同。

測試一下,就用一個最簡單程序:

WinMain版:

#include<windows.h>
int WINAPI WinMain(HINSTANCE h1,HINSTANCE h2,LPTSTR cmdline,int cmdshow)
{    
 MessageBox(NULL, 
               cmdline,
               "CmdLine", 
               MB_OK | MB_ICONINFORMATION);

    return 0;
}

因爲WinMaincmdline不包含程序名,所以就什麼也沒有顯示。

main版:

#include<windows.h>
int main(int argc,char *argv)
{
    LPTSTR cmdline;  //
要用到這個參數,就用變量代替原來的參數
    cmdline=GetCommandLine();//
獲取命令行字符串,包括程序名本身

   MessageBox(NULL, 
               cmdline,
               "CmdLine", 
               MB_OK | MB_ICONINFORMATION);

    return 0;
}

main代替WinMain除了命令行參數是否包含程序本身名字這一點外,其他未發現不同。

測試了《Windows程序設計第五版》中的幾個程序,都可以正常運行。

最後補充說明:對於iCmdShow還可以不在程序中指定,由系統輸入獲得:

STARTUPINFO   StartupInfo;   
memset(&StartupInfo,0,sizeof(STARTUPINFO));
GetStartupInfo(&StartupInfo);
iCmdShow = (int)StartupInfo.wShowWindow;//
獲取窗口顯示模式

另外爲了獲得更準確的cmdline,可以自編一個函數,不過我自編的這個函數,會去掉命令行中多餘的空格:

//用這個函數可以返回去掉了多餘空格的szCmdLine
LPTSTR GetCmdLine(int argc,char *argv[])
{
    int i=0;
    int length=0;
    char * cmdline;
    if(argc<2)
        return TEXT("");
    for(i=1; i<argc; i++)
    {
        length=length + strlen(argv[i]);
    }
    cmdline = (char *)malloc(sizeof(char)*(length + argc -1));
    strcpy(cmdline,argv[1]);
    if(argc>2)
    {
        for(i=2;i<argc;i++)
        {
            strcat(cmdline," ");
            strcat(cmdline,argv[i]);
        }
    }
    return TEXT(cmdline);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章