'===========================================================================
' Subject: Set Default Printer                Date: 06-14-02 (  :  )       
'  Author: Fred Buffington                    Code: PBDLL                  
'  Origin: oasys@sbcglobal.net              Packet: PBDLL.ABC
'===========================================================================
'PACKET: PBDLL.ABC 
'COMPILER: PBDLL 6.0 up 
'AUTHOR: Pierre Bellisle - modified for command line by 
'Fred Buffington - oasys@sbcglobal.net 
'DATE: 05/05.2003 
'Pierre Bellisle 
'bellisle@vif.com 
'--------------------------------------------------------------------------------

'The need for this grew out of a network using another 
'OS and windows as clients on this other OS. 
 
'The workstations on this other OS could have local printers 
'(connected to the other OS physically) and/or remote printers 
'(which to the windows workstation are local or network printers). 
 
'The trouble is only 1 remote printer on the other OS can be used 
'(others could be attached but it goes to the same place). 
 
'The other OS sends the report and whatever printer is the default for the workstation. 
 
'So, if you wanted to print to a different printer you had to change 
'it in the workstation software (which is easy enough but an extra step). 
'This program changes the default printer 
'on the windows machine and has an optional "command line" 
'ability so that in conjuntion with some other software i wrote i can change the default printer on the workstation, if needed, 
'and send the report to the specified printer without the user 
'making a change other that selecting the printer on the other OS. 
 
'At first I used a free downloaded program to change the default printer. This works fine but is 126K. 
 
'The compiled code here comiles to 27K on PB 6.11 
 
'Thanks to Pierre Bellisle for most of the code. 
'I added the option for the modeless dialog and command line 
'process (a minor part). 
 
 
'Routine to set Windows default printer, 
'works under 95/98/Me/NT/2000/XP. 
 
#COMPILE EXE             '#Win 702# 
#DIM ALL 
#INCLUDE "Win32Api.Inc"  '2003-03-27 
 
$AppName         = "PrinterSelect" 
 
%FramePS         = 1001 
%ButtonSetPS     = 1002 
%ButtonInfoPS    = 1003 
%ButtonExitPS    = 1004 
%ListboxPS       = 1005 
%LabelPS         = 1006 
 
%PAll            = 1 
%PName           = 2 
%PDriver         = 3 
%PPort           = 4 
%PNonSelect      = 5 
%PRetry          = 6 
%MaxPrinterCount = 20 
 
'-------------------------- 
'my added global fcb. 
GLOBAL dialogistrue& 
'------------------------- 
GLOBAL hDlg              AS LONG 
GLOBAL lResult           AS LONG 
GLOBAL hList             AS DWORD 
GLOBAL PrinterDefault    AS LONG 
GLOBAL PrinterDefaultOld AS LONG 
GLOBAL PrinterCount      AS LONG 
GLOBAL PList()           AS STRING 
'_______________________________________________________________________ _______ 
 
