HBPrintPDF - Bitmap als Hintergrundformular

Von Ausgaben mit der Gra-Engine über Generatoren bis zum Export in diversen Formaten

Moderator: Moderatoren

Antworten
Benutzeravatar
henxl
UDF-Programmierer
UDF-Programmierer
Beiträge: 91
Registriert: Fr, 10. Feb 2006 19:46
Wohnort: Mannheim

HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von henxl » Do, 08. Jun 2017 13:33

Hallo Hubert,

ich nutze Deine Klasse mit QuickPDF Version 11. Ich bin damit sehr zufrieden.
Ich habe bisher Formulare in der Weise als PDF erstellt, dass ich ein BMP als Form drucke und dann die Daten "drüber" drucke.
Das BMP ist über ARC in der EXE gelinkt.
Jetzt möchte ich das BMP in eine DLL auslagern. Ich habe es jedoch nicht geschafft, das BMP zu drucken. Ich weiß nicht, wo ich die DLL angeben muss.
Hast Du ein Beispiel oder einen Tipp, wie das funktioniert?

Viele Grüße
Heinz
Das einzige, was ich weiß ist, dass ich nichts weiß, Sokrates

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 14549
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von brandelh » Do, 08. Jun 2017 13:45

Hi,

zeig doch mal die ARC und CH Dateien mit denen du die Bitmap (welche ART ?) anlegst,
sowie die PRG Auszüge mit denen du die Bitmap aus der Exe liest und an QuickPDF weiter gibst.
Beim Resourcen laden braucht man eigentlich nur die DLL angeben in der die neue Resource liegen soll.
Bei der Weitergabe an QuickPDF sollte sich nichts ändern.
Gruß
Hubert

Benutzeravatar
henxl
UDF-Programmierer
UDF-Programmierer
Beiträge: 91
Registriert: Fr, 10. Feb 2006 19:46
Wohnort: Mannheim

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von henxl » Do, 08. Jun 2017 15:15

Hallo,

mache ich, brauche jedoch ein wenig Zeit...

Grüße
Heinz
Das einzige, was ich weiß ist, dass ich nichts weiß, Sokrates

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 14549
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von brandelh » Do, 08. Jun 2017 15:57

die haben wir ... und lassen sie uns nicht nehmen ;-)
Gruß
Hubert

Benutzeravatar
henxl
UDF-Programmierer
UDF-Programmierer
Beiträge: 91
Registriert: Fr, 10. Feb 2006 19:46
Wohnort: Mannheim

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von henxl » Do, 08. Jun 2017 16:32

Hallo,

diesen Code benutze ich:

Code: Alles auswählen

********************************** Alt
//  GB.ARC
...
USERDEF MANIFEST
        MANIFEST_RESID = FILE "gb.exe.manifest"
VERSION
  "CompanyName"      = "HEN"
...
ICON        101 =   "ENA.ICO"
BITMAP    501 =   "ena11.bmp"           /                   
...

FUNCTION cl_PrnPdf()
   ...
   oHBPDF := HBPrintPDF():new():create( GetQuickPDFLizenzKey() )
   ...
   cl_PrnBMPPdf( oHBPdf, aPrnPara )  
   ...
RETURN .T.

FUNCTION cl_PrnBMPPdf( oHBPdf, aPrnPara )
LOCAL lSuccess:=.F.
    ...
*   nID ist 501
*   Druck der Form, BMP aus Gb.exe
    
    IF !EMPTY(cFileName)
      oHBPDF:CompressImages(1)
      lSuccess := oHBPDF:DrawImageFile( nX, nY, nXSize, nYSize, 0, 0, 0, cFileName ) 
    ELSE
      IF !EMPTY(nID)
        oHBPDF:CompressImages(1)
        lSuccess := oHBPDF:DrawImageResource( nX, nY, nXSize, nYSize, 0, 0, 0, nID )
      ENDIF
    ENDIF
   
*   Druck des Textes über das BMP
RETURN lSuccess
*
********************************** Neu

//  GB_Res.ARC
BITMAP    501 =   "ena11.bmp"                       

Gb.xpj

