天天看點

vc常用技巧總結五

(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() );