Visual C++編程技巧(上)

來源:互聯網
上載者:User
1. 如何擷取應用程式的執行個體控制代碼?

應用程式的 執行個體控制代碼儲存在CWinAppIm_hInstance 中,可以這麼調用

AfxGetInstancdHandle獲得控制代碼.

Example: HANDLE hInstance=AfxGetInstanceHandle();

2. 如何通過代碼獲得應用程式主視窗的指標?

主視窗的 指標儲存在CWinThread::m_pMainWnd中,調用 AfxGetMainWnd實現。

AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程式最大化.

3.如何在程式中獲得其他程式的 表徵圖?

兩種方法:

(1) SDK函數 SHGetFileInfo 或使用 ExtractIcon獲得表徵圖資源的 handle,

(2) SDK函數 SHGetFileInfo獲得有關檔案的 很多資訊,如大小表徵圖,屬性,類型等.

Example(1): 在程式視窗左上方顯示 NotePad表徵圖.

void CSampleView: OnDraw(CDC * pDC)

{

if( :: SHGetFileInfo(_T("c://pwin95//notepad.exe"),0,

&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))

{

pDC ->DrawIcon(10,10,stFileInfo.hIcon);

}

}

Example(2):同樣功能,Use ExtractIcon Function

void CSampleView:: OnDraw(CDC *pDC)

{

HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T

("NotePad.exe"),0);

if (hIcon &&hIcon!=(HICON)-1)

pDC->DrawIcon(10,10,hIcon);

}

說明: 獲得notepad.exe的路徑正規上來說用GetWindowsDirectory 函數得到,如果是調用 win95下的畫筆,應該用訪問註冊表的方法獲得其路徑,要作成一個比較考究的程式,考慮應該全面點.

4.如何編程結束應用程式?如何編程式控制制windows的重新引導?

這是個很簡單又是編程中經常要遇到的問題.

第一問,向視窗發送 WM_CLOSE訊息,調用 CWnd::OnClose成員函數.允許對使用者提示

是否儲存修改過的資料.

Example: AfxGetMainWindow()->SendMessage(WM_CLOSE);

還可以建立一個自訂的函數 Terminate Window

void Terminate Window(LPCSTR pCaption)

{

CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption);

if (pWnd)

pWnd ->SendMessage(WM_CLOSE);

}

說明: FindWindow函數不是提倡的做法,因為它無法處理標題列自動改變,比如我們要檢測 Notepad是不是已運行而事先不知道Notepad的標題列,這時 FindWindow就無能為力了,可以通過枚舉 windows工作清單的辦法來實現。 在 機械出版社"Windows 95 API開發人員指南"一書有比較詳細的介紹,這裡就不再多說樂。

第二問,Use ExitWindowsEx Function函數控制系統是重新引導,還是重啟 windows.前面已經有人講過樂,就不再提了。

5.怎樣加栽其他的應用程式?

我記得這好象是出場頻度很高的問題。

三個SDK函數 winexec, shellexecute,createprocess可以使用。

WinExec最簡單,兩個參數,前一個指定路徑,後一個指定顯示方式.後一個參數值得說一下,比如泥用 SW_SHOWMAXMIZED方式去加栽一個無最大化按鈕的程式,呵呵就是Neterm,calc等等,就不會出現正常的表單,但是已經被加到工作清單裡了。ShellExecute較 WinExex靈活一點,可以指定工作目錄,下面的 Example就是直接開啟 c:/temp/1.txt,而不用加栽與 txt檔案關聯的應用程式,很多安裝程式完成後都會開啟一個視窗,來顯示Readme or Faq,偶猜就是這麼作的啦.

ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED);

CreateProcess最複雜,一共有十個參數,不過大部分都可以用NULL代替,它可以指定進程的安全屬性,繼承資訊,類的優先順序等等.來看個很簡單的 Example:

STARTUPINFO stinfo; //啟動視窗的資訊