[PROJECT]
    COMPILE       = xpp
    COMPILE_FLAGS = /q
    DEBUG         = yes
    GUI           = no
    LINKER        = alink
    LINK_FLAGS    = 
    RC_COMPILE    = arc
    RC_FLAGS      = 
    VERSION       = 2.1
    GB.XPJ
[GB.XPJ]
    GB.exe
    GB.dll
    GBR.dll
[GB.exe]
...
[GB.dll]
...
[GBR.dll]
    COMPILE       = xpp
    COMPILE_FLAGS = /DLL:DYNAMIC /wi /wu /q /p /w /d_GbLk /d_HEN2
    DEBUG_SAVE    = yes
    GUI           = yes
    LINKER        = ALINK
    LINK_FLAGS    = /debug /dll
    RC_COMPILE    = ARC
    RC_FLAGS      = /v
    OBJ_DIR       = K:\XPP2\OBJ\GB
// $START-AUTODEPEND
    GB_Res.obj
    .\GB.lib
    GBR.def
    ..\..\Source\Gb\GB_Res.res
// $STOP-AUTODEPEND
    ..\..\Source\Gb\GB_Res.ARC
    ..\..\Source\Gb\GB_Res.PRG

Die Version "Alt" funktioniert.
In der Version "Neu" werden die BMP zusammen mit einer kleinen PRG in die DLL GBR.DLL gelinkt.
In der Gb.EXE verbleiben die Icons und andere BMP (Buttons etc.), siehe Gb.Arc

Ich benutze Huberts HBPrintPDF.
Wo kann ich jetzt angeben, dass das BMP nicht mehr aus der Exe, sondern aus der GBR.DLL geladen wird?

Grüße
Heinz
Das einzige, was ich weiß ist, dass ich nichts weiß, Sokrates

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 14549
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von brandelh » Fr, 09. Jun 2017 9:20

Ich verstehe wo dein Problem ist ;-)

Normalerweise nutzt man in Xbase++ diesen Befehl um eine Resource BMP zu laden:

Code: Alles auswählen

LoadResource( <nResId>|<cResId>, [<nDll|cDll>], [<nRestype>|<cResType>], <nLanguageId|cLanguageId> ) --> xResource 
Wenn [<nDll|cDll>] leer ist, holt er sich z.B. die Bitmap aus der EXE, ansonsten gibt man die DLL (als Name oder ID nach dllload() ) ... oder man nutzt XbpBitmap() direkt:

Code: Alles auswählen

XbpBitmap()
 Syntax 
:load( [<cDLLname>], <nID> ) --> lSuccess 
Bei PDF Dateien ist es mit den Bildern etwas anders als bei normalem Drucken.
Eine PDF bindet eine BITMAP genau EINMAL in die Datei ein und vergibt Name und/oder ID.
Danach druckt man mit dieser ID, welche NICHT der im Xbase++ Programm verwendeten ResourceID entspricht, daher ist auch keine DLL Angabe in dem obigen Befehl möglich.

Je nachdem was man im Xbase++ Programm schon hat, kann man verschiedene Befehle nutzen um die Grafik in die PDF zu bekommen.
Für dich dürfte das am Besten passen (Resource wurde noch NICHT in XbpBitmap geladen):

HBPrintPDF:PrintBmp( nPosX, nPosY, nXSize, nYSize, cFileNameID, nID, nHAlign, nVAlign, nRotate, nBox, nDotsPerUnit ) - sehen wir den Quellcode an:

Code: Alles auswählen

*---------------------------------------------------
METHOD HBPrintPDF:PrintBmp( nPosX, nPosY, nXSize, nYSize, cFileNameID, nID, nHAlign, nVAlign, nRotate, nBox, nDotsPerUnit )
   local nImageID, lFehler := .f., cErrTxt, nDLL, nOldLineWidth, nOldImage           // cFileNameID = C or N ...
   ...
   nOldImage := ::SelectedImage()   // die selektierte Image-ID (Bitmap) für folgende Image Befehle

   do case
      case nID==NIL .and. empty(cFileNameID)
           // Keine Resource, Kein Dateiname, Kein Stringpuffer => aktuell selektierte Grafik benutzen !
...
      case nID==NIL .and. valtype(cFileNameID)=="C" // Datei auf Festplatte nutzen
           // Dateiname !
           nImageID := ::AddImageFile(cFileNameID,0)
