Página 1 de 2

GetDefaultPrinter()+PdfCreator

Enviado: 14 Nov 2007 07:35
por zefilho
Olá pessoal,

Tenho um sisitema que migrei para o xHarbour recentemente mas sem usar nenhuma lib gráfica.

Estou com o PdfCreator instalado numa máquina e configurado como impressora padrão.

A finalidade é poder visualizar o relatório antes de imprimir como tb poder salvar uma cópia localmente.

O código que estou usando é o seguinte :

Código: Selecionar todos

.....
Set Printer to (GetDefaultPrinter() )
Set Devi to Printer
Set Console off
Set printer on
@  1,1  Say Repli("-",77)
@  2,1  Say "GOVERNO DO ESTADO DA PARAIBA                               Data : "+Dtoc(Date())
@  3,1  Say "SISTEMA DE CADASTRO - PROGRAMA MEU TRABALHO                Hora : "+Left(Time(),5)
@  4,1  Say "HISTORICO DO CLIENTE                                       Pag. : 001"
@  5,1  Say Repli("-",77)
@  8,1  Say "                             H I S T O R I C O"
@ 11,1  Say TitRel
@ 13,1  Say "Situacao                         | Atualizacao | Usuario"
@ 14,1  Say "---------------------------------+-------------+------------------------------"
Lin:=15       
Do While !Eof()
   @ Lin,1  Say Situacao+" |"
   @ Lin,25 Say Dtoc(DtIncAlt) +" |"
   @ Lin,38 Say Usuario
   Lin++
   Skip
Enddo
@ Lin,1  Say "---------------------------------+-------------+------------------------------"
Set printer to
Set printer off
Set Console on
Set Devi to Screen
...............
O problema é que o PDF criado fica em branco!

Alguém poderia dar um HELP aí ?
(não estou usando nenhuma lib gráfica)

Enviado: 14 Nov 2007 12:56
por rochinha
Amiguinho

Se voce esta usando o modo console provavelmente os comandos de impressão atuarão de forma direta na impressora e o driver, por ser virtual não vai entender os comandos.

Faça a impressão e salve em arquivo e depois despeje o arquivo diretamente para a porta.

Enviado: 14 Nov 2007 14:53
por sygecom
ou se vc usar a classe win32prn ele vai gerar no automatico...

Manda um exmplo.

Enviado: 14 Nov 2007 16:07
por zefilho
Olá.. primeiramente muito obrigado pela atenção! :-)

Certo.. posso direcionar a impressão para um aqruivo .TXT usando :

Set printer to "Texto.txt"

Mas, depois de gerar o arquivo, como faço para mandar direto para a impressora virtual PdfCreator ?
Tentei com :

PrintFileRaw() <---- Prints a file to a Windows printer in RAW mode.

Mas não deu certo tb.


Se puder mostrar um código como mandar um arquivo .TXT para a impressora PdfCreator eu agradeço. :-)

Vlw

Win32prn

