Change default printer works only once

This one is weird...

I use the followin function to change my default printer:

FUNCTION SetaImpDefa(imp,muda)
Declare long WriteProfileString in "kernel32" ;
string lpszSection, string lpszKeyName, string lpszString

Declare long SendMessage in "user32" ;
long hwnd, long wMSg, long wParam, String lParam

if muda
HWND_BROADCAST = -1
WM_WININICHANGE = 26
endif

printer_name = imp
printer_buffer = space(200)
*
len_ret = GetProfileString("PrinterPorts", printer_name, "", ;
@printer_buffer, Len(printer_buffer))
printer_buffer = left(printer_buffer,len_ret)
*
printer_driver = left(printer_buffer,at(',',printer_buffer)-1)
printer_buffer = substr(printer_buffer,at(',',printer_buffer)+1)
*
printer_port = left(printer_buffer,at(',',printer_buffer)-1)
*
new_printer_default = printer_name + "," + printer_driver + "," + printer_port
updated = WriteProfileString("Windows","device",new_printer_default)
*
if muda and updated = 1
SendMessage(HWND_BROADCAST,WM_WININICHANGE,0,"windows")
endif

return updated

endfunc


I call it twice on my code like this

setaImpDefa(text_only_printer,.t.)
PrintJob
Inicio
Items
Fim
EndPrintJob
setaImpDefa(laser_printer,.t.)

Where text_only_printer and laser_printer are strings containing printer names. (Inicio, Items and Fim are strings with printer comands and text to be printed).


Ok, the first time it works fine and the text goes to my text-only printer. Problem is, when I try to print a report afterwards, it also goes to the text-only printer, not to the laser printer. Wierdest thing is, it does change the default printer on Windows, only Fox doesn't seem to recognize it.

Anyone has any idea what I should be looking for
Thanks in advance.


Answer this question