'------------------------------ 
'set the default printer here 
'------------------------------ 
SUB SetPrinterDefault() 
 LOCAL OsInfo      AS OSVERSIONINFO 
 LOCAL PD          AS PRINTER_DEFAULTS 
 LOCAL PI5         AS PRINTER_INFO_5 
 LOCAL DeviceLine  AS STRING 
 LOCAL Win         AS STRING 
 LOCAL PrinterName AS STRING 
 LOCAL hPrinter    AS LONG 
 LOCAL Need        AS LONG 
 LOCAL LastError   AS LONG 
 LOCAL Retval      AS LONG 
 
 OsInfo.dwOsVersionInfoSize = SIZEOF(OsInfo) 
 GetVersionEx OsInfo 
 
 IF OsInfo.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS THEN 'Windows 95/98/Me 
 
   'Get the selected printer 
   PrinterName = PList(PrinterDefault, %PName) 
   IF PrinterName = "" THEN 
     MSGBOX "Win 9x error: No printer specified !", _
	%MB_ICONERROR OR %MB_OK, $AppName 
     EXIT SUB 
   END IF 
 
   'Set the PRINTER_DEFAULTS members 
   PD.pDatatype = 0& 
   PD.DesiredAccess = %PRINTER_ALL_ACCESS OR PD.DesiredAccess 
 
   'Get an handle to the printer 
   Retval = OpenPrinter(BYCOPY PrinterName, hPrinter, PD) 
   IF Retval = 0 THEN 
     MSGBOX "Win 9x error: " & PrinterName & " is not a valid printer !", _
	%MB_ICONERROR OR %MB_OK, $AppName 
     EXIT SUB 
   END IF 
 
   'Check how many bytes we need 
   Retval = GetPrinter(hPrinter, 5, BYVAL 0, BYVAL 0, Need) 
   REDIM PArray((Need \ 4)) AS LONG 
 
   'Get info 
   Retval = GetPrinter(hPrinter, 5, PArray(0), Need, Need) 
   IF Retval = %False THEN 
     MSGBOX "Win 9x error: " & STR$(Retval) & " bytes unavaible !", _
	%MB_ICONERROR OR %MB_OK, $AppName 
     EXIT SUB 
   END IF 
 
   PI5.pPrinterName             = PArray(0) 
   PI5.pPortName                = PArray(1) 
   PI5.Attributes               = PArray(2) 
   PI5.DeviceNotSelected        = PArray(3) 
   PI5.TransmissionRetryTimeout = PArray(4) 
   PI5.Attributes               = %PRINTER_ATTRIBUTE_DEFAULT 'This make it the default printer 
   Retval = SetPrinter(hPrinter, BYVAL 5, BYVAL VARPTR(PI5), BYVAL 0) 
   IF Retval = 0 THEN 
       MSGBOX "SetPrinter failed" 
       EXIT SUB 
   END IF 
 
   ClosePrinter hPrinter 
 
 ELSE 'Windows NT/2000/XP 
 
   DeviceLine = PList(PrinterDefault, %PName)   & "," & _ 
                PList(PrinterDefault, %PDriver) & "," & _ 
                PList(PrinterDefault, %PPort) 
 
   'Store WIN.INI, [WINDOWS], DEVICE = 
   Retval = WriteProfileString("windows", "Device", BYCOPY DeviceLine) 
 
   'Cause all applications to reload the INI file 
   Win = "Windows" 
   Retval = SendMessage(%HWND_BROADCAST, %WM_WININICHANGE, 0, BYCOPY VARPTR(Win)) 
 
 END IF 
END SUB 
'_______________________________________________________________________ _______ 
 
FUNCTION GetPrinterDefault() AS STRING 
 LOCAL zPrinterDefault AS ASCIIZ * 255 
 
 'Will return something like...     Epson LQ-500=EPSON24,LPT1:,15,45 
 '                                  Printer Name=Driver,Port,NonSelect,Retry 
 GetProfileString "WINDOWS", "DEVICE", ",,,", zPrinterDefault, SIZEOF(zPrinterDefault) 
 FUNCTION = zPrinterDefault 
 
END FUNCTION 
'_______________________________________________________________________ _______ 
'---------------------------- 
'Get a list of all printers 
'to compare or display and 
'let user choose optionally 
'-------------------------- 
SUB GetPrinterAll() 
 LOCAL Section         AS ASCIIZ * 32767 
 LOCAL SectionPtr      AS ASCIIZ PTR 
 LOCAL sPrinterDefault AS STRING 
 LOCAL Retval          AS LONG 
 
 sPrinterDefault = PARSE$(GetPrinterDefault, "," , 1) 
'msgbox "im here "+sprinterDefault 
 CONTROL SET TEXT hDlg, %LabelPS, "Default is: " & sPrinterDefault 
 
 Retval = GetProfileSection("PrinterPorts", Section, SIZEOF(Section)) 
 SectionPtr = VARPTR(Section) 
 PrinterCount = 0 
 DIM pList(%MaxPrinterCount, 7) AS STRING 
 DO 
   IF LEN(@SectionPtr) = 0 THEN EXIT DO 
    INCR PrinterCount 
    IF PrinterCount > %MaxPrinterCount THEN EXIT LOOP 
    PList(PrinterCount, %PAll)       = @SectionPtr                      'Epson LQ-500=EPSON24,LPT1:,15,45 
    PList(PrinterCount, %PName)      = PARSE$(@SectionPtr, ANY "=", 1)  'Epson LQ-500 
    PList(PrinterCount, %PDriver)    = PARSE$(@SectionPtr, ANY "=,", 2) 'EPSON24 
    PList(PrinterCount, %PPort)      = PARSE$(@SectionPtr, ANY "=,", 3) 'LPT1: 
    PList(PrinterCount, %PNonSelect) = PARSE$(@SectionPtr, ANY "=,", 4) '15 
    PList(PrinterCount, %PRetry)     = PARSE$(@SectionPtr, ANY "=,", 5) '45 
    IF sPrinterDefault  = PList(PrinterCount, %PName) THEN PrinterDefaultOld = PrinterCount 
    IF dialogistrue& THEN 'do only if command line not sent 
      LISTBOX ADD hDlg, %ListboxPS, PList(PrinterCount, %PName) 
      'LISTBOX ADD hDlg, %ListboxPS, @SectionPtr 
    END IF 
    SectionPtr = SectionPtr + LEN(@SectionPtr) + 1 
 LOOP 
 IF dialogistrue& THEN 'do only if command line not sent 
 'Highlight the default 
   SendMessage hList, %LB_SETSEL, PrinterDefaultOld - 1, 0 
   SendMessage hList, %LB_SETCURSEL, PrinterDefaultOld - 1, 0 
   UpdateWindow hList 
 END IF 
