MFC怎樣編寫後臺運行的程序

MFC怎樣編寫後臺運行的程序

---------------------------------------------------------------

http://www.codeproject.com/system/xservice.asp
---------------------------------------------------------------

以下爲轉載---------
1、實現開機自運行

     我在csdn網站上經常看到有人問這樣的問題,其實要實現開機時就自動運行自己的程序並不難。在註冊表的HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run鍵下可以看到有一系列鍵值,它們都是開機自動運行的軟件的路徑。那麼我們要做的就是編程實現將我們的程序的路徑也添加到這個鍵值下,就搞定了。著名的“windows優化大師”也就是用去掉不必要的開機運行軟件這個方法來實現開機速度優化的。
     既然要讀寫註冊表,就要用到兩個重要的操作註冊表的函數:RegOpenKey()和RegSetValueEx()。前者用於打開註冊表的鍵,後者則爲打開的鍵設置鍵值,至於這兩個API函數的具體參數,請參見MSDN。爲了代碼重用的要求,我爲此封裝了一個專門的函數,如下所示:

BOOL SetAutoRun(CString strPath)//開機自動運行
{
    CString str;
    HKEY hRegKey;
    BOOL bResult;
    str=_T("Software\\Microsoft\\Windows\\CurrentVersion\\Run");
    if(RegOpenKey(HKEY_LOCAL_MACHINE, str, &hRegKey) != ERROR_SUCCESS)
        bResult=FALSE;
    else
    {
        _splitpath(strPath.GetBuffer(0),NULL,NULL,str.GetBufferSetLength(MAX_PATH+1),NULL);
        strPath.ReleaseBuffer();
        str.ReleaseBuffer();
        if(::RegSetValueEx( hRegKey,
                            str,
                            0,
                            REG_SZ,
                            (CONST BYTE *)strPath.GetBuffer(0),
                            strPath.GetLength() ) != ERROR_SUCCESS)
           bResult=FALSE;
        else
           bResult=TRUE;
        strPath.ReleaseBuffer();
    }
    return bResult;
}

     其中strPath參數表示要設置爲自運行的程序的絕對路徑。當設置成功時返回true,否則返回false。
這裏又帶來一個問題:既然需要本程序的絕對路徑,那麼怎麼得到它呢?總不能指定一個值吧,那麼當本程序的路徑改變時就又要修改程序,太麻煩了。可以用這個封裝的函數來實現:
//得到程序文件本身的路徑(包括文件名)

CString GetMyPath()
{
    CString strPath;
    GetModuleFileName(NULL,strPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
    strPath.ReleaseBuffer();
    return strPath;
}

     其中GetModuleFileName()是一個得到路徑的API函數。本函數將這個API函數封裝在其中,爲的是簡化調用的目的。
     當執行這個函數時,返回本程序所在的絕對路徑,包括本程序的文件名。
好了,得到本程序的路徑,然後將它加載到註冊表中,下次系統啓動時,我們的程序就能自動隨之啓動了。


2、實現運行時自動隱藏

    這是一個很有趣很古老的話題,csdn上經常有人爲此討論不休,提出不少方案,比如在對話框的OnInitDialog()中添加一句:ShowWindow(SW_HIDE);,或者在對話框屬性框中去掉對話框的Visible屬性;或者將對話框移到桌面以外的地方去;或者首先將對話框最小化,然後實現最小化時隱藏……有趣的是這些很容易想到的常規方法都不能解決這個問題,或者說解決的不夠好。我通過查找相關文章和多次修改代碼,找出了真正解決這個問題的辦法。
    之所以用ShowWindow()函數失效,我認爲可能是對話框的DoModal()在作怪,這麼一來就只能繞開DoModal(),那麼就自然想到可以把對話框變成一個無模式對話框。無模式對話框平時我們用到的不多,它與模式對話框不同,是用Create方法Create出來的,而不是DoModal()創建的。
    假設建立一個VC.NET工程GetTime,首先在CGetTimeApp類中添加一個成員變量:CGetTimeDlg *dlg;然後在InitInstance()中將原來的:

     int nResponse = dlg.DoModal();
     if (nResponse == IDOK)
     {
        // TODO: Place code here to handle when the dialog is
        //   dismissed with OK
     }
     else if (nResponse == IDCANCEL)
     {
        // TODO: Place code here to handle when the dialog is
        //   dismissed with Cancel
     }
以及return FALSE;全部刪除掉,改爲:      dlg=new CGetTimeDlg;
     m_pMainWnd = dlg;
     return dlg->Create(IDD_GETTIME_DIALOG);
    最後別忘了在ExitInstance()中加上一句:delete dlg;好了,這下把本程序的對話框變成了一個無模式對話框。不過既然是無模式對話框,就不能再用OnOK(),OnCancel()來退出了,要用DestroyWindow()。
    由於在上面的代碼中沒有將對話框設爲可見,所以運行時就實現了隱藏,而且在Windows任務欄上也沒有顯示。至此,第二個問題得到完美解決。

****************************************************************************************************************************************************

 

基於對話框的的程序,如果要達到完全運行時隱藏,光將對話框的Visible屬性設爲FALSE是不夠的,因爲副對話框在App初始化的時候一個DoModal(),對話框就會顯示出來,如果在對話框的OnInitDialog()使用如下兩行代碼:

SetWindowPos(&wndBottom, 0, 0, 0, 0, SWP_HIDEWINDOW); ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW);

雖然能去掉窗體和任務欄上的圖標,但避免不了,程序窗口的一閃,而且,在任務管理器的任務列表裏會有該程序的運行圖標。

如果在App的InitInstance()裏將顯示對話框的模式從“模式”改寫爲“無模式”,則能達到後臺執行該對話框程序的目的,首先將父對話框的Visible屬性設爲FALSE,然後在程序的App類中定義一個成員變量:

CWnd* m_pWnd;

在程序的App類裏面的InitInstance()裏面將模式顯示部分註釋掉,改爲:

CMyTestDlg* pDlg = new CMyTestDlg(); m_pWnd = pDlg; m_pMainWnd = pDlg; return pDlg->Create(IDD_MYTEST_DIALOG);

重寫ExitInstance(),加入:

delete m_pWnd;

這樣就達到了後臺啓動MFC對話框程序了。


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