PROCESSINFO procinfo; //進程的資訊

CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, NORMAL_PRIORITY_

CLASS,NULL,NULL, &stinfo,&procinfo);

6. 確定應用程式的 路徑

前些天好象有人問過這個問題.

Use GetModuleFileName 獲得應用程式的路徑,然後去掉可執行檔名。

Example:

TCHAR exeFullPath[MAX_PATH]; // MAX_PATH在API中定義了吧,好象是128

GetModuleFileName(NULL,exeFullPath,MAX_PATH)

7. 獲得各種目錄資訊

Windows目錄: Use "GetWindowsDirectory“

Windows下的system目錄: Use "GetSystemDirectory"

temp目錄: Use "GetTempPath "

目前的目錄: Use "GetCurrentDirectory"

請注意前兩個函數的第一個參數為目錄變數名,後一個為緩衝區; 後兩個相反.

8. 如何自訂訊息

也有人問過的,其實不難。

(1) 手工定義訊息,可以這麼寫 #define WM_MY_MESSAGE(WM_USER+100),

MS 推薦的至少是 WM_USER+100;

(2)寫訊息處理函數,用 WPARAM,LPARAM返回LRESULT.

LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

{

//加入你的處理函數

}

(3) 在類的 AFX_MSG處進行聲明,也就是常說的"宏映射"

1. 如何擷取應用程式的執行個體控制代碼?

應用程式的 執行個體控制代碼儲存在CWinAppIm_hInstance 中,可以這麼調用

AfxGetInstancdHandle獲得控制代碼.

Example: HANDLE hInstance=AfxGetInstanceHandle();

2. 如何通過代碼獲得應用程式主視窗的指標?

主視窗的 指標儲存在CWinThread::m_pMainWnd中,調用 AfxGetMainWnd實現。

AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程式最大化.

3.如何在程式中獲得其他程式的 表徵圖?

兩種方法:

(1) SDK函數 SHGetFileInfo 或使用 ExtractIcon獲得表徵圖資源的 handle,

(2) SDK函數 SHGetFileInfo獲得有關檔案的 很多資訊,如大小表徵圖,屬性,類型等.

Example(1): 在程式視窗左上方顯示 NotePad表徵圖.

void CSampleView: OnDraw(CDC * pDC)

{

if( :: SHGetFileInfo(_T("c://pwin95//notepad.exe"),0,

&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))

{

pDC ->DrawIcon(10,10,stFileInfo.hIcon);

}

}

Example(2):同樣功能,Use ExtractIcon Function

void CSampleView:: OnDraw(CDC *pDC)

{

HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T

("NotePad.exe"),0);

if (hIcon &&hIcon!=(HICON)-1)

pDC->DrawIcon(10,10,hIcon);

}

說明: 獲得notepad.exe的路徑正規上來說用GetWindowsDirectory 函數得到,如果是調用 win95下的畫筆,應該用訪問註冊表的方法獲得其路徑,要作成一個比較考究的程式,考慮應該全面點.

4.如何編程結束應用程式?如何編程式控制制windows的重新引導?

這是個很簡單又是編程中經常要遇到的問題.

第一問,向視窗發送 WM_CLOSE訊息,調用 CWnd::OnClose成員函數.允許對使用者提示

是否儲存修改過的資料.

Example: AfxGetMainWindow()->SendMessage(WM_CLOSE);

還可以建立一個自訂的函數 Terminate Window

void Terminate Window(LPCSTR pCaption)

{

CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption);

if (pWnd)

pWnd ->SendMessage(WM_CLOSE);

}

說明: FindWindow函數不是提倡的做法,因為它無法處理標題列自動改變,比如我們要檢測 Notepad是不是已運行而事先不知道Notepad的標題列,這時 FindWindow就無能為力了,可以通過枚舉 windows工作清單的辦法來實現。 在 機械出版社"Windows 95 API開發人員指南"一書有比較詳細的介紹,這裡就不再多說樂。