END SUB 
'_______________________________________________________________________ _______ 
CALLBACK FUNCTION DlgProc2() 
 
 SELECT CASE CBMSG 
     CASE %WM_COMMAND 
       SELECT CASE CBCTL 
         CASE 103 
           DIALOG END CBHNDL,1 
           lResult=0 
           EXIT FUNCTION 
       END SELECT 
 
      IF CBCTLMSG=%BN_CLICKED THEN 
        IF CBCTL=%IDOK THEN 
          DIALOG END CBHNDL,1 
          lResult=0 
        ELSEIF CBCTL=%IDCANCEL THEN 
          DIALOG END CBHNDL,0 
          lResult=0 
        END IF 
      END IF 
 END SELECT 
END FUNCTION 
 
CALLBACK FUNCTION DlgProc() AS LONG 
 LOCAL Retval AS LONG 
 
 SELECT CASE CBMSG 
   CASE %WM_INITDIALOG 
     CONTROL HANDLE hDlg, %ListboxPS TO hList 
     GetPrinterAll 
 
   CASE %WM_COMMAND 
     SELECT CASE CBCTL 
 
       CASE %ButtonSetPS 
         IF CBCTLMSG = %BN_CLICKED THEN 
           CONTROL SEND hDlg, %ListboxPS, %LB_GetCurSel, 0, 0 TO Retval 
           PrinterDefault = Retval + 1 
           SetPrinterDefault 
         END IF 
 
       CASE %ListboxPS 
         IF CBCTLMSG = %LBN_DBLCLK THEN 
           CONTROL SEND hDlg, %ListboxPS, %LB_GetCurSel, 0, 0 TO Retval 
           PrinterDefault = Retval + 1 
           SetPrinterDefault 
         END IF 
 
       CASE %ButtonInfoPS 
         IF CBCTLMSG = %BN_CLICKED THEN 
           CONTROL SEND hDlg, %ListboxPS, %LB_GetCurSel, 0, 0 TO Retval 
           INCR Retval 
           MSGBOX "Name:"   & $TAB & PList(Retval, %PName)      & $CRLF & _ 
                  "Driver:" & $TAB & PList(Retval, %PDriver)    & $CRLF & _ 
                  "Port:"   & $TAB & PList(Retval, %PPort)      & $CRLF & _ 
                  "Select:" & $TAB & PList(Retval, %PNonSelect) & $CRLF & _ 
                  "Retry:"  & $TAB & PList(Retval, %PRetry), _
				%MB_ICONINFORMATION OR %MB_OK, $AppName 
         END IF 
 
       CASE  %ButtonExitPS, %IDCANCEL 
         IF CBCTLMSG = %BN_CLICKED THEN DIALOG END CBHNDL, 0 
 
     END SELECT 
 
   CASE %WM_WININICHANGE 
     'Here, we will be inform by Window if the default printer change 
     CONTROL SET TEXT hDlg, %LabelPS, "Default is: " & PARSE$(GetPrinterDefault, "," , 1) 
 
 END SELECT 
 
END FUNCTION 
'_______________________________________________________________________ _______ 
 
FUNCTION PBMAIN AS LONG 
 LOCAL Pnam$ 
 LOCAL RetVal AS LONG 
 LOCAL found% 
 LOCAL k&,Start&,Endit&,Count& 
 LOCAL msg$ 
 Pnam$=COMMAND$ 
 IF Pnam$="" THEN 
