2010年11月11日 星期四

CMyCommandLineInfo

在遠古的DOS時代,我們常會在可執行檔後面加上一大堆的command來指定特殊的功能,進到了視窗模式後command已經很少有人在使用了。今天就來談談要始何在透過MFC實現這種原始人才會想用的特殊技藝。

不論產生的是MDISDI或是dialog baseapp,都可以在自動產生的CWinAppInitInstance中找到這段code

CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);

if (!ProcessShellCommand(cmdInfo))
    return FALSE;

ParseCommandLine會將執行的指令進行剪貼轉換為CCommandLineInfo物件的格式,而ProcessShellCommand則依傳入的cmdInfo所擁有的屬性進行相對應的處理。

ParseCommandLine內的作用方式如下,如果我們想做的指令不在預設的列表中時,我們必需改寫ParseParam來對應我們想要的功能。

void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo)
{
    for (int i = 1; i < __argc; i++)
    {
        LPCTSTR pszParam = __targv[i];
        BOOL bFlag = FALSE;
        BOOL bLast = ((i + 1) == __argc);
        if (pszParam[0] == '-' || pszParam[0] == '/')
        {
            // remove flag specifier
            bFlag = TRUE;
            ++pszParam;
        }
        rCmdInfo.ParseParam(pszParam, bFlag, bLast);
    }
}

極簡單的範例:

我在開發一些演算法時常需要反覆測試一些已知的影像比較程式修改前修改後的差異,我懶得每次開啟程式時都要去按File選單來選擇我上一次測試的影像,這時我就會在我的debug條件中加入”/default”command

繼承自CcommandLineInfo產生CMyCommandLineLifo類別,並覆載(override) ParseParam函式。小心,UnicodeMulti-Byte有一點點的不同,若想讓這類別二者通吃必需多覆載針對UnicodeParseParam

完成後記得把InitInstanceCCommandLineInfo cmdInfo改為CMyCommandLineInfo cmdInfo

class CMyCommandLineInfo :  public CCommandLineInfo
{
public:
    virtual void ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast);
#ifdef _UNICODE
    virtual void ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast);
#endif
};

void CMyCommandLineInfo::ParseParam(const TCHAR* pszParam, BOOL bFlag, BOOL bLast)
{
    if (bFlag)
    {
        const CString strParam(pszParam);
        if(strParam.CompareNoCase(_T("default")) == 0)
        {
            m_nShellCommand = CCommandLineInfo::FileOpen;
            m_strFileName   = AfxGetApp()->GetProfileString(_T("Recent File List"),_T("File1"));

            ParseLast(bLast);

            return;
        }
    }

    CCommandLineInfo::ParseParam(pszParam, bFlag, bLast);
}

#ifdef _UNICODE
void CMyCommandLineInfo::ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast)
{
    const CString strParam(pszParam);

    ParseParam(strParam, bFlag, bLast);
}
#endif

只為了擴充單一功能而必需繼承產生一個新類別,每次遇到這種例子我就有點懷念Object-C

沒有留言:

張貼留言