Hello,
Could anybody help me here. I want to show a pdf file in my application. It should not be inside the application. Calling the pdf assosiated program is ok.
Thanks for any help.
Marc
ShellExecute API should work. I use: ShellExecute(HWND_FORM, ByVal 0, fileToOpenZ, ByVal 0, ByVal 0, %SW_Show)
I just love this forum!!!
Thank you very much Roger.
Marc
I use the Foxit Reader SDK ActiveX component which is free from Foxit.com They also have a version that you have to pay for with more features. But the free version is a full featured PDF reader that you can incorporate into any application. I use it as a control in a form. Works very well.
Robert
As in " www.foxitsoftware.com "?
Exactly! On the download site they have the developer kit.
http://www.foxitsoftware.com/downloads/index.php
I got a Dev license of Quick PDF a few years back with plans to convert to PB, but it never panned out. Looks like they changed yet again and started their own site wanting money to upgrade to the most recent. One other trick I thought of was putting a browser window in your app and opening it with the browser which if linked should put Acrobat inside the browser.
Here is a PB program to display a .PDF Its a .exe for testing but I use it as a .dll
At least it will point you in the correct direction. NOTE this works with Acrobat 6, haven't tested it with other versions.
You don't need any 3rd party stuff. The acrobat reader installs any .dll's called and that's free..............
Doug
#COMPILE EXE
#INCLUDE "WIN32API.INC"
DECLARE FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
%WM_FORWARDMSG = &H37F ' (895)
%IDC_PDF = 1001
' *********************************************************************************************
DECLARE FUNCTION AtlAxWinInit LIB "ATL.DLL" ALIAS "AtlAxWinInit" () AS LONG
' *********************************************************************************************
DECLARE FUNCTION AtlAxWinTerm () AS LONG
' *********************************************************************************************
FUNCTION AtlAxWinTerm () AS LONG
UnregisterClass ("AtlAxWin", GetModuleHandle(BYVAL %NULL))
END FUNCTION
' *********************************************************************************************
' **********************************************************************************************
DECLARE FUNCTION AtlAxGetControl LIB "ATL.DLL" ALIAS "AtlAxGetControl" _
( _
BYVAL hWnd AS DWORD, _ ' [in] A handle to the window that is hosting the control.
BYREF pp AS DWORD _ ' [out] The IUnknown of the control being hosted.
) AS DWORD
' *********************************************************************************************
' *********************************************************************************************
' Puts the address of an object in a variant and marks it as containing a dispatch variable
' *********************************************************************************************
SUB AtlMakeDispatch ( _
BYVAL lpObj AS DWORD, _ ' Address of the object instance
BYREF vObj AS VARIANT _ ' Variant to contain this address
) EXPORT
LOCAL lpvObj AS VARIANTAPI PTR ' Pointer to a VARIANTAPI structure
LET vObj = EMPTY ' Make sure is empty to avoid memory leaks
lpvObj = VARPTR(vObj) ' Get the VARIANT address
@lpvObj.vt = %VT_DISPATCH ' Mark it as containing a dispatch variable
@lpvObj.vd.pdispVal = lpObj ' Set the dispatch pointer address
END SUB
' *********************************************************************************************
' *********************************************************************************************
' Program entrance
' *********************************************************************************************
FUNCTION WINMAIN (BYVAL hInst AS DWORD, BYVAL hPrevInstance AS DWORD, _
BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
LOCAL hDlg AS DWORD
LOCAL hPdf AS DWORD
LOCAL wcex AS WndClassEx
LOCAL szClassName AS ASCIIZ * 256
LOCAL szTitle AS ASCIIZ * 256
LOCAL rc AS RECT
LOCAL pUnk AS DWORD
LOCAL oPdf AS DISPATCH
LOCAL vVar AS VARIANT
szClassName = "sk_pdf01"
wcex.cbSize = SIZEOF(wcex)
wcex.style = 0 '%CS_DBLCLKS OR %CS_HREDRAW OR %CS_VREDRAW
wcex.lpfnWndProc = CODEPTR(WndProc)
wcex.cbClsExtra = 0
wcex.cbWndExtra = 0
wcex.hInstance = hInst
wcex.hCursor = LoadCursor (%NULL, BYVAL %IDC_ARROW)
wcex.hbrBackground = %COLOR_3DFACE + 1
wcex.lpszMenuName = %NULL
wcex.lpszClassName = VARPTR(szClassName)
wcex.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION)
wcex.hIconSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION)
CALL RegisterClassEx (wcex)
SystemParametersInfo %SPI_GETWORKAREA, 0, BYVAL VARPTR(rc), 0
szTitle = "PDF Test"
hDlg = CreateWindowEx (%WS_EX_CONTROLPARENT, szClassName, szTitle, _
%WS_OVERLAPPEDWINDOW, rc.nLeft, rc.nTop, rc.nRight - rc.nLeft + 2, _
rc.nBottom - rc.nTop + 1, 0, 0, hInst, BYVAL %NULL)
AtlAxWinInit ' // Initializes ATL
GetClientRect hDlg, rc
hPdf = CreateWindowEx(0, "AtlAxWin", "PDF.PdfCtrl.5", _
%WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %WS_BORDER, _
rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, _
hDlg, %IDC_PDF, hInst, BYVAL %NULL)
AtlAxGetControl(hPdf, pUnk)
AtlMakeDispatch(pUnk, vVar)
SET oPdf = vVar
'*****pass the file name you want***********
vVar = "c:\audiofile\cfa_635_v1.4.pdf" ' "D:\TTDS\Server_v1-2.pdf" ' <-- change
OBJECT CALL oPdf.LoadFile(vVar)
SetFocus hPdf
ShowWindow hDlg, nCmdShow
UpdateWindow hDlg
OBJECT CALL oPdf.PrintWithDialog
LOCAL uMsg AS tagMsg
WHILE GetMessage(uMsg, %NULL, 0, 0)
TranslateMessage uMsg
DispatchMessage uMsg
WEND
AtlAxWinTerm ' // Uninitializes ATL
SET oPdf = NOTHING
FUNCTION = uMsg.wParam
END FUNCTION
' *********************************************************************************************
' *********************************************************************************************
' Main Window procedure
' *********************************************************************************************
FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
LOCAL rc AS RECT
SELECT CASE wMsg
CASE %WM_SIZE
MoveWindow GetDlgItem(hWnd, %IDC_PDF), 0, 0, LOWRD(lParam), HIWRD(lParam), %TRUE
FUNCTION = 0 : EXIT FUNCTION
CASE %WM_DESTROY
PostQuitMessage 0
FUNCTION = 0 : EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
END FUNCTION
' ***************
That is an old example I posted in August 2003. The AtlMakeDispatch funcion it uses is not suitable for the new compilers because it does not increment the reference count (I had to do it this way because of a bug in PB 7.0). When PB 8.x was released, I posted the following modification in the next message of the same thread (in September, 2005):
Quote
With the PBWin 8.x compiler, when the "home made" dispatch variant goes
out of scope, is set to empty or you assign a new value to it, the
reference counter is decreased, so we need to increment the count with
IUnknown_AddRef to keep the reference count balanced.
Just replace the AtlMakeDispatch procedure with the following:
' ********************************************************************************************
' The IUnknown::AddRef method increments the reference count for an interface on an object. It
' should be called for every new copy of a pointer to an interface on a given object.
' ********************************************************************************************
FUNCTION IUnknown_AddRef (BYVAL pthis AS DWORD PTR) AS DWORD
LOCAL DWRESULT AS DWORD
IF ISFALSE pthis THEN EXIT FUNCTION
CALL DWORD @@pthis[1] USING IUnknown_AddRef(pthis) TO DWRESULT
FUNCTION = DWRESULT
END FUNCTION
' ********************************************************************************************
' *********************************************************************************************
' Puts the address of an object in a variant and marks it as containing a dispatch variable
' *********************************************************************************************
SUB AtlMakeDispatch (BYVAL lpObj AS DWORD, BYREF vObj AS VARIANT) EXPORT
LOCAL lpvObj AS VARIANTAPI PTR ' Pointer to a VARIANTAPI structure
LET vObj = EMPTY ' Make sure is empty to avoid memory leaks
lpvObj = VARPTR(vObj) ' Get the VARIANT address
@lpvObj.vt = %VT_DISPATCH ' Mark it as containing a dispatch variable
@lpvObj.vd.pdispVal = lpObj ' Set the dispatch pointer address
IUnknown_AddRef lpObj ' Increment the reference counter
END SUB
' *********************************************************************************************
It should be noted that hosting Acrobat Reader directly you will experience some repainting problems. Because this control has been designed to work mainly with Internet Explorer, I found that it was a better way to use ATL or my OLE container to host the WebBrowser control and then use it to load the .pdf file.
For those using my include files, there are a couple of examples in my forum that illustrate how to do it: the first one using ATL, the second one using my OLE Container.
WebBrowser Control: Embedding Acrobat Reader
http://www.jose.it-berater.org/smfforum/index.php?topic=2710.0
Foxit doesn't have a very interesting pricing model on the SDK!
Not anymore - they used to have the basic edition for free.
Jose,
I know this is an old thread but somehow I missed it. I just want to say thanks for explaining the code was for pb7. and you have modified it since then. As you can guess It worked perfectly as it is in use everyday. If i have the need I'll change my code to reflect your changes. But...if its not broke don't fix it.
BTW, at the top of the code, header, I did give you credit. I should have pasted that also. Sorry
Thank you
Doug
Foxit does have a free PDF reader that is a good replacement for the Acrobat reader. It is much faster and takes up a lot less resources (disk space, memory, etc.). It comes with an OCX that can be used in FireFly or even VB. I have used it successfully. They also sell an SDK and they used to give a free eval, but no more. Just use the OCX that comes with their free reader and it works great with FireFly.
Robert