HGLOBAL返回Crystal Reports UFL的UF5SaveState和UF5RestoreState中的值

时间:2010-11-26 09:58:15

标签: c++ windows crystal-reports

使用C ++为Crystal报表编写UFL我可以选择实现UF5SaveState和UF5RestoreState函数,COM接口无法实现这些函数,导致存在这些函数需要解决的问题。

我必须实现的UF5SaveState函数具有以下签名: -

HGLOBAL __stdcall UF5SaveState (UFTInt32u jobId)

我的问题是我不确定如何形成它预期返回的HGLOBAL。

文档只说这个: -

  

UF5SaveState此过程必须是   只有你的UFL有一个   具有副作用的功能 [确实如此] 。它是   由Crystal Reports调用获取   来自UFL的状态给定   点。 Crystal Reports作业号   被传递给函数。该   函数返回UFL状态二进制   在第二个参数中流,和   返回中的状态大小   第三个参数。

我最困惑,尤其是因为它谈到了在第二个甚至第三个参数中返回的东西。我不是一个真正的Windows用户,所以对我来说HGLOBAL看起来很像一个无效指针,所以我希望它对windows人更有意义。我试过传回一个GlobalAlloc的结果,尝试从它创建一个流(CreateStreamOnHGlobal)并传回来,只尝试了一个char *,所有结果都是一个未处理的异常: -

  

0x7c92a978处的未处理异常   crw32.exe中的(ntdll.dll):0xC0000005:   访问违规写入位置   0x00030fa4。

我毫不怀疑这是因为它期待别的东西,但是......

一大堆代码,只是为了帮助你们全力以赴: -

HGLOBAL __stdcall UF5SaveState (UFTInt32u jobId)
{
 ULONG bytesWritten;
 HGLOBAL result = GlobalAlloc(GHND, 2048);
 LPSTREAM stream = LPSTREAM(); 
 CreateStreamOnHGlobal(result, false, &stream);
 stream->Write("ABC", 3, &bytesWritten);
 stream->Release();

 return result;
}

所以,想象一下我想保存一个只有三个字符的状态“ABC”零终结器可选,我该怎么做?

2 个答案:

答案 0 :(得分:0)

我在一百万年前写过一个自定义CR函数。 uffuncs.h头文件包含以下定义:

HGLOBAL CR_EXPORT UF5SaveState (UFTInt32u jobId);
UFError CR_EXPORT UF5RestoreState (UFTInt32u jobId,
                                   HGLOBAL savedState);

你发现的文档引人注目,HGLOBAL还不足以在报告中保留。它是一个指针,当在另一个会话中再次加载报表时,它无法正常恢复。那些神秘的额外论点将允许这一点。

此头文件具有1997时间戳。我只能建议您尝试查找uffuncs.h头文件的更新版本。无论它在哪里,我都不记得从哪里得到它。网站文档和链接完全不合适。相当典型的CR损失,我决定在经历了痛苦之后再也不会使用CR。

答案 1 :(得分:0)

在设置Windows剪贴板时,仍然使用常用的HGLOBAL内存句柄。 Crystal Reports可能期望与您使用的句柄完全相同。

以下是创建带有“ABC”的HGLOBAL的相关代码:

const char *szInput = "ABC";
size_t cchBufLen = strlen(szInput) + 1; // +1 for the null-terminator.
size_t cbBufSize = cchBufLen * sizeof(char); // Len==Size, but wouldn't if you were using wchar_t instead of char.

bool bSuccess = false;
HGLOBAL hGlobalClipMem = ::GlobalAlloc(GHND, cbBufSize);

if (hGlobalClipMem != NULL)
{
    // Since the "GHND" flags include GMEM_MOVEABLE we must use GlobalLock to
    // get a pointer to the buffer, and later GlobalFree to get back to normal.
    char *pGlobalBuffer = reinterpret_cast<char *>( ::GlobalLock(hGlobalClipMem) );

    if (pGlobalBuffer != NULL)
    {
        strcpy(pGlobalBuffer, szInput);
        bSuccess = true; // Set false if anything fails here, so you clean-up.

        ::GlobalUnlock(hGlobalClipMem); // You unlock the hGlobal, not the pointer that came out of GlobalLock.
    }

    // Error-handling path.
    if (!bSuccess)
    {
        ::GlobalFree(hGlobalClipMem);
        hGlobalClipMem = NULL;
    }
}

return hGlobalClipMem; // Returns NULL on failure.