Anyone did a better InputRequester module or include?

Everything else that doesn't fall into one of the other PB categories.
Fred
Administrator
Administrator
Posts: 18150
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Anyone did a better InputRequester module or include?

Post by Fred »

Here we go:

Code: Select all

; inputDialog.pbi
; PureBasic 6.20 and possibly also before
; WINDOWS ONLY

EnableExplicit

#inpDialogEscMenu = 32767 ; ESC key menu event number
#inpDialogRetMenu = 32768 ; RETURN key menu event number

; Alternative inputDialog
;  appTitle.s      : dialog title
;  message.s       : dialog message
;  width.i         : dialog width (px), defaults to 400
;  defaultText.s   : the default to put into the text field
;  cancelResult.s  : what to return if dialog is cancelled (no NULL in PB), default to "-1". This allows "" as valid result.
Procedure.s inputDialog(appTitle.s, message.s, width.i = 400, defaultText.s = "", cancelResult.s = "-1")
  Protected inputText.s = ""
  Protected result.i = 0
  Protected NWndParent.i, hParent.i, wflag.i
  
  NWndParent.i = GetActiveWindow() 
  If NWndParent.i <> -1 
    hParent.i = WindowID(NWndParent.i) 
    DisableWindow(NWndParent.i, 1) ; <- disable parent window (because of our own event loop) 
    wflag.i = #PB_Window_Tool | #PB_Window_WindowCentered 
  Else 
    hParent = 0 
    wflag.i = #PB_Window_Tool | #PB_Window_ScreenCentered 
  EndIf
  
  ; helpers
  Protected margin.i = 12   ; generic gadget margin
  Protected gadH.i = 24     ; usual gadget height (text, buttons)
  Protected buttonW.i = 70  ; button width
  
  ; calc the size of the Textgadget! 
  Protected rc.RECT
  Protected hdc.i = GetDC_(0) 
  Protected hFont.i = GetGadgetFont(#PB_Default) 
  SelectObject_(hdc.i, hFont.i) 
  rc\right = DesktopScaledX(width.i - (margin * 2))
  DrawText_(hdc.i, message.s, Len(message.s), @rc, #DT_CALCRECT|#DT_WORDBREAK)
  ReleaseDC_(0, hdc.i) 
  Protected txtHeight.i = DesktopUnscaledY(rc\bottom - rc\top) ; <- TextGadget height!
  
  ; calc final window height
  Protected WndH.i = margin + txtHeight.i + margin + gadH + margin + gadH + margin.i 

  Protected inputWin.i = OpenWindow(#PB_Any,
                                    0, 0, 
                                    width.i, WndH.i, 
                                    "   " + appTitle.s, 
                                    wflag.i, hParent.i)
  
  If inputWin.i = 0
    Debug "Failed to open dialog window!"
    ProcedureReturn cancelResult.s
  EndIf
  
  Protected labelGadget.i = TextGadget(#PB_Any, 
                                       margin, 
                                       margin, 
                                       width.i - margin * 2, 
                                       txtHeight.i, 
                                       message.s)

  Protected inputGadget.i = StringGadget(#PB_Any, 
                                         margin, 
                                         margin + txtHeight.i + margin, 
                                         width.i - margin * 2, 
                                         gadH.i, 
                                         defaultText.s)
  
  Protected okButton.i = ButtonGadget(#PB_Any, 
                                      width.i - margin.i - buttonW.i - margin.i - buttonW.i, 
                                      margin.i + txtHeight.i + margin.i + gadH.i + margin.i, 
                                      buttonW.i, 
                                      gadH.i, 
                                      "OK")
  
  Protected cancelButton.i = ButtonGadget(#PB_Any, 
                                          width.i - margin.i - buttonW.i, 
                                          margin.i + txtHeight.i + margin.i + gadH.i + margin.i, 
                                          buttonW.i, 
                                          gadH.i, 
                                          "Cancel")

  SetActiveGadget(inputGadget.i)
  
  AddKeyboardShortcut(inputWin, #PB_Shortcut_Escape, #inpDialogEscMenu)
  AddKeyboardShortcut(inputWin, #PB_Shortcut_Return, #inpDialogRetMenu)
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case okButton
            inputText.s = GetGadgetText(inputGadget.i)
            result.i = 1
            Break
          Case cancelButton
            inputText.s = ""
            result.i = 0
            Break
        EndSelect
        
      Case #PB_Event_CloseWindow
        inputText.s = ""
        result.i = 0
        Break
        
      Case #PB_Event_Menu
        Select EventMenu()
          Case #inpDialogEscMenu
            inputText.s = ""
            result.i = 0
            Break
          Case #inpDialogRetMenu
            inputText.s = GetGadgetText(inputGadget.i)
            result.i = 1
            Break
        EndSelect
    EndSelect
  ForEver
  
  RemoveKeyboardShortcut(inputWin.i, #PB_Shortcut_Escape)
  RemoveKeyboardShortcut(inputWin.i, #PB_Shortcut_Return)
  
  CloseWindow(inputWin.i)
  
  If NWndParent.i <> -1  
    DisableWindow(NWndParent.i, 0)  ; enable parent window again, now we use the main event loop 
  EndIf 
  
  If result.i = 1
    ProcedureReturn inputText.s
  EndIf
  ProcedureReturn cancelResult.s
EndProcedure

CompilerIf #PB_Compiler_IsMainFile = #True
  ; test if started from include file
  Define proxy.s = inputDialog("Testing inputDialog 1", 
                               "Enter proxy server in the following format:"+#CR$+#CR$+
                               "proxyServer:Port optionalUsername optionalPassword"+#CR$+#CR$+
                               "Supported protocols:"+#CR$+
                               "- http://    - HTTP proxy (Default)"+#CR$+
                               "- socks4://  - SOCKS4 proxy"+#CR$+
                               "- socks4a:// - SOCKS4 proxy with domain name support rather than IP address"+#CR$+
                               "- socks5://  - SOCKS5 proxy"+#CR$+
                               "- socks5h:// - SOCKS5 proxy and ask the proxy to do the hostname resolving",
                               500)
  Debug "inputDialog result: [" + proxy.s + "]"
  
  proxy.s = inputDialog("Testing inputDialog 2", 
                        "Enter proxy server:")
  Debug "inputDialog result: [" + proxy.s + "]"
CompilerEndIf
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: Anyone did a better InputRequester module or include?

Post by Mijikai »

Thanks for the cool examples, i learned only now how useful DisableWindow() can be :shock:
I also wanted to give it a try, this should be platform independent + DPI.
This still needs more testing (different OS + DPI).

Image

The size of the dialog is automatically determined (min width is set to 320).
*error can be used for errors or to see if the dialog was canceled.

Code:

Code: Select all

EnableExplicit

;PureBasic 6.21 (x64)
;Tested: Windows 11
;Version: Draft 1

Procedure.s input_requester(title.s,message.s,*error.Integer)
  Protected.i parent,active,window,font,image,index
  Protected.i x,y,w,h,tw,ty,th,tx,a,b,c,d
  Protected.s text,result
  x = DesktopScaledX(10)
  y = DesktopScaledY(10)
  font = GetGadgetFont(#PB_Default)
  image = CreateImage(#PB_Any,64,64,32,#White)
  If IsImage(image)
    If StartDrawing(ImageOutput(image))
      DrawingFont(font)
      Repeat
        index + 1  
        text = StringField(message,index,#CR$)
        If text
          w = DesktopScaledX(TextWidth(text))
          h = DesktopScaledY(TextHeight(text))
          If ty < h
            ty = h
          EndIf
          If tw < w
            tw = w
          EndIf
          th + ty
        Else
          Break
        EndIf
      ForEver
      w = tw + x * 2
      h = th + ty * 2
      tx = DesktopScaledX(320)
      If w < tx
        tw = tx
        tx = (tx - w) / 2
        w = tw
      Else
        tx = x
      EndIf
      StopDrawing()
    Else
      *error\i = 3
    EndIf
    FreeImage(image)
  Else
    *error\i = 2
  EndIf
  If tw And th
    image = CreateImage(#PB_Any,w,h,32,#White)
    If IsImage(image)
      If StartDrawing(ImageOutput(image))
        DrawingFont(font)
        index = 0
        Repeat
          index + 1
          text = StringField(message,index,#CR$)
          If text
            DrawText(tx,ty * index,text,#Black,#White)
          Else
            Break
          EndIf
        ForEver
        StopDrawing()
      Else
        *error\i = 5
      EndIf
      active = GetActiveGadget()
      parent = GetActiveWindow()
      If parent <> -1
        DisableWindow(parent,#True)
      EndIf
      window = OpenWindow(#PB_Any,#Null,#Null,w,h + y * 8,title,#PB_Window_Tool | #PB_Window_ScreenCentered)
      If IsWindow(window)
        tw = DesktopScaledX(80)
        a = ImageGadget(#PB_Any,0,0,w,h,ImageID(image))
        b = StringGadget(#PB_Any,x,h + y,w - x * 2,y * 2,#Null$)
        c = ButtonGadget(#PB_Any,w - tw - x,h + y * 4,tw,y * 3,"Cancel")
        d = ButtonGadget(#PB_Any,w - (tw * 2) - x * 2,h + y * 4,tw,y * 3,"Ok")
        SetActiveGadget(b)
        AddKeyboardShortcut(window,#PB_Shortcut_Escape,0)
        AddKeyboardShortcut(window,#PB_Shortcut_Return,1)
        Repeat
          Select WaitWindowEvent()
            Case #PB_Event_Menu
              If EventWindow() = window
                Select EventMenu()
                  Case 0
                    *error\i = 1
                    Break
                  Case 1
                    result = GetGadgetText(b)
                    Break
                EndSelect
              EndIf
            Case #PB_Event_Gadget
              If EventWindow() = window
                Select EventGadget()
                  Case c
                    *error\i = 1
                    Break
                  Case d
                    result = GetGadgetText(b)
                    Break
                EndSelect
              EndIf
            Case #PB_Event_CloseWindow
              If EventWindow() = window
                Break
              EndIf
          EndSelect
        ForEver
        CloseWindow(window)
      Else
        *error\i = 6
      EndIf
      FreeImage(image)
      If parent <> -1
        DisableWindow(parent,#False)
      EndIf
      If IsGadget(active)
        SetActiveGadget(active)
      EndIf
    Else
      *error\i = 4
    EndIf
  EndIf
  ProcedureReturn result
EndProcedure

Procedure.i main()
  Protected.i error
  Protected.s result
  result = input_requester("Title","Hello World Message!" + #CR$ + "This is a message requester!" + #CR$ + ":)",@error)
  If error = 0
    Debug "Result: " + result
  ElseIf error = 1
    Debug "Resulet: Cancel!"
  EndIf
  ProcedureReturn #Null
EndProcedure

End main()
User avatar
Mindphazer
Enthusiast
Enthusiast
Posts: 456
Joined: Mon Sep 10, 2012 10:41 am
Location: Savoie

Re: Anyone did a better InputRequester module or include?

Post by Mindphazer »

Hi,
here's how it looks on MacOS, with DPI enabled :
Image
Not sure it's what was expected :-)
MacBook Pro 16" M4 Pro - 24 Gb - MacOS 15.4.1 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
Post Reply