An Ordeal of OLE

本文详细介绍了在AutoCAD中使用OLE技术实现图像嵌入和链接的过程,包括存在的问题、解决方案及最终实现方法。重点讨论了如何通过复制图像对象到剪贴板并作为复合文档传递给Teigha库,以及遇到的问题和最终找到的解决办法。
nlp_gte_sentence-embedding_chinese-large

nlp_gte_sentence-embedding_chinese-large

文本生成
特征提取
模型微调

GTE (General Text Embeddings) 是阿里达摩院推出的通用文本向量模型,专门针对中文场景优化,可将文本转换为高质量的向量表示。

OLE(Object Linking and Embedding) is a critical technology by Microsoft to carry out its enterprise applications, based on COM it's also a quite old one. Despite of its importance, it doesn't seem to be so necessary to me as .NET is far more than enough. However in a recent task I have to touch on it.

The task is mainly about enabling the CAD exporting library to export embedded images in addition to linked images which is supported well by both AutoCAD and the Teigha library underlying our library. After a bit of search online it was discovered that image embedding in a similar manner to image linking were not supported or suggested. There are a few solutions/workarounds including

- using OLE that embodies a paint brush application that includes the image, which is a supported feature by AutoCAD for exchanging embedded images.

- leveraging AutoCAD Raster Design (ARD) that has introduced an IEMBED command to allow images to be embeddes as they can be linked; however ARD is not part of a normal version of AutoCAD and unlikely can be easily supported by the Teigha library that we are using (however the official AutoCAD secondary development may do)

- An uncofirmed solution proposed by a discussion thread that creates an AutoCAD entity that includes the image data and is able to externalise it to a temporary file to be referenced by a normal linked image. (needs a bit investigation into how to create an object like that)

Due to the limit of time and resources available, the first option was chosen for the time being, although the third may be proven the best as OLE is neither stable nor performant when being rendered in the AutoCAD. The development of this task involved a lot of investigation and experimentation and turned out to be purely based on a copy of online queries below,

http://www.dimcax.com/hust/showpost.php?p=18114&postcount=1

The final implemenation mostly matches what's described in the link. It mainly involves in the following steps

- obtain an COleDataSource object from the image file using certain APIs

- retrieve COleDataObject from COleDataSource

- create COleClientItem from COleDataObject

- put the COleClientItem on clipboard (to mimic the process of manual copy of image object to AutoCAD)

- enumerate the binary data items from the clipboard and pass them as a compound document to Teigha by calling setCompoundDocument on its OdDbOle2Frame object

The link above suggested creating a static OLE data object from COleDataSource would be fine, which I muddled through and got work with the code below,

// The  method of creating a compound document for a static OLE object from a picture file
void CreateStaticOleCompoundDocument()
{
    HANDLE hDibCopy = CreateDibFromBmp("c:\\temp\\garbage\\sample.bmp");

    COleDataSource src;
    src.CacheGlobalData(CF_DIB, hDibCopy);

    LPDATAOBJECT lpDataObject = (LPDATAOBJECT)src.GetInterface(&IID_IDataObject);

    COleDataObject obj;
    obj.Attach(lpDataObject);

    COleDocument doc;
    COleClientItem item(&doc);
    item.CreateStaticFromData(&obj);

    item.CopyToClipboard();

    COleDataObject objReceiver;
    if (objReceiver.AttachClipboard())
    {
        objReceiver.EnsureClipboardObject();
        
        objReceiver.BeginEnumFormats();
        FORMATETC format;
        FILE *fp;
        fopen_s(&fp, "c:\\temp\\garbage\\olestatic.bin", "wb");
        while (objReceiver.GetNextFormat(&format))
        {
            HGLOBAL hmem = objReceiver.GetGlobalData(format.cfFormat);
            int size = ::GlobalSize(hmem);
            byte *pdata = (byte *)::GlobalLock(hmem);

            fwrite(pdata, 1, size, fp);

            ::GlobalUnlock(hmem);
        }
        
        fclose(fp);
    }

    obj.Detach();
    objReceiver.Release();
}

The bin file will be fed to the Teigha through invocation on its setCompoundDocument

To make it work the image has to be converted to a DIB (Device Independent Bitmap) which is given by the code below as a simplified approach,

// references: 
// http://www.codeguru.com/cpp/g-m/bitmap/article.php/c1693/Creating-a-DIB-section-from-a-BMP-file.htm
HGLOBAL CreateDibFromBmp(char *filename)
{
    FILE *fp;
    fopen_s(&fp, filename, "rb");
    fseek(fp, 0, SEEK_END);
    int flen = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    byte *buf = new byte[flen];

    fread(buf, 1, flen, fp);

    // this simplified version just takes off the header of the BMP to turn it into DIB
    HGLOBAL hmem = ::GlobalAlloc(GMEM_MOVEABLE, flen - 14);

    byte *pdib = (byte*)::GlobalLock(hmem);
    memcpy(pdib, buf+14, flen-14);

    ::GlobalUnlock(hmem);

    delete[] buf;

    fclose(fp);

    return hmem;
}

