Question

#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.

}

Hello.

I'm trying to gain access to clipboard through IStream interface. IStream::Stat seems like giving me correct status of the IStream, but IStream::Read is not really giving me any data.

I have almost zero experience in using COM object and IStream interface. Please, point out if there is obvious error.

Thank you.

Was it helpful?

Solution

My condolences for having to use COM and C++. It's been 4 or 5 years since I've touched the stuff, but looking at what you have, I'd guess one of two things is a problem:

  1. The IStream pointer starts out at the end of the data. In this case you have to call pis->Seek(0, STREAM_SEEK_SET, NULL) to reset it at the beginning. It may be that the call to pis->Read() returns S_FALSE rather than S_OK; the MSDN docs on Read() say that this can occur if the stream pointer is at the end of the stream.

  2. The Clipboard just doesn't support using IStream. Actually I've never heard of doing this; I thought the usual method was to access Clipboard data as a global memory block. (See this example which is a lot simpler than your code) IStreams are necessary when you get into icky subjects like structured storage which was the old way that MS Office applications stored hierarchical data in one file.

A side note: if you don't have to use C++, and are familiar with other languages that have bindings for Windows clipboard access (C#, VB for "native" .NET access; Java has portable Clipboard access with a subset of the native Windows features, I think Python does also), you don't have to mess with any of those ugly COM features.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top