User Module: Global and cross Platform Stuff

Share your advanced PureBasic knowledge/code with the community.
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

User Module: Global and cross Platform Stuff

Post 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.
Last edited by collectordave on Wed Mar 16, 2016 4:53 am, edited 1 time in total.
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: User Module: Global and cross Platform Stuff

Post 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 .
Windows (x64)
Raspberry Pi OS (Arm64)
collectordave
Addict
Addict
Posts: 1310
Joined: Fri Aug 28, 2015 6:10 pm
Location: Portugal

Re: User Module: Global and cross Platform Stuff

Post by collectordave »

Thanks Wilbert

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

Regards

collectordave
Any intelligent fool can make things bigger and more complex. It takes a touch of genius — and a lot of courage to move in the opposite direction.
Post Reply