'--------------------------------- 
'no command line entry detected so 
'show the modal dialog to choose 
'default printer. 
'--------------------------------- 
   dialogistrue&=1 
   DIALOG NEW 0, $AppName, , , 280, 150, _ 
             %WS_POPUP OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CAPTION OR _ 
             %WS_SYSMENU OR %WS_MINIMIZEBOX OR %DS_3DLOOK OR %DS_NOFAILCREATE _ 
             OR %DS_SETFONT, %WS_EX_CONTROLPARENT TO hDlg 
 
   CONTROL ADD FRAME, hDlg, %FramePS, "Printer", 9, 9, 264, 93 
 
   CONTROL ADD LISTBOX, hDlg, %ListboxPS, , 21, 24, 240, 76, _ 
             %WS_CHILD OR %WS_VISIBLE OR %WS_BORDER OR %WS_VSCROLL OR _ 
             %WS_TABSTOP OR %LBS_NOTIFY, 0 
 
   CONTROL ADD LABEL, hDlg, %LabelPS, "Default Printer is...", 21, 110, 240, 12 
 
   CONTROL ADD BUTTON, hDlg, %ButtonSetPS, "Set default printer", 9, 126, 130, 18, _ 
             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_CENTER OR %BS_VCENTER 
 
   CONTROL ADD BUTTON, hDlg, %ButtonInfoPS, "Info", 150, 126, 30, 18, _ 
             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_CENTER OR %BS_VCENTER 
 
   CONTROL ADD BUTTON, hDlg, %ButtonExitPS, "Exit", 192, 126, 78, 18, _ 
             %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %BS_CENTER OR %BS_VCENTER 
 
   DIALOG SHOW MODAL hDlg, CALL DlgProc 
 ELSE 
'-------------------------------- 
'command line entry detexted, so 
'try to set default based on name 
'from the command line 
'-------------------------------- 
   dialogistrue&=0 
   GetPrinterAll 
   found%=0 
 
   FOR k&=1 TO PrinterCount 
    IF PList(k&, %PName)=Pnam$ THEN RetVal=k& : k&=%MAXPRINTERCOUNT:found%=1 
   NEXT k& 
   IF RetVal THEN 
     IF RetVal<>PrinterDefaultOld AND found%=1 THEN 
       PrinterDefault = Retval ' not coming from listbox so don't to add + 1 
       SetPrinterDefault 
       msg$="Default Printer Set to:" 
     ELSEIF found%=1 AND RetVal=PrinterDefaultOld THEN 
       msg$="Default printer already is:" 
'     else 'Not needed error message will be shown in msgbox if no match 
'       msg$="Command Line doesn't match any" 
     END IF 
'-------------------------------- 
'modeless dialog to display if 
'result was successful. auto 
'self-destructs after couple of 
'seconds or press ok 
'------------------------------- 
     DIALOG NEW 0,"Set Default Printer",,,130,60,%WS_SYSMENU OR %WS_CAPTION,_
			%WS_EX_CONTROLPARENT TO hDlg 
'                   , _ 
'                  %WS_POPUP OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CAPTION OR _ 
'                  %WS_SYSMENU OR %WS_MINIMIZEBOX OR %DS_3DLOOK OR %DS_NOFAILCREATE _ 
'               OR %DS_SETFONT, %WS_EX_CONTROLPARENT TO hDlg 
       CONTROL ADD LABEL, hDlg,101,msg$,10,5,100,12 
       CONTROL ADD LABEL, hDlg,102,Pnam$,10,20,120,12,%SS_NOWORDWRAP 
       CONTROL ADD BUTTON, hDlg,103,"OK",40,40,50,15 
      lResult=1 
     DIALOG SHOW MODELESS hdlg CALL dlgproc2 
'------------------- 
'start a timer for 
'the dialog 
'------------------- 
     Start&=VAL(RIGHT$(TIME$,2)) 
     Endit&=Start&+2 
     IF Endit&>=59 THEN Endit&=Endit&-59 
     DO 
        ' Allow messages to be dispatched 
       DIALOG DOEVENTS 
       IF VAL(RIGHT$(TIME$,2))>endit& THEN 
         lresult=0 
       END IF 
     LOOP WHILE lResult>0 'VAL(RIGHT$(TIME$,2))<Endit& OR Count&<100000 OR lResult>0 ''x 
 
   ELSE 
'----------------------- 
'this may not be needed 
'either - may show in 
'getall subroutine 
'----------------------- 
     MSGBOX "Invalid Printer name specified",%MB_ICONERROR,"No Match Found" 
   END IF 
 END IF 
END FUNCTION 
'___________________________________________________ 
 
' 
'------------------ 
 
 

'Pierre Bellisle 
'bellisle@vif.com 
'modified for command line ability by Fred Buffington 
 
