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來設定標題。記住自己設定標題時要遵循介面風格指南。