ComboBoxGadget inside EditorGadget as a tip.

Just starting out? Need help? Post your questions and find answers here.
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

ComboBoxGadget inside EditorGadget as a tip.

Post by ZX80 »

Hi, all.

I want to make a small editor. And my goal is to autocomplete the string, just like in the PB environment. Please, see if this can be done better ? I want to calculate the font size (height) in pixels and take into account the size of the comboboxgadget to position it correctly when displayed.

Thank you in advance.

Code: Select all

#EFontName   = "lucida console"
#EFontSize   = 14
#EFontStyle  = #PB_Font_Bold

#MainWindow = 0
#Editor     = 1
#ComboBox   = 2

Global cbWnd.i, eWnd.i

Procedure GetFontHeight(text.s, FontID)   
  Protected dc = GetDC_(0)
  Protected sz.Size
  
  SelectObject_(dc, FontID)
  GetTextExtentPoint32_(dc, text, Len(text), sz)
  ReleaseDC_(0, dc)
  
  ProcedureReturn sz\cy
EndProcedure

Procedure WndProc(hWnd, uMsg, wParam, lParam)
  If lParam = cbWnd
    If uMsg = #WM_COMMAND
      Select wParam >> 16 & $FFFF
        Case #CBN_CLOSEUP
          HideGadget(#ComboBox, #True)
          insert$ = GetGadgetText(#ComboBox)
          SendMessage_(eWnd, #EM_REPLACESEL, 0, insert$)
          SetActiveGadget(#Editor)
        Case #CBN_SELCHANGE
          If cbState
            ProcedureReturn 0
          EndIf
      EndSelect
    EndIf
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


OpenWindow(#MainWindow, 0, 0, 800, 600, "EG-test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
eWnd  = EditorGadget(#Editor, 10, 10, WindowWidth(0)-20, 150, #PB_Editor_WordWrap)
cbWnd = ComboBoxGadget(#ComboBox, 10, 10, 150, 25)
HideGadget(#ComboBox, #True)
h = SendMessage_(cbWnd, #CB_GETITEMHEIGHT, 0, 0)
h = h / 2

userfont = FontID(LoadFont(#PB_Any, #EFontName, #EFontSize, #EFontStyle))
SetGadgetFont(#Editor, userfont)
SetGadgetFont(#ComboBox, userfont)

For a = 1 To 5
  AddGadgetItem(#ComboBox, -1, "str " + Str(a))
Next
SetGadgetState(#ComboBox, 3)

AddGadgetItem(#Editor, 0, "string #1")      
AddGadgetItem(#Editor, 1, "string #2")      

SetActiveGadget(#Editor)

FontHeight = GetFontHeight("Ag", userfont)
HeightCOR  = FontHeight + h

SetWindowCallback(@WndProc())

Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Quit = 1
    
    Case #WM_CHAR
      If GetActiveGadget() = #Editor
        key = EventwParam()
        If key = 32
          GetCaretPos_(p.POINT)
          ResizeGadget(#ComboBox, p\x, p\y + HeightCOR, #PB_Ignore, #PB_Ignore)
          HideGadget(#ComboBox, #False)
          SetActiveGadget(#ComboBox)
          SendMessage_(cbWnd, #CB_SHOWDROPDOWN, 1, 0)
        EndIf
      EndIf
          
  EndSelect
Until Quit = 1
P.S. I also have suspicions that the insert action was done incorrectly.
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: ComboBoxGadget inside EditorGadget as a tip.

Post by Axolotl »

Maybe you should peek in the PB very own autocomplete.pb and others.
The implementation is based on an invisible and borderless window and a ListViewGadget.
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: ComboBoxGadget inside EditorGadget as a tip.

Post by Axolotl »

Okay, I hacked something together based on your example code.......
Maybe this can be a start.
Press Crtl+Space to open the selection window (not Space)
Select by UP and DOWN key, and insert it by RETURN or TAB key or use mouse double click

Code: Select all

EnableExplicit 

Enumeration EWindow 1 
  #WINDOW_Main 
EndEnumeration 

Enumeration EGadget 1 
  #GADGET_Editor
  #GADGET_ComboBox
EndEnumeration 


;-
;-{--== Window Listbox ==--------------------------------------------------------------------------------------------
;-

Enumeration EWindow  ; next constant 
  #WINDOW_Listbox
EndEnumeration 

Enumeration EGadget  ; next constant 
  #GADGET_Listbox_List 
EndEnumeration 

Procedure WindowListbox_OnCallback(hWnd, uMsg, wParam, lParam) 
  Select uMsg 
    Case #WM_ACTIVATE 
      ; user clicked outside the window / listbox 
      ; 
      If wParam = #WA_INACTIVE  
        HideWindow(#WINDOW_Listbox, 1) 
      EndIf 
  EndSelect 

  ProcedureReturn #PB_ProcessPureBasicEvents 
EndProcedure 

; --- 

Procedure WindowListbox_CreateWindow(Width=200, Height=200) 
  Protected oldGadgetList 

  If OpenWindow(#WINDOW_Listbox, 0, 0, Width, Height, "", #PB_Window_Invisible|#PB_Window_BorderLess) 
    StickyWindow(#WINDOW_Listbox, 1) ; because main window is also sticky 
    oldGadgetList = UseGadgetList(WindowID(#WINDOW_Listbox))  ; Create GadgetList and store old GadgetList
    ListViewGadget(#GADGET_Listbox_List, 0, 0, Width, Height) 
    SetWindowCallback(@WindowListbox_OnCallback(), #WINDOW_Listbox) 
    UseGadgetList(oldGadgetList)             ; return to previous GadgetList 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; ---

Procedure WindowListbox_ShowWindowPos(X, Y) 
  If IsGadget(#GADGET_Listbox_List) 
    ResizeWindow(#WINDOW_Listbox, X, Y, #PB_Ignore, #PB_Ignore) 

    HideWindow(#WINDOW_Listbox, 0)  ; show now 
    SetActiveGadget(#GADGET_Listbox_List) 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure 

; --- 

Procedure.s WindowListbox_GetSelectedText() 
  Protected result$ 

  result$  = GetGadgetText(#GADGET_Listbox_List) 
  HideWindow(#WINDOW_Listbox, 1) 
  ProcedureReturn result$ 
EndProcedure 

;} Eod of Window_Listbox 

Macro IsCtrlPressed() 
  Bool(GetAsyncKeyState_(#VK_CONTROL) & $8000) 
EndMacro 


Procedure GetFontHeight(text.s, FontID)   
  Protected dc = GetDC_(0)
  Protected sz.Size
  
  SelectObject_(dc, FontID)
  GetTextExtentPoint32_(dc, text, Len(text), sz)
  ReleaseDC_(0, dc)
  
  ProcedureReturn sz\cy
EndProcedure 


Procedure main() 
  Protected result, a, eWnd, userfont  
  Protected FontHeight, HeightCOR, h, key, p.POINT  
  Protected text$ 


  WindowListbox_CreateWindow() 

  If OpenWindow(#WINDOW_Main, 0, 0, 800, 600, "EG-test", #PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
    eWnd = EditorGadget(#GADGET_Editor, 10, 10, WindowWidth(#WINDOW_Main)-20, 150, #PB_Editor_WordWrap)

    userfont = FontID(LoadFont(#PB_Any, "Consolas", 10)) 
    SetGadgetFont(#GADGET_Editor, userfont) 
    SetGadgetFont(#GADGET_ComboBox, userfont) 

    For a = 1 To 5
      AddGadgetItem(#GADGET_Listbox_List, -1, "str " + a) 
    Next
    SetGadgetState(#GADGET_Listbox_List, 3) 

    AddGadgetItem(#GADGET_Editor, 0, "string #1")      
    AddGadgetItem(#GADGET_Editor, 1, "string #2")      

    SetActiveGadget(#GADGET_Editor)  

    FontHeight = GetFontHeight("Ag", userfont)
    HeightCOR  = FontHeight + h

    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Break 
    
        Case #PB_Event_Gadget 
          Select EventGadget() 
            Case #GADGET_Listbox_List 
              If EventType() = #PB_EventType_LeftDoubleClick 
                text$ = WindowListbox_GetSelectedText() 
                SendMessage_(eWnd, #EM_REPLACESEL, 0, text$)
             
              EndIf 
          EndSelect 

        Case #WM_KEYUP 
          key = EventwParam()  
          Select GetActiveGadget() 
            Case #GADGET_Listbox_List 
              If key = 13 Or key = 9  ; RETURN or TAB 
                text$ = WindowListbox_GetSelectedText() 
                SendMessage_(eWnd, #EM_REPLACESEL, 0, text$)
              EndIf
          EndSelect 

        Case #WM_CHAR
          key = EventwParam()
          Select GetActiveGadget() 
            Case #GADGET_Editor 
              If key = 32 And IsCtrlPressed() 
                If GetCaretPos_(@p) 
                  ClientToScreen_(eWnd, @p)  
                  WindowListbox_ShowWindowPos(p\x, p\y + HeightCOR) 

                  Debug "Caret Pos = " + p\x + ", " + p\y 
                EndIf 
              EndIf
            
          EndSelect 
          
      EndSelect
    ForEver 
  EndIf 

  ProcedureReturn 0 
EndProcedure 

End main() 

;\BoF 
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
ZX80
Enthusiast
Enthusiast
Posts: 361
Joined: Mon Dec 12, 2016 1:37 pm

Re: ComboBoxGadget inside EditorGadget as a tip.

Post by ZX80 »

Axolotl, thanks a lot!

I really appreciate your help. This is a good starting point (much better than my original one).

Thanks again!
Post Reply