第二問,Use ExitWindowsEx Function函數控制系統是重新引導,還是重啟 windows.前面已經有人講過樂,就不再提了。

5.怎樣加栽其他的應用程式?

我記得這好象是出場頻度很高的問題。

三個SDK函數 winexec, shellexecute,createprocess可以使用。

WinExec最簡單,兩個參數,前一個指定路徑,後一個指定顯示方式.後一個參數值得說一下,比如泥用 SW_SHOWMAXMIZED方式去加栽一個無最大化按鈕的程式,呵呵就是Neterm,calc等等,就不會出現正常的表單,但是已經被加到工作清單裡了。ShellExecute較 WinExex靈活一點,可以指定工作目錄,下面的 Example就是直接開啟 c:/temp/1.txt,而不用加栽與 txt檔案關聯的應用程式,很多安裝程式完成後都會開啟一個視窗,來顯示Readme or Faq,偶猜就是這麼作的啦.

ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c://temp"),SW_SHOWMAXMIZED);

CreateProcess最複雜,一共有十個參數,不過大部分都可以用NULL代替,它可以指定進程的安全屬性,繼承資訊,類的優先順序等等.來看個很簡單的 Example:

STARTUPINFO stinfo; //啟動視窗的資訊

PROCESSINFO procinfo; //進程的資訊

CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE, NORMAL_PRIORITY_

CLASS,NULL,NULL, &stinfo,&procinfo);

6. 確定應用程式的 路徑

前些天好象有人問過這個問題.

Use GetModuleFileName 獲得應用程式的路徑,然後去掉可執行檔名。

Example:

TCHAR exeFullPath[MAX_PATH]; // MAX_PATH在API中定義了吧,好象是128

GetModuleFileName(NULL,exeFullPath,MAX_PATH)

7. 獲得各種目錄資訊

Windows目錄: Use "GetWindowsDirectory“

Windows下的system目錄: Use "GetSystemDirectory"

temp目錄: Use "GetTempPath "

目前的目錄: Use "GetCurrentDirectory"

請注意前兩個函數的第一個參數為目錄變數名,後一個為緩衝區; 後兩個相反.

8. 如何自訂訊息

也有人問過的,其實不難。

(1) 手工定義訊息,可以這麼寫 #define WM_MY_MESSAGE(WM_USER+100),

MS 推薦的至少是 WM_USER+100;

(2)寫訊息處理函數,用 WPARAM,LPARAM返回LRESULT.

LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

{

//加入你的處理函數

}

(3) 在類的 AFX_MSG處進行聲明,也就是常說的"宏映射"
9. 如何改變視窗的表徵圖?

向視窗發送 WM_SECTION訊息。

Example:

HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON);

ASSERT(hIcon);

AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM) hIcon);

10. 如何改變視窗的預設風格?

重栽 CWnd:: PreCreateWindow 並修改CREATESTRUCT結構來指定視窗風格和其他

建立資訊.

Example: Delete "Max" Button and Set Original Window's Position and Size

BOOL CMainFrame:: PreCreateWindow (CREATESTRUCT &cs)

{

cs.style &=~WS_MAXINIZEMOX;

cs.x=cs.y=0;

cs.cx=GetSystemMetrics(SM_CXSCREEN/2);

cs.cy=GetSystemMetrics(SM_CYSCREEN/2);

return CMDIFramewnd ::PreCreateWindow(cs);

}

11. 如何將視窗置中顯示?

Easy, Call Function CWnd:: Center Windows

Example(1): Center Window( ); //Relative to it's parent

// Relative to Screen

Example(2): Center Window(CWnd:: GetDesktopWindow( ));

//Relative to Application's MainWindow

AfxGetMainWnd( ) -> Center Window( );

12. 如何讓視窗和 MDI視窗一啟動就最大化和最小化?

先說視窗。

在 InitStance 函數中設定 m_nCmdShow的 取值.

