User Module: Global and cross Platform Stuff
Posted: Thu Mar 10, 2016 9:24 am
				
				Writing cross platform programs in PB I felt it a good idea to gather all platform specific stuff into one place together with anything such as constants and procedures I need to be application global. It is also to answer some of the questions I find when searching the forum.
So I started this. Not all are complete so if anyone can fill in some of the blanks I would be gratefull.
I have posted this after searching for some method to get the minimum margins for a printer to allow me to position text etc accurately on a page. I found code for windows on the forum but not for MAC or Linux.
The macro FileExists() is also here.
The example programme just deals with the printer bits I will extend this to include messages etc if needed.
I just think it would be a good idea to gather all the cross platform stuff and other requests into one place.
If anyone can suggest further procedures etc please post here.
App.pbi updated. Cannot get the printer information for MAC or Linux but a procedure to enumerate connected printers is now included working on Windows and MAC.
Now the code
First App.pbi:-
And now the throw away test programme frmMain.pb:-
Hope this is of use to someone.
I will update App.pbi when I can add new bits and pieces.
			So I started this. Not all are complete so if anyone can fill in some of the blanks I would be gratefull.
I have posted this after searching for some method to get the minimum margins for a printer to allow me to position text etc accurately on a page. I found code for windows on the forum but not for MAC or Linux.
The macro FileExists() is also here.
The example programme just deals with the printer bits I will extend this to include messages etc if needed.
I just think it would be a good idea to gather all the cross platform stuff and other requests into one place.
If anyone can suggest further procedures etc please post here.
App.pbi updated. Cannot get the printer information for MAC or Linux but a procedure to enumerate connected printers is now included working on Windows and MAC.
Now the code
First App.pbi:-
Code: Select all
UsePNGImageDecoder() 
DeclareModule App
  
  ;All OS's
  
Macro FileExists(filename)
  Bool(FileSize(fileName) > -1)
EndMacro
  Global PPmm.i ;Used to store Screen Dots Per mm
  
  Global NewList Printers.s()
  ;Constants for Flags
  #OkOnly = 1
  #OkCancel = 2
  #YesNo = 4
  #YesNoCancel = 8
  #InformationIcon = 16
  #WarningIcon = 32
  #StopIcon = 64
  
  ;Constants for return values
  #MsgOk = 1
  #MsgYes = 2
  #MsgNo = 3
  #MsgCancel = 4
  
  ;Some Colours
  #ColWhite = $FFFFFF
  
  DataSection
  Info: 
  IncludeBinary "information.png"  ;Add your own image
  Warn:
  IncludeBinary "warning.png"      ;Add your own image
  Stop:
  IncludeBinary "stop.png"         ;Add your own image
  EndDataSection
  
  ;OS Specific details
  CompilerSelect #PB_Compiler_OS
    
    CompilerCase   #PB_OS_MacOS
        
      #DefaultFolder = "/Volumes" ;For explorertreegadget etc
      ImportC ""
        CFArrayGetCount(theArray.i)
        CFArrayGetValueAtIndex(theArray.i, idx.i)
        PMPaperGetHeight(paper, *paperHeight.Double)
        PMPaperGetWidth(paper, *paperWidth.Double)
        PMPaperGetPPDPaperName(paper.i, *paperName)
        PMPrinterGetName(printer.i)
        PMPrinterGetPaperList(printer.i, *paperList)
        PMPrinterIsDefault(printer.i)
        PMServerCreatePrinterList(server.i, *printerList)
      EndImport
      
    CompilerCase   #PB_OS_Linux 
      
       #DefaultFolder = "/"       ;For explorertreegadget etc    
      
    CompilerCase   #PB_OS_Windows
      #DefaultFolder = "C:\"      ;For explorertreegadget etc
    
  CompilerEndSelect
  
  ;App Global procedures
  Declare.i Message(Title.s,Msg.s,Flags.i)
  Declare EnumeratePrinters()
  
