DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Sat, 4 Aug 2007 10:04:00 -0700,    posted on: microsoft.public.dotnet.framework.interop        back       

Thread Index
  1    krzys


How to place a custom .NET control in clipboard for OLE data trans   
Hi,

I'd like to insert a custom .NET control into clipboard as a part of OLE 
drag and drop data transfer, or to be manually pasted something like Word or 
Excel. My control otherwise works as an ActiveX (you can insert it manually 
using "insert object" in Word, for example), but I have difficulties getting 
it to "materialize" into a Word document via drag and drop. I'm getting an 
error message shown below.

There is a problem saving the file. Usually this is because the disk or 
floppy disk is too small for the file or is full, RAM memory is low, or there 
is a permission problem with the drive the file is being saved to. If the 
amount of disk space for a paging file is low, save the file to another 
drive. If the RAM memory is low, increase available RAM. If permissions to 
the drive do not allow you to save to that drive, save the file to another 
drive or request permissions from the administrator to save files to the 
drive.

Weirdly enough, my control gets pasted just fine into Wordpad or a Visio 
document, but not to Word or Outlook. Once it gets pasted into Wordpad, you 
can move it into Word just fine, though. But a direct transfer into Word or 
Outlook fails.

Here's my code that attempts (and fails) at transferring my custom object 
(here, object "counter1" is the AxctiveX .NET). I'm passing "Object 
Descriptor" and "Embedded Object" clipboard formats, the former through 
HGLOBAL and the latter via file on a disk, filled in with data using OleSave, 
given the IPersistStorage of my .NET control as argument. My custom 
DataObject just stores the references to memory or IStorage and copies them 
to the recipient. I think reference counting is working just fine.

Here's the insertion code:
(it might get distorted by smileys, but you can find the good version at 
http://www.cs.cornell.edu/~krzys/embedding.html).


STGMEDIUM stm[2];
FORMATETC fe[2];

IUnknown *pUnkObject = (IUnknown *)
System::Runtime::InteropServices::Marshal::GetIUnknownForObject(counter1).ToPointer();
if (pUnkObject == NULL)
throw gcnew Exception("GetIUnknownForObject failed");

::IOleObject *pOleObject;
HRESULT hr = pUnkObject->QueryInterface(__uuidof(::IOleObject), (LPVOID FAR 
*) &pOleObject);
if (FAILED(hr))
throw gcnew Exception("QueryInterface failed (" + hr.ToString("x") + ")");

CLSID objectclsid;               
if (FAILED(pOleObject->GetUserClassID(&objectclsid)))
throw gcnew Exception("GetUserClassID failed.");

DWORD objectmiscstatus;
if (FAILED(pOleObject->GetMiscStatus(DVASPECT_CONTENT, &objectmiscstatus)))
throw gcnew Exception("GetMiscStatus failed.");

pOleObject->Release();

POINTL ptl;
ptl.x = 0;
ptl.y = 0;
               
SIZEL szl;
szl.cx = 200;
szl.cy = 200;

HGLOBAL hgDescriptor =
_AfxOleGetObjectDescriptorData(objectclsid, DVASPECT_CONTENT, szl, ptl, 
objectmiscstatus,
OLESTR("a very nice live counter"), OLESTR("a nice drag and drop app"));

stm[0].tymed = ::TYMED_HGLOBAL;
stm[0].hGlobal = hgDescriptor;

fe[0].cfFormat = RegisterClipboardFormat(L"Object Descriptor");
fe[0].dwAspect = DVASPECT_CONTENT;
fe[0].ptd = NULL;
fe[0].tymed = ::TYMED_HGLOBAL;
fe[0].lindex = -1;

::IStorage *pIS;

hr = :Tongue TiedtgCreateDocfile(L"C:\\QuickSilver\\TEMP\\object.txt",
STGM_TRANSACTED | STGM_READWRITE | STGM_CREATE |
STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE, 0, &pIS);
if (FAILED(hr))
throw gcnew Exception("StgCreateDocfile failed (" + hr.ToString("x") + ")");

LPPERSISTSTORAGE pIPS;
hr = pUnkObject->QueryInterface(__uuidof(::IPersistStorage), (LPVOID FAR *) 
&pIPS);
if (FAILED(hr))
throw gcnew Exception("QueryInterface for IPersistStorage failed (" + 
hr.ToString("x") + ")");

:SurpriseleSave(pIPS, pIS, FALSE);
pIPS->SaveCompleted(NULL);
pIPS->Release();

stm[1].tymed = TYMED_ISTORAGE;
stm[1].pstg = pIS;

fe[1].cfFormat = RegisterClipboardFormat(L"Embedded Object");
fe[1].dwAspect = :Big SmileVASPECT_CONTENT;
fe[1].ptd = NULL;
fe[1].tymed = ::TYMED_ISTORAGE;
fe[1].lindex = -1;

::IDataObject *pDataObject;
hr = CreateDataObject(fe, stm, 2, &pDataObject);

if (hr == S_OK)
{
OleSetClipboard(pDataObject);
OleFlushClipboard();
pDataObject->Release();
}

GlobalFree(hgDescriptor);
pIS->Release();

The code for _AfxOleGetObjectDescriptorData is borrowed from "olemisc.cpp".

The code for the data object is based mostly on 
http://www.codeproject.com/managedcpp/Ghost_drag_image.asp, and various 
articles linkes to it. The code just copies the arguments to the recipient.

CDataObject::CDataObject(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count)
{
m_lRefCount  = 1;
m_nNumFormats = count;
m_pFormatEtc  = new FORMATETC[count];
m_pStgMedium  = new STGMEDIUM[count];
for(int i = 0; i < count; i++)
{
m_pFormatEtcIdea = fmtetcIdea;
m_pStgMediumIdea = stgmedIdea;
}
}


HRESULT __stdcall CDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM 
*pMedium)
{
int idx;
if ((idx = LookupFormatEtc(pFormatEtc)) == -1)
return DV_E_FORMATETC;
pMedium->tymed = m_pFormatEtc[idx].tymed;
pMedium->pUnkForRelease = 0;    
switch (m_pFormatEtc[idx].tymed)
{
case ::TYMED_HGLOBAL:
pMedium->hGlobal = DupMem(m_pStgMedium[idx].hGlobal);
break;

case ::TYMED_ISTORAGE:            
::CopyStgMedium(&m_pStgMedium[idx], pMedium);
break;

default:
return DV_E_FORMATETC;
}
return S_OK;
}

I'd appreciate any help with this...

Krzys
http://www.cs.cornell.edu/~krzys
Date:Sat, 4 Aug 2007 10:04:00 -0700   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us