MFC中文档类的 OnOpenDocument是怎样打开文件的呢?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC中文档类的 OnOpenDocument是怎样打开文件的呢?相关的知识,希望对你有一定的参考价值。
BOOL CQuanXinDoc::OnOpenDocument(LPCTSTR lpszPathName)
DeleteContents();
// 更改光标形状
BeginWaitCursor();
// 读取图像并附加到m_Image上
if(!m_Image.AttachFromFile(lpszPathName))
EndWaitCursor();
AfxMessageBox("打开文件时出错!请确保正确的位图(*.bmp)文件类型。");
return FALSE;
// 恢复光标形状
EndWaitCursor();
// 判断读取成功否
if (!m_Image.m_lpData)
// 失败,可能非BMP格式
CString strMsg;
strMsg = "读取图像时出错!可能是不支持该类型的图像文件!";
// 提示出错
MessageBox(NULL, strMsg, "系统提示", MB_ICONINFORMATION | MB_OK);
// 返回FALSE
return FALSE;
Init(); //对图像的尺寸和调色板信息进行初始化
// 设置文件名称
SetPathName(lpszPathName);
// 拷贝当前m_Image到m_OImage
m_OImage = m_Image;
// 初始化胀标记为FALSE
SetModifiedFlag(FALSE);
// 返回TRUE
return TRUE;
其中上文中的AttachFromFile(LPCTSTR lpcPathName)函数定义如下:
BOOL CImg::AttachFromFile(LPCTSTR lpcPathName)
// 使用CFile对象简化操作
CFile file;
if(!file.Open(lpcPathName, CFile::modeRead|CFile::shareDenyWrite))
return FALSE;
BOOL bSuc = AttachFromFile(file);
file.Close();
return bSuc;
我没有定义 CFileDialog dlg 当我点击系统自动给我创建的“打开” 按钮时候怎么会弹出文件选取对话框呢?? 不懂 而且LPCTSTR lpcPathName这个参数我并没有定义它到哪个位置,file.Open函数不是需要指定的路径吗?
实际上,在到达文档类的OnOpenDocument的时候,大部分之前的关联、文件对话框的工作已经做完了,而函数的参数,实际就是CFileDialog获取到的文件名。
封装的过程比较复杂,都是在MFC的基类代码中实现的(大部分为开源,可以在安装目录找到),处理关联是在APP基类,处理绑定是在文档模板类(注意不是文档类),处理工具条消息响应是在框架类基类。这些处理过程,除了模板类的只能完全替换,其它的都可以通过重载来定制。
而你说的“LPCTSTR lpcPathName这个参数我并没有定义它到哪个位置”,描述并不准确。参数是不需要提前进行定义的,只是传递的过程是封装在模板类中。本回答被提问者和网友采纳
MFC 打开大文档
【中文标题】MFC 打开大文档【英文标题】:MFC Open big document 【发布时间】:2015-05-25 10:57:37 【问题描述】:我有一个单文档接口 (SDI) Microsoft 基础类 (MFC) 应用程序,它必须加载一个大文档文件(大约需要 2 分钟)。因此,当我打开文档时,我的应用程序一直没有响应。
但是,我希望我的应用在打开文档时能够做出响应。问题是,如果我尝试在线程上加载我的文档,我的 OnopenDocument
函数(在我的文档中)将在我实际打开文档之前返回:
BOOL CmodguiDoc::OnOpenDocument(LPCTSTR lpszPathName)
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
start_tread(_open_doc); // just an example
return TRUE; // Will return before the document will actually be open
我怎样才能做到这一点是非锁定的,但只有在文档实际打开后才返回?或者,在加载文档时,如何至少让我的应用程序响应?
谢谢
【问题讨论】:
你不能希望一个线程同时阻塞并继续执行。除非你买一台昂贵的量子计算机。 @IInspectable 这就是我要求替代架构的原因 另一种方法是将文件名存储在您的OnOpenDocument
回调中并按需加载数据。您不能在 GUI 线程上等待加载操作运行完成并同时为其他消息提供服务。在加载文档之前,您必须以一种或另一种方式返回。
如果您的应用程序准备好处理重入问题,您还可以从文档加载器定期调用CWinThread::PumpMessage,以在 GUI 线程上处理消息。
【参考方案1】:
创建线程后返回即可。您应该为文档定义一个状态,例如loading
和loaded
。当你启动线程时,状态应该是loading
。视图应该查看状态并相应地显示。当线程完成加载文档时,它应该向文档发布一条消息。在处理程序中,将状态设置为 loaded
并调用 UpdateAllViews()
以使视图有机会使用新的文档数据进行更新。
示例:这将在文档加载时打印“正在加载”,并在文档在视图中完成后“加载”和加载。
在resource.h中:
#define IDD_NotifyDocumentFinished 101
在文档标题中:
public:
enum DocState
None,
Failed,
Loading,
Loaded
;
DocState GetDocState() const return m_state;
private:
DocState m_state;
void StartLoading();
在文档实现中:
BOOL CMFCDocViewAsyncDoc::OnOpenDocument(LPCTSTR lpszPathName)
if(!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
m_state = Loading;
StartLoading();
return TRUE;
UINT LongRunningFunction(LPVOID param)
Sleep(3000);
HWND hWnd = AfxGetApp()->m_pMainWnd->GetSafeHwnd();
NMHDR hdr = hWnd, IDD_NotifyDocumentFinished, 0;
::SendMessage(hWnd, WM_NOTIFY, 0, reinterpret_cast<LPARAM>(&hdr));
return 0;
void CMFCDocViewAsyncDoc::StartLoading()
AfxBeginThread(&LongRunningFunction, nullptr);
BOOL CMFCDocViewAsyncDoc::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
if(HIWORD(nCode) == WM_NOTIFY)
WORD wCode = LOWORD(nCode);
AFX_NOTIFY * notify = reinterpret_cast<AFX_NOTIFY*>(pExtra);
if(notify->pNMHDR->idFrom == IDD_NotifyDocumentFinished)
m_state = Loaded;
UpdateAllViews(nullptr);
return TRUE;
在视图中:
void CMFCDocViewAsyncView::OnDraw(CDC* pDC)
CMFCDocViewAsyncDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CMFCDocViewAsyncDoc::DocState state = pDoc->GetDocState();
CString sstate;
switch(state)
case CMFCDocViewAsyncDoc::None:
sstate = "None";
break;
case CMFCDocViewAsyncDoc::Failed:
sstate = "Failed";
break;
case CMFCDocViewAsyncDoc::Loading:
sstate = "Loading";
break;
case CMFCDocViewAsyncDoc::Loaded:
sstate = "Loaded";
break;
pDC->TextOut(50, 50, sstate);
更新:也可以在此处查找类似的更详细示例 http://www.codeproject.com/Articles/14706/Notifying-the-Document。
【讨论】:
谢谢,但你能说得更具体点吗?如何定义文档状态? 还有另一个问题。我无法从线程获取文档句柄,我无法从线程更新状态 不是来自线程,而是在线程完成后发布的消息的处理程序中。 还有一个问题,文档数据集是什么时候?例如带有项目名称的窗口标题?【参考方案2】:如果只加载一个东西就需要两分钟,那么有两个原因:
-
加载时您正在做一些愚蠢的事情,例如在数据上运行昂贵的算法,如索引或图形渲染。如果将数据存储在容器中,分配的开销也会变得很大。如果是这种情况,请仅按需执行它们或在后台异步执行这些操作。例如,您可以在完成后通知主线程(运行 UI 的线程)以显示渲染的图形。
数据非常庞大。在这种情况下,您将不得不重新考虑如何访问这些数据,因为任何操作都可能很昂贵。您最好的选择是使用异步模型,例如向模型发送请求以执行某些操作。然后模型向 UI 发送响应以显示数据。在这种情况下,您需要考虑如何使这对用户透明。一种方法是在更改请求后使显示区域变暗,并仅在响应或进度条后将其变亮。
【讨论】:
我的项目文件由一个唯一的文件组成,最大可以增长到 2gb以上是关于MFC中文档类的 OnOpenDocument是怎样打开文件的呢?的主要内容,如果未能解决你的问题,请参考以下文章
MFC项目组合:如何将没有文档类的SDI应用程序添加到MDI应用程序中?应该使用子窗口吗?[MFC]
在Visual C++设计中,单文档应用程序中常用的MFC类如何相互获得类的指针?(如CView类获得CDoc类的指针等