VC 和 MFC 的一些常见问题

发布时间:2011-03-15 11:22:58   来源:文档文库   
字号:
本文由hengzoo_xu贡献 doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 如何抛出(throw)由 CUserException 派生的异常? 当我试图捕获(catch)一个派生类异常时,我得到以下错误"error C2039:'classCMyExce ption': is not a member of 'CMyException' 'classCMyException': undeclared ident ifier 'IsKindOf': cannot convert parameter 1 from 'int*' to 'const struct CRunt imeClass*" 你必需通过使用 DECLARE_DYNAMIC()和 IMPLEMENT_DYNAMIC()宏来使你的 CMyException 类可以动态地创建。CATCH 宏希望能够得到关于被抛出类的运行时刻信息。 异常类一定要从 CUserException 中派生出来吗? 不,CUserException 中的"User"仅仅指用户产生的异常。而把它当作你所能派生的唯一异 常是种常见的误解。 如何从 HDC 建立一个 CDC 类? 有时 Windows API 将会给你一个 DC 句柄,你可以通过它建立一个 CDC 类。例如:下拉式列 表、组合框和按钮。通过 hDC 你将接收到绘制消息。下面是将 HDC 转换成你更熟悉的 CDC 的程序段。你也可以将该技巧用在其他任何 MFC 类和 Windows 句柄的转换中。 void MyODList::DrawItem(LPDRAWITEMSTRUCT lpDrawItem) { CDC myDC; 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 的大小? 要想详细了解的话,你可以看有关 Visual C++基础知识的文章 Q98598 《Using CFormVi ew in SDI and MDI Applications》。基本上,在从 CFormView 类派生出来的类中,你必须 覆盖函数 OnInitialUpdate()。 其他有关建立 CFormView 的细节问题, 可以从该文章中获得。 在类 Cl ikethisView 中声明如下函数: virtual void OnInitialUpdate(); 在 ClikethisView 的代码中,函数如下: void ClikethisView::OnInitialUpdate() { //使窗口与主对话框同样大小 CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit( /*FALSE*/ ); } 如何使用一个文档模板的新视图? 在用 AppWizard 创建的应用程序中, 你有两种选择: 改变当前视图的派生关系或者建立一个 新视图并且在你的 MDI 程序中同时利用新视图和原先的视图。 为了创建一个新视图,你可以用 ClassWizard 由 CView 派生一个新的类。当新类创建以后, 利用新视图或修改由 AppWizard 提供的视图,两者的步骤是相同的。 修改视类的头文件,从而将所有对 CView 类的引用改名为你所想要的名称。本例中的类由 C ScrollView 派生而来。通常,这个步骤包括对类的改变,视类将由如下方式派生而来: class CMyView : public CScrollView 修改视类的实现文件,从而将所有对 CView 的引用改名为你所想要的名称。这包括将 IMPLE MENT_DYNCREATE 那一行的语句改为: IMPLEMENT_DYNCREATE(CMyView, CScrollView) 将 BEGIN_MESSAGE_MAP 那一行的语句改为: BEGIN_MESSAGE_MAP(CMyView, CScrollView) 并且将其他所有的 CView 改成 CScrollView. 假如你修改的视图是由 AppWizard 生成的, 那么就不需要作更多的修改了。 而如果你在创建 一个新视图,先在 CWinApp::InitInstance()函数中找到对 AddDocTemplate()函数的调用。 AddDocTemplate()函数的第三个参数是 RUNTIME_CLASS(CSomeView),用 CMyView 来代替 CS omeView,就可以将当前视图改为新视图。在 MDI 应用程序中,你可以增加第二个 AddDocTe mplate()函数调用来使用多视图类型,将 RUNTIME_CLASS(CSomeView)改为 RUNTIME_CLASS (CMyView)。 要想获得更多的信息请参阅 Q99562 中相关文章 《Switching Views in a Single Document Interface Program》 。 如何改变视图的背景色? 你可以通过处理 WM_ERASEBKGND 消息来改变 CView、 CFrameWnd 或 CWnd 对象的背景色。 请看 如下的程序段: BOOL CSampleView::OnEraseBkgnd(CDC* pDC) { // 设置所要求背景色的刷子 CBrush backBrush(RGB(255, 128, 128)); // 保存旧刷子 CBrush* pOldBrush = pDC->SelectObject(&backBrush); CRect rect; pDC->GetClipBox(&rect); // 擦除所需的区域 pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); pDC->SelectObject(pOldBrush); return TRUE; } 而我则用如下方法解决这个问题: HBRUSH dlgtest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { switch (nCtlColor) { case CTLCOLOR_BTN: case CTLCOLOR_STATIC: { pDC->SetBkMode(TRANSPARENT); } case CTLCOLOR_DLG: { CBrush* back_brush; COLORREF color; color = (COLORREF) GetSysColor(COLOR_BTNFACE); back_brush = new CBrush(color); return (HBRUSH) (back_brush->m_hObject); } } return(CFormView::OnCtlC olor(pDC, pWnd, nCtlColor)); } 如何得到当前视图? 最佳方法是将视图当作一个参数来传递。 如果不能这样做, 但你确信它是当前激活文档和当 前激活视图的话,你也可以得到该视图。具体细节见 Visual C++文章 Q108587《Get Current CDocument or CView from Anywhere》 。 简单说来,用: ((CFrameWnd*) AfxGetApp()->m_pMainWnd))->GetActiveDocument() 和: ((CFrameWnd*)(AfxGetApp()->m_pMainWnd))->GetActiveView() 来得到文档和视图。一个好的方法是将它们封装在你的 CMyDoc 和 CMyView 类的静态函数 中,并且核对它们是否属于正确的 RUNTIME_CLASS。然而,假如这个视图不是当前激活视 图或者你在运行 OLE 本地激活,这样将不成功。 如何在一个文档中建立多个视图? CDocTemplate::CreateNewFrame()函数创建 MFC MDI 应用程序中的文档的附加视图。为了调 用该函数,要指定一个指向 CDocument 对象(指将为之建立视图的文档)的指针和一个指 向可从中复制属性的框架窗口的指针。一般情形下,该函数的第二个参数为 NULL。 当应用程序调用函数 CreateNewFrame()时, 该函数就创建一个框架窗口和在该窗口内的视图。 框架窗口和它的视图的类型由与 CreateNewFrame()函数调用指定的文档相关的文档摸板 (CDocTemplate)决定。 Visual C++中的 CHKBOOK MFC 样例程序也演示了如何为文档建立附加的框架和视图。检查 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 的类可以帮助你显示所 有的视图和文档。请参考《MFC Internals》获得更详细的信息。 如何建立一个可用鼠标拉动的 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 = new CMultiDocTemplate( IDR_DOC2TYPE, RUNTIME_CLASS(CDoc2), RUNTIME_CLASS(CMDIChildWnd),RUNTIME_CLASS(CView2)); AddDocTemplate(pDocTemplate2); 最后,将定制的序列化和绘图代码加入到你的新文档和视图类中。 如何得到一个打开文档的列表? 下面的程序段指明如何得到用 CDocTemplate 对象建立的所有文档的指针列表。 下面的程序段中, CMyApp 由 CWinApp 派生而来。 变量 m_templateList 是一个 CPtrList 对象, 它 是 CwinApp 的 成 员 变 量 , 包 含 一 个 所 有 文 档 模 板 指 针 的 列 表 。 文 档 模 板 函 数 GetFirstDocPosition()和 GetNextDoc()被用来在文档模板列表中进行迭代来得到每一个文档模 板。 void CMyApp::GetDocumentList(CObList * pDocList) { ASSERT(pDocList->IsEmpty()); POSITION pos = m_templateList.GetHeadPosition(); while (pos) { CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos); POSITION pos2 = pTemplate->GetFirstDocPosition(); while (pos2) { CDocument * pDocument; if ((pDocument=pTemplate->GetNextDoc(pos2)) != NULL) pDocList->AddHead(pDocument); } } } 在参考手册或在线帮助中,有两个 CdocTemplate 类的公共成员函数没有被说明。然而, 这 些公共成员函数在 CDocTemplate 类中被定义,并且为在打开文档的列表中前后搜索提供了 简单的支持。 这些函数如下: Function virtual POSITION GetFirstDocPosition() const; 调 用该函数得到在打开的文档列表中与模板相关联的第一个文档的位置。返回的 POSITION 的值能够被 GetNextDoc 成员函数反复使用。 Function Virtual CDocument* GetNextDoc(POSITION& rPosition) const; rPostion 是前面调用 GetNextDoc 或 GetFirstDocPosition 成员函数返回的 POSITION 值。这个 值不能是 NULL。调用该函数来在所有打开的文档中进行迭代。该函数返回被 rPosition 所标 识的文档并将 rPosition 设置为列表中的下一个文档的 POSITION 值。假如所检索的是列表中 的最后一个文档,rPosition 将被设为空值。 注意,这仅对 MFC3.2 版本或更低版本有效,对 MFC4.0 版本请参考下面: void CMyApp::DoSomethingToAllDocs() { CObList pDocList; POSITION pos = GetFirstDocTemplatePosition(); while(pos) { CDocTemplate* pTemplate = GetNextDocTemplate(pos); POSITION pos2 = 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

本文来源:https://www.2haoxitong.net/k/doc/7103f5fd700abb68a982fb06.html

《VC 和 MFC 的一些常见问题.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式