`
isiqi
  • 浏览: 16488220 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

VC和MFC的一些常见问题

阅读更多

VC和MFC的一些常见问题

2002-11-2 9:34:25 PCVC.NET 作者不详 阅读次数:35261
如何抛出(throw)由CUserException派生的异常?

当我试图捕获(catch)一个派生类异常时,我得到以下错误"errorC2039:'classCMyException':isnotamemberof'CMyException''classCMyException':undeclaredidentifier'IsKindOf':cannotconvertparameter1from'int*'to'conststructCRuntimeClass*"

你必需通过使用DECLARE_DYNAMIC()和IMPLEMENT_DYNAMIC()宏来使你的CMyException类可以动态地创建。CATCH宏希望能够得到关于被抛出类的运行时刻信息。

异常类一定要从CUserException中派生出来吗?

不,CUserException中的"User"仅仅指用户产生的异常。而把它当作你所能派生的唯一异常是种常见的误解。

如何从HDC建立一个CDC类?

有时WindowsAPI将会给你一个DC句柄,你可以通过它建立一个CDC类。例如:下拉式列表、组合框和按钮。通过hDC你将接收到绘制消息。下面是将HDC转换成你更熟悉的CDC的程序段。你也可以将该技巧用在其他任何MFC类和Windows句柄的转换中。

voidMyODList::DrawItem(LPDRAWITEMSTRUCTlpDrawItem)
{
CDCmyDC;
myDC.Attach(lpDrawItem->hDC);
//在此插入其他需要的代码。

//如果你不将句柄分离,它将被删除,从而导致问题。
myDC.Detach();
}
另一个方法是调用CDC类的FromHandle方法:
CDC*pDC=CDC:FromHandle(lpDrawItem->hDC);

目前还不清楚哪种方法更优越―使用FromHandle()的错误也许会更少些,因为它不要求你分离(detach)句柄。
如何从磁盘上读取256色位图文件?

当前,MFC并不支持直接读取和显示DIB文件和BMP文件。然而,有很多样例应用程序能够说明如何完成该项任务。第一个例子是MFC样例程序DIBLOOK。样例MULTDOCS用DIBLOOK提供的相同源代码来读取并显示DIB文件和BMP文件。其他两个VC++中附带的例子是SDK软件包中的DIBVIEW程序和SHOWDIB程序。

如何改变一个视图的大小?

通常,你可以调用函数MoveWindow()来改变窗口的大小。在用MFC库开发的应用程序中,视图是被框架窗口所围绕的一个子窗口。为了改变一个视图的大小,你可以通过调用函数GetParentFrame()来得到框架窗口的指针,然后调用函数MoveWindow()来改变父窗口的大小。当父框架窗口改变大小时,视图也会自动地改变大小来适应父窗口。

如何改变一个CFormView的大小?

要想详细了解的话,你可以看有关VisualC++基础知识的文章Q98598《UsingCFormViewinSDIandMDIApplications》。基本上,在从CFormView类派生出来的类中,你必须覆盖函数OnInitialUpdate()。其他有关建立CFormView的细节问题,可以从该文章中获得。

在类ClikethisView中声明如下函数:
virtualvoidOnInitialUpdate();

在ClikethisView的代码中,函数如下:

voidClikethisView::OnInitialUpdate()
{
//使窗口与主对话框同样大小
CFormView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit(/*FALSE*/);
}

如何使用一个文档模板的新视图?
在用AppWizard创建的应用程序中,你有两种选择:改变当前视图的派生关系或者建立一个新视图并且在你的MDI程序中同时利用新视图和原先的视图。


为了创建一个新视图,你可以用ClassWizard由CView派生一个新的类。当新类创建以后,利用新视图或修改由AppWizard提供的视图,两者的步骤是相同的。


修改视类的头文件,从而将所有对CView类的引用改名为你所想要的名称。本例中的类由CScrollView派生而来。通常,这个步骤包括对类的改变,视类将由如下方式派生而来:
classCMyView:publicCScrollView


修改视类的实现文件,从而将所有对CView的引用改名为你所想要的名称。这包括将IMPLEMENT_DYNCREATE那一行的语句改为:
IMPLEMENT_DYNCREATE(CMyView,CScrollView)


将BEGIN_MESSAGE_MAP那一行的语句改为:
BEGIN_MESSAGE_MAP(CMyView,CScrollView)


并且将其他所有的CView改成CScrollView.


假如你修改的视图是由AppWizard生成的,那么就不需要作更多的修改了。而如果你在创建一个新视图,先在CWinApp::InitInstance()函数中找到对AddDocTemplate()函数的调用。AddDocTemplate()函数的第三个参数是RUNTIME_CLASS(CSomeView),用CMyView来代替CSomeView,就可以将当前视图改为新视图。在MDI应用程序中,你可以增加第二个AddDocTemplate()函数调用来使用多视图类型,将RUNTIME_CLASS(CSomeView)改为RUNTIME_CLASS(CMyView)。

要想获得更多的信息请参阅Q99562中相关文章《SwitchingViewsinaSingleDocumentInterfaceProgram》。

如何改变视图的背景色?

你可以通过处理WM_ERASEBKGND消息来改变CView、CFrameWnd或CWnd对象的背景色。请看如下的程序段:

BOOLCSampleView::OnEraseBkgnd(CDC*pDC)
{
//设置所要求背景色的刷子
CBrushbackBrush(RGB(255,128,128));
//保存旧刷子
CBrush*pOldBrush=pDC->SelectObject(&backBrush);
CRectrect;
pDC->GetClipBox(&rect);//擦除所需的区域
pDC->PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATCOPY);
pDC->SelectObject(pOldBrush);
returnTRUE;
}


而我则用如下方法解决这个问题:
HBRUSHdlgtest::OnCtlColor(CDC*pDC,CWnd*pWnd,UINTnCtlColor)
{
switch(nCtlColor)
{
caseCTLCOLOR_BTN:
caseCTLCOLOR_STATIC:
{
pDC->SetBkMode(TRANSPARENT);
}
caseCTLCOLOR_DLG:
{
CBrush*back_brush;
COLORREFcolor;
color=(COLORREF)GetSysColor(COLOR_BTNFACE);
back_brush=newCBrush(color);
return(HBRUSH)(back_brush->m_hObject);
}
}
return(CFormView::OnCtlColor(pDC,pWnd,nCtlColor));
}

如何得到当前视图?

最佳方法是将视图当作一个参数来传递。如果不能这样做,但你确信它是当前激活文档和当前激活视图的话,你也可以得到该视图。具体细节见VisualC++文章Q108587《GetCurrentCDocumentorCViewfromAnywhere》。

简单说来,用:

((CFrameWnd*)AfxGetApp()->m_pMainWnd))->GetActiveDocument()

和:

((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->GetActiveView()


来得到文档和视图。一个好的方法是将它们封装在你的CMyDoc和CMyView类的静态函数中,并且核对它们是否属于正确的RUNTIME_CLASS。然而,假如这个视图不是当前激活视图或者你在运行OLE本地激活,这样将不成功。
如何在一个文档中建立多个视图?

CDocTemplate::CreateNewFrame()函数创建MFCMDI应用程序中的文档的附加视图。为了调用该函数,要指定一个指向CDocument对象(指将为之建立视图的文档)的指针和一个指向可从中复制属性的框架窗口的指针。一般情形下,该函数的第二个参数为NULL。

当应用程序调用函数CreateNewFrame()时,该函数就创建一个框架窗口和在该窗口内的视图。框架窗口和它的视图的类型由与CreateNewFrame()函数调用指定的文档相关的文档摸板(CDocTemplate)决定。

VisualC++中的CHKBOOKMFC样例程序也演示了如何为文档建立附加的框架和视图。检查CHKBOOK.CPP文件中的CChkBookApp::OpenDocumentfile()函数。

另一个用函数CreateNewFrame()的例子是MULTVIEW样本程序。

CreateNewFrame()函数建立了一个框架和一个视图,而不仅仅是一个视图。假如CreateNewFrame()函数不能完全符合你的需要,可参考CreateNewFrame()函数的源程序来了解对建立结构和视图所必须的步骤。

如何在MDI程序中得到所有的视图?

你必须用一些文档中没有记载的函数:

CDocument::GetFirstViewPosition();//DOCCORE.CPP
CDocument::GetNextView();//DOCCORE.CPP
CMultiDocTemplate::GetFirstDocPosition();//DOCMULTI.CPP
CMultiDocTemplate::GetNextDoc();//DOCMULTI.CPP


你还需要与CWinApp的成员m_templateList打交道。
注意:在MFC版本4.0中已改变。现在已经有一个叫CDocManager的类可以帮助你显示所有的视图和文档。请参考《MFCInternals》获得更详细的信息。

如何建立一个可用鼠标拉动的CScrollView类

在CIS上从MSMFC库下载AUTOSV.LZH。这个程序告诉你如何实现一个辅助消息循环来管理鼠标的活动,并提供了钩挂来对代码进行定制。这是一个免费软件。

一定要用视图/文档结构吗?

MFC并不一定要求你使用文档/视图结构。查看HELLO、MDI和HELLOAPP例子―它们就没有用那种结构。大多数MFC特性都可以在非文档/视图应用程序中得到运用。但是当你不用文档/视图结构时,你确实会失去一些特性,例如打印预览和许多OLE特性。

如何得到当前文档?

请详细参阅"如何得到当前视图?"章节。

文档何时被析构?

在SDI程序中,程序退出后文档就被删除。在MDI程序中,与该文档相关的最后一个视图关闭时文档就被删除。为了在SDI和MDI中同时用这个文档,你应该在虚函数DeleteContents()函数中删除该文档的数据,而不是在析构器中。

如何建立多文档?

为了加入对附加文档类型的支持,你可以在CWinApp派生类中创建和注册附加CmultiDocTemplate对象。这种方法已经在MULTDOCS样例程序中得以说明。将一个附加文档类型加入到MFC程序的一般步骤如下:

用AppWizard来创建一个新的文档类和视图类。
用资源编辑器增加新的资源字串来支持新的文档类。要想知道关于文档样板字符串格式的更多内容,请参阅"如何理解文档样板字符串"。

用资源编辑器增加附加的应用程序图标和菜单资源。注意,这些资源中每一个的ID都必须与在步骤2中创建的文档模板字符串的ID是相同的。这个ID被CmultiDocTemplate类用来识别与附加文档类型相关的资源。

在应用程序的InitInstance()函数中,创建了另一个CMultiDocTemplate对象并且用CWinApp::AddDocTemplate()函数来注册。例如:

CMultiDocTemplate*pDocTemplate2=newCMultiDocTemplate(
IDR_DOC2TYPE,RUNTIME_CLASS(CDoc2),
RUNTIME_CLASS(CMDIChildWnd),RUNTIME_CLASS(CView2));
AddDocTemplate(pDocTemplate2);

最后,将定制的序列化和绘图代码加入到你的新文档和视图类中。
如何得到一个打开文档的列表?

下面的程序段指明如何得到用CDocTemplate对象建立的所有文档的指针列表。
下面的程序段中,CMyApp由CWinApp派生而来。变量m_templateList是一个CPtrList对象,它是CwinApp的成员变量,包含一个所有文档模板指针的列表。文档模板函数GetFirstDocPosition()和GetNextDoc()被用来在文档模板列表中进行迭代来得到每一个文档模板。

voidCMyApp::GetDocumentList(CObList*pDocList)
{
ASSERT(pDocList->IsEmpty());
POSITIONpos=m_templateList.GetHeadPosition();
while(pos)
{
CDocTemplate*pTemplate=
(CDocTemplate*)m_templateList.GetNext(pos);
POSITIONpos2=pTemplate->GetFirstDocPosition();
while(pos2)
{
CDocument*pDocument;
if((pDocument=pTemplate->GetNextDoc(pos2))!=NULL)
pDocList->AddHead(pDocument);
}
}
}


在参考手册或在线帮助中,有两个CdocTemplate类的公共成员函数没有被说明。然而,这些公共成员函数在CDocTemplate类中被定义,并且为在打开文档的列表中前后搜索提供了简单的支持。

这些函数如下:


FunctionvirtualPOSITIONGetFirstDocPosition()const;
调用该函数得到在打开的文档列表中与模板相关联的第一个文档的位置。返回的POSITION的值能够被GetNextDoc成员函数反复使用。

FunctionVirtualCDocument*GetNextDoc(POSITION&rPosition)const;
rPostion是前面调用GetNextDoc或GetFirstDocPosition成员函数返回的POSITION值。这个值不能是NULL。调用该函数来在所有打开的文档中进行迭代。该函数返回被rPosition所标识的文档并将rPosition设置为列表中的下一个文档的POSITION值。假如所检索的是列表中的最后一个文档,rPosition将被设为空值。

注意,这仅对MFC3.2版本或更低版本有效,对MFC4.0版本请参考下面:

voidCMyApp::DoSomethingToAllDocs()
{
CObListpDocList;
POSITIONpos=GetFirstDocTemplatePosition();
while(pos)
{
CDocTemplate*pTemplate=GetNextDocTemplate(pos);
POSITIONpos2=pTemplate->GetFirstDocPosition();
while(pos2)
{
CDocument*pDocument;
if(pDocument=pTemplate->GetNextDoc(pos2))
pDocList.AddHead(pDocument);
}
}
if(!pDocList.IsEmpty()){
pos=pDocList.GetHeadPosition();
while(pos)
{
//为每一个文档调用CDocument函数
((CDocument*)pDocList.GetNext(pos))
->UpdateAllViews(NULL);
}
}

如何使我的程序在启动时不创建一个新文档?

在程序的InitInstance中的ProcessShellCommand函数之前加入:cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing

分享到:
评论

相关推荐

    MFC常见问题集

    本资料集主要聚焦于在使用MFC过程中遇到的常见问题及其解决方案。 1. **MFC基本概念** - **框架类(Frame Classes)**:如CWinApp,CFrameWnd,CMDIFrameWnd,它们是应用程序的主要入口点,管理应用程序的生命周期...

    VC6中MFC常见编译错误

    总之,理解和解决这些常见的VC6 MFC编译和链接错误是开发过程中的重要环节,通过仔细检查代码、配置项目设置以及确保正确的库链接,开发者能够有效地调试和修复这些问题,从而顺利地进行MFC应用程序的开发。

    VC基于MFC实现学生成绩管理系统

    通过以上步骤,一个基于VC和MFC的学生成绩管理系统便得以实现。这样的系统不仅简化了教育机构的管理工作,还为教学评估提供了准确的数据支持,提高了教育信息化水平。在实际应用中,可以根据具体需求进一步定制和...

    vc6.0 mfc类库参考手册

    《VC6.0 MFC类库参考手册》是面向Visual C++ 6.0开发者的一份重要参考资料,它深入解析了Microsoft Foundation Classes (MFC)库的使用和功能。MFC是一个C++类库,它封装了Windows API,使得开发者能够更加方便地进行...

    基于VC6.0 MFC写的串口助手

    本文将详细介绍基于Visual C++ 6.0(简称VC6.0)和MFC(Microsoft Foundation Classes)开发的串口助手应用程序。MFC是微软提供的一套C++类库,用于构建Windows应用程序,它简化了Windows API的使用。 **1. MFC框架...

    VC/MFC 控件demo

    **VC/MFC 控件demo** 是一个用于展示Visual C++/MFC(Microsoft Foundation Classes)框架下各种基础控件使用的示例程序。该程序在Visual Studio 2005环境下已成功编译并通过测试,为开发者提供了一个学习和理解MFC...

    VC,MFC获取现有的串口列表

    在VC++和MFC(Microsoft Foundation Classes)编程环境中,开发者经常需要处理硬件设备通信,而串口通信是其中一种常见的接口。"VC,MFC获取现有的串口列表"这一主题聚焦于如何在程序中获取系统中所有可用的串行端口...

    简易计算器VCMFC

    总之,"简易计算器VCMFC"是一个利用VC++和MFC进行的实践项目,旨在教授开发者如何使用MFC创建图形用户界面,并实现简单的数学计算功能。通过这个项目,实习生可以学习到C++编程、Windows程序设计、MFC框架的应用以及...

    VC-MFC编程实例.pdf

    - `CObject`: 提供了一些基础功能,比如动态类型信息和序列化支持。 - `CWnd`: 是所有窗口类的基类,提供了与窗口相关的操作。 - `CCmdTarget`: 用于处理命令消息。 - **MFC类分类**: - **应用程序类**: 如`...

    VC MFC类库详解 中文版

    《VC MFC类库详解》这本中文版的资料,对于理解和掌握MFC非常有帮助。CHM文件是一种常见的帮助文档格式,通常包含丰富的索引和搜索功能,方便快速查找所需信息。通过阅读此书,你可以深入理解MFC的类结构、使用方法...

    VC6MFC md5计算 返回CString字符串

    这个标题提到的"VC6MFC md5计算 返回CString字符串"是一个简单实用的实现方式,它允许开发者在MFC应用中方便地计算MD5值,并以常见的CString对象返回结果。 首先,我们要理解MD5的基本原理。MD5是由Ronald Rivest...

    VC6.0MFC实现的网格图像图像识别

    在VC6.0中,我们可以利用OpenCV等图像处理库来实现这一过程,但原生的MFC也提供了基本的图像处理函数,如位图操作和颜色转换。 1. **灰度化**:这是图像预处理的第一步,将彩色图像转化为灰度图像,以减少计算复杂...

    VC/MFC 基于对话框 按钮加载PNG图片

    PNG(Portable Network Graphics)是一种支持透明度的无损压缩图像格式,与常见的JPG格式相比,PNG提供了更好的透明效果和颜色保真度。在MFC中,由于默认不支持PNG,因此需要引入额外的库来处理PNG图像。 1. **引入...

    VC/MFC使用日期控件设置、获取日期时间信息

    总结起来,VC/MFC中的日期控件CDateTimeCtrl提供了一种直观的方式来显示和选择日期和时间。通过设置控件的格式、获取和设置日期,以及处理用户选择的事件,我们可以构建出用户友好的界面来处理日期和时间相关的功能...

    注销重启VC_MFC

    在注销和重启VC_MFC的上下文中,Apisys可能包含了用于执行这些操作的函数或类。例如,它可能提供了封装好的注册表操作,或者帮助管理COM组件的生命周期。具体功能和用法需要查看Apisys的相关文档或源代码才能详细...

    VC/MFC实现简单的Http服务器(可访问图片和网站内页)

    对于一个简单的HTTP服务器,我们主要关注GET请求,因为这是访问网页和图片最常见的方式。 在VC/MFC环境下创建HTTP服务器,首先需要集成一个网络库,如Winsock,它提供了底层的TCP/IP通信功能。要启用Winsock,你...

    VC基于MFC文本编辑程序

    本项目“VC基于MFC文本编辑程序”旨在实现一个基本的文本编辑器,具备常见的文本编辑功能,如文本输入、字体设置、文本缩进,以及一些附加特性,如简单的画图功能和状态栏信息显示。下面将详细解释这些功能的实现...

    \VC6.0中MFC生成.exe安装包步骤.

    - **文档准备**:为用户提供详细的安装指南和常见问题解答文档,有助于提高用户体验。 通过上述步骤,您可以顺利地在Visual C++ 6.0中将MFC编写的应用程序打包成安装包,进而方便地分发给用户。

    VC 2015 MFC 图片列表ListCtrl

    在VC 2015中,使用MFC进行开发时,可以利用丰富的库支持和文档来实现图片列表功能。通过理解这些基本概念和API,开发者可以创建出功能丰富的用户界面,提供更好的用户体验。同时,`vc 2015缩图` 文件可能包含了示例...

Global site tag (gtag.js) - Google Analytics