现在的位置: 首页 > 综合 > 正文

VC技巧总结108条(二)

2013年12月13日 ⁄ 综合 ⁄ 共 11236字 ⁄ 字号 评论关闭

(68) 如何检索原先的Task Manager应用程序使用的任务列表
原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。

void GetTadkList (CListBox&list)
{
CString strCaption
//Caption of window.

list.ResetContent ()
//Clear list box.

//Get first Window in window list.
ASSERT_VALID (AfxGetMainWnd ())
CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)

//Walk window list.
while (pWnd)
{
// I window visible, has a caption, and does not have an owner?
if (pWnd ->IsWindowVisible()
&& pWnd ->GetWindowTextLength ()
&&! pWnd ->GetOwner ())
{

//Add caption o window to list box.

pWnd ->GetWindowText (strCaption)

list.AddString (strCaption)
}
//Get next window in window list.
pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
}
}

(69) 如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数:

TCHAR szDir [MAX_PATH]
//Get the full path of the windows directory.
∶ : GetWindowsDirectory (szDir, MAX_PATH)
TRACE ("Windows directory %s\n", szDir)
//Get the full path of the windows system directory.
∶ : GetSystemDirectory (szDir, MAX_PATH)
TRACE ("Windows system directory %s\n", szDir)

(70) 在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。


//get unique temporary file.
CString strFile
GetUniqueTempName (strFile)
TRY
{
//Create file and write data.Note that file is closed
//in the destructor of the CFile object.
CFile file (strFile,CFile ::modeCreate | CFile:: modeWrite)

//write data
}

CATCH (CFileException, e)
{
//error opening file
}
END_CATCH

Void GetuniqueTempName (CString& strTempName)
{
//Get the temporary files directory.
TCHAR szTempPath [MAX_PATH]
DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
ASSERT (dwResult)

//Create a unique temporary file.
TCHAR szTempFile [MAX_PATH]
UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
ASSERT (nResult)

strTempName=szTempFile
}

(71) 我怎样才能建立一个等待光标?
调 用 BeginWaitCursor 函数来启动等待光标,调用EndWaitCursor函数来结束等待光标。要注意,二者都要调用 app 的成员函数,如下所示:

AfxGetApp()->BeginWaitCursor();
// 要做的事
AfxGetApp()->EndWaitCursor();

(72)我在MDI框架中有个form视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?
调用OnCloseDocument函数。

(73)如何访问桌面窗口
静态函数CWnd::GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。

void CFrameWnd::BeginModalState ()
{

//first count all windows that need to be disabled
UINT nCount=0
HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
while (hWnd!=NULL)
{
if (:: IsWindowEnabled (hwnd)
&& CWnd::FromHandlePermanent (hWnd)!=NULL
&& AfxIsDescendant (pParent->m_hWnd, hWnd)
&& :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
{
++nCount
}
hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
}

(74) 什么是COLORREF? 我该怎样用它?
COLORREF 是 一个32-bit整型数值,它代表了一种颜色。你可以使用RGB函数来初始化COLORREF。例如:

COLORREF color = RGB(0, 255, 0);
RGB函数接收三个0-255数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为0,所以在该颜色中没有红色和蓝色。绿色为最大值255。所以该颜色为绿色。0,0,0为黑色,255,255,255为白色。

另一种初始化COLORREF的方法如下所示:

CColorDialog colorDialog;
COLORREF color;

if( colorDialog.DoModal() == IDOK )
{
color = colorDialog.GetColor();
}
这 段代码使用了MFC中的颜色对话框,它需要文件。


(75) AppWizard所产生的STDAFX文件是干什么用的?
它主要是协助产生预编译头文件的。通常你是不需要修改它的。

(76) 我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?
CDWordArray 是很好用的,只是因为你没有指定数组的最大尺寸。因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。解决该问题的方法是,你可以使用SetSize函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为500,则每次数组空间超出时它才重新分配并添加500个新空间,而不是1个。这样一来,你就可以不用重新分配而添加了另外499个元素空间,这也会大大提高程序的运行速度。


(77) 我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?
在 视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。GetParentFrame会返回一指向一保存有该视的框架窗口的指针。然后调用在框架窗口上调用MoveWindow。

(78)在我的程序的某些部分,我可以调用MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?
MessageBox函数来自CWnd类,所以你只能在从CWnd继承的类(如CView)中调用它。但是,MFC也提供了AfxMessageBox函数,你可以在任何地方调用它。


(79) 我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?
把该变量放到该应用程序类的头文件中的attribute处。然后,在程序的任何地方,你都可以用下面的方法来访问该变量:

CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...

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

/*你可以通过如下代码来获得文本的大小:
(A)获得被使用的字体*/

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);
/*
(B) 获得菜单项的文本: */
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);
}
/*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4

比较合适。*/


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

转自:http://hi.baidu.com/hackeryongsheng/blog/item/376abaddf61682c38c1029df.html

抱歉!评论已关闭.