Unfortunately this solution however reasonable it looks doesn't work out well at all, the first and foremost issue it has is the recent versions of AutoCAD show it as a white placeholder for image and upon editing the placeholder object an error message is popped up saying it's a static ActiveX object and is unable to be activated. And it is truly a static ActiveX as is clearly indicated by the subroutine that is used to create a COleClientItem. And that subroutine cannot be replaced by CreateFromData() simply because the way the data object is created from the picture file doesn't allow that.

So I had to find another way which apparently as suggested by the error message has to be creating a non-static OLE object. Hours of effort with alternate attempts for other possibilities was committed and the final solution was inspired by a link http://support.microsoft.com/kb/220844 but not in the same flavour as I couldn't figure out a way to get a simple graft of the Win32 approach to the OLE objects manipulation that follows to work. Below is my current approach,

// The method of creating a compound document for an OLE from a picture file
void CreateNonStaticCompoundDocument()
{
    *(&afxCurrentAppName) = L"testapp";

    COleDocument doc;
    COleClientItem item(&doc);
    item.CreateFromFile(L"C:\\temp\\garbage\\sample.bmp");

    item.CopyToClipboard();

    COleDataObject objReceiver;
    if (objReceiver.AttachClipboard())
    {
        objReceiver.EnsureClipboardObject();
        
        objReceiver.BeginEnumFormats();
        FORMATETC format;
        FILE *fp;
        fopen_s(&fp, "c:\\temp\\garbage\\olenonstatic.bin", "wb");
        while (objReceiver.GetNextFormat(&format))
        {
            HGLOBAL hmem = objReceiver.GetGlobalData(format.cfFormat);
            int size = ::GlobalSize(hmem);
            byte *pdata = (byte *)::GlobalLock(hmem);

            fwrite(pdata, 1, size, fp);

            ::GlobalUnlock(hmem);
        }
        
        fclose(fp);
    }

    objReceiver.Release();
}

The above approach brings me much closer to the goal. Although it still just creates a white box with no sign of image but AutoCAD doesn't complain when the user is trying to open the OLE and it does show the right image in the paintbrush application.

Note both of the above approaches preserve the data fine as one can copy paste image from AutoCAD.

It can be obviously see how awkward OLE/COM technologies are (I suppose I might have missed some COM object finalisation). They may provide some runtime performance benefit and extensibility, however it's far less productive than .NET and the performance is not that much at all if .NET and its interoperability are optimally used. And I see products using this kind of technology as well as MFC/ATL such as AutoCAD etc. for most part of it including the architecture just because they've long been used rather than they are necessary.

 

您可能感兴趣的与本文相关的镜像

nlp_gte_sentence-embedding_chinese-large

nlp_gte_sentence-embedding_chinese-large

文本生成
特征提取
模型微调

GTE (General Text Embeddings) 是阿里达摩院推出的通用文本向量模型,专门针对中文场景优化,可将文本转换为高质量的向量表示。

内容概要:本文介绍了一种用于电磁暂态(EMT)研究的第四类全变流器型风力发电系统的通用Simulink仿真模型,旨在构建一个能够准确反映实际风电系统动态特性的简化通用模型。该模型涵盖了风力机、传动链、发电机、全功率变流器及其控制策略等关键组成部分,重点突出系统在电网故障、风速波动等复杂工况下的动态响应能力,适用于风电并网电磁暂态分析、新型电力系统稳定性评估及高比例可再生能源接入场景的研究。模型设计兼顾准确性与仿真效率,便于研究人员快速搭建和调试,推动风电系统建模与控制技术的发展; 适合人群:具备一定电力系统理论基础和MATLAB/Simulink仿真能力,从事新能源发电、电力电子变换、风电并网控制及相关方向的研究生、科研人员及工程技术人员; 使用场景及目标:①开展风电系统在电网扰动下的电磁暂态仿真分析;②研究全功率变流器风电机组的动态行为与控制特性;③支撑新型电力系统中高渗透率风电接入的稳定性与电能质量评估,服务于学术研究、课程教学与工程项目前期仿真验证; 阅读建议:建议读者结合文中提供的模型结构与参数设置,在Simulink环境中动手复现并调试仿真模型,通过设置不同运行工况(如三相短路、低电压穿越、风速突变等)观察系统响应,深入理解全变流器风电机组的建模方法、控制逻辑与动态特性,进而拓展应用于更复杂的多机并网或综合能源系统仿真场景。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值