c ++ - HGLOBAL returværdier i Crystal Reports UFLs UF5SaveState og UF5RestoreState

Indlæg af Hanne Mølgaard Plasc

Problem



Ved at bruge C ++ til at skrive en UFL til Crystal rapporter får jeg mulighed for at implementere UF5SaveState og UF5RestoreState funktionerne, som du ikke får med COM interface, hvilket resulterer i de problemer, som disse funktioner eksisterer for at løse.


UF5SaveState-funktionen, som jeg skal implementere, har denne underskrift: -


HGLOBAL \_\_stdcall UF5SaveState (UFTInt32u jobId)


Mit problem er, at jeg ikke er sikker på, hvordan man danner HGLOBAL, det forventes at vende tilbage.


Dokumenterne siger kun dette:



  UF5SaveState Denne procedure skal være
  implementeret kun, hvis din UFL har en
  funktion med bivirkninger [[Det gør det rigtigt]] . det er
  kaldet af Crystal Reports at opnå
  staten fra UFL på en given
  punkt. Crystal Reports jobnummer
  sendes til funktionen. Det
  funktionen returnerer UFL-tilstandens binære
  strøm i den anden parameter, og
  returnerer statens størrelse i
  tredje parameter.



Jeg er mest forvirret, ikke mindst fordi det snakker om at returnere ting i anden og endda tredje parametre. Jeg er ikke rigtig en Windows-person, så for mig HGLOBAL ser meget ud som en tomrumpeger, og jeg forventer, at det er mere meningsfuldt at Windows-folk. Jeg har forsøgt at returnere resultaterne fra en GlobalAlloc, forsøgte at skabe en strøm fra den ( CreateStreamOnHGlobal) og passerer det tilbage, forsøgte bare en char *, alt sammen resulterer i en un-handled-undtagelse: -



  Uhåndteret undtagelse på 0x7c92a978
  (ntdll.dll) i crw32.exe: 0xC0000005:
  Adgang til brudskrivning sted
  0x00030fa4.



Jeg er ikke i tvivl om, at dette skyldes, at det forventer noget andet, men hvad ...


Et stykke kode, der ikke virker bare for at hjælpe dig med at komme i gang: -


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;
}


Så forestill mig, at jeg vil gemme en stat, der kun er de tre bogstaver 'ABC' nul terminator valgfri, hvordan gør jeg det?

Bedste reference


Jeg skrev en brugerdefineret CR-funktion for en million år siden. Uffuncs.h header filen indeholdt disse definitioner:


HGLOBAL CR\_EXPORT UF5SaveState (UFTInt32u jobId);
UFError CR\_EXPORT UF5RestoreState (UFTInt32u jobId,
                                   HGLOBAL savedState);


Den dokumentation, du fandt, er overbevisende, men en HGLOBAL er ikke så god nok til at fortsætte inde i en rapport. Det er en pointer, der ikke vil genoprette ordentligt, når rapporten er indlæst igen i en anden session. Disse mystiske ekstra argumenter ville tillade dette.


Denne headerfil har en 1997 tidsstempel. Jeg kan kun anbefale dig at forsøge at finde en mere opdateret version af uffuncs.h header filen. Hvor det end måtte være, husker jeg ikke, hvor jeg fik det fra. Webstedets dokumenter og links er fuldstændig utilstrækkelige. Præcis typiske CR-tab, jeg besluttede aldrig at bruge CR igen efter den elendighed, jeg gik igennem.

Andre referencer 1


Det fælles sted HGLOBAL hukommelseshåndtag er stadig brugt, er når du indstiller Windows udklipsholder. Crystal Reports forventer formentlig den samme type håndtag som du ville bruge til det.


Her er den relevante kode for at oprette en HGLOBAL med 'ABC' i den:


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.