2013-03-13 57 views
3

我想使用IDataObject的GetData方法从TOleContainer中提取位图。从TOleContainer中提取位图?

OleContainer1.CreateObject('Paint.Picture', false); 
OleContainer1.OleObjectInterface.QueryInterface(IDataObject, DataObject); 

EnumFormatEtc与DATADIR_GET对数据对象返回如下:

cfFormat, ptd, dwAspect, lIndex, tymed 

CF_METAFILEPICT, nil, DVASPECT_CONTENT, -1, TYMED_MFPICT 
CF_DIB, nil, DVASPECT_CONTENT, -1, TYMED_HGLOBAL or TYMED_ISTREAM 
CF_BITMAP, nil, DVASPECT_CONTENT, -1, TYMED_HGLOBAL 

但是当我做:

FormatEtc.cfFormat := CF_BITMAP; 
FormatEtc.ptd := nil; 
FormatEtc.dwAspect := DVASPECT_CONTENT; 
FormatEtc.lIndex := -1; 
FormatEtc.tymed := TYMED_HGLOBAL; 

OleCheck(DataObject.GetData(FormatEtc, StorageMedium)); 

我得到无效的FORMATETC stucture错误。我究竟做错了什么?

+0

尝试从'TYMED_HGLOBAL'到'TYMED_GDI'更换介质类型的建议在['这个线程中](http://www.delphigroups.info/2/bc/272674.html)。 – TLama 2013-03-13 19:19:48

+0

我已经试过了。同样的错误。 – forsajt 2013-03-13 20:02:02

+0

这样做的另一种方法:http://stackoverflow.com/questions/2861008/how-to-extract-metafile-from-tolecontainer – 2013-03-13 21:33:45

回答

1

我使用找到的代码here来做同样的事情。就我而言,我发现最好做到以下几点,它采用了DrawOleOnBmp()中提供的链接:

oleMain.UpdateObject; 
if oleMain.OleObjectInterface = nil then 
    raise Exception.Create('OLE Container is empty.'); 
DrawOleOnBmp(oleMain.OleObjectInterface, imgMain.Bitmap); 
imgMain.Bitmap.SaveToFile('Filename.bmp'); 

oleMainTOleContainer,并imgMainTImage32。两者都是在表单上可见...

为了方便起见,这里是从链接的方法,通过@MarkElder写着:

{ 
    DrawOleOnBmp 
    --------------------------------------------------------------------------- 
    Take a OleObject and draw it to a bitmap canvas. The bitmap will be sized 
    to match the normal size of the OLE Object. 
} 
procedure DrawOleOnBmp(Ole: IOleObject; Bmp: TBitmap32); 
var 
    ViewObject2: IViewObject2; 
    ViewSize: TPoint; 
    AdjustedSize: TPoint; 
    DC: HDC; 
    R: TRect; 
begin 
    if Succeeded(Ole.QueryInterface(IViewObject2, ViewObject2)) then 
    begin 
    ViewObject2.GetExtent(DVASPECT_CONTENT, -1, nil, ViewSize); 

    DC := GetDC(0); 
    AdjustedSize.X := MulDiv(ViewSize.X, GetDeviceCaps(DC, LOGPIXELSX), 2540); 
    AdjustedSize.Y := MulDiv(ViewSize.Y, GetDeviceCaps(DC, LOGPIXELSY), 2540); 
    ReleaseDC(0, DC); 

    Bmp.Height := AdjustedSize.Y; 
    Bmp.Width := AdjustedSize.X; 

    Bmp.FillRect(0, 0, Bmp.Width, Bmp.Height, clWhite); 

    SetRect(R, 0, 0, Bmp.Width, Bmp.Height); 

    OleDraw(Ole, DVASPECT_CONTENT, Bmp.Canvas.Handle, R); 
    end 
    else 
    begin 
    raise Exception.Create('Could not get the IViewObject2 interfact on the OleObject'); 
    end; 
end; 
+0

感谢您的意见。我想这可能会起作用,但是有一件事,你碰巧知道'GetData'失败的原因是什么?似乎它与'TYMED_HGLOBAL'有关,因为当我将'CF_BITMAP'改为'CF_DIB'和'TYMED_HGLOBAL'为'TYMED_ISTREAM'时,我就可以成功地检索数据了。另一方面,我也想写回数据,这只能通过'IDataObject'接口实现,不是吗? – forsajt 2013-03-13 22:12:00

+0

我并没有使用'TOleContainer'玩过那么多,所以我并不擅长使用'IDataObject'接口。但去年7月,我试图将RTF文档转换为另一种格式。其中许多包含OLE对象。当我的计算机上没有安装某个OLE对象时,我只看到“无效的FORMATETC结构”。如果你的错误是由同一个问题引起的(缺少OLE服务器),那么你可以用代码来消除错误。 OLE服务器必须存在才能解析OLE数据并进行呈现。 – 2013-03-13 22:21:45