Printing - Page number paradox

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

User avatar
Rathinagiri
Posts: 5148
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 124 times
Been thanked: 126 times
Contact:

Re: Printing - Page number paradox

Post by Rathinagiri » Thu Oct 20, 2016 7:58 pm

I don't know anything about the internal structure of the EMF files, but just taking a quick look, it appears to be that strings are there, so, it could be only matter of put a placeholder for total pages in each one and then... DIRECTORY, MEMOREAD, STRTRAN, MEMOWRIT... you know...
That is right Roberto. I too have gone into deep about EMF. What that had given in Microsoft site is that 'Yes EMF can be enumerated and edited. EMF is an array of EnhanceMetaRecords (EMR) as they call it. These EMRs are in variable size.

From MSDN:

An EMF metafile consists of a sequence of EMF records. The first record in the metafile is always an EMF header record, and the last is always an EMF end-of-file record. Between these are records that specify drawing operations, the configuration of properties, and the creation of graphics objects, all of which together compose a device-independent picture.

EMF records are contiguous; this is required, because the information that is available for traversing the file from record to record depends on it. That is, from any given EMF record, including the header record, in order to move to the next sequential record in the file, the length of the record is used.

So even if we search text and replace with other text, we need to replace the exact size. Otherwise EMR size will be changed.

Or the safest way is grab the EMR using Win32API and replace it after modification.

EMR_EXTTEXTOUTW is the EMR type for Unicode Text.

https://msdn.microsoft.com/en-us/library/cc230533.aspx

And yours is a nice idea! Put some XXXX in every page and replace that with the number of pages afterwards with exactly 4 characters. I will try that!
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
Roberto Lopez
HMG Founder
Posts: 3897
Joined: Wed Jul 30, 2008 6:43 pm
Has thanked: 13 times
Been thanked: 132 times

Post by Roberto Lopez » Thu Oct 20, 2016 8:08 pm

Roberto Lopez wrote: Again... maybe I'm missing something important... sorry in advance.
And...

We should generate emf files always (preview or not) because the 'totalpages' tag must be available always (not only when preview is required).

So we always should print as from preview (from emf files) so, it could drive to a speed problem in 'no-preview' situations...

Again...again: I could be missing something (print system had suffered many changes since my watch :) )

Sorry for that.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)

User avatar
Roberto Lopez
HMG Founder
Posts: 3897
Joined: Wed Jul 30, 2008 6:43 pm
Has thanked: 13 times
Been thanked: 132 times

Post by Roberto Lopez » Thu Oct 20, 2016 8:41 pm

Rathinagiri wrote: And yours is a nice idea! Put some XXXX in every page and replace that with the number of pages afterwards with exactly 4 characters. I will try that!
Exactly... the placeholder and the the total page number string must have the same size.
Regards/Saludos,

Roberto


(Veritas Filia Temporis)

User avatar
Pablo César
Posts: 4058
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil
Has thanked: 100 times
Been thanked: 176 times

Post by Pablo César » Thu Oct 20, 2016 9:11 pm

I advice you to use "@@@@" instead of "XXXXX" in order to avoid any coincidence in the text.
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein

User avatar
srvet_claudio
Posts: 1934
Joined: Thu Feb 25, 2010 8:43 pm
Location: Uruguay
Has thanked: 28 times
Been thanked: 112 times
Contact:

Post by srvet_claudio » Thu Oct 20, 2016 10:27 pm

Is possible you draw inside EMF with GDI functions. I will prepare a demo.
Best regards.
Dr. Claudio Soto
(from Uruguay)
http://srvet.blogspot.com

User avatar
Rathinagiri
Posts: 5148
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 124 times
Been thanked: 126 times
Contact:

Post by Rathinagiri » Fri Oct 21, 2016 10:42 am

Thank you Roberto, Claudio, Pablo.

