使用IStream接口访问剪贴板

时间:2014-04-03 20:02:54

标签: c++ windows com

#include <Windows.h>
#include <iostream>
#include <vector>
#include <string>  
//
// Desired Output: Text in clipboard should be displayed to the screen.
//
int main( void )
{
    //
    // OLE COM Interface
    // 
    HRESULT hr;

    // Get Clipeboard
    IDataObject* pcb = 0;
    OleGetClipboard(&pcb);


    // Get Clipeboard Data Interface
    FORMATETC format;
    format.cfFormat = CF_TEXT;
    format.ptd = NULL;
    format.dwAspect = DVASPECT_CONTENT;
    format.lindex = -1;
    format.tymed = TYMED_ISTREAM;
    STGMEDIUM medium;
    hr = pcb->GetData(&format, &medium);
    if( FAILED(hr) )
        return hr;

    // Get Stat of returned IStream
    IStream* pis = medium.pstm;
    STATSTG stat;
    ULONG cb = 0;
    hr = pis->Stat(&stat,STATFLAG_DEFAULT);
    if( SUCCEEDED(hr) )
    {
        if( stat.pwcsName )
            std::wcout << L"Name: " << stat.pwcsName << std::endl;
        std::cout << "DataSize: " << stat.cbSize.QuadPart << std::endl;
        std::cout << "Type: " << stat.type << std::endl;
        cb = stat.cbSize.QuadPart;
    }

    // Read Data from IStream
    std::vector<char> v;
    v.resize(cb);
    ULONG ret;
    hr = pis->Read(v.data(), cb, &ret);
    if( FAILED( hr ) )
    {
        std::cout << "Failed to Read" << std::endl;
    }
    else
    {
        std::string out(v.begin(),v.end());
        std::cout << "Read " << ret << "chars. Content: {" << out << "}" << std::endl;
    }

    pis->Release();

//
// My Output when I have 40 characters in Clipboard
//
// DataSize: 40
// Type: 2
// Read 0chars. Content: {                                        }
// The number of characters are correct, but content always appear empty.

}

您好。

我试图通过IStream界面访问剪贴板。 IStream :: Stat似乎给了我正确的IStream状态,但IStream :: Read并没有给我任何数据。

我几乎没有使用COM对象和IStream接口的经验。 请指出是否有明显的错误。

谢谢。

1 个答案:

答案 0 :(得分:1)

我对必须使用COM和C ++表示哀悼。自从我触及这些东西已经4到5年了,但看看你有什么,我猜两件事中的一件是问题:

  1. IStream指针从数据末尾开始。在这种情况下,您必须在开始时调用pis->Seek(0, STREAM_SEEK_SET, NULL)重置它。可能是对pis->Read()的调用返回S_FALSE而不是S_OK; MSDN docs on Read()表示如果流指针位于流的末尾,则会发生这种情况。

  2. 剪贴板不支持使用IStream。其实我从来没有听说过这样做过;我认为通常的方法是将Clipboard数据作为全局内存块访问。 (参见this example比你的代码简单得多)当你进入像structured storage这样的icky主题时,IStream是必要的,这是MS Office应用程序在一个文件中存储分层数据的旧方式。

  3. 附注:如果您不必使用C ++,并且熟悉其他具有Windows剪贴板访问绑定的语言(C#,VB用于&#34;本机&#34; .NET访问; Java我可以使用本机Windows功能的一部分进行便携式剪贴板访问,我认为Python也可以),你不必弄乱任何丑陋的COM功能。