...
      case nID==NIL .and. valtype(cFileNameID)=="N"
           // Image ID  ! - also die ID einer schon enthaltenen Bitmap in der PDF !
           if ::SelectImage(cFileNameID)
...
      case nID==NIL
           // ERROR
...
      case nID == -1          // XbpBitmap SetBuffer() String
           if valtype(cFileNameID)=="C" .and. ! empty(cFileNameID)
              nImageID := ::AddImageFromXbpBMP(cFileNameID) // XbpBitmap als Bitmap hinzufügen
...
      case nID > 0            // RESOURCE ID DER EXE ODER DLL
           // *** das müsste für dich am Besten passen ***
           if valtype(cFileNameID)=="C" .and. ! empty(cFileNameID) // IN DLL
              nDLL := DllLoad(cFileNameID)
           else
              nDLL := NIL
           endif
           nImageID := ::AddImageResource(nID,0,nDLL)
           if nImageID > 0
              // OK
           else
              cErrTxt := "RESOURCE-ID NOT VALID"
              lFehler := .t.
           endif

      otherwise
...
   end
der letzte Teil passt wohl für dich am Besten, solange du die Bitmap aus der Resource nicht schon geladen hast (wie ganz oben erwähnt):

Code: Alles auswählen

      case nID > 0            // RESOURCE ID DER EXE ODER DLL
           // *** das müsste für dich am Besten passen ***
           if valtype(cFileNameID)=="C" .and. ! empty(cFileNameID) // IN DLL
              nDLL := DllLoad(cFileNameID)
           else
              nDLL := NIL
           endif
           nImageID := ::AddImageResource(nID,0,nDLL)
cFileNameID := "MeineBitmapinDLL.DLL"
nID := 501 // besser einen NAMEN per CH Datei (#define bmpHintergrund 501)
HBPrintPDF:PrintBmp( nPosX, nPosY, nXSize, nYSize, cFileNameID, nID, nHAlign, nVAlign, nRotate, nBox, nDotsPerUnit )

Intern wird der Befehl dann die Bitmap in die PDF laden und verwenden:

Code: Alles auswählen

// -------------------------------------------------------------------------------------------------------------------
METHOD HBPrintPDF:AddImageResource(nResourceID,nOptions,nDLL)          // ONLY / NUR    BMP BITMAP RESOURCEN !!!
   LOCAL nImageID, cImageName
   DEFAULT nResourceID TO 0
   if nResourceID > 0
      cImageName := "RES_ID_"+alltrim(str(nResourceID))
      // schon vorhanden ?
      nImageID := ::GetImageIDByName(cImageName)                  // ist das Image schon enthalten / only once
      if nImageID == 0
         nImageID := ::AddImageFromString(  ::cLoadResource(nDLL,nResourceID, 2, , .t. ) , nOptions )
         if nImageID > 0 // OK !
            ::AddImageID(nImageID,cImageName)
         endif
      endif
   endif
return nImageID
wie man sieht, wird eine Resource einer DLL nur einmal in die PDF eingebunden und danach einfach wieder verwendet.
Allerdings muss ich hier feststellen, dass zwei gleiche ResourceIDs in zwei verschiedenen DLL so nicht möglich sind, da immer die ID der ersten Bitmap benutzt wird. Unschön ... wohl ein Fehler.

Auf jeden Fall solltest du dir die PDF Hilfe zu QuickPDF ansehen, AddImage* DrawImage* und verschiedene Manipulationsbefehle.
Zu jedem Namen findest du eine Methode hier, wobei ich auch zusätzliche aufgenommen habe um das Leben zu erleichtern.
Wenn z.B. eine Variable schon mit XbpBitmap():load ... mit einer Grafik oder Resourcegrafik geladen wurde, kann man die direkt übergeben und die Methode kümmert sich um den BMP Header:

Code: Alles auswählen

// -------------------------------------------------------------------------------------------------------------------
METHOD HBPrintPDF:AddImageFromXbpBMP(cBMP) // NUR BEI BMP für Rückgabewert von XbpBitmap():setBuffer()   !!! *.BMP !!!
                                           // ONLY with BMP and return value from XbpBitmap():setBuffer()!!! *.BMP !!!
   if left(cBMP,2) # "BM"
      cBMP := "BM"+U2BIN(len(cBMP)+14)+W2BIN(0)+W2BIN(0)+U2BIN(BIN2U(left(cBMP,4))+14)+cBMP
   endif