m_nCmdShow=SW_SHOWMAXMIZED ; //最大化

m_nCmdShow=SW_SHOWMINMIZED ; //最小化

m_nCmdShow=SW_SHOWNORMAL ; //正常方式

MDI視窗:

如果是建立新的應用程式,可以用 MFC AppWizard 的Advanced 按鈕並在

MDI子視窗風格組中檢測最大化或最小化; 還可以重載 MDI Window 的

PreCreateWindow函數,設定WS_MAXMIZE or WS_MINMIZE;

如果從 CMDIChildWnd 派生,調用 OnInitialUpdate函數中的 CWnd::Show

Window來指定 MDI Child Window的 風格。

13. 如何使程式保持極小狀態?

很有意思的 問題

這麼辦: 在恢複程式表單大小時, Windows會發送WM_QUERY-OPEN訊息,

用 ClassWizard設定成員函數 OnQueryOpen() ,add following code:

Bool CMainFrame:: OnQueryOpen( )

{

Return false;

}

14. 如何限制視窗的大小?

也就是 FixedDialog形式。 Windows 發送 WM_GETMAXMININFO訊息來跟蹤,

響應它,在 OnGetMAXMININFO 中寫代碼:

15. 如何使視窗不可見?

很簡單,用SW_HIDE 隱藏視窗,可以結合 FindWindow,ShowWindow 控制.

16. 如何使視窗始終在最前方?

兩種途徑.

BringWindowToTop(Handle);

SetWindowPos函數,指定視窗的最頂風格,用WS_EX_TOPMOST擴充視窗的風格

Example:

void ToggleTopMost( CWnd *pWnd)

{

ASSERT_VALID(pWnd);

pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?

&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE);

}

17、如何建立一個字迴繞的CEditView

重載CWnd : : PreCreateWindow和修改CREATESTRUCT結構,關閉CEditView對象的ES_AUTOHSCROLL和WS_HSCROLL風格位,由於CEditView : : PreCreateWindow顯示設定cs. style,調用基類函數後要修改cs . style。

BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)

{

//First call basse class function .

BOOL bResutl =CEditView : : PreCreateWindow (cs) ;

// Now specify the new window style .

cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL);

return bResult ;

}

18、通用控制項的顯示視窗

MFC提供了幾個CView派生的視窗類,封裝了通用控制項的功能,但仍然使用工

作框文檔顯示視窗體繫結構:CEditView封裝了編輯控制項,CTreeView保持了樹列表

控制項,CListView封裝了列表顯示視窗控制項,CRichEditView可以處理多種編輯控制項。

19、移動視窗

調用CWnd : : SetWindowPos並指定SWP_NOSIZE標誌。目的位置與父視窗

有關(頂層視窗與螢幕有關)。調用CWnd : : MoveWindow時必須要指定視窗

的大小。

//Move window to positoin 100 , 100 of its parent window .

SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER);

20、重設視窗的大小

調用CWnd: : SetWindowPos並指定SWP_NOMOVE標誌, 也可調用

CWnd : : MoveWindow 但必須指定視窗的位置。

// Get the size of the window .

Crect reWindow ;

GetWindowRect (reWindow );

//Make the window twice as wide and twice as tall .

SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,

reWindow . Height () * 2,

SWP_NOMOVE |SWP_NOZORDER );

21、如何單擊除了視窗標題列以外的地區使視窗移動

當視窗需要確定滑鼠位置時Windows向視窗發送WM_NCHITTEST資訊,可以處理

該資訊使Windows認為滑鼠在視窗標題上。對於對話方塊和基於對話的應用程式,可

以使用ClassWizard處理該資訊並調用基類函數,如果函數返回HTCLIENT 則表明

滑鼠在客房地區,返回HTCAPTION表明滑鼠在Windows的標題列中。

UINT CSampleDialog : : OnNcHitTest (Cpoint point )

