(80) 我聽說MFC可以發現記憶體漏洞,我怎樣使用該特性?
如 果 你 在 Debug 菜 單 中 的 Go 選 項 ( 不 是 Project 菜 單 中 的 Execute 選 項 )來運作你的應用程式,MFC應該在程式終止時報告記憶體漏洞。如果沒有,那麼試試運作MFCTracer工具程式(在VC++程式組中),并啟動跟蹤。然後傳回應用程式。
(81) 我怎樣才能在我的應用程式中循環浏覽已經打開的文檔?
使用CDocTemplate中未公開的GetFirstDocPosition()和GetNextDoc()函數。
(82)才能在我的應用程式中循環浏覽已經打開的視?
使 用 CDocument中未公開的 GetFirstViewPosition() 和 GetNextView() 函 數。
(83)數PreCreateWindow是幹什麼用的?
PreCreateWindow 允許你在調用CreateWindow之前來改變視窗屬性。
(84)該怎樣防止MFC在視窗标題欄上把文檔名預置成應用程式名?
在PreCreateWindow 函 數 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 樣 式:
cs.style &= ~FWS_PREFIXTITLE;
(85) 我應該怎樣防止MFC在視窗标題欄上添加文檔名?
在 PreCreateWindow 函 數 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 樣 式:
cs.style &= ~FWS_ADDTOTITLE ;
(86) 我應該如何改變視視窗的大小?
因為視視窗實際上是架構視窗的子視窗,是以你必須改變架構視窗的大小,而不是改變視視窗。使用CView類中的GetParentFrame()函數獲得指向架構視窗的指針,然後調用MoveWindow()函數來改變架構的大小。這會使變尺寸的視充滿架構視窗。
(87) 我有一無模式對話框。我怎樣才能在視窗退出時删除CDialog對象?
把“delete this”加 到 PostNcDestroy 中。這主要用在需要自動删除對象的場合。
(88) 為什麼把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
OnNcDestroy 隻被已建立的視窗調用。如果建立視窗失敗(如PreCreateWindow),則沒有視窗處來發送WM_NCDESTROY消息。PostNcDestroy是在對象視窗被完全删除,在OnNcDestroy後,甚至在視窗建立失敗之後調用的。
(89) File菜單中的MRU清單是從哪兒來的?清單中的名字放在哪兒了?我怎樣才能改變清單中項目的最大值?
在應用程式類的InitInstance函數中對LoadStdProfileSettings的調用中。該調用接受一個參數(在預設情況下如果沒有傳遞值則為4)。MRU檔案名是從INI檔案中調用的。如果你有帶有ID_FILE_MRU_FILE1的ID的菜單選項,它會為調入的MRU清單所替換。如果你改變傳遞給LoadStdProfileSettings的數值(最大為16),則你就改變了所裝如檔案名的最大值。
(90) 我在菜單中添加了新的項。但是,當我選該項時,在狀态欄上沒有出現任何提示資訊。為什麼?
打開資源檔案中的菜單模闆。打開新菜單選項的屬性對話框。在對話框的底部的Prompt編輯框中,你可以如下指定狀态欄上的提示資訊和工具欄上的提示資訊(如果你已經建立的工具欄按鈕):
Status bar string/nFlying tag
(91) 我怎樣才能在應用程式的預設系統菜單中加上一些東西?
系統菜單與其它菜單類似,你可以添加或删除項目,這需要使用CMenu類的成員函數。下面的代碼在你的系統菜單後面添加一個新菜單項:
CMenu*sysmenu;
sysmenu=m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING,1000, "xxx");
參見MFC幫助檔案中的CMenu類。
(92) 我建立了一個對話框。但是當我顯示該對話框時,第一個編輯框總是不能獲得焦點,我必須單擊它來使它獲得焦點。我怎樣才能使第一個編輯框在對話框打開時就獲得焦點?
打 開 資 源 編 輯 器 中 的 對 話 框 模 闆。在 Layout 菜單 中 選 擇 Tab Order 選 項。按 你 的 需 求 單 擊 對 話 框 中 的 控 制 來 重 新 排 列 這 些 控 制 的 tab 順 序。
(93) 我怎樣才能使一個視窗具有“always on top”特性?
在 調 用 OnFileNew 後,在 你 的 InitInstance 函 數 中 加 上 下 面 的 代 碼:
m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
(94) 我要為我的form view添加文檔模闆。我先建立了對話框模闆,然後使用ClassWizard建立了基于CFormView的新類,它也是從CDocument繼承來的。我還建立了相應的資源并在InitInstance中添加了新的文檔模闆。但是,當我試圖運作該程式時,出現了Assertion資訊。為什麼?
form的對話框模闆需要些特殊設定以便可用于CFromView。確定這些設定的最簡單方法是使用AppWizard來建立CFormView應用程式,并檢視AppWizard所建立的對話框模闆所選擇的StylesProperties。你會發現該對話框模闆具有下列樣式:沒有标題欄、不可見和“Child”。把你的formview的對話框屬性變成這樣就可以了。
(95)我在一對話框中有一清單框,我需要tabbed清單框中的項目。但是,當我處理含有tab字元(用AddString添加的)的清單項時,tab被顯示成小黑塊而沒有展開。哪兒出錯了?
在對話框模版中,打開清單框的屬性。確定選擇了“UseTabstops”樣式。然後,確定在對話框類中OnInitDialog函數中調用SetTabStops。
(96)我建立了一個應用程式,并使用了CRecordset類。但是,當我運作該程式時,它試圖要通路資料庫,并給出“InternalApplicationError”對話框。我應該怎樣做?
通常情況下,當你的程式中向資料庫發送資訊的SQL語句出現問題時才出現該對話框。例如,參見下面的例子:
set.m_strFilter = "(ZipCode = '27111')";
如 果 ZipCode 列被定義為字元串時不會出現問題,如果定義為long,則會出現“InternalApplicationError”對話框,這是由于類型不比對的緣故。如果你删除27111的單引号,則不會出現問題。當你看到“InternalApplicationError”時,最好檢查一下試圖要發送給資料庫的SQL語句。
(97)我用ClassWizard建立了一個類。但是,我把名字取錯了,我想把它從項目中删除,應該如何做?
在ClassWizard對話框關閉後,用檔案管理器删除新類的H和CPP檔案。然後打開ClassWizard,它會提示丢失了兩個檔案,并詢問你該如何做。你可以選擇從項目中删除這兩個問的按鈕。
(98)當我打開應用程式中的視窗時,我要傳遞該視窗的矩形尺寸。該矩形指定了視窗的外圍大小,但是當我調用GetClientRect時,所得到的尺寸要比所希望的值要小(因為工具欄和視窗邊框的緣故)。有其它方法來計算視窗的尺寸嗎?
參見CWnd::CalcWindowRect。
(99)我在文檔類中設定了一個整型變量。但是,當我試圖把該變量寫入Serialize函數中的archive檔案中時,出現了類型錯誤。而文檔中的其它變量沒有問題。為什麼?
archive類隻重載某些類型的>>和<<操作符。“int”類型沒有在其中,也許是因為int變量在Windows3.1與WindowsNT/95有所不同的緣故吧。“long”類型得到了支援,是以你可以把int類型改成long型。參見MFC幫助檔案中CArchive類。
(100)如何控制菜單的大小?
我用MFC的CMenu生成了一個動态菜單(例如File,Edit,View...Help),我想控制這個菜單的大小(長+高).
方法一:查找WM_MEASUREITEM和MEASUREITEMSTRUCT.
方法二:查詢系統::GetSystemMetric(SM_CXMENUSIZE).
NONCLIENTMETRICSncm;
HFONThFontMenu;
SIZEsize;
size.cy = size.cy = 0;
memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
{
hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
char szText[_MAX_PATH];
pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
HFONT hFontOld;
HDC hDC;
hDC = ::GetDC(NULL);
hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
SelectObject(hDC, hFontOld);
::ReleaseDC(NULL, hDC);
}
(101) 改變LVIS_SELECTED的狀态顔色?
我想将CListCtrl項和CTreeCtrl項在LVIS_SELECTED狀态時的顔色變灰.
方法一:查找函數CustomDraw,它是IE4提供的公共控制,允許有你自己的代碼.
方法二:生成一個draw控件,然後在DrawItem中處理文本顔色.
(102) 如何隻存儲文檔的某一部分?
我隻想存儲文檔的某一部分,能否象使用檔案一樣使用文檔?(也就是有定位函數).将每個CArchive類設定為CFile類的派生類,這樣你就能使用Seek等成員函數.
(103) 儲存工具條菜單有bug嗎?
使用浮動菜單條時,SaveBarState和LoadBarState出現了問題.如果菜單是浮動的,重起應用程式時它會出現在左上角,而它固定在螢幕其它位置時,下一次啟動就會出現在該位置,這是什麼原因?你試試這個PToolBar->Create(this,...,ID_MYTOOLBAR);
你的工具條需要包括id,而不是象預設的工具條那樣.
(104) Tip of the day的bug
我建立了一個簡單的mdi應用程式,使用.BSF(自定義的文檔擴充名)作為它的文檔我儲存一個foo.bsf文檔後,可以在資料總管中輕按兩下該檔案打開mdi應用程式同時打開foo.bsf文檔.但當我給mdi應用程式加上a tip of the day元件之後,從資料總管中輕按兩下foo.bsf後,就會給我一個警告:ASSERT(::IsWindow(m_hWnd)),然後mdi應用程式就死那了.
當從dde啟動應用程式(例如:輕按兩下相關文檔)時,"Tip of the Day"是有bug的.你可以看看函數"ShowTipAtStartup",它在"InitInstance"中調用,可以看到tip of the day作為一個模式對話框顯示,在處理其它消息時它一直進行消息循環你可心修改ShowTipAtStartup使其從dde啟動時不出現tip of the day.
void CTipOfApp::ShowTipAtStartup(void)
{
// CG: This function added by 'Tip of the Day' component.
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (
cmdInfo.m_bShowSplash &&
cmdInfo.m_nShellCommand != CCommandLineInf:FileDDE
)
{
CTipDlg dlg;
if (dlg.m_bStartup)
dlg.DoModal();
}
}
如果還有其它bug,你可以設定cmdInfo.m_nShellCommand的過濾.
(105) 如何可以讓我的程式可以顯示在其它的視窗上面?
讓使用者選擇"總是在最上面"最好是在系統菜單裡加入一個選項.可以通過修改WM_SYSCOMMAND消息來發送使用者的選擇.菜單的指令辨別(id)會作為一個參數傳給OnSysCommand().要定義辨別(id),将如下代碼加入到CMainFrame.CPP中:
#define WM_ALWAYSONTOP WM_USER + 1
将"總在最上面"的菜單項加入到系統菜單中,将如下代碼加入到函數CMainFrame::OnCreate()中:
CMenu* pSysMenu = GetSystemMenu(FALSE);
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,
"&Always On Top");
使用ClassWizard,加入對WM_SYSCOMMAND消息的處理,你應該改變消息過濾器,使用系統可以處理這個消息.
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam)
{
switch ( nID )
{
case WM_ALWAYSONTOP:
if ( GetExStyle() & WS_EX_TOPMOST )
{
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,
MF_UNCHECKED);
}
else
{
SetWindowPos(&wndTopMost, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE);
GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED);
}
break;
default:
CFrameWnd::OnSysCommand(nID, lParam);
}
}
(106) 如何控制視窗架構的最大最小尺寸?
要控制一個架構的的最大最小尺寸,你需要做兩件事情.在CFrameWnd的繼承類中處理消息WM_GETMINMAXINFO,結構MINMAXINFO設定了整個視窗類的限制,是以記住要考慮工具條,卷動條等等的大小.
// 最大最小尺寸的象素點 - 示例
#define MINX 200
#define MINY 300
#define MAXX 300
#define MAXY 400
void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
CRect rectWindow;
GetWindowRect(&rectWindow);
CRect rectClient;
GetClientRect(&rectClient);
// get offset of toolbars, scrollbars, etc.
int nWidthOffset = rectWindow.Width() - rectClient.Width();
int nHeightOffset = rectWindow.Height() - rectClient.Height();
lpMMI->ptMinTrackSize.x = MINX + nWidthOffset;
lpMMI->ptMinTrackSize.y = MINY + nHeightOffset;
lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset;
lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset;
}
第二步,在CFrameWnd的繼承類的PreCreateWindow函數中去掉WS_MAXIMIZEBOX消息,否則在最大化時你将得不到預料的結果.
BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style &= ~WS_MAXIMIZEBOX;
return CFrameWnd::PreCreateWindow(cs);
}
(107) 如何改變視窗架構的顔色?
MDI架構的客戶區被另一個視窗的架構所覆寫.為了改變客戶區的背景色,你需要重畫這個客戶視窗.為了做到這點,你要處理消息WM_ERASEBKND産生一個新類,從CWnd繼承,姑且稱之為CMDIClient.給它加上一個成員變量,
#include "MDIClient.h"
class CMainFrame : public CMDIFrameWnd
{
...
protected:
CMDIClient m_wndMDIClient;
}
在CMainFrame中重載CMDIFrameWnd::OnCreateClient
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) )
{
m_wndMDIClient.SubclassWindow(m_hWndMDIClient);
return TRUE;
}
else
return FALSE;
}
然後就可以加入對消息WM_ERASEBKGND的處理了.
(108) 如何将應用程式視窗置于螢幕正中?
要将你的應用程式視窗放置在螢幕正中央,隻須在MainFrame的OnCreate函數中加入:
CenterWindow( GetDesktopWindow() );