Results 1 to 13 of 13

Thread: [twinBASIC] gPdfMerge - A GUI-based PDF merger

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    [twinBASIC] gPdfMerge - A GUI-based PDF merger


    gPdfMerge v1.2

    Latest version: v1.2.14, 07 Jul 2024

    gPdfMerge is a simple utility written in twinBASIC mainly for me to try out using pdfium.dll, Google's open source PDF utility. It will merge the selected PDFs together, either into a new file, or into the first file on the list. You can optionally specify which pages in each document should be merged, and if you're appending the first in list, where to insert them at. That's all there is to it right now; just a brief experiment before I make a 64bit version of a more complex PDF control.

    Updates:

    Important: Starting with version 1.2, newer builds of pdfium.dll are used. These are obtained from https://github.com/bblanchon/pdfium-binaries/releases. Version 1.2 was tested with 128.0.6569.0 (01 Jul 2024), but newer versions should continue to work fine. Click 'Show all .. assets' to find the Windows versions; the file names you need are pdfium-win-x86.tgz and pdfium-win-x64.tgz. gPdfMerge v1.2+ will not work with the 2018-era original DLLs used with version 1.0.

    (Version 1.2 - 07 Jul 2024)
    -Adds a 'Search for pages' function which opens a new dialog you can use to search for a range of pages to merge:



    (Version 1.1)
    -Range entry textbox now only enabled if an item is selected.
    -Specifying a single pdf with page range to trim it now supported.




    Build notes:
    The project is configured as follows:
    -The project's root folder should contain the .twinproj file, and folders win32 and win64 with the respective bitness version of pdfium.dll
    -The compiled project must have pdfium.dll in the same folder with the .exe (the build output is set to \win32 and \win64).

    One thing of interest, all the VB6 samples didn't have save functionality. I wasn't positive on how to implement it at first; it uses a very VB/tB unfriendly method:
    Code:
    typedef struct FPDF_FILEWRITE_ {
    
      int version;
    
      int (*WriteBlock)(struct FPDF_FILEWRITE_* pThis,
                        const void* pData,
                        unsigned long size);
    } FPDF_FILEWRITE;
    
    FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
                                                        FPDF_FILEWRITE* pFileWrite,
                                                        FPDF_DWORD flags);
    Functions in UDTs defined like that isn't something you usually see. pdfium makes you write your own write function. Other languages weren't helpful here... it seems all the ones I looked at had a built in class that somehow worked with this layout. We're not so lucky. It looked like a simple function pointer to a routine with a file write would work, and it did with one caveat: Despite the DLL's 32bit export calling convention being _stdcall, this callback had to be _cdecl, which might explain why nobody had done it in VB6 before. While there were solutions for APIs, afaik it wasn't until 2021 CDecl functions became practical with The trick's VBCDeclFix, an amazing piece of work that actually seems to finish VB6's incomplete CDecl support.

    twinBASIC, of course, supports CDecl natively, so no hacks are needed.

    The code opens for write the output using CreateFile prior to calling FPDF_SaveAsCopy, then fills in a copy of the UDT with AddressOf WriteBlock
    Code:
        Private Type FPDF_FILEWRITE
            version As Long
            WriteBlock As LongPtr
        End Type
    
                Dim tWrite As FPDF_FILEWRITE
                tWrite.version = 1
                tWrite.WriteBlock = AddressOf WriteBlock
    
        Private Function WriteBlock CDecl(ByVal pThis As LongPtr, ByVal pData As LongPtr, ByVal size As Long) As Long
            If hFileOut Then
                Dim cbRet As Long
                Return WriteFile(hFileOut, ByVal pData, size, cbRet, vbNullPtr)
            End If
        End Function
    Et voilà.

    Thanks and Notes

    Developed using pdfium builds from https://github.com/bblanchon/pdfium-binaries/releases

    Merge routine based on pdfium-cli: https://github.com/klippa-app/pdfium-cli

    Also special thanks to tB Discord user mike webb for getting me interested in this and helping test the program while under development. mike also contributed the code for the CompressRange function in v1.2-- very good work, I was having trouble getting my head around it!

    Command line
    Command line usage:

    Merge: gPdfMerge.exe /i "C:...\Input1.pdf" "C:...\Input2.pdf" /o "C:\path\Output.pdf"

    Append: gPdfMerge.exe /i "C:...\Input1.pdf" "C:...\Input2.pdf"

    Append or merge with ranges and/or insert idx not support via command line in v1.0


    Download from GitHub

    Repo includes browsable source and binary builds.

    (Project use my WinDevLib package for Windows APIs; since all files are built into a .twinproj right now, it's too big to attach to this post even if I wanted to-- that's also why the source is so large)
    Last edited by fafalone; Jul 7th, 2024 at 03:19 AM.

  2. #2
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,509

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    You should make a link to this in the VB6 getting the ball rolling thread. You are coming up with some great utils.
    Spurred on by the new life in TB64?
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  3. #3
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Quote Originally Posted by fafalone View Post
    One thing of interest, all the VB6 samples didn't have save functionality. I wasn't positive on how to implement it at first; it uses a very VB/tB unfriendly method:
    Code:
    typedef struct FPDF_FILEWRITE_ {
    
      int version;
    
      int (*WriteBlock)(struct FPDF_FILEWRITE_* pThis,
                        const void* pData,
                        unsigned long size);
    } FPDF_FILEWRITE;
    
    FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
                                                        FPDF_FILEWRITE* pFileWrite,
                                                        FPDF_DWORD flags);
    Functions in UDTs defined like that isn't something you usually see. pdfium makes you write your own write function.
    Would have to disagree on this.
    Any C-Sourcecode i've seen had those.
    In a nutshell: It's C's "try" to "offer" something like Class-Methods we're used to from vb6, with one difference:
    It allows you to write your own Procedure/Function, and as you pointed out: pdfium EXPECTS you to do that, which in the end "translates" to a callback, since you're just passing a pointer to the function
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    It's unusual in structure in terms of what I'm normally porting to VB/tB, the Windows API. The few places a callback is used in UDTs, the function is defined separately and the UDT definition makes it clear it's a function pointer to that definition, not just putting the definition in the UDT.

    Like take the GetOpenFileName API; the callback entry is LPOFNHOOKPROC lpfnHook;, then elsewhere is the typedef UINT_PTR (CALLBACK *LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM);; that's just a lot more clear to me what is expected, and pretty much without exception how the Windows API is done.

    I got it right on my first guess how to do it (other than initially not realizing it was CDecl and trying other things for 2-3 minutes before trying that), so it's not like I was lost for hours, just a little different than my own experience.

    ----------------

    You should make a link to this in the VB6 getting the ball rolling thread. You are coming up with some great utils.
    Spurred on by the new life in TB64?
    I used to do lots of VB6 code bank projects. I've been wanting so many of the features tB offers for so many years... 64bit support, more language features, etc. Having those is so great I'm ok with the bugs and unimplemented stuff during beta, so tB is now my daily driver, and yes the new features do open up a few more options and reasons to do 64bit conversions, but mainly it's just replaced VB6 for me. If I use VB6 now, it's to test compatibility or backport something I think is so cool the people who haven't yet embraced tB should get to use it too

  5. #5
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,736

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Quote Originally Posted by fafalone View Post
    It's unusual in structure in terms of what I'm normally porting to VB/tB, the Windows API. The few places a callback is used in UDTs, the function is defined separately and the UDT definition makes it clear it's a function pointer to that definition, not just putting the definition in the UDT.

    Like take the GetOpenFileName API; the callback entry is LPOFNHOOKPROC lpfnHook;, then elsewhere is the typedef UINT_PTR (CALLBACK *LPOFNHOOKPROC) (HWND, UINT, WPARAM, LPARAM);; that's just a lot more clear to me what is expected, and pretty much without exception how the Windows API is done.

    I got it right on my first guess how to do it (other than initially not realizing it was CDecl and trying other things for 2-3 minutes before trying that), so it's not like I was lost for hours, just a little different than my own experience.
    Faf, maybe i wasn't clear enough or you misunderstood: I'm NOT critisizing you or your knowledge. On the contrary, you probably have more expierence than me with stuff like that.

    All said: Nicely done tool.

    The only thing weirding me out at first look was the listbox top-right, being alphanumerically sorted, which probably was pure happenstance that it was the correct order.
    It took me a few minutes to spot the "up"/"Down"-Buttons on the left of the Listbox...
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    No worries I hadn't taken it as a criticism, was just clarifying why I said it.

    The ListBox's initial order is just whatever the file dialog returns... if you sorted your open dialog by date, they'd be in that order. Windows defaults to sort by name, so it would be that unless you changed it.

  7. #7
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,509

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Quote Originally Posted by fafalone View Post
    I think is so cool the people who haven't yet embraced tB should get to use it too
    Agreed. When I am familiar and confident using TB64 generated utils. then ultimately I will eventually migrate myself, lock, stock and barrel. At the moment though I am in a great migration of my own, from javascript to VB6 along with a leap into getting my head around RC6. When that is finally complete I will take small steps toward TB64.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Just a heads up, you can use RC6 in tB, but Olaf hasn't and is very unlikely to make a 64bit version even if tB made it possible, so any RC6 project would be limited to 32bit in tB.

    tB has so, so much more to offer than 64bit, but just to let you know.

  9. #9
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,428

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Btw, RC6 recompile in TB could also get rid of all support DLLs baggage (sqlite, cairo) by embedding OBJ/LIB files directly into final Ax-DLL.

    cheers,
    </wqw>

  10. #10
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,509

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Quote Originally Posted by fafalone View Post
    Just a heads up, you can use RC6 in tB, but Olaf hasn't and is very unlikely to make a 64bit version even if tB made it possible, so any RC6 project would be limited to 32bit in tB.

    tB has so, so much more to offer than 64bit, but just to let you know.
    I suppose it is time to ask Olaf some questions on his roadmap. I'll try that and see how that goes. I am assuming that a 64bit version of RC6 will be on the cards especially when TB64 can be used to recompile his code. I can't see a technical reason why he wouldn't use it. I always assume he has his own plans and that he will eventually come up with something to surprise us all. He certainly has the brains.

    I have to move away from .js if I want to retain my 'widget' designs as working entities. I see 32bit VB6 with RC6 as an enabler to keep my graphical 'stuff' going. The resulting 32bit binaries are for me, no problem for the moment, I now call them WoW64! (sounds good, almost exciting, to the great unwashed).

    Ultimately though, I do want to build using TB64 to achieve a 64 bit binary, if that is possible by some sort of linking/embedding 32bit DLLs to produce 64 binaries - then that would be acceptable. IF not, then Olaf must know that he has to eventually come up with a 64bit set of DLLs. Possibly, he will come to the acceptance that TB64's workable existence meets his criteria for releasing his code as FOSS.

    Something will come along, I am sure of that. I am positive.

    I do have a TwinBasic 'question' that needs to be answered regarding transparent forms and click-through PNGs, what I have seen so far is basic legacy-style Windows forms and I would like to know whether TB64 has suitability for creation of non-standard, form less applications, graphical applications using partly transparent graphical controls with associated events and proper handling of click-throughs &c. My 'sort' of application that you have already seen. I am not expecting you to answer this question, I need to dig into TB64 myself and determine this.

    RC6 handles it well. Not perfectly in the way I have grown accustomed, but it does it. One just has to know how and realise that there are limitations/characteristics that have to be overcome using methods to which I have been previously unfamiliar. I'm getting there.
    https://github.com/yereverluvinunclebert

    Skillset: VMS,DOS,Windows Sysadmin from 1985, fault-tolerance, VaxCluster, Alpha,Sparc. DCL,QB,VBDOS- VB6,.NET, PHP,NODE.JS, Graphic Design, Project Manager, CMS, Quad Electronics. classic cars & m'bikes. Artist in water & oils. Historian.

    By the power invested in me, all the threads I start are battle free zones - no arguing about the benefits of VB6 over .NET here please. Happiness must reign.

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    There's no built in help for it but you could implement it the same way RC6 does. Or use OpenGL/DirectX. tB did however add a lot more transparency-related stuff lately; child control transparency and alpha blending taking advantage of Windows 8+ APIs.

    Olaf has the brains but he's not the most personable sort... seems quite unhappy Wayne didn't sign on to his vision and build tB's UI around RC6, so I wouldn't hold out much hope for 64bit RC6 until OlafBasic or whatever in 2050+. And then it probably won't be a standalone DLL that can be called from anywhere but built into his compiler/IDE.

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Critical update: Please download v1.0.6.2. The initial release contains a bug that truncates the last 2 bytes of PDFs read. This didn't result in any corrupt files in my tests, but it's highly likely to at some point. I apologize for the inconvenience.

    https://github.com/fafalone/gPdfMerge

  13. #13

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    6,257

    Re: [twinBASIC] gPdfMerge - A GUI-based PDF merger

    Project updated: v1.2

    Important: Starting with version 1.2, newer builds of pdfium.dll are used. These are obtained from https://github.com/bblanchon/pdfium-binaries/releases. Version 1.2 was tested with 128.0.6569.0 (01 Jul 2024), but newer versions should continue to work fine. Click 'Show all .. assets' to find the Windows versions; the file names you need are pdfium-win-x86.tgz and pdfium-win-x64.tgz. gPdfMerge v1.2+ will not work with the 2018-era original DLLs used with version 1.0.

    (Version 1.2 - 07 Jul 2024)
    -Adds a 'Search for pages' function which opens a new dialog you can use to search for a range of pages to merge:



    (Version 1.1)
    -Range entry textbox now only enabled if an item is selected.
    -Specifying a single pdf with page range to trim it now supported.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width