• COleChangeSourceDialog不能Change Source的解决方法


     

    在微软给的例子OClient中,有选中一个OLE对象然后Change Source的功能,但是会报错。分析了一下是这样的:

    void CMainView::OnOleChangeSource()

    {

        ASSERT(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);

     

        COleChangeSourceDialog dlg(m_pSelection);

        dlg.DoModal();

    }

     

    然后找到COleChangeSourceDialog 的定义,在c:Program Files (x86)Microsoft Visual Studio 9.0VCatlmfcincludeafxodlgs.h中。

    可以看到里面有个成员m_xLinkInfo.

    然后找到COleChangeSourceDialog的实现文件,在C:Program Files (x86)Microsoft Visual Studio 9.0VCatlmfcsrcmfcoledlgs3.cpp。

    先看构造函数:

    COleChangeSourceDialog::COleChangeSourceDialog(COleClientItem* pItem,

        CWnd* pParentWnd) : COleDialog(pParentWnd), m_xLinkInfo(NULL)

    {

        ASSERT_VALID(pItem);

     

        memset(&m_cs, 0, sizeof(m_cs)); // initialize structure to 0/NULL

     

        // fill in common part

        m_cs.cbStruct = sizeof(m_cs);

        m_cs.dwFlags = 0;

        if (AfxHelpEnabled())

            m_cs.dwFlags |= CSF_SHOWHELP;

        m_cs.lpfnHook = AfxOleHookProc;

        m_nIDHelp = AFX_IDD_CHANGESOURCE;

     

        // specific to this dialog

        m_cs.lpOleUILinkContainer = &m_xLinkInfo;

        COleDocument* pDoc = pItem->GetDocument();

        DWORD dwItem = 0;

        if (pDoc != NULL)

        {

            POSITION posItem = pDoc->GetStartPosition();

            ULONG iItem = 1;

            while ((posItem != NULL) && (dwItem == 0))

            {

                COleClientItem* pSearchItem = pDoc->GetNextClientItem(posItem);

                if (pSearchItem == pItem)

                {

                    dwItem = iItem;

                }

                iItem++;

            }

        }

        m_cs.dwLink = dwItem;

    }

     

    可以看到,这里面把成员m_xLinkInfo设置为NULL.

    这里面用到了pItem,就是我们在CMainView::OnOleChangeSource传进来的m_pSelection, pItem->GetDocument()得到的就是我们主程序的CMainDoc指针,构造函数利用这个指针,获得当前文档中被选中的OLE对象的索引,比如第一个就是1.

    m_xLinkInfo被赋给了m_cs.lpOleUILinkContainer,m_cs的定义如下:

    OLEUICHANGESOURCE m_cs

     

    构造函数根据传入的pItem,初始化m_cs成员,以备它的其他函数调用。

    现在我们回头看CMainView::OnOleChangeSource事件,这个事件中调用了COleChangeSourceDialog.DoModal函数。下面是这个函数的代码:

    INT_PTR COleChangeSourceDialog::DoModal()

    {

        ASSERT_VALID(this);

        ASSERT(m_cs.lpfnHook != NULL); // can still be a user hook

     

        m_cs.hWndOwner = PreModal();

        INT_PTR iResult = MapResult(::OleUIChangeSource(&m_cs));

        PostModal();

        return iResult;

    }

     

    可以看到这里用到了m_cs变量。

    然后执行这步的时候报错了,报错点在这个文件的这个函数:

    C:Program Files (x86)Microsoft Visual Studio 9.0VCatlmfcsrcmfcoledlgs1.cpp

    COleClientItem* COleUILinkInfo::GetLinkItem( DWORD dwLink )

    {

        POSITION posItem = m_pDocument->GetStartPosition();

        COleClientItem* pItem = NULL;

        for (ULONG iLink = 0; iLink < dwLink; ++iLink)

        {

            pItem = m_pDocument->GetNextClientItem(posItem);

        }

     

        return pItem;

    }

     

    调试了一下发现m_pDocument为NULL(0x00000000)

    为什么那?

    我们看COleUILinkInfo的构造函数:

     

    COleUILinkInfo::COleUILinkInfo(COleDocument* pDocument)

    {

        ASSERT(pDocument == NULL ||

            pDocument->IsKindOf(RUNTIME_CLASS(COleDocument)));

        m_pDocument = pDocument;

        m_pSelectedItem = NULL;

        m_pos = NULL;

        m_bUpdateLinks = FALSE;

        m_bUpdateEmbeddings = FALSE;

    }

     

    现在问题明确了,因为在COleChangeSourceDialog的构造函数中把成员m_xLinkInfo设置为NULL, 所以传给COleUILinkInfo构造函数的参数也是空,所以COleUILinkInfo的m_pDocument成员为空,所以m_pDocument->GetStartPosition()会报错。

    【解决方法】

    继承COleChangeSourceDialog类自己写一个类来修复这个问题。

    #pragma once

    #include "afxodlgs.h"

     

    class MyOleChangeSourceDialog :

        public COleChangeSourceDialog

    {

    public:

        MyOleChangeSourceDialog(COleClientItem* pItem, CWnd* pParentWnd = NULL);

    };

     

    #include "MyOleChangeSourceDialog.h"

     

    MyOleChangeSourceDialog::MyOleChangeSourceDialog(COleClientItem* pItem,

                                                     CWnd* pParentWnd) : COleChangeSourceDialog(pItem, pParentWnd)

    {

        m_xLinkInfo = COleUILinkInfo(pItem->GetDocument());

    }

     

    然后调用新类。

    void CMainView::OnOleChangeSource()

    {

        ASSERT(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);

     

        MyOleChangeSourceDialog dlg(m_pSelection);

        

        dlg.DoModal();

    }

     

    运行起来后,成功!选择Change Source的时候不再报错了。

  • 相关阅读:
    为什么 "auto a = 1;" 在C语言中可以编译通过?
    谈谈duilib
    软工第一次作业
    数独_个人项目
    统计Github项目信息
    字符串中的匹配之递归
    软工第0次作业
    c++浅拷贝与深拷贝(LeetCode669)
    修改xcode初始生成代码
    树上处理的问题总结
  • 原文地址:https://www.cnblogs.com/time-is-life/p/5780609.html
Copyright © 2020-2023  润新知