{

UINT nHitTest =Cdialog: : OnNcHitTest (point );

return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest ;

}

上述技術有兩點不利之處,其一是在視窗的用戶端區域雙擊時, 視窗將極大;

其二,它不適合包含幾個視窗的主框視窗。還有一種方法,當使用者按下滑鼠左鍵

使主框視窗認為滑鼠在其視窗標題上,使用ClassWizard在視窗中處理WM_LBUTTODOWN

資訊並向主框視窗發送一個WM_NCLBUTTONDOWN資訊和一個單擊測試HTCAPTION。

void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point )

{

CView : : OnLButtonDow (nFlags , pont );

//Fool frame window into thinking somene clicked on

its caption bar .

GetParentFrame ( ) —> PostMessage (

WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARAM (poitn .x , point .y) );

}

該技術也適用於對話方塊和基於對的應用程式,只是不必調用CWnd : : GetParentFrame 。

void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )

{

Cdialog : : OnLButtonDow (nFlags, goint );

//Fool dialog into thinking simeone clicked on its caption bar .

PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x , point. y ) )

}

22、如何改變視窗的背景顏色

Windows向視窗發送一個WM_ERASEBKGND訊息通知該視窗擦除背景,可以使用

ClassWizard重載該訊息的預設處理常式來擦除背景(實際是畫),並返回TRUE以

防止Windows擦除視窗。

//Paint area that needs to be erased.

BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)

{

// Create a pruple brush.

CBrush Brush (RGB (128 , 0 , 128) );

// Select the brush into the device context .

CBrush* pOldBrush = pDC—>SelcetObject (&brush);

// Get the area that needs to be erased .

CRect reClip ;

pDC—>GetCilpBox (&rcClip);

//Paint the area.

pDC—> PatBlt (rcClip.left , rcClip.top ,

rcClip.Width ( ) , rcClip.Height ( ) , PATCOPY );

//Unselect brush out of device context .

pDC—>SelectObject (pOldBrush );

// Return nonzero to half fruther processing .

return TRUE;

}

23、如何改變視窗標題

調用CWnd : : SetWindowText可以改變任何視窗(包括控制項)的標題。

//Set title for application's main frame window .

AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") );

//Set title for View's MDI child frame window .

GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title") );

//Set title for dialog's push button control.

GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") );

如果需要經常修改視窗的標題(註:控制項也是視窗),應該考慮使用半文檔化

的函數AfxSetWindowText。該函數在AFXPRIV.H中說明,在WINUTIL.CPP中實現,在

線上說明中找不到它,它在AFXPRIV.H中半文檔化,在以後發行的MFC中將文檔化。

AfxSetWindowText的實現如下:

voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )

{

itn nNewLen= Istrlen (Ipaznew);

TCHAR szOld [256];

//fast check to see if text really changes (reduces flash in the controls )

if (nNewLen >_contof (szOld) ||

: : GetWindowText (hWndCrtl , szOld , _countof (szOld) !=nNewLen ||

Istrcmp (szOld , IpszNew )! = 0

{

//change it

: : SetWindowText (hWndCtrl , IpszNew );

}

}

24、如何防止主框視窗在其說明中顯示活動的文檔名

建立主框視窗和MDI子視窗進通常具有FWS_ADDTOTITLE風格位, 如果不希望在

說明中自動添加文檔名, 必須禁止該風格位,可以使用ClassWizard重設

CWnd: : PreCreateWindow並關閉FWS_ADDTOTITLE風格。

BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)

{

//Turn off FWS_ADDTOTITLE in main frame .

cs.styel & = ~FWS_ADDTOTITLE ; 

return CMDIFrameWnd : : PreCreateWindow (cs );

}

關閉MDI子視窗的FWS _ADDTOTITLE風格將建立一個具有空標題的視窗,可以調

用CWnd: : SetWindowText來設定標題。記住自己設定標題時要遵循介面風格指南。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.