return ::AddImageFromString(cBMP,0)        // !!! *.BMP !!!
Ich meine diese Befehle sind alle in der 11er Version enthalten.
Gruß
Hubert

Benutzeravatar
henxl
UDF-Programmierer
UDF-Programmierer
Beiträge: 91
Registriert: Fr, 10. Feb 2006 19:46
Wohnort: Mannheim

Re: HBPrintPDF - Bitmap als Hintergrundformular

Beitrag von henxl » Fr, 09. Jun 2017 11:51

Hallo Hubert,


vielen Dank für Deinen Einsatz und die schnelle Antwort.
Ich habe es gestern Abend hinbekommen, wahrscheinlich aber auf eine abenteuerliche Weise.

Ich habe das BMP außerhalb Deiner Klasse mit XbpBitmap geladen. Das Laden der DLL mit dem BMP und die Übergabe von nDLL an AddImageResource ist mir nicht gelungen. Deshalb habe ich zuerst DrawImageResource und dann AddImageResource um den Parameter cBMP erweitert und das BMP übergeben. In AddImageResource wird dann nicht mehr ::cLoadResource ausgeführt, sondern mit AddImageFromXbpBMP der Header hinzugefügt. Dann zurück in DrawImageResource wird noch FitImage ausgeführt (unbedingt erforderlich?).

Hier mein Code (Aufruf):

Code: Alles auswählen


*Laden und Rückgabe des BMP
lSuccess := cl_LRes(cFileNameID,nID,, @cBMP)
IF lSuccess
*Aufruf Deine Klasse und Übergabe des BMP
lSuccess := oHBPDF:DrawImageResource( nX, nY, nXSize, nYSize, 0, 0, 0, nID, , cBMP)
ENDIF

und die Änderungen Deiner Klasse (in ii/Ende ii eingeschlossen):

Code: Alles auswählen


*METHOD HBPrintPDF:AddImageResource(nResourceID,nOptions,nDLL)          // ONLY / NUR    BMP BITMAP RESOURCEN !!!
// ii
METHOD HBPrintPDF:AddImageResource(nResourceID,nOptions,nDLL,cBMP)     // ONLY / NUR    BMP BITMAP RESOURCEN !!!
// Ende ii
   LOCAL nImageID, cImageName
   DEFAULT nResourceID TO 0
   if nResourceID > 0
      cImageName := "RES_ID_"+alltrim(str(nResourceID))
      // schon vorhanden ?
      nImageID := ::GetImageIDByName(cImageName)                  // ist das Image schon enthalten / only once
      if nImageID == 0
// ii
IF EMPTY(cBMP) 
// Ende ii
        nImageID := ::AddImageFromString(  ::cLoadResource(nDLL,nResourceID, 2, , .t. ) , nOptions )
// ii
ELSE
        nImageID := ::AddImageFromXbpBMP(@cBMP)
// ii
ENDIF
// Ende ii
         if nImageID > 0 // OK !
            ::AddImageID(nImageID,cImageName)
         endif
      endif
   endif
return nImageID


*METHOD HBPrintPDF:DrawImageResource(nLeft, nTop, nWidth, nHeight,nHAlign,nVAlign,nRotate,nResourceID,nOptions)
// ii
METHOD HBPrintPDF:DrawImageResource(nLeft, nTop, nWidth, nHeight,nHAlign,nVAlign,nRotate,nResourceID,nOptions,cBMP)
// Ende ii
   local nImageID, lOK := .f.
*  nImageID := ::AddImageResource(nResourceID,nOptions)
// ii
   nImageID := ::AddImageResource(nResourceID,nOptions,,cBMP)
// Ende ii
   if nImageID > 0
      lOK := ::FitImage(nLeft, nTop, nWidth, nHeight,nHAlign,nVAlign,nRotate)
   endif
return lOK
Wie gesagt, wahrscheinlich nicht so elegant gelöst, es funktioniert aber.

Nochmals vielen Dank!

Viele Grüße
Heinz
Das einzige, was ich weiß ist, dass ich nichts weiß, Sokrates

Antworten