I will wait for Claudio's demo.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
srvet_claudio
Posts: 1934
Joined: Thu Feb 25, 2010 8:43 pm
Location: Uruguay
Has thanked: 28 times
Been thanked: 112 times
Contact:

Post by srvet_claudio » Tue Oct 25, 2016 2:11 pm

srvet_claudio wrote:Is possible you draw inside EMF with GDI functions. I will prepare a demo.
Hi all,
sorry for the delay but I've been very busy...

Code: Select all


#include "hmg.ch"
#include "Directry.ch"

Function Main()
   DEFINE WINDOW Win_1 ;
      AT 0,0 ;
      WIDTH 400 ;
      HEIGHT 400 ;
      TITLE 'MiniPrint Library Test: Insert Page Number' ;
      MAIN 

      @ 50, 50 BUTTON Button_1 CAPTION "Test" ACTION PrintTest()

   END WINDOW
   CENTER WINDOW Win_1
   ACTIVATE WINDOW Win_1
Return


*------------------------------------------------------------------------------*
Procedure PrintTest
*------------------------------------------------------------------------------*
LOCAL lSuccess

   SELECT PRINTER DIALOG TO lSuccess PREVIEW

   If lSuccess == .F.
      MsgInfo('Print Error')
      Return
   EndIf


   // Measure Units Are Millimeters

   START PRINTDOC


         START PRINTPAGE

            @ 20,20 PRINT "Filled Rectangle Sample:" ;
               FONT "Arial" ;
               SIZE 20 

            @ 30,20 PRINT RECTANGLE ;
               TO 40,190 ;
               PENWIDTH 0.1;
               COLOR {255,255,0}

            @ 60,20 PRINT RECTANGLE ;
               TO 100,190 ;
               PENWIDTH 0.1;
               COLOR {255,255,0};
               FILLED

            @ 110,20 PRINT RECTANGLE ;
               TO 150,190 ;
               PENWIDTH 0.1;
               COLOR {255,255,0};
               ROUNDED

            @ 160,20 PRINT RECTANGLE ;
               TO 200,190 ;
               PENWIDTH 0.1;
               COLOR {255,255,0};
               FILLED;
               ROUNDED

         END PRINTPAGE


         START PRINTPAGE

            @ 20,20 PRINT "Filled Rectangle Sample:" ;
               FONT "Arial" ;
               SIZE 20 

            @ 30,20 PRINT RECTANGLE ;
               TO 40,190 ;
               PENWIDTH 0.1

            @ 60,20 PRINT RECTANGLE ;
               TO 100,190 ;
               PENWIDTH 0.1;
               FILLED

            @ 110,20 PRINT RECTANGLE ;
               TO 150,190 ;
               PENWIDTH 0.1;
               ROUNDED

            @ 160,20 PRINT RECTANGLE ;
               TO 200,190 ;
               PENWIDTH 0.1;
               FILLED;
               ROUNDED

         END PRINTPAGE

         // call this function after last END PRINTPAGE and before END PRINTDOC 
         ProcInsertPageNumber( OpenPrinterGetDC() )

   END PRINTDOC

Return


************************************************************************************************************

PROCEDURE ProcInsertPageNumber( hDC )
LOCAL cFuncNameCallBack := "ProcDrawEMFCallBack"
LOCAL cNamePrefix := GetTempFolder() + _HMG_SYSDATA [ 379 ] + "_hmg_print_preview_"
LOCAL aFiles :=  DIRECTORY( cNamePrefix + "*.EMF" )
LOCAL cFileNameOld, cFileNameNew, i
PRIVATE nPageNumber := 1

   FOR i := 1 TO HMG_LEN( aFiles ) 
      cFileNameOld := GetTempFolder() + aFiles [ i ] [ F_NAME ]
      cFileNameNew := GetTempFolder() + "New_" + aFiles [ i ] [ F_NAME ]
      nError := BT_DrawEMF( hDC, cFileNameOld, cFileNameNew, cFuncNameCallBack )
      IF nError == 0
         FERASE( cFileNameOld ) 
         FRENAME( cFileNameNew, cFileNameOld )
      ELSE
         MsgStop("Error ("+ hb_NtoS( nError ) +") in write into EMF: " + cFileNameOld )
      ENDIF
   NEXT

