MFC默认的文档/视图的操作方式,是操作文件的。当我的文档是数据库等非文本文件时,麻烦了问题出现了。需要重写CwinApp::OnFileOpen()等函数。
谁有现成的代码,提供一下,多谢了!
谁有现成的代码,提供一下,多谢了!
解决方案 »
- MFC中的移动效果
- 求助:自定义控件
- 请问用udp过socks5代理的步骤是怎样的?
- 对话框 使用SkinMagic换皮肤后,菜单怎么不见了?
- 急急急。HtmlLayout如何学习
- 请问CListCtrl的style为LVS_REPORT时的问题
- 为什么我的CSpinButtonCtrl在GetPos()时返回的值不在我设定的range内?
- VC6做的Acrobat5插件为什么不能在AcrobatReader5里面用?
- 请赐教: 如何将一个没有源代码的Dll文件转化为LIB库文件?
- 想知道瑞星杀毒软件界面的杀毒时间是怎么计算的啊
- 网上的免费stun服务器是不是有两个地址的?
- socket传输中判断数据流长度
这样,再次按打开时,就不会执行默认的打开对话框,而是你自己的函数了.
wizard生产的代码:
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)CWinApp::OnFileOpen 代码:
void CWinApp::OnFileOpen()
{
ENSURE(m_pDocManager != NULL);
m_pDocManager->OnFileOpen();
}m_pDocManager->OnFileOpen(); 代码:void CDocManager::OnFileOpen()
{
// prompt the user (with all document templates)
CString newName;
if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
return; // open cancelled AfxGetApp()->OpenDocumentFile(newName);
// if returns NULL, the user has already been alerted
}AfxGetApp()->OpenDocumentFile(newName); 代码:CDocument* CWinApp::OpenDocumentFile(LPCTSTR lpszFileName)
{
ENSURE_VALID(m_pDocManager);
return m_pDocManager->OpenDocumentFile(lpszFileName);
}return m_pDocManager->OpenDocumentFile(lpszFileName); 代码:CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)
{
if (lpszFileName == NULL)
{
AfxThrowInvalidArgException();
}
// find the highest confidence
POSITION pos = m_templateList.GetHeadPosition();
CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
CDocTemplate* pBestTemplate = NULL;
CDocument* pOpenDocument = NULL; TCHAR szPath[_MAX_PATH];
ASSERT(lstrlen(lpszFileName) < _countof(szPath));
TCHAR szTemp[_MAX_PATH];
if (lpszFileName[0] == '\"')
++lpszFileName;
Checked::tcsncpy_s(szTemp, _countof(szTemp), lpszFileName, _TRUNCATE);
LPTSTR lpszLast = _tcsrchr(szTemp, '\"');
if (lpszLast != NULL)
*lpszLast = 0;
if( AfxFullPath(szPath, szTemp) == FALSE )
{
ASSERT(FALSE);
return NULL; // We won't open the file. MFC requires paths with
// length < _MAX_PATH
} TCHAR szLinkName[_MAX_PATH];
if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
Checked::tcscpy_s(szPath, _countof(szPath), szLinkName); while (pos != NULL)
{
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
ASSERT_KINDOF(CDocTemplate, pTemplate); CDocTemplate::Confidence match;
ASSERT(pOpenDocument == NULL);
match = pTemplate->MatchDocType(szPath, pOpenDocument);
if (match > bestMatch)
{
bestMatch = match;
pBestTemplate = pTemplate;
}
if (match == CDocTemplate::yesAlreadyOpen)
break; // stop here
} if (pOpenDocument != NULL)
{
POSITION posOpenDoc = pOpenDocument->GetFirstViewPosition();
if (posOpenDoc != NULL)
{
CView* pView = pOpenDocument->GetNextView(posOpenDoc); // get first one
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->GetParentFrame(); if (pFrame == NULL)
TRACE(traceAppMsg, 0, "Error: Can not find a frame for document to activate.\n");
else
{
pFrame->ActivateFrame(); if (pFrame->GetParent() != NULL)
{
CFrameWnd* pAppFrame;
if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
{
ASSERT_KINDOF(CFrameWnd, pAppFrame);
pAppFrame->ActivateFrame();
}
}
}
}
else
TRACE(traceAppMsg, 0, "Error: Can not find a view for document to activate.\n"); return pOpenDocument;
} if (pBestTemplate == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
return NULL;
} return pBestTemplate->OpenDocumentFile(szPath);
}pBestTemplate->OpenDocumentFile(szPath); 代码这里就先不列出里....
在这一系列的调用中,完成了基于对文件文档的对打开的管理,比如:同一个文件文档不会打开2次。而我现在的代码,仅仅:
ON_COMMAND(ID_FILE_OPEN, &CMyApp::OnFileOpen)void CMyApp::OnFileOpen()
{
// TODO: 在此添加命令处理程序代码
}谁有现成的这个函数的实现,不是基于文件的,是基于数据库的应用的,就是说一个文档就是一个数据库的记录。给我一份,我好省省力。提前谢了。
跟我之前看过的书里写的是一样的,是孙鑫的VC++深入详解,第13章文档与串行化.
你贴出来的代码,也是跟 DOCMGR.CPP 里的源代码一样的.他主要是在 match = pTemplate->MatchDocType(szPath, pOpenDocument);这一句这里
如果这个是已经打开了的文档,第二个参数会返回文档的指针,否则第二个参数返回空值.下面再用 if (pOpenDocument != NULL) 来看是否要做打开操作.我试了一下,把 DOCMGR.CPP 的内容,放到自己的 void CSDIDEMOApp::OnFileOpen() 里运行是可以的.
楼主,你提供一下你的数据库读写的代码.我们帮你放到OnFileOpen里面试试吧.
这样,再次按打开时,就不会执行默认的打开对话框,而是你自己的函数了.
我其实是想避开CDocManager类中的OnFileOpen的实现,MFC的实现中使用打开文件的对话框,并且把文件名前加上了绝对路径。其实这对于非文件的应用都是必须去掉的。真不知道,MFC的开发小组是怎么想的,怎么就不肯加上一个对处理非文件的DocManager类呢,唉,毕竟,现实中大部分应用都是都是基于非文件数据的,谁又能开发几个excel或word呢?
好了,不抱怨了,下面把我新写的CMyDocManager文件源码贴出来,共享一下,我仅重写了我需要的2个函数,谁要用可以接着重新其他的,并请同行指正!文件:MyDocManager.h#pragma once
// CMyDocManagerclass CMyDocManager : public CDocManager
{
DECLARE_DYNAMIC(CMyDocManager)public:
CMyDocManager();
virtual ~CMyDocManager(); virtual void OnFileOpen();
virtual CDocument* OpenDocumentFile(LPCTSTR lpszFileName); // open named file};文件:MyDocManager.cpp// MyDocManager.cpp : 实现文件
//#include "stdafx.h"
#include "MyDocManager.h"
#include <afxwin.h>
// CMyDocManagerIMPLEMENT_DYNAMIC(CMyDocManager, CDocManager)CMyDocManager::CMyDocManager()
{
CDocManager();
}CMyDocManager::~CMyDocManager()
{
}void CMyDocManager::OnFileOpen()
{
// prompt the user (with all document templates)
CString newName;
//if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
// OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
// return; // open cancelled
//在这里把打开文件对话框的代码去掉了,需要填上自己的取得文件名的代码
AfxGetApp()->OpenDocumentFile(newName);
// if returns NULL, the user has already been alerted
}CDocument* CMyDocManager::OpenDocumentFile( LPCTSTR lpszFileName )
{ if (lpszFileName == NULL)
{
AfxThrowInvalidArgException();
}
// find the highest confidence
POSITION pos = m_templateList.GetHeadPosition();
CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
CDocTemplate* pBestTemplate = NULL;
CDocument* pOpenDocument = NULL; TCHAR szPath[_MAX_PATH];
ASSERT(lstrlen(lpszFileName) < _countof(szPath));
TCHAR szTemp[_MAX_PATH];
if (lpszFileName[0] == '\"')
++lpszFileName;
Checked::tcsncpy_s(szTemp, _countof(szTemp), lpszFileName, _TRUNCATE);
LPTSTR lpszLast = _tcsrchr(szTemp, '\"');
if (lpszLast != NULL)
*lpszLast = 0;
//我增加的代码
Checked::tcsncpy_s(szPath, _countof(szPath), szTemp, _TRUNCATE); // 加入文件路径的,无用
//if( AfxFullPath(szPath, szTemp) == FALSE )
//{
// ASSERT(FALSE);
// return NULL; // We won't open the file. MFC requires paths with
// // length < _MAX_PATH
//} // 文件快捷方式的处理,也无用
//TCHAR szLinkName[_MAX_PATH];
//if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
// Checked::tcscpy_s(szPath, _countof(szPath), szLinkName); while (pos != NULL)
{
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
ASSERT_KINDOF(CDocTemplate, pTemplate); CDocTemplate::Confidence match;
ASSERT(pOpenDocument == NULL);
match = pTemplate->MatchDocType(szPath, pOpenDocument);
if (match > bestMatch)
{
bestMatch = match;
pBestTemplate = pTemplate;
}
if (match == CDocTemplate::yesAlreadyOpen)
break; // stop here
} if (pOpenDocument != NULL)
{
POSITION posOpenDoc = pOpenDocument->GetFirstViewPosition();
if (posOpenDoc != NULL)
{
CView* pView = pOpenDocument->GetNextView(posOpenDoc); // get first one
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->GetParentFrame(); if (pFrame == NULL)
TRACE(traceAppMsg, 0, "Error: Can not find a frame for document to activate.\n");
else
{
pFrame->ActivateFrame(); if (pFrame->GetParent() != NULL)
{
CFrameWnd* pAppFrame;
if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
{
ASSERT_KINDOF(CFrameWnd, pAppFrame);
pAppFrame->ActivateFrame();
}
}
}
}
else
TRACE(traceAppMsg, 0, "Error: Can not find a view for document to activate.\n"); return pOpenDocument;
} if (pBestTemplate == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
return NULL;
} return pBestTemplate->OpenDocumentFile(szPath);
}使用时候要注意:
1 替换CWinApp 的包含的CDocManager类对象
在 CMyApp::InitInstance()函数中,添加代码 //用把CDocManager类的对象替换为自己的CMyDocManager类的对象
if (m_pDocManager) delete m_pDocManager;
m_pDocManager = new CMyDocManager();注意,这代码一定要填写在下面代码的前面: CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_ValuerUITYPE,
RUNTIME_CLASS(CCompanyDoc),
RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架
RUNTIME_CLASS(CCompanyView));2 重写CMyDocument中的OnOpenDocument函数。
因为MFC开发人员在CDocument在的默认OnOpenDocument实现是打开一个文件,现在需要把它改写成你自己需要的了。3 重写CMyDocument中的SetPathName等函数。
只用改写了SetPathName函数才能让MFC框架正确判断一个文档是否打开了。因为在
在CMyDocManger类中的:
match = pTemplate->MatchDocType(szPath, pOpenDocument);
就是依靠CDocument中的m_strPathName做的判断。
最好在在SetPathName函数中重新调用一次SetTitle,把文档标题设置成自己需要的。下面是我的SetPathName的实现:void CCompanyDoc::SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU)
{
//CDocument::SetPathName(lpszPathName, bAddToMRU);
m_strPathName = lpszPathName;
SetTitle(lpszPathName); //临时用用,正式使用时候在修改
}
好了,就这么多。经过如此增补,MFC的文档/视图模式(其实就是MVC模式),可以支持任何抽象类型的文件了,呵呵。