Enviado: 14 Nov 2007 16:11
por zefilho
Li no "xHarbour Refence Guide" que a class Win32Prn() não pode ser usada no modo console. :-(

"Description
Objects of class Win32Prn provide the means for printing using the Windows Graphical Device Interface (GDI). For this reason, an application using Win32Prn objects must be created as GUI application. Text mode applications, or console applications, cannot use the Win32Prn class.

Enviado: 14 Nov 2007 17:31
por sygecom
Depois de gerar o arquivo TXT use assim:

Código: Selecionar todos

PRIVATE cPrinter := PRINTERPORTTONAME( "PDF", .T. )
PrintFileRaw( cPrinter, "texto.txt", "Impressao do Sistema" )

PDF em branco!

Enviado: 15 Nov 2007 07:10
por zefilho
Não funciona.. o PDF fica em branco. :-(
Ser q tem de fazer alguma configuração no PdfCreator ?

Enviado: 15 Nov 2007 16:57
por rochinha
Amiguinho

E se voce despejar o conteudo do arquivo texto via write ou notepad, assim:

write arquivo.txt /p

ou

notepad arquivo.txt /p

Re: PDF em branco!

Enviado: 15 Nov 2007 17:49
por sygecom
zefilho escreveu:Não funciona.. o PDF fica em branco. :-(
Ser q tem de fazer alguma configuração no PdfCreator ?
Tche, eu instalei o PDFCREATOR aqui e fiz um teste e funcionou...posto como vc esta fazendo !!!

Mstra o código q vc usou.

Enviado: 15 Nov 2007 20:26
por zefilho
Estou usando assim apenas para testar :

Código: Selecionar todos

Function Main
PRIVATE cPrinter := PRINTERPORTTONAME( "PDF", .T. ) 
PrintFileRaw( cPrinter, "texto.txt", "Impressao do Sistema" ) 
return
e não dá certo.. o PDF fca em branco.

Meu msn é zefilhoguitarrista@hotmail.com

se puder, me add pra gente trocar uma idéia online... se der certo.. eu coloco o procedimento no forum.
Obg.

Consegui!

Enviado: 16 Nov 2007 05:55
por zefilho
Oi Leonardo,

Achei um post seu de agosto desse ano, usando a classe Win32Prn().
Fiz algumas adaptações e está dando certo!

Não tinha tentado com essa classe porque no próprio Guia de Referência do xHarbour vem dizendo que não pode ser usada em modo console.

Mas pode sim!!! rs

Estou fazendo uns testes e logo colacarei aqui os meus reultados.
Muito obrigado pelas dicas.

Grande abraço.

Zé Filho
www.zefilho.com.br

Enviado: 18 Nov 2007 10:06
por zefilho
Olá,

Consegui gerar o PDF e estou usando um programinha feito com a MINIGUI chamado "PDFReader" que usa a classe TActivex para abrir e visualizar o PDF com o Abobe.

A vantagem deste programa é q a janela que abre o PDF pode ser personalizada e tal.

MAs estou agora com o seguinte problema : Quando fecho a janela de exibição do PDF, o processo Acrord32.exe não é encerrado.

Alguém já teve esse problema ??

Enviado: 18 Nov 2007 14:46
por rochinha
Amiguinho

Voce pode postar aqui o codigo MiniGUI em que voce faz acesso Activex para eu dar uma olhada, pois uso Activez e OLE com Fivewin e gostaria de vee as diferenças.

Em relação a não fechar voce esta usando END() ou QUIT() para finalizar o processo?

Enviado: 18 Nov 2007 17:49
por zefilho
Rochinha,

A classe TAcvtivex() não possui os métodos end(), close() ou quit().

Pelo menos no arquivo TAxPrg.prg que tem na pasta C:\MiniGUI\SAMPLES\Advanced\PDFReader da MINIGUI que baixei.

Eu crio o arquivo PDF usando a PDFLib da contrib e em seguida chamo a função PdfReader(ArqPDF).

O código do PdfReader.prg está assim :

Código: Selecionar todos

SET PROCEDURE TO "TAxPrg.prg"
#include "minigui.ch"
STAT oWActiveX
STAT oActiveX
DECLARE WINDOW FORMPDFReader
FUNCTION PDFReader(cFilePdf)
SET NAVIGATION EXTENDED
DEFINE WINDOW FORMPDFREADER ; 
   AT 0, 0 ; 
   WIDTH 800 HEIGHT 800 ; 
   TITLE "MTRAB.NET - PDF Reader"; 
   NOSIZE; 
   NOMAXIMIZE; 
   NOMINIMIZE; 
   MAIN ; 
   ICON 'ADOBE.ICO' ; 
   ON INIT fOpenActivex(cFilePDF) ; 
   ON RELEASE fCloseActivex() 
END WINDOW 


E o código das funções fOpenActivex() e fCloseActivex() é o seguinte :

Código: Selecionar todos

Static FUNCTION fOpenActivex(cFilePdf) 
LOCAL cPDF:=cFilePdf 
IF FILE(cPDF) 
   oWActiveX := TActiveX():New(ThisWindow.Name, ; 
                                               "AcroPDF.PDF.1", ; 
                                                0, ; 
                                                0, ; 
                                                GetProperty(ThisWindow.Name, "width") - 02 * GetBorderWidth() - 1 , ; 
                                                GetProperty(ThisWindow.Name, "height") - 05 * GetBorderHeight() - ; 
                                                GetTitleHeight() - ; 
                                                GetMenuBarHeight() ) 

   oActiveX := oWActiveX:Load() 
   oActiveX:LoadFile(cPDF) 
ELSE 
   MsgStop("Arquivo PDF não encontrado.") 
   FORMPDFREADER.Release() 
ENDIF
Return NIL
*--------------------------------------------------
Stat FUNCTION fCloseActivex() 
IF VALTYPE(oWActivex) <> "U" .AND. VALTYPE(oActivex) <> "U" 
   oWActivex := Nil 
   oActivex := Nil 
ENDIF
Return NIL


Desse jeito, a janela é encerrada mas o processo AcroRd32.exe não.

A aplicação está rodando num TS e sendo acessada através de clientes win xp usando a Internet.
Acontece que a conexão não é encerrada assim que o programa é fechado pq o processo AcroRd32.exe fica sendo executado ainda.

Qual a solução pra isso ???

Segue abaixo o código do TAxPrg.prg p vc dar uma analizada.

Código: Selecionar todos

#include "hbclass.ch"
#ifndef __XHARBOUR__
   #xcommand TRY                => bError := errorBlock( {|oError| break( oError ) } ) ;;
                                   BEGIN SEQUENCE
   #xcommand CATCH [<!oError!>] => errorBlock( bError ) ;;
                                   RECOVER [USING <oError>] <-oError-> ;;
                                   errorBlock( bError )
#endif

CLASS TActiveX
   DATA oOle
   DATA hWnd
   DATA cWindowName
   DATA cProgId
   DATA nRow
   DATA nCol
   DATA nWidth
   DATA nHeight
   DATA nOldWinWidth
   DATA nOldWinHeight
   DATA bHide INIT .F.
   METHOD New( cWindowName, cProgId , nRow , nCol , nWidth , nHeight )
   METHOD Load()
   METHOD ReSize( nRow , nCol , nWidth , nHeight )
   METHOD Hide()
   METHOD Show()
   METHOD Release()
   METHOD Refresh()
   METHOD Ajust()
   METHOD GetRow()
   METHOD GetCol()
   METHOD GetWidth()
   METHOD GetHeight()
ENDCLASS

METHOD New( cWindowName , cProgId , nRow , nCol , nWidth , nHeight ) CLASS TActiveX
   if( empty( nRow )    , nRow    := 0                              , )
   if( empty( nCol )    , nCol    := 0                              , )
   if( empty( nWidth )  , nWidth  := GetProperty( cWindowName , "width" ) , )
   if( empty( nHeight ) , nHeight := GetProperty( cWindowName , "Height" ) , )
   ::nRow := nRow
   ::nCol := nCol
   ::nWidth := nWidth
   ::nHeight := nHeight
   ::cWindowName := cWindowName
   ::cProgId := cProgId
   ::nOldWinWidth := GetProperty( cWindowName , "width" )
   ::nOldWinHeight := GetProperty( cWindowName , "Height" )
Return Self

METHOD Load() CLASS TActiveX
   local oError, bError
   local nHandle := GetFormHandle(::cWindowName)
   local xObjeto
   local OCX_Error := 0
   AtlAxWinInit()
   ::hWnd := CreateWindowEx( nHandle, ::cProgId )
   MoveWindow( ::hWnd , ::nCol , ::nRow , ::nWidth , ::nHeight , .t. )
   xObjeto := AtlAxGetDisp( ::hWnd )
   TRY
      ::oOle := CreateObject( xObjeto )
   CATCH
      MsgInfo( oError:description )
   END
RETURN ::oOle

METHOD ReSize( nRow , nCol , nWidth , nHeight ) CLASS TActiveX
   if !::bHide
      MoveWindow( ::hWnd , nCol , nRow , nWidth , nHeight , .t. )
   endif
   ::nRow := nRow
   ::nCol := nCol
   ::nWidth := nWidth
   ::nHeight := nHeight
   ::nOldWinWidth := GetProperty( ::cWindowName , "width" )
   ::nOldWinHeight := GetProperty( ::cWindowName , "Height" )
RETURN .T.

METHOD Ajust() CLASS TActiveX
   Local nAuxRigth , nAuxBottom
   nAuxRigth := ( ::nOldWinWidth - ( ::nWidth + ::nCol ) )
   nAuxBottom := ( ::nOldWinHeight - ( ::nHeight + ::nRow ) )
   MoveWindow( ::hWnd , ::nCol , ::nRow , GetProperty( ::cWindowName , "width" ) - ::nCol - nAuxRigth , GetProperty( ::cWindowName , "height" ) - ::nRow - nAuxBottom , .t. )
   ::nWidth := GetProperty( ::cWindowName , "width" ) - ::nCol - nAuxRigth
   ::nHeight := GetProperty( ::cWindowName , "height" ) - ::nRow - nAuxBottom
   ::nOldWinWidth := GetProperty( ::cWindowName , "width" )
   ::nOldWinHeight := GetProperty( ::cWindowName , "Height" )
RETURN .T.

METHOD GetRow() CLASS TActiveX
RETURN ::nRow

METHOD GetCol() CLASS TActiveX
RETURN ::nCol

METHOD GetWidth() CLASS TActiveX
RETURN ::nWidth

METHOD GetHeight() CLASS TActiveX
RETURN ::nHeight

METHOD Hide() CLASS TActiveX
   MoveWindow( ::hWnd , 0 , 0 , 0 , 0 , .t. )
   ::bHide := .T.
RETURN .T.

METHOD Show() CLASS TActiveX
   MoveWindow( ::hWnd , ::nCol , ::nRow , ::nWidth , ::nHeight , .t. )
   ::bHide := .F.
RETURN .T.

METHOD Release() CLASS TActiveX
   AtlAxWinEnd()
   DestroyWindow( ::hWnd )
RETURN .T.

METHOD Refresh() CLASS TActiveX
   ::Hide()
   ::Show()
RETURN .T.

/*-----------------------------------------------------------------------------------------------*/
#pragma BEGINDUMP
#include <windows.h>
#include <commctrl.h>
#include <hbapi.h>
#include <hbvm.h>
#include <hbstack.h>

typedef HRESULT ( WINAPI *LPAtlAxWinInit )    ( void );
typedef HRESULT ( WINAPI *LPAtlAxGetControl ) ( HWND hwnd, IUnknown** unk );

HMODULE hAtl = NULL;
LPAtlAxWinInit    AtlAxWinInit;
LPAtlAxGetControl AtlAxGetControl;

static void _Ax_Init( void )
{
   if( ! hAtl )
   {
      hAtl = LoadLibrary( "Atl.Dll" );
      AtlAxWinInit    = ( LPAtlAxWinInit )    GetProcAddress( hAtl, "AtlAxWinInit" );
      AtlAxGetControl = ( LPAtlAxGetControl ) GetProcAddress( hAtl, "AtlAxGetControl" );
      ( AtlAxWinInit )();
   }
}

HB_FUNC( ATLAXWININIT )
{
   _Ax_Init();
}

HB_FUNC( ATLAXWINEND )
{
   if( hAtl )
      FreeLibrary( hAtl );
}

HB_FUNC( ATLAXGETDISP ) // hWnd -> pDisp
{
   IUnknown *pUnk;
   IDispatch *pDisp;
   _Ax_Init();
   AtlAxGetControl( (HWND)hb_parnl( 1 ), &pUnk );
   pUnk->lpVtbl->QueryInterface( pUnk, &IID_IDispatch, ( void ** ) &pDisp );
   hb_retnl( (LONG)pDisp );
}

HB_FUNC_STATIC( CREATEWINDOWEX ) // hWnd, cProgId -> hActiveXWnd
{
   HWND hControl;
   hControl = CreateWindowEx( 0, "AtlAxWin", hb_parc( 2 ),
              WS_VISIBLE|WS_CHILD, 0, 0, 0, 0, (HWND)hb_parnl( 1 ), 0, 0, NULL );
   hb_retnl( (LONG) hControl );
}

#pragma ENDDUMP

Enviado: 18 Nov 2007 18:19
por rochinha
Amiguinho

Coloque uma critica ou alerta na fCloseActivex(0 e ao fechar veja se lhe é apresentado algo. Talvez esteja passando batido por este codigo.

Outra coisa:

Quando voce aciona via Activex um controle qualquer, todos os métodos deste controle passam a ser controlados pelo usuário.

Neste trecho voce esta usando o método LOAD() do controle Acrobat e não da classe Activex:

Código: Selecionar todos

oWActiveX:Load() 
Portanto se voce acionar o método CLOSE(), END() ou QUIT() através da classe, voce estara acionando os métodos do controle Acrobat que provavelmente possuem um destes métodos.

Portanto, acho que o codigo abaixo será válido:

Código: Selecionar todos

oWActiveX:End() 
Ou o máximo que irá ocorrer é erro de método inexistente.

Baixe da net o utilitário ActiveXXX, que permite visualizar métodos e eventos de vários controles.

Agora verifique se ao acionar várias vezes o controle, vários processos são abertos, pois se isto acontecer, será um grave problema.

Se apenas um se mantiver, fique sossegado pois será uma espécie de serviço em modo espera, para agilizar outros processos.