none
请问 IOleObject.GetClipboardData() 返回 OLE_E_NOTRUNNING 错误的原因和解决方法 RRS feed

  • 问题

  • 在读取 richeditview 中的图片时, IOleObject.GetClipboardData() 函数总是返回 OLE_E_NOTRUNNING ,这是为什么呢?有什么解决方法吗?
            REOBJECT reobject;
            reobject.cbStruct = sizeof(REOBJECT); 
    
            if (E_INVALIDARG == pOle->GetObject(i, &reobject, REO_GETOBJ_ALL_INTERFACES))
            {    //正常应该返回 S_OK
                AfxMessageBox(L"获取对象失败!");
                return;
            }
    
    //      OleRun(reobject.poleobj);  //找了2个api,也不知道对不对
    //      if (!OleIsRunning(reobject.poleobj))
    //      {    
    //           AfxMessageBox(L"对象未运行!"); //程序直接来到这句
    //           return;
    //      }
    
            IDataObject *pDataObject;   
            if (OLE_E_NOTRUNNING == reobject.poleobj->GetClipboardData(0, &pDataObject))//这里总是返回OLE_E_NOTRUNNING 
            {    //错误值有OLE_E_NOTRUNNING,E_NOTIMPL两种S_OK !
                AfxMessageBox(L"获取数据失败!");
                return;
            }
    
    
    
    
    
    
    
    
    • 已编辑 happyhhb 2009年8月26日 11:18
    2009年8月26日 11:00

答案

  • 估计是sm和fm的成员没有赋值的缘故。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 happyhhb 2009年8月28日 11:50
    2009年8月27日 23:41
    版主

