Page 1 of 1

User Module: Global and cross Platform Stuff

Posted: Thu Mar 10, 2016 9:24 am
by collectordave
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:-

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
And now the throw away test programme frmMain.pb:-

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
Hope this is of use to someone.

I will update App.pbi when I can add new bits and pieces.

Re: User Module: Global and cross Platform Stuff

Posted: Thu Mar 10, 2016 9:28 am
by wilbert
collectordave wrote:I found code for windows on the forum but not for MAC or Linux.
For Mac you can find some printer related things in the Tips & Tricks thread http://www.purebasic.fr/english/viewtop ... 19&t=50795 .
For example some code from Shardik concerning printer margins http://www.purebasic.fr/english/viewtop ... 96#p394796 .

Re: User Module: Global and cross Platform Stuff

Posted: Thu Mar 10, 2016 11:01 am
by collectordave
Thanks Wilbert

Will take me a little time to check it out but will update original post when I can.

Regards

collectordave