EndDeclareModule
Module App
  
  Procedure.i Message(Title.s,Msg.s,Flags.i)
  
    Define This_Window.i,btn1,btn2,btn3,txtMsg,RetVal,IconImage,Testimg
  
    This_Window = OpenWindow(#PB_Any, 0, 0, 300, 130, Title,  #PB_Window_Tool | #PB_Window_ScreenCentered)
    
    ;Add the buttons
    If Flags & #YesNoCancel > 0
      btn1 = ButtonGadget(#PB_Any, 30, 90, 80, 30, "Yes")
      btn2 = ButtonGadget(#PB_Any, 120, 90, 80, 30, "No")
      btn3 = ButtonGadget(#PB_Any, 210, 90, 80, 30, "Cancel")
    ElseIf   Flags & #OkCancel > 0
      btn2 = ButtonGadget(#PB_Any, 120, 90, 80, 30, "Ok")
      btn3 = ButtonGadget(#PB_Any, 210, 90, 80, 30, "Cancel")
    ElseIf   Flags & #YesNo > 0
      btn2 = ButtonGadget(#PB_Any, 120, 90, 80, 30, "Yes")
      btn3 = ButtonGadget(#PB_Any, 210, 90, 80, 30, "No")
    Else
      btn3 = ButtonGadget(#PB_Any, 210, 90, 80, 30, "Ok")
    EndIf
    
    ;Add the message image
    IconImage = ImageGadget(#PB_Any, 20, 20, 50, 50, 0)
    If Flags & #InformationIcon > 0
      CatchImage(0, ?Info)
      If IsImage(0)
        SetGadgetState(IconImage,ImageID(0)) 
      EndIf
    EndIf
    If Flags & #WarningIcon > 0
      CatchImage(Testimg, ?Warn)
      SetGadgetState(IconImage,ImageID(0))    
    EndIf  
    If Flags & #StopIcon > 0
      CatchImage(0, ?Stop)
      SetGadgetState(IconImage,ImageID(0))   
    EndIf
  
    ;Add the main message text
    txtMsg = TextGadget(#PB_Any, 70, 10, 220, 70, Msg)
    
    ;Make sure it stays on top
    StickyWindow(This_Window,#True)
    
    ;Start of message handling loop
    ;Not to be mixed up with the main application loop
    ;Allways include code to close this window!
    Repeat
      Event = WaitWindowEvent()
      
      Select EventWindow()
        
        Case This_Window ;Messages for this window only all others discarded
          Select Event
           
            Case #PB_Event_Gadget
            
              Select EventGadget()
                  
                ;Each button has a different meaning depending on
                ;the typr of message box
                  
                Case btn1
                  If Flags&#YesNoCancel > 0
                    RetVal = #MsgYes
                  EndIf 
                  CloseWindow(This_Window)
                  
                Case btn2
                  If Flags&#YesNoCancel > 0 
                    RetVal = #MsgNo
                  ElseIf Flags&#YesNo > 0
                    RetVal = #MsgYes  
                  ElseIf Flags&#OkCancel > 0
                    RetVal = #MsgOk                   
                  EndIf
                  CloseWindow(This_Window)
                  
                Case btn3
                  If Flags&#YesNoCancel > 0 Or Flags&#OkCancel > 0
                    RetVal = #MsgCancel
                  ElseIf Flags&#YesNo > 0
                    RetVal = #MsgNo 
                  Else
                    RetVal = #MsgOk
                  EndIf
                  CloseWindow(This_Window)
                
              EndSelect ;Eventgadget
            
          EndSelect ;Event
  
    EndSelect ;Eventwindow
    
  Until Not IsWindow(This_Window)
  
  ProcedureReturn RetVal
  
EndProcedure
  Procedure EnumeratePrinters()
  
  CompilerSelect #PB_Compiler_OS
    
    CompilerCase   #PB_OS_MacOS
      PMServerCreatePrinterList(0, @printers)
      printerCount = CFArrayGetCount(printers)
      For i = 0 To printerCount - 1
        printer = CFArrayGetValueAtIndex(printers, i)
        printerName.s = PeekS(CocoaMessage(0, PMPrinterGetName(printer), "UTF8String"), -1, #PB_UTF8)
        AddElement(Printers())
        Printers() = PeekS(CocoaMessage(0, PMPrinterGetName(printer), "UTF8String"), -1, #PB_UTF8)
      Next i
  
    CompilerCase   #PB_OS_Linux   
      
      ;Not Defined Yet
      
    CompilerCase   #PB_OS_Windows 
      
      enum.l=#PRINTER_ENUM_LOCAL|#PRINTER_ENUM_CONNECTIONS  
      Protected buf,cnt,mem,bytes,cntret,size,i
      If EnumPrinters_(enum,0,1,0,0,@buf,@cnt)=0
        mem=AllocateMemory(buf)
        If mem And EnumPrinters_(enum,0,1,mem,buf,@bytes,@cntret)
          size=SizeOf(PRINTER_INFO_1)
          If cntret
            For i=0 To cntret-1
              AddElement(Printers())
              Printers() = PeekS(PeekL(mem+i*size+ 8))
            Next
          EndIf
          FreeMemory(mem)
          ProcedureReturn 1
        EndIf
      EndIf
      
  CompilerEndSelect   
  
EndProcedure
EndModule
Code: Select all
IncludeFile "App.pbi" ;Allways Included first
Global Window_0
Global ListView_0, Button_0
Window_0 = OpenWindow(#PB_Any, 0, 0, 200, 100, "", #PB_Window_SystemMenu)
Button_0 = ButtonGadget(#PB_Any, 30, 30, 90, 30, "Printer")
Repeat
  
  Event = WaitWindowEvent()
  Select event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Button_0
          If PrintRequester()
            
            App::GetPrinterInfo()
          
            Debug "Horizontal DPmm = " + Str(App::PrinterInfo\HDPI)
            Debug "Vertical DPI = " + Str(App::PrinterInfo\VDPI)
            Debug "Horizontal Margin = " + Str(App::PrinterInfo\HMargin)
            Debug "Vertical Margin = " + Str(App::PrinterInfo\VMargin)
            Debug "Physical Width = " + Str(App::PrinterInfo\Width)
            Debug "Physical Height = " + Str(App::PrinterInfo\Height)
            Debug "Usable Width mm = " + Str(App::PrinterInfo\Widthmm)
            Debug "Usable Height mm = " + Str(App::PrinterInfo\Heightmm)
            
          EndIf
          
      EndSelect
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow
I will update App.pbi when I can add new bits and pieces.