全部回复

  • AfxOleInit调用了么?

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月26日 14:23
    版主
  •     谢谢!几次都是你回答我的问题
        这段代码是放在我的单文档程序**doc.cpp中的,由于要操作数据库,::CoUninitialize()/::CoInitialize(NULL)有在一个自定义总管类中使用,刚才又在doc.cpp构造\析构函数中添加,::CoUninitialize()/::CoInitialize(NULL),问题依旧,如果换成添加AfxOleInit(),编译通过但程序运行立即出错,可能和总管类的初始化冲突了
        我该怎么改呢?

    2009年8月26日 16:38
  • 去掉CoInitialize和CoUninitialize,换AfxOleInit。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月26日 17:01
    版主
  • 为什么我一用AfxOleInit();就出错呢,都是编译通过,但运行程序就
    "Debug Assertion Failed!”
    "Program:D:\*****"
    "File: oleinit.cpp"
    "Line:54"

    我的这个程序是vc60下的unicode编程,难道和unicode编程冲突吗?
    2009年8月26日 17:23
  • 第54行是
     _AFX_THREAD_STATE* pState = AfxGetThreadState();
     ASSERT(!pState->m_bNeedTerm); // calling it twice?
    看起来你已经调用过了?


    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月26日 17:37
    版主
  • 谢谢!

    我的这个程序是继承 richeditview 的,是否 richeditview 中有对 ole 对象初始化的操作呢?
    如果是,也就是AfxOleInit相关操作已经执行过了,那么为什么 IOleObject.GetClipboardData() 还会返回 OLE_E_NOTRUNNING ?
    如果否,在程序中AfxOleInit我只调用一次,怎么会出现这样的断言呢?

    困惑。。。
    2009年8月27日 1:03
  • 我把手动添加的所有有关初始化com对象的操作AfxOleInit()\::CoUninitialize()\::CoInitialize(NULL)全部注释掉,需要许多com操作的程序竟然也能正常运行,包括通过ado对access数据库的读取删改也能正常操作,也许真的是 richeditview 中有对 ole 对象初始化 ,既然如此,为什么 IOleObject.GetClipboardData() 还会返回 OLE_E_NOTRUNNING ?

    越来越困惑了。。。。

    希望得到指教,谢谢 ^_^
    2009年8月27日 1:19
  • 你把剪贴板代码加到WordPad示例看看。有可能是你初始化OLE的地方不对,应该在程序一开始初始化一次。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月27日 2:54
    版主
  • 可否用 ::CoUninitialize()/::CoInitialize(NULL) 代替 AfxOleInit() 呢?
    ::CoUninitialize()/::CoInitialize(NULL) 多放几个地方都没问题,但似乎不能解决 IOleObject.GetClipboardData() 返回 OLE_E_NOTRUNNING

    2009年8月27日 5:04
  • 终于找到最初调用 AfxOleInit() 的地方了,在app.cpp的 InitInstance() 里 :
    BOOL C×××App::InitInstance()
    {
     // Initialize OLE libraries
     if (!AfxOleInit())   // ----------> 就是这里
     {
      AfxMessageBox(IDP_OLE_INIT_FAILED);
      return FALSE;
     }

     AfxEnableControlContainer();
     .......
    }

    既然这里已经调用了 AfxOleInit() ,而别处已无法调用(调用就出错),是否表明了 IOleObject.GetClipboardData() 返回 OLE_E_NOTRUNNING 的真正原因并不在于 AfxOleInit() 呢?还会是在什么地方存在问题呢?

    谢谢指教 ^_^

    • 已编辑 happyhhb 2009年8月30日 6:06
    2009年8月27日 5:24
  • 得看对象怎么实现GetClipboardData的了。直接调用QueryInterface IDataObject 看看。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月27日 11:21
    版主
  • 非常感谢版主,使用了QueryInterface竟然可以顺利地获取了IDataObject,太开心了,但还没有得到我想要的结果
    我修改后的代码如下:

    	IRichEditOle* pOle = edit.GetIRichEditOle();
    	int nCount = pOle->GetObjectCount();
    
    	for (int i = 0; i < nCount; i++)
    	{
    		REOBJECT reobject;
    		ZeroMemory(&reobject, sizeof(REOBJECT));
    		reobject.cbStruct = sizeof(REOBJECT); //不填这个结构,会导致GetObject()失败
    	
    		if (E_INVALIDARG == pOle->GetObject(i, &reobject, REO_GETOBJ_ALL_INTERFACES))
    		{	//正常应该返回 S_OK
    			AfxMessageBox(_T("获取对象失败!"));
    			return;
    		}
    
    		IDataObject *pDataObject;   
    		if (S_OK != reobject.poleobj->QueryInterface(IID_IDataObject, (void **)&pDataObject))
    		{
    			AfxMessageBox(_T("获取数据失败!"));
    			return;
    		}
    
    		FORMATETC fm;   
    		STGMEDIUM sm;   
    
    		pDataObject->GetData(&fm, &sm);   
    		if (fm.cfFormat == CF_BITMAP) //fm.cfFormat返回的是52428,显然是一个错误的值
    		{
    			SaveBMPToFile(sm.hBitmap, _T("d:\\55.bmp")); //根据句柄保存为位图,测试过可用
    		}       //但如果去掉if判断,直接调用句柄生成位图,会导致程序退出
    
    
    	}
    似乎表明没能得到正确的 IDataObject,这是为什么呢?
    2009年8月27日 16:31
  • 说明对象格式不是位图。一般插入图片、文件到richedit之后,生成的是一个包(package)。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月27日 16:42
    版主
  • 图片我是用屏幕截图的方式取得位图句柄,随后贴入richeditview的,这样一个ole对象,理应是一个位图啊,难道需要我手工重构FORMATETC fm;  
    STGMEDIUM sm;  
    的部分参数?
    或者还有别的方法吗?
    再或者说,我该如何还原这样一个包(package)为位图呢?
    谢谢
    • 已编辑 happyhhb 2009年8月27日 16:57
    2009年8月27日 16:47
  • 你的代码好像没有错误检测。每一步COM操作都要检查返回值是不是S_OK再继续。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月27日 16:58
    版主
  • 谢谢,代码不够严谨,确实会带来很多错误判断啊
    修改后的代码如下,但 GetData() 怎么会出错呢,莫非获取的 pDataObject 有问题?
    		IDataObject *pDataObject;   
    		if (S_OK != reobject.poleobj->QueryInterface(IID_IDataObject, (void **)&pDataObject))
    		{
    			AfxMessageBox(_T("获取数据失败!"));
    			return;
    		}
    
    		FORMATETC fm;   
    		STGMEDIUM sm;   
    
    		if (S_OK != pDataObject->GetData(&fm, &sm)) //---->果然这里出错了
    		{
    			AfxMessageBox(_T("获取结构失败!")); //---->运行结果显示这个
    			return;
    		}
    
    		if (fm.cfFormat == CF_BITMAP) // return sm.hBitmap; 
    		{
    			SaveBMPToFile(sm.hBitmap, _T("d:\\55.bmp"));
    		}
    		else AfxMessageBox(_T("对象并非位图!"));
    
    2009年8月27日 17:11
  • 得看返回值是什么

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月27日 17:36
    版主
  • sorry,忘了贴上来了,pDataObject->GetData(&fm, &sm)的返回值是 DV_E_LINDEX,msdn 对其的解释是

    The value for lindex is not valid; currently, only -1 is supported.
    对于lindex是无效的价值,目前,只有-1支持。

    这是什么意思呢,百渡了一下,没有找到解决方案,谢谢指教 ^_^

    2009年8月27日 23:19
  • 估计是sm和fm的成员没有赋值的缘故。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    • 已标记为答案 happyhhb 2009年8月28日 11:50
    2009年8月27日 23:41
    版主
  • 谢谢,问题终于解决了,早上一看到你的回复,修改下代码就通过了测试,可惜正在上班,没能及时回复并感谢你!
    寻遍论坛,除了你的回复,貌似还没有公开的帖子解决了这个问题,呵呵,再次谢谢了!
    • 已标记为答案 happyhhb 2009年8月28日 11:48
    • 取消答案标记 happyhhb 2009年8月28日 11:49
    2009年8月28日 6:33