RETURN


*************************************************************************************************************

FUNCTION ProcDrawEMFCallBack( hDC, leftMM, topMM, rightMM, bottomMM, leftPx, topPx, rightPx, bottomPx, IsParamHDC )   // rectangle that bounded the area to draw, in milimeters and pixels
LOCAL Old_PageDC := OpenPrinterGetPageDC()

   OpenPrinterGetPageDC() := hDC
   @ 180, 100 PRINT " Page Number: " + hb_NtoS( nPageNumber++ ) + " of " + hb_NtoS( _HMG_SYSDATA [ 380 ] ) FONT "Arial" SIZE 12 
   OpenPrinterGetPageDC() := Old_PageDC

   // MsgDebug( hDC, leftMM, topMM, rightMM, bottomMM, leftPx, topPx, rightPx, bottomPx, IsParamHDC )
RETURN NIL



#pragma BEGINDUMP

#include "HMG_UNICODE.h"
#include <windows.h>
#include "hbvm.h"
#include "hbapi.h"


//*********************************************************************************************************************************
//* BT_DrawEMF ( [ hDC ] , cFileNameOld , cFileNameNew , cFuncNameCallBack )  ---> Return nError, e.g. Zero is OK
//*********************************************************************************************************************************

HB_FUNC (BT_DRAWEMF)
{
   HDC   hDC                = (HDC)    HMG_parnl (1);
   TCHAR *cFileNameOld      = (TCHAR*) HMG_parc  (2);
   TCHAR *cFileNameNew      = (TCHAR*) HMG_parc  (3);
   CHAR  *cFuncNameCallBack = (CHAR* ) hb_parc   (4);

   BOOL IsParamHDC = ( hDC ? TRUE : FALSE );

   HDC           hDC_EMF  = NULL;
   HENHMETAFILE  hEMF_Old = NULL;
   HENHMETAFILE  hEMF_New = NULL;

   ENHMETAHEADER emh;
   HRSRC         hResourceData;
   HGLOBAL       hGlobalResource;
   LPVOID        lpGlobalResource;
   DWORD         nFileSize;


   PHB_DYNS pDynSym = hb_dynsymFindName( cFuncNameCallBack );
   if( pDynSym == NULL )
   {  hb_retni (1);
      return;
   }
    
   // Load MetaFile from Resource
   hResourceData = FindResource (NULL, cFileNameOld, _TEXT("EMF"));
   if ( hResourceData )
   {   hGlobalResource = LoadResource (NULL, hResourceData);
       if ( hGlobalResource )
       {    lpGlobalResource = LockResource (hGlobalResource);
            nFileSize = SizeofResource (NULL, hResourceData);
            hEMF_Old = SetEnhMetaFileBits (nFileSize, lpGlobalResource);
       }
   }

   // If fail, load MetaFile from Disk
   if (hEMF_Old == NULL)
       hEMF_Old = GetEnhMetaFile (cFileNameOld);

   // If fail load from Resource and Disk return False
   if (hEMF_Old == NULL)
   {  hb_retni (2);
      return;
   }

   // Get the header of MetaFile
   ZeroMemory (&emh, sizeof(ENHMETAHEADER));
   emh.nSize = sizeof(ENHMETAHEADER);
   if ( GetEnhMetaFileHeader(hEMF_Old, sizeof(ENHMETAHEADER), &emh) == 0 )
   {  DeleteEnhMetaFile (hEMF_Old);
      hb_retni (3);
      return;
   }

   if( IsParamHDC )
      hDC_EMF = CreateEnhMetaFile( hDC, cFileNameNew, (RECT *)&emh.rclFrame, _TEXT("") ); 
   else
   {
      hDC = GetDC( NULL );
      INT iWidthMM  = GetDeviceCaps( hDC, HORZSIZE );
      INT iHeightMM = GetDeviceCaps( hDC, VERTSIZE );
      INT iWidthPx  = GetDeviceCaps( hDC, HORZRES  );
      INT iHeightPx = GetDeviceCaps( hDC, VERTRES  );
      hDC_EMF = CreateEnhMetaFile( hDC, cFileNameNew, (RECT *)&emh.rclFrame, _TEXT("") );

      if (hDC_EMF == NULL)
         ReleaseDC (NULL, hDC);

      emh.rclBounds.left   = (emh.rclFrame.left   / 100) * iWidthPx  / iWidthMM;
      emh.rclBounds.top    = (emh.rclFrame.top    / 100) * iHeightPx / iHeightMM;
      emh.rclBounds.right  = (emh.rclFrame.right  / 100) * iWidthPx  / iWidthMM;
      emh.rclBounds.bottom = (emh.rclFrame.bottom / 100) * iHeightPx / iHeightMM;
   }

   if (hDC_EMF == NULL)
   {  DeleteEnhMetaFile (hEMF_Old);
      hb_retni (4);
      return;
   }
   
   // Play Old MetaFile into New MetaFile 
   PlayEnhMetaFile (hDC_EMF, hEMF_Old, (RECT *)&emh.rclBounds);

   hb_vmPushSymbol (hb_dynsymSymbol ( pDynSym ));
   hb_vmPushNil ();                                       // places NIL at Self 
   hb_vmPushNumInt ((LONG_PTR) hDC_EMF );
   hb_vmPushLong   ((LONG) emh.rclFrame.left   / 100 );   // push values in milimeters
   hb_vmPushLong   ((LONG) emh.rclFrame.top    / 100 );
   hb_vmPushLong   ((LONG) emh.rclFrame.right  / 100 );
   hb_vmPushLong   ((LONG) emh.rclFrame.bottom / 100 );
   hb_vmPushLong   ((LONG) emh.rclBounds.left   );        // push values in pixels
   hb_vmPushLong   ((LONG) emh.rclBounds.top    );
   hb_vmPushLong   ((LONG) emh.rclBounds.right  );
   hb_vmPushLong   ((LONG) emh.rclBounds.bottom );
   hb_vmPushLogical((BOOL) IsParamHDC );
   hb_vmDo ( 1+4+4+1 );

   // Release hDC
   hEMF_New = CloseEnhMetaFile (hDC_EMF);

   // Release handles
   DeleteEnhMetaFile (hEMF_Old);
   DeleteEnhMetaFile (hEMF_New);

   if( IsParamHDC == FALSE )
      ReleaseDC (NULL, hDC);

   hb_retni (0);   // OK status
}


#pragma ENDDUMP
Best regards.
Dr. Claudio Soto
(from Uruguay)
http://srvet.blogspot.com

User avatar
Pablo César
Posts: 4058
Joined: Wed Sep 08, 2010 1:18 pm
Location: Curitiba - Brasil
Has thanked: 100 times
Been thanked: 176 times

Post by Pablo César » Tue Oct 25, 2016 2:20 pm

WOW Geniously !

Thank you Claudio. Our C Guru.
HMGing a better world
"Matter tells space how to curve, space tells matter how to move."
Albert Einstein

User avatar
mustafa
Posts: 584
Joined: Fri Mar 20, 2009 11:38 am
Location: Alicante - Spain
Been thanked: 44 times

Post by mustafa » Tue Oct 25, 2016 6:08 pm

Claudio, fabuloso !!! :idea: :roll:
Gracias
Mustafa

User avatar
Rathinagiri
Posts: 5148
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 124 times
Been thanked: 126 times
Contact:

Post by Rathinagiri » Tue Oct 25, 2016 8:10 pm

That is unbelievable! :)
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

Post Reply