【问题标题】:Open MultiDocTemplate without open File在不打开文件的情况下打开 MultiDocTemplate
【发布时间】:2020-11-09 03:22:11
【问题描述】:

我生成了一个带有CMultiDocTemplate 的Visual MFC 项目。 新建和文件打开已经实现。但我现在想打开一个数据库并查询数据。

CDocument::OnOpenDocument 下,我可以读到可以为此编写一个应用程序。但我不知道如何在不打开文件的情况下打开带有附加视图的文档。

我需要的是一个函数OnOpenDB(LPCTSTR tableName),它创建文档和视图,但不尝试打开文件并扩展表名。

Google 没有帮助我。我找不到任何有用的文档。

@阿德里安, 是否有其他解决方案? 最后,我想为不同的功能使用多个模板。 在您的解决方案中,我错过了将表名发送到文档以进行数据库查询并将数据提供给视图的可能性。 我可以覆盖模板类吗? 在您的代码中,是否 dynamic_cast ... 占据了视野?

所以最后我需要一个公共函数,它允许我发送一个带有表名的新文档的请求。 这可能吗?

更新: 我试图覆盖 CMultiDocTemplate::OpenDocumentFile(...),但它不起作用。看来这个功能不是虚拟的。 因此,我在 CMultiDocTemplate 的覆盖中创建了一个 OpenDocumentFile(...)

CDocument* CStreamAuswertungMDT::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bAddToMRU, BOOL bMakeVisible)
{
CDocument* pDoc = CreateNewDocument();
if (pDoc == NULL)
{
    TRACE(traceAppMsg, 0, "CDocTemplate::CreateNewDocument returned NULL.\n");
    AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
    return NULL;
}
ASSERT_VALID(pDoc);
BOOL bAutoDelete = pDoc->m_bAutoDelete;
pDoc->m_bAutoDelete = FALSE;   // don't destroy if something goes wrong
CFrameWnd* pFrame = CreateNewFrame(pDoc, NULL);
pDoc->m_bAutoDelete = bAutoDelete;
if (pFrame == NULL)
{
    AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
    delete pDoc;       // explicit delete on error
    return NULL;
}
ASSERT_VALID(pFrame);

// avoid creating temporary compound file when starting up invisible
if (!bMakeVisible)
    pDoc->m_bEmbedded = TRUE;

if (!pDoc->OnNewDocument())
{
    // user has be alerted to what failed in OnNewDocument
    TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
    pFrame->DestroyWindow();
    return NULL;
}

// it worked, now bump untitled count
pDoc->SetTitle(lpszPathName);
pDoc->OnDocumentEvent(CDocument::onAfterOpenDocument);
InitialUpdateFrame(pFrame, pDoc);
return pDoc;
}

这对我有用!

【问题讨论】:

  • 调用CWinApp::OnFileNew()(这将创建一个无标题的文档和一个视图)然后调用另一个从数据库传输数据并设置标题的方法不是更简单吗?

标签: c++ visual-studio visual-c++ mfc


【解决方案1】:

您必须小心一点,但您可以通过创建CMultiDocTemplate 对象的本地(静态)“副本”然后使用@ 手动调用OpenDocumentFile() 来做到这一点987654326@参数:

static CMultiDocTemplate MY_tmplate(IDR_MYDOC, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMDIChild), RUNTIME_CLASS(CMyView));

void OnOpenDB(LPCTSTR tableName)
{
    CMyDoc* pDoc = dynamic_cast<CMyDoc *>(MY_tmplate.OpenDocumentFile(nullptr));
    //... do stuff with pDoc (using `tableName` to probe the database, maybe)
    //
}

pDoc 对象及其关联视图中初始化任何必需的数据成员和任何限制时,等等,您需要小心。

您可以在任何阶段设置文档的文件名/路径,使用SetPathName() 基类函数;或者您可以使用pDoc-&gt;SetTitle() 更改显示的标题(显示在视图的框架窗口中)。

或者,除了使用本地(复制)文档模板之外,您还可以向应用程序类添加一个成员,以运行其“已安装”模板列表,查找与给定字符串标识符的匹配项:

CMultiDocTemplate *MyApp::GetDocTemplate(CString name)
{
    POSITION dtPos = GetFirstDocTemplatePosition(); CString dtName;
    while (dtPos != nullptr) {
        CMultiDocTemplate *mdTmp = dynamic_cast<CMultiDocTemplate *>(GetNextDocTemplate(dtPos));
        if ((mdTmp == nullptr) || !mdTmp->GetDocString(dtName, CDocTemplate::docName)) break;
        if (dtName == name) return mdTmp;
    }
    return nullptr;
}

然后,如果该函数返回一个非 NULL 指针,则使用它来调用 OpenDocumentFile。有关可用于匹配相关模板的各种字符串组件的列表,请参阅CDocTemplate 文档。

【讨论】:

  • 见我上面的评论。
  • @HGA 我在答案中添加了更多信息。您可以在函数中使用tableName 参数,对数据库执行任何您需要的操作。此外,我还添加了一种更通用的方法来获取应用程序的任何一个模板。
  • @HGA 另外,调用“OpenDocumentFile”确实(或应该)创建关联的视图;这就是 OnFileNew 在内部所做的,IIRC。
  • GetDocTemplate 函数为我提供了指向现有 DocTemplate 的指针。但是我仍然必须编写自己的CMultiDocTemplate 版本,因为我不能使用标准OpenDocumentFile。这将失败,因为它只是一个表名而不是文件路径。
  • @HGA OpenDocumentFile 不需要文件名 - 因此 nullptr 参数。它将创建一个 new 空文档+视图对。然后,您可以从数据库中填充该文档。也许您将CDocTemplate 代表的内容与某种模板文档混淆了。我现在不清楚你的问题。
猜你喜欢
  • 2017-07-18
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-08
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多