Change default printer works only once

  • Donaghy

    I tried your code, and I still have the same problem...

    It's strange: It does chage the Windos Default printer, only my VFP program still tries to print to the text_only_printer

  • James Miles

    Well, since you're printing directly, I think you may use this code:
    Copy the Code to a PRG and then runnit:

    Declare Integer OpenPrinter In WinSpool.DRV As OpenPRN String, Integer @, Integer
    Declare Integer StartDocPrinter In WinSpool.DRV As StartDocPRN Integer, Integer, String @
    Declare Integer StartPagePrinter In WinSpool.DRV As StartPagePRN Integer
    Declare Integer WritePrinter In WinSpool.DRV As WritePRN Integer, String, Integer, Integer @
    Declare Integer EndPagePrinter In WinSpool.DRV As EndPagePRN Integer
    Declare Integer EndDocPrinter In WinSpool.DRV As EndDocPRN Integer
    Declare Integer ClosePrinter In WinSpool.DRV As ClosePRN Integer
    Declare Integer GlobalFree In Win32API Integer
    Declare Integer GlobalAlloc In Win32API Integer, Integer
    Declare RtlMoveMemory In Win32API As Str2Heap Integer, String @, Integer

    hPrinter =OpenST("Generica / So Texto")
    =LineST(hPrinter, "Isto e um Teste")
    =CloseST(hPrinter)
    Clear DLLs

    *********************************************************************************
    * Open The Printer via Windows API *
    *********************************************************************************
    Function OpenST (NomePRN)
    Store 0 To hPrinter, nRetornoAPI
    && Start Printer...
    nRetornoAPI =OpenPRN(NomePRN, @hPrinter, 0)
    If Empty(nRetornoAPI) Then
    =Messageb([Printer "] + Upper(AllTr(NomePRN)) + [" not found.], 48)
    Return
    EndIf
    oDocName =CreateObj("PChar", "Documento")
    sDocInf =oDocName.sMem + Replic(Chr(0), 8)
    =StartDocPRN(hPrinter, 1, @sDocInf)
    =StartPagePRN(hPrinter)
    Release oDocName, nRetornoAPI
    Return hPrinter
    EndFunc

    *********************************************************************************
    * Send Data to Printer via Windows API
    *********************************************************************************
    Procedure LineST (phPrinter, pcString)
    nGuarda =Len(pcString)
    nGuarda =WritePRN(phPrinter, pcString, nGuarda, @nGuarda)
    If Empty(nGuarda) Then
    =Messageb("Cannot send Data to the Printer.", 48)
    =CloseST(phPrinter)
    EndIf
    EndProc

    ******************************************************************************
    * Close the Printer Job
    ******************************************************************************
    Function CloseST (hnPRN)
    =EndPagePRN(hnPRN)
    =EndDocPRN(hnPRN)
    =ClosePRN(hnPRN)
    EndFunc

    *********************************************************************************
    * Transform a DWord (Integer - 32 bits) in a String
    *********************************************************************************
    Function DWord2Str (pInteiro)
    Return Chr(Mod(pInteiro, 256)) + Chr(Mod(pInteiro, 65536)/256) + ;
    Chr(Mod(pInteiro, 256^3)/65536) + Chr(Mod(pInteiro, 256^4)/256^3)
    EndFunc

    *********************************************************************************
    * Pointer Class
    *********************************************************************************
    Define Class PChar As Custom
    hMem =0
    sMem =Replic(Chr(0), 4)
    Procedure Destroy
    =GlobalFree(This.hMem)
    EndProc
    Procedure Init (lcString)
    lcString =lcString + Chr(0)
    lnSize =Len(lcString)
    This.hMem =GlobalAlloc(0, lnSize)
    If !Empty(This.hMem) Then
    =Str2Heap(This.hMem, @lcString, lnSize)
    This.sMem =DWord2Str(This.hMem)
    EndIf
    EndProc
    EndDefine




  • james_cline_

    I don't know function GetProfileString but the returned value should be a integer.

    I ran your code on my computer and it is working fine. I did not use GetProfileString and I am using Vfp 9 SP1.



  • Cammyr

    >>It does chage the Windos Default printer, only my VFP program still tries to print to the text_only_printer

    Sounds like you have the output printer saved in the report. You may need to clear out the fields that save the printer with the report definition (off the top of my head I think it is EXPR, TAG and TAG2 in the first record in the FRX file). When you create a report, ensure that you do not save the printer enviornment with it.



  • Swimmer84

    Hi,
    I Have this code to change and restore the Default Printer Driver.
    The code was written in VFP5 and tested in VFP6.

    Procedure DefaultPrn (pOldPrn, pNewPrn)
    && If pOldPrn is empty (""), we want to restore the last default printer stored in a variable.
    && pNewPrn, should have the format: "<printer name>,WINSPOOL,<port>:"
    && if the format is not given, no printer is defined.
    If !Empty(pOldPrn) Then
    If Type(pOldPrn) ="U" Then
    Public &pOldPrn
    EndIf
    EndIf
    Local nAPIReturn, cBuffer
    cBuffer =Replicate(Chr(0), 255)
    && Get the current default printer and store it in the public variavel &pOldPrn...
    Declare Integer GetProfileString In Kernel32 String, String, String, String @, Integer
    nAPIReturn =GetProfileString("Windows", "device", ",,,", @cBuffer, 255)
    &pOldPrn =Left(cBuffer, nAPIReturn)
    && Setup the new printer...
    If !Empty(AllTr(pNewPrn)) Then
    Declare Integer WriteProfileString In Kernel32 String, String, String
    nAPIReturn =WriteProfileString("Windows", "device", pNewPrn)
    && this will make the printer shows as default in Windows...
    && other programs must wait 1 second to get the new printer
    Declare Integer SendMessageTimeout In User32 Integer, Integer, Integer, String, Integer, Integer, String
    && 0xFFFF = Inform all open Applications (HWnd_BroadCast)
    && 0x1A = Wait for the registry update (Wm_WinINIChange)
    && 0x0 = normal behavior (SMTo_Normal)
    If At("NT", OS()) >0 Then && Windows NT
    =SendMessageTimeout(0xFFFF, 0x1A, 0, "", 0x0, 1000, NULL) && 1000 = 1 Sec.
    Else
    =SendMessageTimeout(0xFFFF, 0x1A, 0, "windows", 0x0, 1000, NULL)
    EndIf
    EndIf
    Clear DLLs
    && It should return 1 (OK).
    Return nAPIReturn
    EndProc

    Hope this helps you.
    Works for me in Win98/2000/XP using VFP6.




  • dpoon

    Yes, GetProfileString returns an integer. What did you use instead of that

    I'm runing a VFP 6.0, maybe that's the problem...

  • Change default printer works only once