Page 1 of 2

Bring combobox visible in ListiconGadget?

Posted: Thu Sep 22, 2005 9:39 am
by Fangbeast
I'm trying to click on a cell in a ListiconGadget and have a ComboBoxGadget embed itself in that cell. When I select an item from the ComboBox, it should vanish, returning the data to that cell.

Problem 1. Not understanding API, I am having trouble getting the combobox to appear exactly where I want it to.

Problem 2. Since it's sitting on top of the list when it appears, it vanishes partly behind the gadget when I click on it.

Problem 3. The height of the cell is smaller than the height of a combobox and the combobox cannot be resized any smaller than the default.

I'm out of my depth here. Could someone have a look at this for me?

Code: Select all

;============================================================================================================================
; 
;============================================================================================================================

Global BubbleTipStyle.l

;============================================================================================================================
; 
;============================================================================================================================

BubbleTipStyle  = 0

Enumeration 1
  #Window_hittest
EndEnumeration

#WindowIndex = #PB_Compiler_EnumerationValue

Enumeration 1
  #Gadget_hittest_fmain
  #Gadget_hittest_ListIcon3
  #Gadget_hittest_hitcombo
EndEnumeration

#GadgetIndex = #PB_Compiler_EnumerationValue

Procedure.l Window_hittest()
  If OpenWindow(#Window_hittest,64,73,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Column hit test")
    If CreateGadgetList(WindowID(#Window_hittest))
      Frame3DGadget(#Gadget_hittest_fmain,5,0,630,475,"")
      ListIconGadget(#Gadget_hittest_ListIcon3,15,15,610,450,"Column 1",292,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
        AddGadgetColumn(#Gadget_hittest_ListIcon3,1,"Column 2",292)
      ComboBoxGadget(#Gadget_hittest_hitcombo,0,0,80,200)
      HideGadget(#Gadget_hittest_hitcombo,1)
      HideWindow(#Window_hittest,0)
      ProcedureReturn WindowID()
    EndIf
  EndIf
EndProcedure

If Window_hittest()

  For flooble = 0 To 10
    AddGadgetItem(#Gadget_hittest_ListIcon3, -1, "column 1" + Chr(10) + "column 2", 0)
  Next flooble
  
  For flooble = 0 To 10
    AddGadgetItem(#Gadget_hittest_hitcombo, -1, "Macaroni " + Str(flooble), 0)
  Next flooble

  quithittest = 0
  
  Repeat
    EventID  = WaitWindowEvent()
    MenuID   = EventMenuID()
    GadgetID = EventGadgetID()
    WindowID = EventWindowID()

    Select EventID
      Case #PB_Event_CloseWindow
        If WindowID = #Window_hittest
          quithittest = 1
        EndIf

      Case #PB_Event_Gadget
        Select GadgetID
          Case #Gadget_hittest_ListIcon3
            Select EventType()
              Case #PB_EventType_LeftDoubleClick    : Gosub TestColumn
              Case #PB_EventType_RightDoubleClick
              Case #PB_EventType_RightClick
              Default
            EndSelect
          Case #Gadget_hittest_hitcombo             : Gosub GetCombo
        EndSelect

    EndSelect
  Until quithittest
  CloseWindow(#Window_hittest)
EndIf
End

TestColumn: 

  ;MessageRequester("Here we are:", "List event fired", #PB_MessageRequester_Ok )
 
  temp.POINT 

  GetCursorPos_(temp)
  
  MapWindowPoints_(0, GadgetID(#Gadget_hittest_ListIcon3), temp, 1)
  
  ; SendMessage_(GadgetID(#Gadget_hittest_ListIcon3), #LVM_GETITEMPOSITION, itemNumber , pItem) ; get item position 
  
  ;Column  = Round(temp\x / 292 + 1, 0)
  
  ;Row     = Round(temp\y / 18 + 1, 0)
  
  Debug Str(Column) + "   --   " + Str(Row)
  
  ResizeGadget(#Gadget_hittest_hitcombo, temp\x/292+1, temp\y/18+1, 292, 18)
  
  HideGadget(#Gadget_hittest_hitcombo, 0)
  
Return

GetCombo:

  If EventType() = #PB_EventType_RightClick
    HideGadget(#Gadget_hittest_hitcombo, 1)
  EndIf
  
Return
I've put extraneous junk in here while I was testing because I really don't know what I am doing here!!!

In case anyone is wondering..

Posted: Fri Sep 23, 2005 4:53 am
by Fangbeast
Simply can't post more code a I have no frame of reference in which I can work in. API and I don't mix so i am hoping someone understands what I am aiming for here.

Posted: Fri Sep 23, 2005 4:37 pm
by Pupil
For #1, try to play with this a bit, probably not exactly what you want but closer than what you have now:

Code: Select all

  ; Goes into the test column subroutine
  SendMessage_(GadgetID(#Gadget_hittest_ListIcon3), #LVM_GETITEMRECT, GetGadgetState(#Gadget_hittest_ListIcon3), @Re.RECT)
  MapWindowPoints_(GadgetID(#Gadget_hittest_ListIcon3), WindowID(#Window_hittest), @Re, 2)

  ResizeGadget(#Gadget_hittest_hitcombo, Re\Left, Re\Top, Re\Right-Re\Left, Re\Bottom-Re\Top)

Posted: Fri Sep 23, 2005 8:28 pm
by srod
Avoiding the Win API in this case is a bit of a no no I'm afraid!

I've twiddled with your code a little and with the help of a few API calls we now have the combo box appearing over the selected cell. Also, I've resized the combo box edit control (again with an API call!)

Getting the combo box to appear in the correct position is best achieved by initially creating the combo box as a child of the listicon gadget, rather than as a control completely independent of the listicon.

The code is very rough and ready and does come with a whole heap of scrolling problems. Problems which require delving into the Win API to address.

Code: Select all

;============================================================================================================================ 
; 
;============================================================================================================================ 

Global BubbleTipStyle.l 

PInfo.LVHITTESTINFO
temp.Point
rc.rect
#LVM_SUBITEMHITTEST = #LVM_FIRST+57 
#LVM_GETSUBITEMRECT = #LVM_FIRST+56 

loadfont(1,"Arial", 9)

;============================================================================================================================ 
; 
;============================================================================================================================ 

BubbleTipStyle  = 0 

Enumeration 1 
  #Window_hittest 
EndEnumeration 

#WindowIndex = #PB_Compiler_EnumerationValue 

Enumeration 1 
  #Gadget_hittest_fmain 
  #Gadget_hittest_ListIcon3 
  #Gadget_hittest_hitcombo 
EndEnumeration 

#GadgetIndex = #PB_Compiler_EnumerationValue 

Procedure.l Window_hittest() 
  If OpenWindow(#Window_hittest,64,73,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Column hit test") 
    If CreateGadgetList(WindowID(#Window_hittest)) 
      Frame3DGadget(#Gadget_hittest_fmain,5,0,630,475,"") 
      ListIconGadget(#Gadget_hittest_ListIcon3,15,15,610,450,"Column 1",292,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection) 
      AddGadgetColumn(#Gadget_hittest_ListIcon3,1,"Column 2",292) 

;Best to create the comboboxgadget as a child of the ListIconGadget.
      CreateGadgetList(gadgetid(#Gadget_hittest_ListIcon3))
      ComboBoxGadget(#Gadget_hittest_hitcombo,0,0,80,200,#PB_ComboBox_Editable) 

      usegadgetlist(windowid(#Window_hittest))
      HideGadget(#Gadget_hittest_hitcombo,1) 
      HideWindow(#Window_hittest,0) 
      setgadgetfont(#Gadget_hittest_ListIcon3,usefont(1))
      ProcedureReturn WindowID() 
    EndIf 
  EndIf 
EndProcedure 

If Window_hittest() 

  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_ListIcon3, -1, "column 1" + Chr(10) + "column 2", 0) 
  Next flooble 
  
  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_hitcombo, -1, "Macaroni " + Str(flooble)) 
  Next flooble 

  quithittest = 0 
  
  Repeat 
    EventID  = WaitWindowEvent() 
    MenuID   = EventMenuID() 
    GadgetID = EventGadgetID() 
    WindowID = EventWindowID() 

    Select EventID 
      Case #PB_Event_CloseWindow 
        If WindowID = #Window_hittest 
          quithittest = 1 
        EndIf 

      Case #PB_Event_Gadget 
        Select GadgetID 
          Case #Gadget_hittest_ListIcon3 
            Select EventType() 
              Case #PB_EventType_LeftClick 
                GetCursorPos_(temp) 
                MapWindowPoints_(0, GadgetID(#Gadget_hittest_ListIcon3), temp, 1) 
                pInfo\pt\x = temp\x
                pInfo\pt\y = temp\y 
                SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_SUBITEMHITTEST, 0, pInfo) 
                if pInfo\iItem <> -1 and pInfo\iSubItem <> -1 ;A cell has been selected.
                  rc\top = pInfo\iSubItem 
                  rc\left = #LVIR_BOUNDS 
                  sendmessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETSUBITEMRECT, pInfo\iItem, rc) 
                  rc\right = rc\left+SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETCOLUMNWIDTH, pInfo\iSubItem, 0)
                  ResizeGadget(#Gadget_hittest_hitcombo, rc\left, rc\top-2, rc\right-rc\left, rc\bottom-rc\top+2)
                  sendmessage_(gadgetid(#Gadget_hittest_hitcombo), #CB_setITEMHEIGHT, -1,rc\bottom-rc\top-2)
                  hidegadget(#Gadget_hittest_hitcombo,0)
                Else
                  hidegadget(#Gadget_hittest_hitcombo,1)
                 endif
              Default 
            EndSelect 
        EndSelect 

    EndSelect 
  Until quithittest 
  CloseWindow(#Window_hittest) 
EndIf 
End 
btw, if you're interested, I've released a beta version of a grid gadget (in the announcement forum) which addresses many of the problems you will face with this code of yours. Instead of a combo box, however, I used a string gadget.

Regards.

Thank you, it's start.

Posted: Sat Sep 24, 2005 3:27 am
by Fangbeast
Pupil wrote:For #1, try to play with this a bit, probably not exactly what you want but closer than what you have now:

Code: Select all

  ; Goes into the test column subroutine
  SendMessage_(GadgetID(#Gadget_hittest_ListIcon3), #LVM_GETITEMRECT, GetGadgetState(#Gadget_hittest_ListIcon3), @Re.RECT)
  MapWindowPoints_(GadgetID(#Gadget_hittest_ListIcon3), WindowID(#Window_hittest), @Re, 2)

  ResizeGadget(#Gadget_hittest_hitcombo, Re\Left, Re\Top, Re\Right-Re\Left, Re\Bottom-Re\Top)
Hello, oh stealer of the royal brain cells?? So this is where you lurk, making it up to those of us with goldfish brains?? Thanks for the hint, this will fix at least one thing:):)

me scared of the API?? Not really!!

Posted: Sat Sep 24, 2005 3:31 am
by Fangbeast
srod wrote:Avoiding the Win API in this case is a bit of a no no I'm afraid!

I've twiddled with your code a little and with the help of a few API calls we now have the combo box appearing over the selected cell. Also, I've resized the combo box edit control (again with an API call!)

Getting the combo box to appear in the correct position is best achieved by initially creating the combo box as a child of the listicon gadget, rather than as a control completely independent of the listicon.

The code is very rough and ready and does come with a whole heap of scrolling problems. Problems which require delving into the Win API to address.

Code: Select all

;============================================================================================================================ 
; 
;============================================================================================================================ 

Global BubbleTipStyle.l 

PInfo.LVHITTESTINFO
temp.Point
rc.rect
#LVM_SUBITEMHITTEST = #LVM_FIRST+57 
#LVM_GETSUBITEMRECT = #LVM_FIRST+56 

loadfont(1,"Arial", 9)

;============================================================================================================================ 
; 
;============================================================================================================================ 

BubbleTipStyle  = 0 

Enumeration 1 
  #Window_hittest 
EndEnumeration 

#WindowIndex = #PB_Compiler_EnumerationValue 

Enumeration 1 
  #Gadget_hittest_fmain 
  #Gadget_hittest_ListIcon3 
  #Gadget_hittest_hitcombo 
EndEnumeration 

#GadgetIndex = #PB_Compiler_EnumerationValue 

Procedure.l Window_hittest() 
  If OpenWindow(#Window_hittest,64,73,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Column hit test") 
    If CreateGadgetList(WindowID(#Window_hittest)) 
      Frame3DGadget(#Gadget_hittest_fmain,5,0,630,475,"") 
      ListIconGadget(#Gadget_hittest_ListIcon3,15,15,610,450,"Column 1",292,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection) 
      AddGadgetColumn(#Gadget_hittest_ListIcon3,1,"Column 2",292) 

;Best to create the comboboxgadget as a child of the ListIconGadget.
      CreateGadgetList(gadgetid(#Gadget_hittest_ListIcon3))
      ComboBoxGadget(#Gadget_hittest_hitcombo,0,0,80,200,#PB_ComboBox_Editable) 

      usegadgetlist(windowid(#Window_hittest))
      HideGadget(#Gadget_hittest_hitcombo,1) 
      HideWindow(#Window_hittest,0) 
      setgadgetfont(#Gadget_hittest_ListIcon3,usefont(1))
      ProcedureReturn WindowID() 
    EndIf 
  EndIf 
EndProcedure 

If Window_hittest() 

  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_ListIcon3, -1, "column 1" + Chr(10) + "column 2", 0) 
  Next flooble 
  
  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_hitcombo, -1, "Macaroni " + Str(flooble)) 
  Next flooble 

  quithittest = 0 
  
  Repeat 
    EventID  = WaitWindowEvent() 
    MenuID   = EventMenuID() 
    GadgetID = EventGadgetID() 
    WindowID = EventWindowID() 

    Select EventID 
      Case #PB_Event_CloseWindow 
        If WindowID = #Window_hittest 
          quithittest = 1 
        EndIf 

      Case #PB_Event_Gadget 
        Select GadgetID 
          Case #Gadget_hittest_ListIcon3 
            Select EventType() 
              Case #PB_EventType_LeftClick 
                GetCursorPos_(temp) 
                MapWindowPoints_(0, GadgetID(#Gadget_hittest_ListIcon3), temp, 1) 
                pInfo\pt\x = temp\x
                pInfo\pt\y = temp\y 
                SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_SUBITEMHITTEST, 0, pInfo) 
                if pInfo\iItem <> -1 and pInfo\iSubItem <> -1 ;A cell has been selected.
                  rc\top = pInfo\iSubItem 
                  rc\left = #LVIR_BOUNDS 
                  sendmessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETSUBITEMRECT, pInfo\iItem, rc) 
                  rc\right = rc\left+SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETCOLUMNWIDTH, pInfo\iSubItem, 0)
                  ResizeGadget(#Gadget_hittest_hitcombo, rc\left, rc\top-2, rc\right-rc\left, rc\bottom-rc\top+2)
                  sendmessage_(gadgetid(#Gadget_hittest_hitcombo), #CB_setITEMHEIGHT, -1,rc\bottom-rc\top-2)
                  hidegadget(#Gadget_hittest_hitcombo,0)
                Else
                  hidegadget(#Gadget_hittest_hitcombo,1)
                 endif
              Default 
            EndSelect 
        EndSelect 

    EndSelect 
  Until quithittest 
  CloseWindow(#Window_hittest) 
EndIf 
End 
btw, if you're interested, I've released a beta version of a grid gadget (in the announcement forum) which addresses many of the problems you will face with this code of yours. Instead of a combo box, however, I used a string gadget.

Regards.
It's isn't that I am scared of the api, it's just that I have no frame of reference when addressing it, not having worked in it at all prior to PureBasic so attemtping to research it is a bit like asming me to translate Chinese to a Dutchman, when all I speak is Australia.

Thanks for pointing out the way, I will start beating the heck out of it and force it to comply.

We are Dyslexic of Borg, prepare to have your ass laminated, Resistance is Ohm!

Found the first problem..

Posted: Sat Sep 24, 2005 5:36 am
by Fangbeast
Under PB; for some weird reason; you have to test for a right click in a combobox when you select an item from its' drop down child list.

For some reason, now that the combo is a child of the form, this selection is no longer being detected as shown when you add the following lines.

Code: Select all

Case #Gadget_hittest_hitcombo ; This is the combobox
  Select EventType()
    Case #PB_EventType_RightClick  : Debug "Item selected"
  EndSelect
You were right, I am going to have lots of problems :roll:

Posted: Sat Sep 24, 2005 1:19 pm
by srod
Fangbeast wrote:Under PB; for some weird reason; you have to test for a right click in a combobox when you select an item from its' drop down child list.
That is weird!

Anyhow, if you proceed with the ComboBox being a child of the ListIcon, then perhaps the best way of trapping the selection of items in the combo is by subclassing the ListIconGadget as shown below. This makes the code quite tight.

Code: Select all

;============================================================================================================================ 
; 
;============================================================================================================================ 

Global BubbleTipStyle.l, OldListProc


PInfo.LVHITTESTINFO 
temp.Point 
rc.rect 
#LVM_SUBITEMHITTEST = #LVM_FIRST+57 
#LVM_GETSUBITEMRECT = #LVM_FIRST+56 

loadfont(1,"Arial", 9) 

;============================================================================================================================ 
; 
;============================================================================================================================ 

BubbleTipStyle  = 0 

Enumeration 1 
  #Window_hittest 
EndEnumeration 

#WindowIndex = #PB_Compiler_EnumerationValue 

Enumeration 1 
  #Gadget_hittest_fmain 
  #Gadget_hittest_ListIcon3 
  #Gadget_hittest_hitcombo 
EndEnumeration 

#GadgetIndex = #PB_Compiler_EnumerationValue 


;The following callback allows a listicon control to be subclassed.
Procedure.l ListIconCallBack(hWnd, uMsg, wParam, lParam) 
Protected result
  Select uMsg 
    case #WM_COMMAND ;This is how the CBN_SELCHANGE message is sent.
      select (wParam>>16) & $ffff ;This contains the notification code.
        case #CBN_SELCHANGE
          debug getgadgetitemtext(#Gadget_hittest_hitcombo,getgadgetstate(#Gadget_hittest_hitcombo),0)
        EndSelect
  
  EndSelect
  result = CallWindowProc_(OldListProc, hWnd, uMsg, wParam, lParam) 
  ProcedureReturn result
EndProcedure



Procedure.l Window_hittest() 
  If OpenWindow(#Window_hittest,64,73,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Column hit test") 
    If CreateGadgetList(WindowID(#Window_hittest)) 
      Frame3DGadget(#Gadget_hittest_fmain,5,0,630,475,"") 
      ListIconGadget(#Gadget_hittest_ListIcon3,15,15,610,450,"Column 1",292,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection) 
      AddGadgetColumn(#Gadget_hittest_ListIcon3,1,"Column 2",292) 

;Best to create the comboboxgadget as a child of the ListIconGadget. 
      CreateGadgetList(gadgetid(#Gadget_hittest_ListIcon3)) 
      ComboBoxGadget(#Gadget_hittest_hitcombo,0,0,80,200,#PB_ComboBox_Editable) 

      usegadgetlist(windowid(#Window_hittest)) 
      HideGadget(#Gadget_hittest_hitcombo,1) 
      HideWindow(#Window_hittest,0) 
      setgadgetfont(#Gadget_hittest_ListIcon3,usefont(1)) 
 
 ;Subclass the ListIconGadget
      OldListProc = SetWindowLong_(GadgetID(#Gadget_hittest_ListIcon3), #GWL_WNDPROC, @ListIconCallBack()) 
      

      ProcedureReturn WindowID() 
    EndIf 
  EndIf 
EndProcedure 

If Window_hittest() 

  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_ListIcon3, -1, "column 1" + Chr(10) + "column 2", 0) 
  Next flooble 
  
  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_hitcombo, -1, "Macaroni " + Str(flooble)) 
  Next flooble 

  quithittest = 0 
  
  Repeat 
    EventID  = WaitWindowEvent() 
    MenuID   = EventMenuID() 
    GadgetID = EventGadgetID() 
    WindowID = EventWindowID() 

    Select EventID 
      Case #PB_Event_CloseWindow 
        If WindowID = #Window_hittest 
          quithittest = 1 
        EndIf 

      Case #PB_Event_Gadget 
        Select GadgetID 
          Case #Gadget_hittest_ListIcon3 
            Select EventType() 
              Case #PB_EventType_LeftClick 
                GetCursorPos_(temp) 
                MapWindowPoints_(0, GadgetID(#Gadget_hittest_ListIcon3), temp, 1) 
                pInfo\pt\x = temp\x 
                pInfo\pt\y = temp\y 
                SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_SUBITEMHITTEST, 0, pInfo) 
                if pInfo\iItem <> -1 and pInfo\iSubItem <> -1 ;A cell has been selected. 
                  rc\top = pInfo\iSubItem 
                  rc\left = #LVIR_BOUNDS 
                  sendmessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETSUBITEMRECT, pInfo\iItem, rc) 
                  rc\right = rc\left+SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETCOLUMNWIDTH, pInfo\iSubItem, 0) 
                  ResizeGadget(#Gadget_hittest_hitcombo, rc\left, rc\top-2, rc\right-rc\left, rc\bottom-rc\top+2) 
                  sendmessage_(gadgetid(#Gadget_hittest_hitcombo), #CB_setITEMHEIGHT, -1,rc\bottom-rc\top-2) 
                  hidegadget(#Gadget_hittest_hitcombo,0) 
                Else 
                  hidegadget(#Gadget_hittest_hitcombo,1) 
                 endif 
              Default 
            EndSelect 
        EndSelect 

    EndSelect 
  Until quithittest 
  CloseWindow(#Window_hittest) 
EndIf 
End 

Thanks srod, this now works great

Posted: Sat Sep 24, 2005 2:11 pm
by Fangbeast
Ive added the few lines left to do in the callback to set the underlying text back to the ListIconGadget.

Only 2 questions left then (grin)

1. What does "SubClassing" mean in English? What does it do to a gadget?

2. Is there any way to restrict the gadget to only popup in column 1, not column 0?

And thank you for all of your kind efforts. I look forward to saving people's wrists and not wearing out their mouse with this way of doing things. 8)

Posted: Sat Sep 24, 2005 2:47 pm
by srod
Fangbeast wrote:What does "SubClassing" mean in English? What does it do to a gadget?
With each control comes a default Window procedure which is responsible for all sorts of processing; painting, resizing etc (depending on the control). Indeed, individual controls (e.g. the ComboBox) either send messages (depending upon the nature of the message) to their own Window procedure or to that of their parent control (main window, container control etc.)

By intercepting such messages (by simply changing the address of the Window procedure to point to one of our own functions) we can take complete charge (almost!) and force the control to behave the way we want it to. For example, consider a string gadget in which we wanted to intercept all characters entered and convert them immediately to uppercase characters. This can be achieved by subclassing the StringGadget and examining each individual character as it is typed before it is displayed in the gadget etc.

In the case of your ComboBox gadget, the message of particular interest; the 'CBN_SELCHANGE' message, which is fired everytime an item is selected, is actually sent to the parent of the ComboBox, i.e. the ListIcon gadget in this case.

I thus subclassed the ListIconGadget by redirecting Windows to send all messages intended for the ListIcon to my own function 'ListIconCallBack()'. This was achieved with the command:

Code: Select all

OldListProc = SetWindowLong_(GadgetID(#Gadget_hittest_ListIcon3), #GWL_WNDPROC, @ListIconCallBack()) 
So, everytime the user selects an item in the ComboBox, the underlying command message is sent to my custom procedure rather than the default procedure. Note, however, that I do call the default procedure within my own custom one in order to allow windows to paint the control etc.
Fangbeast wrote:Is there any way to restrict the gadget to only popup in column 1, not column 0?
Done!

Code: Select all

;============================================================================================================================ 
; 
;============================================================================================================================ 

Global BubbleTipStyle.l, OldListProc


PInfo.LVHITTESTINFO 
temp.Point 
rc.rect 
#LVM_SUBITEMHITTEST = #LVM_FIRST+57 
#LVM_GETSUBITEMRECT = #LVM_FIRST+56 

loadfont(1,"Arial", 9) 

;============================================================================================================================ 
; 
;============================================================================================================================ 

BubbleTipStyle  = 0 

Enumeration 1 
  #Window_hittest 
EndEnumeration 

#WindowIndex = #PB_Compiler_EnumerationValue 

Enumeration 1 
  #Gadget_hittest_fmain 
  #Gadget_hittest_ListIcon3 
  #Gadget_hittest_hitcombo 
EndEnumeration 

#GadgetIndex = #PB_Compiler_EnumerationValue 


;The following callback allows a listicon control to be subclassed.
Procedure.l ListIconCallBack(hWnd, uMsg, wParam, lParam) 
Protected result
  Select uMsg 
    case #WM_COMMAND ;This is how the CBN_SELCHANGE message is sent.
      select (wParam>>16) & $ffff ;This contains the notification code.
        case #CBN_SELCHANGE
          debug getgadgetitemtext(#Gadget_hittest_hitcombo,getgadgetstate(#Gadget_hittest_hitcombo),0)
        EndSelect
  
  EndSelect
  result = CallWindowProc_(OldListProc, hWnd, uMsg, wParam, lParam) 
  ProcedureReturn result
EndProcedure



Procedure.l Window_hittest() 
  If OpenWindow(#Window_hittest,64,73,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Column hit test") 
    If CreateGadgetList(WindowID(#Window_hittest)) 
      Frame3DGadget(#Gadget_hittest_fmain,5,0,630,475,"") 
      ListIconGadget(#Gadget_hittest_ListIcon3,15,15,610,450,"Column 1",292,#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection) 
      AddGadgetColumn(#Gadget_hittest_ListIcon3,1,"Column 2",292) 

;Best to create the comboboxgadget as a child of the ListIconGadget. 
      CreateGadgetList(gadgetid(#Gadget_hittest_ListIcon3)) 
      ComboBoxGadget(#Gadget_hittest_hitcombo,0,0,80,200,#PB_ComboBox_Editable) 

      usegadgetlist(windowid(#Window_hittest)) 
      HideGadget(#Gadget_hittest_hitcombo,1) 
      HideWindow(#Window_hittest,0) 
      setgadgetfont(#Gadget_hittest_ListIcon3,usefont(1)) 
 
 ;Subclass the ListIconGadget
      OldListProc = SetWindowLong_(GadgetID(#Gadget_hittest_ListIcon3), #GWL_WNDPROC, @ListIconCallBack()) 
      

      ProcedureReturn WindowID() 
    EndIf 
  EndIf 
EndProcedure 

If Window_hittest() 

  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_ListIcon3, -1, "column 1" + Chr(10) + "column 2", 0) 
  Next flooble 
  
  For flooble = 0 To 10 
    AddGadgetItem(#Gadget_hittest_hitcombo, -1, "Macaroni " + Str(flooble)) 
  Next flooble 

  quithittest = 0 
  
  Repeat 
    EventID  = WaitWindowEvent() 
    MenuID   = EventMenuID() 
    GadgetID = EventGadgetID() 
    WindowID = EventWindowID() 

    Select EventID 
      Case #PB_Event_CloseWindow 
        If WindowID = #Window_hittest 
          quithittest = 1 
        EndIf 

      Case #PB_Event_Gadget 
        Select GadgetID 
          Case #Gadget_hittest_ListIcon3 
            Select EventType() 
              Case #PB_EventType_LeftClick 
                GetCursorPos_(temp) 
                MapWindowPoints_(0, GadgetID(#Gadget_hittest_ListIcon3), temp, 1) 
                pInfo\pt\x = temp\x 
                pInfo\pt\y = temp\y 
                SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_SUBITEMHITTEST, 0, pInfo) 
;The 'pInfo\iSubItem = 1' in the following statement ensures that the combo only
;appears when the user clicks column 1.
                if pInfo\iItem <> -1 and pInfo\iSubItem = 1;A cell has been selected. 
                  rc\top = pInfo\iSubItem 
                  rc\left = #LVIR_BOUNDS 
                  sendmessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETSUBITEMRECT, pInfo\iItem, rc) 
                  rc\right = rc\left+SendMessage_(gadgetid(#Gadget_hittest_ListIcon3), #LVM_GETCOLUMNWIDTH, pInfo\iSubItem, 0) 
                  ResizeGadget(#Gadget_hittest_hitcombo, rc\left, rc\top-2, rc\right-rc\left, rc\bottom-rc\top+2) 
                  sendmessage_(gadgetid(#Gadget_hittest_hitcombo), #CB_setITEMHEIGHT, -1,rc\bottom-rc\top-2) 
                  hidegadget(#Gadget_hittest_hitcombo,0) 
                Else 
                  hidegadget(#Gadget_hittest_hitcombo,1) 
                 endif 
              Default 
            EndSelect 
        EndSelect 

    EndSelect 
  Until quithittest 
  CloseWindow(#Window_hittest) 
EndIf 
End 

Posted: Sat Sep 24, 2005 3:57 pm
by rsts
Man - this comunity is fantastic.

You guys who give so freely are wonderful.

Hope someday I'll be able to make these kinds of contributions.

Posted: Sat Sep 24, 2005 4:10 pm
by srod
Aye, without the generosity of the PB community, I'd have thrown my computer through a window a long time ago!
Hope someday I'll be able to make these kinds of contributions.
:D

Lots of great people here

Posted: Sat Sep 24, 2005 11:36 pm
by Fangbeast
I got my start from asking loads of questions and many people helped me. Sometimes I was cranky and got hit over the head repeatedly and with great force with a rubber chicken. When i asked nicely, I got help.

Have also been able to contribute myself (now that I learned a few things) with small sources, complete projects, tutorials and snippet (never thought I could). Also released the complete source to my address book to someone (i'm very happy that it works properly) (grin).

@srod. Thank you for your patience, I'm learning a lot. Now I can update the address book code with this and re-release a better program.

Now to sneak into the kitchen ad have breakfast!

Success!

Posted: Sun Sep 25, 2005 2:38 am
by Fangbeast
After starting to integrate srod's code this morning (before breakfast!!), I nearly destroyed the code when my daughter barged into the room, scared the heck out of me and started flapping her gums.

But I did it, stayed calm, just listened, gave short yes and no answers (like the ones you give the police until you know what you are being accused of: Jeff Foxworthy quote).

It works well in the main program. Seriously, this saves a lot of mouse movement and possible wrist pain. You don't have to go up and down the form any more, mapping fields.

@Srod, thanks for the help, this was a great acheivment.

WIll update this to my home page today.

Posted: Sun Sep 25, 2005 12:47 pm
by srod
Glad to help.