ComboBox with large icons

Windows specific forum
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

ComboBox with large icons

Post by IdeasVacuum »

Here is code by netmaestro (see RS Basic's WinAPI Library) that customises a ComboBox Gadget to display large icons. It works very well but I have some issues.

Code: Select all

;Autor: netmaestro

EnableExplicit

Define EventID
Define hIcon1
Define hIcon2
Define hIcon3
Global CBID = 1
Global CBIconSize = 32;oder 64
Global CBTextTopPos = 10;oder 28

hIcon1 = ExtractIcon_(0, #PB_Compiler_Home + "PureBasic.exe", 1)
hIcon2 = ExtractIcon_(0, "shell32.dll", 10)
hIcon3 = ExtractIcon_(0, "shell32.dll", 20)

Global Dim CBIcons(2)
CBIcons(0) = hIcon1
CBIcons(1) = hIcon2
CBIcons(2) = hIcon3

Procedure FreehIcons()
  Protected k
  
  For k = 0 To ArraySize(CBIcons())
    DestroyIcon_(CBIcons(k))
  Next
  
EndProcedure

Procedure WinProc(hwnd, msg, wparam, lparam)
  Protected result
  Protected *dis.DRAWITEMSTRUCT
  Protected text$
  Protected hBrush
  Protected oldbrush
  Protected *mis.MEASUREITEMSTRUCT
  
  result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lparam
      If *dis\ctlid = CBID
        With *dis
          text$ = GetGadgetItemText(\ctlid, \itemid)
          If \itemstate & #ODS_SELECTED 
            hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
            oldbrush = SelectObject_(\hdc, hBrush)
            FillRect_(\hdc, \rcitem, hBrush)
            DeleteObject_(hBrush)
            DrawFocusRect_(\hdc, \rcitem)
            If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
              DrawIconEx_(\hdc, 4,\rcitem\top+1, CBIcons(\itemid),CBIconSize,CBIconSize, 0,0,#DI_NORMAL|#DI_COMPAT)
            EndIf
            SelectObject_(\hdc, oldbrush)
            SetBkColor_( \hdc, GetSysColor_(#COLOR_HIGHLIGHT))
            TextOut_( \hdc, \rcItem\left+CBIconSize+8, \rcItem\top+CBTextTopPos, text$, Len(text$))
          Else
            hBrush = CreateSolidBrush_(#White)
            oldbrush = SelectObject_(\hdc, hBrush)
            FillRect_(\hdc, \rcitem, hBrush)
            DeleteObject_(hBrush)
            SelectObject_(\hdc, oldbrush)
            If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
              DrawIconEx_(\hdc, 4,\rcitem\top+1, CBIcons(\itemid),CBIconSize,CBIconSize, 0,0,#DI_NORMAL)
            EndIf
            SetBkColor_( \hdc, #White)
            TextOut_( \hdc, \rcItem\left+CBIconSize+8, \rcItem\top+CBTextTopPos, text$, Len(text$))
          EndIf
        EndWith
      EndIf
      
    Case #WM_MEASUREITEM
      *mis.MEASUREITEMSTRUCT = lparam
      If *mis\ctlid = CBID
        *mis\itemheight = CBIconSize+2
      EndIf
  EndSelect
  
  ProcedureReturn result
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinProc())
  
  ComboBoxGadget(1, 10, 10, 200, CBIconSize+8, #CBS_OWNERDRAWVARIABLE | #CBS_HASSTRINGS)
  AddGadgetItem(1, -1, "Eintrag 1", 0, 0)
  AddGadgetItem(1, -1, "Eintrag 2", 0, 0)
  AddGadgetItem(1, -1, "Eintrag 3", 0, 0)
  
  SetGadgetState(1, 0)
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      FreehIcons()
      End
    EndIf
  ForEver
EndIf
The problems are:
1) How to have multiple custom combos on the same window? A callback for each? (owch).
2) The drop down drops by only one row - so a lot of clicking is required to select an item.
3) Tiny text - having added a large icon, a bigger font height for the text would be good.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
breeze4me
Enthusiast
Enthusiast
Posts: 523
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: ComboBox with large icons

Post by breeze4me »

1) How to have multiple custom combos on the same window? A callback for each? (owch).
2) The drop down drops by only one row - so a lot of clicking is required to select an item.
3) Tiny text - having added a large icon, a bigger font height for the text would be good.
1) Only icons need to be managed separately in the code below.
2), 3) See the code.

Code: Select all

;Autor: netmaestro

EnableExplicit

Define EventID, i
Global CBIconSize = 32

Global Dim CBIcons(11)

For i = 0 To 11
  CBIcons(i) = ExtractIcon_(0, "shell32.dll", i + 7)
Next

Procedure FreehIcons()
  Protected k
  
  For k = 0 To ArraySize(CBIcons())
    DestroyIcon_(CBIcons(k))
  Next
  
EndProcedure

Procedure WinProc(hwnd, msg, wparam, lparam)
  Protected result
  Protected *dis.DRAWITEMSTRUCT
  Protected text$, hIcon
  Protected hBrush
  Protected oldbrush
  Protected *mis.MEASUREITEMSTRUCT
  
  result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lparam
      Select *dis\ctlid
        Case 1, 2
          If *dis\itemid >= 0
            
            With *dis
              hIcon = GetGadgetItemData(\ctlid, \itemid)
              text$ = GetGadgetItemText(\ctlid, \itemid)
              
              If \itemstate & #ODS_SELECTED 
                hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                DrawFocusRect_(\hdc, \rcitem)
                If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
                  DrawIconEx_(\hdc, 4,\rcitem\top+1, hIcon,CBIconSize,CBIconSize, 0,0,#DI_NORMAL|#DI_COMPAT)
                EndIf
                SelectObject_(\hdc, oldbrush)
                SetBkColor_( \hdc, GetSysColor_(#COLOR_HIGHLIGHT))
                \rcItem\left+CBIconSize+8
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              Else
                hBrush = CreateSolidBrush_(#White)
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                SelectObject_(\hdc, oldbrush)
                If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
                  DrawIconEx_(\hdc, 4,\rcitem\top+1, hIcon,CBIconSize,CBIconSize, 0,0,#DI_NORMAL)
                EndIf
                SetBkColor_( \hdc, #White)
                \rcItem\left+CBIconSize+8
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              EndIf
            EndWith
            
          EndIf
          
      EndSelect
  EndSelect
  
  ProcedureReturn result
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinProc())
  
  
  ComboBoxGadget(1, 10, 10, 200, CBIconSize+8, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(1, -1, "Eintrag 1")
  AddGadgetItem(1, -1, "Eintrag 2")
  AddGadgetItem(1, -1, "Eintrag 3")
  AddGadgetItem(1, -1, "Eintrag 4")
  AddGadgetItem(1, -1, "Eintrag 5")
  AddGadgetItem(1, -1, "Eintrag 6")
  
  For i = 0 To 5
    SetGadgetItemData(1, i, CBIcons(i))
  Next
  
  ComboBoxGadget(2, 10, 70, 200, CBIconSize+8, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(2, -1, "test 1")
  AddGadgetItem(2, -1, "test 2")
  AddGadgetItem(2, -1, "test 3")
  AddGadgetItem(2, -1, "test 4")
  AddGadgetItem(2, -1, "test 5")
  AddGadgetItem(2, -1, "test 6")
  
  For i = 0 To 5
    SetGadgetItemData(2, i, CBIcons(i + 6))
  Next
  
  LoadFont(0, "arial", 13)
  SetGadgetFont(1, FontID(0))
  SetGadgetFont(2, FontID(0))
  
  SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBIconSize+8)
  SendMessage_(GadgetID(1), #CB_SETMINVISIBLE, 3, 0)
  
  SetGadgetState(1, 0)
  
  SendMessage_(GadgetID(2), #CB_SETITEMHEIGHT, 0, CBIconSize+8)
  SendMessage_(GadgetID(2), #CB_SETMINVISIBLE, 4, 0)
  
  SetGadgetState(2, 0)
  
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      FreehIcons()
      End
    EndIf
  ForEver
EndIf
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ComboBox with large icons

Post by IdeasVacuum »

That works very well breeze4me, thank you!

I was getting strange results using SetGadgetFont() and thought it was because of the API used in the CallBack but your code jumps that hurdle. I also had the icons in seperate arrays for the separate Combos. Your method of having "1 array for all" fixed further weird behaviour where I was getting all icons in all combos. I was extremely tired while trying to modify the code but I wouldn't have discovered the solution anyway.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
kernadec
Enthusiast
Enthusiast
Posts: 146
Joined: Tue Jan 05, 2010 10:35 am

Re: ComboBox with large icons

Post by kernadec »

hi,
cool, we can choose the size of icons
so for fun
best regard

Code: Select all

;Autor: netmaestro

EnableExplicit

Define EventID, i
Global CBIconSize = 32    ; defaut

;############# set width height icon and font
Global WH_icon = 60        ; width height icon and combobox
Global WH_font = 20        ; heigh font
                           ;########################################################

Global Dim CBIcons(11)

For i = 0 To 11
  CBIcons(i) = ExtractIcon_(0, "shell32.dll", i + 7)
Next

Procedure FreehIcons()
  Protected k
  
  For k = 0 To ArraySize(CBIcons())
    DestroyIcon_(CBIcons(k))
  Next
  
EndProcedure

Procedure WinProc(hwnd, msg, wparam, lparam)
  Protected result
  Protected *dis.DRAWITEMSTRUCT
  Protected text$, hIcon
  Protected hBrush
  Protected oldbrush
  Protected *mis.MEASUREITEMSTRUCT
  
  result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lparam
      Select *dis\ctlid
        Case 1, 2
          If *dis\itemid >= 0
            
            With *dis
              hIcon = GetGadgetItemData(\ctlid, \itemid)
              text$ = GetGadgetItemText(\ctlid, \itemid)
              
              If \itemstate & #ODS_SELECTED
                hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                DrawFocusRect_(\hdc, \rcitem)
                If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
                  DrawIconEx_(\hdc, 4,\rcitem\top+1, hIcon,CBIconSize + WH_icon,CBIconSize + WH_icon, 0,0,#DI_NORMAL|#DI_COMPAT)
                EndIf
                SelectObject_(\hdc, oldbrush)
                SetBkColor_( \hdc, GetSysColor_(#COLOR_HIGHLIGHT))
                \rcItem\left+CBIconSize + WH_icon  + WH_font
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              Else
                hBrush = CreateSolidBrush_(#White)
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                SelectObject_(\hdc, oldbrush)
                If \itemid >=0 And \itemid <= CountGadgetItems(\ctlid)-1
                  DrawIconEx_(\hdc, 4,\rcitem\top+1, hIcon,CBIconSize + WH_icon,CBIconSize + WH_icon, 0,0,#DI_NORMAL)
                EndIf
                SetBkColor_( \hdc, #White)
                \rcItem\left+CBIconSize + WH_icon + WH_font
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              EndIf
            EndWith
            
          EndIf
          
      EndSelect
  EndSelect
  
  ProcedureReturn result
EndProcedure

If OpenWindow(0, 0, 0, 500, 500, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinProc())
  
  
  ComboBoxGadget(1, 10, 10, 300, CBIconSize + WH_icon + 6, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(1, -1, " Eintrag 1")
  AddGadgetItem(1, -1, " Eintrag 2")
  AddGadgetItem(1, -1, " Eintrag 3")
  AddGadgetItem(1, -1, " Eintrag 4")
  AddGadgetItem(1, -1, " Eintrag 5")
  AddGadgetItem(1, -1, " Eintrag 6")
  
  For i = 0 To 5
    SetGadgetItemData(1, i, CBIcons(i))
  Next
  
  ComboBoxGadget(2, 10, 160, 300, CBIconSize + WH_icon + 6, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(2, -1, " test 1")
  AddGadgetItem(2, -1, " test 2")
  AddGadgetItem(2, -1, " test 3")
  AddGadgetItem(2, -1, " test 4")
  AddGadgetItem(2, -1, " test 5")
  AddGadgetItem(2, -1, " test 6")
  
  For i = 0 To 5
    SetGadgetItemData(2, i, CBIcons(i + 6))
  Next
  
  LoadFont(0, "arial", WH_font)
  SetGadgetFont(1, FontID(0))
  SetGadgetFont(2, FontID(0))
  
  SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBIconSize + WH_icon + 6)
  SendMessage_(GadgetID(1), #CB_SETMINVISIBLE, 3, 0)
  
  SetGadgetState(1, 0)
  
  SendMessage_(GadgetID(2), #CB_SETITEMHEIGHT, 0, CBIconSize + WH_icon + 6)
  SendMessage_(GadgetID(2), #CB_SETMINVISIBLE, 4, 0)
  
  SetGadgetState(2, 0)
  
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      FreehIcons()
      End
    EndIf
  ForEver
EndIf
User avatar
kernadec
Enthusiast
Enthusiast
Posts: 146
Joined: Tue Jan 05, 2010 10:35 am

Re: ComboBox with large icons

Post by kernadec »

hi,
the previous code modifying does this without problem
best regard
Example by changing the size on line 9

Code: Select all

WH_icon = 60
Image
Last edited by kernadec on Sat Mar 06, 2021 6:50 am, edited 3 times in total.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ComboBox with large icons

Post by IdeasVacuum »

Thanks guys.

Well, nearly there, but not nearly there. When I integrate the code into my project, I have an issue with the drop-down rows being too narrow.

Image

In your code:

Code: Select all

SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBIconSize + 8)
... I can change 8 to 80 and I get very tall rows - if I do that in mine, I get no rows at all.

Second issue is that only .ico bitmaps are accepted, I can't just load my icon files via LoadImage(). I'm going to try Rashad's code here: viewtopic.php?f=12&t=59815 using CreateIconIndirect
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
breeze4me
Enthusiast
Enthusiast
Posts: 523
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: ComboBox with large icons

Post by breeze4me »

IdeasVacuum wrote:Thanks guys.

Well, nearly there, but not nearly there. When I integrate the code into my project, I have an issue with the drop-down rows being too narrow.

Image

In your code:

Code: Select all

SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBIconSize + 8)
... I can change 8 to 80 and I get very tall rows - if I do that in mine, I get no rows at all.
Some code parts seem to be preventing the size change. This may be due to the combobox flags, or an issue within the callback function. It could be just a drawing coordinate issue. I don't know.
IdeasVacuum wrote:Second issue is that only .ico bitmaps are accepted, I can't just load my icon files via LoadImage(). I'm going to try Rashad's code here: viewtopic.php?f=12&t=59815 using CreateIconIndirect

To use a PB image...

Code: Select all

;Autor: netmaestro

EnableExplicit

Define EventID, i
Global CBIconSize = 32

Global Dim CBIcons(11)

For i = 0 To 11
  ;CBIcons(i) = ExtractIcon_(0, "shell32.dll", i + 7)
  CBIcons(i) = CreateImage(#PB_Any, 32, 32, 24, #Green)
Next

Procedure WinProc(hwnd, msg, wparam, lparam)
  Protected result
  Protected *dis.DRAWITEMSTRUCT
  Protected text$, Image, hDC
  Protected hBrush
  Protected oldbrush
  Protected *mis.MEASUREITEMSTRUCT
  
  result = #PB_ProcessPureBasicEvents
  
  Select msg
    Case #WM_DRAWITEM
      *dis.DRAWITEMSTRUCT = lparam
      Select *dis\ctlid
        Case 1, 2
          If *dis\itemid >= 0
            
            With *dis
              Image = GetGadgetItemData(\ctlid, \itemid)
              text$ = GetGadgetItemText(\ctlid, \itemid)
              
              If \itemstate & #ODS_SELECTED 
                hBrush = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                DrawFocusRect_(\hdc, \rcitem)
                
                hDC = StartDrawing(ImageOutput(Image))
                If hDC
                  BitBlt_(\hdc, 4, \rcitem\top+1, 32, 32, hDC, 0, 0, #SRCCOPY)
                  StopDrawing()
                EndIf
                
                SelectObject_(\hdc, oldbrush)
                SetBkColor_( \hdc, GetSysColor_(#COLOR_HIGHLIGHT))
                \rcItem\left+CBIconSize+8
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              Else
                hBrush = CreateSolidBrush_(#White)
                oldbrush = SelectObject_(\hdc, hBrush)
                FillRect_(\hdc, \rcitem, hBrush)
                DeleteObject_(hBrush)
                SelectObject_(\hdc, oldbrush)
                
                hDC = StartDrawing(ImageOutput(Image))
                If hDC
                  BitBlt_(\hdc, 4, \rcitem\top+1, 64, 64, hDC, 0, 0, #SRCCOPY)
                  StopDrawing()
                EndIf
                
                SetBkColor_( \hdc, #White)
                \rcItem\left+CBIconSize+8
                DrawText_( \hdc, text$, Len(text$), \rcItem, #DT_SINGLELINE | #DT_VCENTER)
              EndIf
            EndWith
            
          EndIf
          
      EndSelect
  EndSelect
  
  ProcedureReturn result
EndProcedure

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  SetWindowCallback(@WinProc())
  
  
  ComboBoxGadget(1, 10, 10, 200, CBIconSize+8, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(1, -1, "Eintrag 1")
  AddGadgetItem(1, -1, "Eintrag 2")
  AddGadgetItem(1, -1, "Eintrag 3")
  AddGadgetItem(1, -1, "Eintrag 4")
  AddGadgetItem(1, -1, "Eintrag 5")
  AddGadgetItem(1, -1, "Eintrag 6")
  
  For i = 0 To 5
    SetGadgetItemData(1, i, CBIcons(i))
  Next
  
  ComboBoxGadget(2, 10, 70, 200, CBIconSize+8, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
  AddGadgetItem(2, -1, "test 1")
  AddGadgetItem(2, -1, "test 2")
  AddGadgetItem(2, -1, "test 3")
  AddGadgetItem(2, -1, "test 4")
  AddGadgetItem(2, -1, "test 5")
  AddGadgetItem(2, -1, "test 6")
  
  For i = 0 To 5
    SetGadgetItemData(2, i, CBIcons(i + 6))
  Next
  
  LoadFont(0, "arial", 13)
  SetGadgetFont(1, FontID(0))
  SetGadgetFont(2, FontID(0))
  
  SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBIconSize+8)
  ;SendMessage_(GadgetID(1), #CB_SETMINVISIBLE, 3, 0)
  
  SetGadgetState(1, 0)
  
  SendMessage_(GadgetID(2), #CB_SETITEMHEIGHT, 0, CBIconSize+8)
  ;SendMessage_(GadgetID(2), #CB_SETMINVISIBLE, 4, 0)
  
  SetGadgetState(2, 0)
  
  
  Repeat
    EventID = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      
      End
    EndIf
  ForEver
EndIf
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4661
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBox with large icons

Post by RASHAD »

- Optimized and straight forward code
- Using normal images
- Can be as many as ComboBox gadgets

Code: Select all

Global Iconsize ,CBh ,hBrush , hBrush2
Global icon.ICONINFO
Global Dim combo(10),Dim combo2(10)

hBrush = CreateSolidBrush_($E8B838)
hBrush2 = CreateSolidBrush_($FFFFFF)
Iconsize = 32
CBh = Iconsize + 2

Procedure img2icon(gad,img,iconsize)
  ResizeImage(img,iconsize,iconsize)
  icon\fIcon = 1
  icon\hbmMask = ImageID(img)
  icon\hbmColor = ImageID(img)
  iconh = CreateIconIndirect_(@ICON)
  If gad = 0
    combo(img) = iconh
  ElseIf gad = 1
    combo2(img) = iconh
  EndIf
  FreeImage(img)
EndProcedure

LoadImage(0, "g:\mmedia\pictures\Image0.bmp")
img2icon(0 ,0,iconsize)
LoadImage(1, "g:\mmedia\pictures\Image2.bmp")
img2icon(0,1,iconsize) 
LoadImage(2, "g:\mmedia\pictures\Image3.bmp")
img2icon(0,2,iconsize) 

LoadImage(0, "g:\mmedia\pictures\Image4.bmp")
img2icon(1 , 0,iconsize)
LoadImage(1, "g:\mmedia\pictures\Image5.bmp")
img2icon(1 , 1,iconsize) 
LoadImage(2, "g:\mmedia\pictures\Image6.bmp")
img2icon(1 , 2,iconsize) 

Procedure winCB(hWnd, uMsg, wParam, lParam) 
  Result = #PB_ProcessPureBasicEvents 
  Select uMsg 
    Case #WM_DRAWITEM 
      *DrawItem.DRAWITEMSTRUCT = lParam
      If *DrawItem\CtlType = #ODT_COMBOBOX 
        If *DrawItem\itemID <> -1
          If *DrawItem\itemstate & #ODS_SELECTED
            FillRect_(*DrawItem\hDC,*DrawItem\rcitem, hBrush)
          Else
            FillRect_(*DrawItem\hDC,*DrawItem\rcitem, hBrush2)
          EndIf
          SetBkMode_(*DrawItem\hDC, #TRANSPARENT	)
          Text$ = GetGadgetItemText(*DrawItem\CtlID,*DrawItem\itemID)
          If *DrawItem\CtlID = 0
            DrawIconEx_(*DrawItem\hDC, *DrawItem\rcItem\left   , *DrawItem\rcItem\top, combo(*DrawItem\itemID) , iconsize,iconsize, 0, 0, #DI_NORMAL) 
          ElseIf *DrawItem\CtlID = 1
            DrawIconEx_(*DrawItem\hDC, *DrawItem\rcItem\left   , *DrawItem\rcItem\top, combo2(*DrawItem\itemID) , iconsize,iconsize, 0, 0, #DI_NORMAL) 
          EndIf          
          *DrawItem\rcItem\left = CBh + 4
          DrawText_(*DrawItem\hDC, text$, Len(text$),*DrawItem\rcItem, #DT_SINGLELINE | #DT_VCENTER)
        EndIf 
      EndIf 
  EndSelect 
  ProcedureReturn Result 
EndProcedure

OpenWindow(0, 0, 0, 600, 400, "Combobox - own icons", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_TitleBar ) 
SetWindowCallback(@winCB())  
ComboBoxGadget(0, 10, 10, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS) 
SendMessage_(GadgetID(0), #CB_SETITEMHEIGHT, 0, CBh)
SendMessage_(GadgetID(0), #CB_SETMINVISIBLE, 10, 0)  ;10 Items before the ScrollBar show up

AddGadgetItem(0, -1, "Item # 1")
AddGadgetItem(0, -1, "Item # 2")
AddGadgetItem(0, -1, "Item # 3") 
SetGadgetState(0, 0)

ComboBoxGadget(1, 10, 65, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS) 
SendMessage_(GadgetID(1), #CB_SETITEMHEIGHT, 0, CBh)
SendMessage_(GadgetID(1), #CB_SETMINVISIBLE, 10, 0)

AddGadgetItem(1, -1, "Item # 4")
AddGadgetItem(1, -1, "Item # 5")
AddGadgetItem(1, -1, "Item # 6")
SetGadgetState(1, 2)

Repeat 
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Quit = 1
  EndSelect
Until Quit = 1
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ComboBox with large icons

Post by IdeasVacuum »

Thanks for all the help guys - looks like Rashad has sneaked into the penalty area and scored a 90+5 minutes goal :mrgreen:
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ComboBox with large icons

Post by IdeasVacuum »

What do you know - When I integrate Rashad's code into my project, I still have an issue with the drop-down rows being too narrow. No matter what height #CB_SETITEMHEIGHT is set to, the item height defaults to 14 pixels. Note also the drop-down has a scrollbar, no matter what value #CB_SETMINVISIBLE is set to. So what I'm trying to work out is what could be stopping those messages from taking effect.

Image

I have butchered Rashad's code to make the environment the same as my project - the Combos are on a Canvas, which is on a Panel Gadget. The font height is tweaked according to dpi, The Window is defined in a procedure, the Window is invisible until built ...... and Rashad's code still works perfectly.

In my project, perhaps the most major difference is that the call back is shared with two sub windows. However, if I comment their stuff out leaving only the combos(main window), still no joy.

Download .bmps

Code: Select all

Enumeration
#Img0
#Img1
#Img2
#Img3
#Img4
#Img5
#Win
#WinTmp
#Panel
#Canvas
#StrFocus
#Combo0
#Combo1
#Font12R
EndEnumeration

If OpenWindow(#WinTmp, 0, 0, 100, 100, "", #PB_Window_Tool | #PB_Window_Invisible)

          If StartVectorDrawing(WindowVectorOutput(#WinTmp, #PB_Unit_Pixel))

                  Global dgDpiY.d = VectorResolutionY()

                  StopVectorDrawing()
          EndIf

          CloseWindow(#WinTmp)
EndIf


Global igFS12.i = ((12 * 100) / dgDpiY)
LoadFont(#Font12R, "Arial Unicode MS", igFS12, #PB_Font_HighQuality)

Global icon.ICONINFO
Global Dim combo0(5), Dim combo1(5)
Global   hBrush = CreateSolidBrush_($E8B838)
Global  hBrush2 = CreateSolidBrush_($FFFFFF)
Global Iconsize = 32
Global      CBh = Iconsize + 12

Procedure img2icon(gad,img,Iconsize)
;#---------------------------------- 
Static Num0 = 0
Static Num1 = 0

               ResizeImage(img, Iconsize, Iconsize, #PB_Image_Smooth)

                  icon\fIcon = 1
                icon\hbmMask = ImageID(img)
               icon\hbmColor = ImageID(img)
               iconh = CreateIconIndirect_(@icon) 

               If gad = #Combo0
                         combo0(Num0) = iconh
                                 Num0 = Num0 + 1

               ElseIf gad = #Combo1
                         combo1(Num1) = iconh
                                 Num1 = Num1 + 1
               EndIf

               FreeImage(img)
EndProcedure

LoadImage(#Img0, "Img0.bmp")
img2icon(#Combo0,#Img0,Iconsize)

LoadImage(#Img1, "Img1.bmp")
img2icon(#Combo0,#Img1,Iconsize)

LoadImage(#Img2, "Img2.bmp")
img2icon(#Combo0,#Img2,Iconsize)

LoadImage(#Img3, "Img3.bmp")
img2icon(#Combo1,#Img3,Iconsize)

LoadImage(#Img4, "Img4.bmp")
img2icon(#Combo1,#Img4,Iconsize)

LoadImage(#Img5, "Img5.bmp")
img2icon(#Combo1,#Img5,Iconsize)

Procedure winCB(hWnd, uMsg, wParam, lParam)
;#-----------------------------------------
Protected *DrawItem.DRAWITEMSTRUCT
Protected sText.s

         Select uMsg 

               Case #WM_DRAWITEM

                         *DrawItem = lParam

                         If *DrawItem\CtlType = #ODT_COMBOBOX

                              If *DrawItem\itemID <> -1

                                    If *DrawItem\itemstate & #ODS_SELECTED
                                    
                                             FillRect_(*DrawItem\hDC,*DrawItem\rcitem, hBrush)
                                    Else
                                             FillRect_(*DrawItem\hDC,*DrawItem\rcitem, hBrush2)
                                    EndIf
                                    
                                    SetBkMode_(*DrawItem\hDC, #TRANSPARENT)

                                    sText = GetGadgetItemText(*DrawItem\CtlID,*DrawItem\itemID)
                                    
                                    If *DrawItem\CtlID = #Combo0
                                    
                                             DrawIconEx_(*DrawItem\hDC, *DrawItem\rcItem\Left + 4, *DrawItem\rcItem\Top + 4, combo0(*DrawItem\itemID), Iconsize, Iconsize, 0, 0, #DI_NORMAL)
                                    
                                    ElseIf *DrawItem\CtlID = #Combo1
                                    
                                             DrawIconEx_(*DrawItem\hDC, *DrawItem\rcItem\Left + 4, *DrawItem\rcItem\Top + 4, combo1(*DrawItem\itemID), Iconsize, Iconsize, 0, 0, #DI_NORMAL)
                                    EndIf
                                    
                                    *DrawItem\rcItem\left = CBh + 6
                                    DrawText_(*DrawItem\hDC, sText, Len(sText),*DrawItem\rcItem, #DT_SINGLELINE | #DT_VCENTER)
                              EndIf
                         EndIf
         EndSelect
         ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Win()
;#-------------
Protected iFlags.i = #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_ScreenCentered

               If OpenWindow(#Win, 0, 0, 600, 400, "Combobox - own icons", iFlags)

                                PanelGadget(#Panel, 2, 2, 596, 390)

                              AddGadgetItem(#Panel, -1, "Tab 0")
                              AddGadgetItem(#Panel, -1, "Tab 1")

                               CanvasGadget(#Canvas, 10, 10, 570, 340, #PB_Canvas_Container)

                                        SetGadgetColor(#Canvas, #PB_Gadget_BackColor, RGB(108,117,146))
                                          StringGadget(#StrFocus, 1, 1, 1, 1, "", #PB_String_BorderLess)
                                        ComboBoxGadget(#Combo0, 10, 10, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
                                         SetGadgetFont(#Combo0, FontID(#Font12R))
                                          SendMessage_(GadgetID(#Combo0), #CB_SETITEMHEIGHT, 0, CBh)
                                          SendMessage_(GadgetID(#Combo0), #CB_SETMINVISIBLE, 10, 0)  ;10 Items before ScrollBar display

                                         AddGadgetItem(#Combo0, -1, "Item # 0")
                                         AddGadgetItem(#Combo0, -1, "Item # 1")
                                         AddGadgetItem(#Combo0, -1, "Item # 2")
                                        SetGadgetState(#Combo0, 0)

                                        ComboBoxGadget(#Combo1, 10, 65, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
                                         SetGadgetFont(#Combo1, FontID(#Font12R))
                                          SendMessage_(GadgetID(#Combo1), #CB_SETITEMHEIGHT, 0, CBh)
                                          SendMessage_(GadgetID(#Combo1), #CB_SETMINVISIBLE, 10, 0)

                                         AddGadgetItem(#Combo1, -1, "Item # A")
                                         AddGadgetItem(#Combo1, -1, "Item # B")
                                         AddGadgetItem(#Combo1, -1, "Item # C")
                                        SetGadgetState(#Combo1, 0)

                             CloseGadgetList()
                             CloseGadgetList()

                                  HideWindow(#Win, #False)
                           SetWindowCallback(@winCB())
               EndIf
EndProcedure

Procedure Wait()
;#--------------
Protected Quit

         Repeat
                Select WaitWindowEvent(1)

                    Case #PB_Event_CloseWindow: Quit = 1
                    Case #PB_Event_Gadget: If( (EventGadget() = #Combo0) Or (EventGadget() = #Combo1) ) : SetActiveGadget(#StrFocus) : EndIf
                EndSelect
         
         Until Quit = 1

EndProcedure

Win()
Wait()
End
[/size]
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4661
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBox with large icons

Post by RASHAD »

Hi IV
See next it may help

# 1 :

Code: Select all

              If OpenWindow(#Win, 0, 0, 600, 400, "Combobox - own icons", iFlags)
                  ;***************************
                  SetWindowCallback(@winCB())
                  ;********************************   
                                PanelGadget(#Panel, 2, 2, 596, 390)

                              AddGadgetItem(#Panel, -1, "Tab 0")
                              AddGadgetItem(#Panel, -1, "Tab 1")

                               CanvasGadget(#Canvas, 10, 10, 570, 340, #PB_Canvas_Container)

                                        SetGadgetColor(#Canvas, #PB_Gadget_BackColor, RGB(108,117,146))
                                          StringGadget(#StrFocus, 1, 1, 1, 1, "", #PB_String_BorderLess)
                                          ;*********************************************
                                        ComboBoxGadget(#Combo0, 10, 10, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS &~ #CBS_NOINTEGRALHEIGHT )
                                        ;********************************************** 
                                         SetGadgetFont(#Combo0, FontID(#Font12R))
                                          SendMessage_(GadgetID(#Combo0), #CB_SETITEMHEIGHT, 0, CBh)
                                          SendMessage_(GadgetID(#Combo0), #CB_SETMINVISIBLE, 10, 0)  ;10 Items before ScrollBar display

                                         AddGadgetItem(#Combo0, -1, "Item # 0")
                                         AddGadgetItem(#Combo0, -1, "Item # 1")
                                         AddGadgetItem(#Combo0, -1, "Item # 2")
                                        SetGadgetState(#Combo0, 0)
                                        ;*******************************************
                                        ComboBoxGadget(#Combo1, 10, 65, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS &~ #CBS_NOINTEGRALHEIGHT )
                                        ;********************************************* 
                                         SetGadgetFont(#Combo1, FontID(#Font12R))
                                          SendMessage_(GadgetID(#Combo1), #CB_SETITEMHEIGHT, 0, CBh)
                                          SendMessage_(GadgetID(#Combo1), #CB_SETMINVISIBLE, 10, 0)

                                         AddGadgetItem(#Combo1, -1, "Item # A")
                                         AddGadgetItem(#Combo1, -1, "Item # B")
                                         AddGadgetItem(#Combo1, -1, "Item # C")
                                        SetGadgetState(#Combo1, 0)

                             CloseGadgetList()
                             CloseGadgetList()

                                  HideWindow(#Win, #False)
                           
               EndIf
# 2:

Code: Select all

               If OpenWindow(#Win, 0, 0, 600, 400, "Combobox - own icons", iFlags)

                                PanelGadget(#Panel, 2, 2, 596, 390)

                              AddGadgetItem(#Panel, -1, "Tab 0")
                              AddGadgetItem(#Panel, -1, "Tab 1")

                               CanvasGadget(#Canvas, 10, 10, 570, 340, #PB_Canvas_Container)

                                        SetGadgetColor(#Canvas, #PB_Gadget_BackColor, RGB(108,117,146))
                                          StringGadget(#StrFocus, 1, 1, 1, 1, "", #PB_String_BorderLess)
  
                             CloseGadgetList()
                             CloseGadgetList()

                                  HideWindow(#Win, #False)
                           SetWindowCallback(@winCB())
               
                            ComboBoxGadget(#Combo0, 10, 10, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
                             SetGadgetFont(#Combo0, FontID(#Font12R))
                              SendMessage_(GadgetID(#Combo0), #CB_SETITEMHEIGHT, 0, CBh)
                              SendMessage_(GadgetID(#Combo0), #CB_SETMINVISIBLE, 10, 0)  ;10 Items before ScrollBar display

                             AddGadgetItem(#Combo0, -1, "Item # 0")
                             AddGadgetItem(#Combo0, -1, "Item # 1")
                             AddGadgetItem(#Combo0, -1, "Item # 2")
                            SetGadgetState(#Combo0, 0)

                            ComboBoxGadget(#Combo1, 10, 65, 250,CBh, #CBS_OWNERDRAWFIXED | #CBS_HASSTRINGS)
                             SetGadgetFont(#Combo1, FontID(#Font12R))
                              SendMessage_(GadgetID(#Combo1), #CB_SETITEMHEIGHT, 0, CBh)
                              SendMessage_(GadgetID(#Combo1), #CB_SETMINVISIBLE, 10, 0)

                             AddGadgetItem(#Combo1, -1, "Item # A")
                             AddGadgetItem(#Combo1, -1, "Item # B")
                             AddGadgetItem(#Combo1, -1, "Item # C")
                            SetGadgetState(#Combo1, 0)
                            
                            SetWindowLongPtr_( GadgetID(#Combo0), #GWL_HWNDPARENT,GadgetID(#Canvas))
                            SetWindowLongPtr_( GadgetID(#Combo1), #GWL_HWNDPARENT,GadgetID(#Canvas))

               EndIf
Egypt my love
User avatar
kernadec
Enthusiast
Enthusiast
Posts: 146
Joined: Tue Jan 05, 2010 10:35 am

Re: ComboBox with large icons

Post by kernadec »

hi RASHAD
Thank you for the choice of the type of image
Thank you for sharing your knowledge
Goodbye
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4661
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBox with large icons

Post by RASHAD »

Hi kernadec
Thanks mate :D
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: ComboBox with large icons

Post by IdeasVacuum »

Hi Rashad

Thanks for those ideas - still no joy. I also tried combining the two and also swapped the Canvas for a Container but no difference.

I think it has to be something subtle, right under my nose.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4661
Joined: Sun Apr 12, 2009 6:27 am

Re: ComboBox with large icons

Post by RASHAD »

Hi IV
Debug CB_SETMINVISIBLE
BTW : are you Disabling XP theme for any control
Modern theme must be enabled

Code: Select all

debug SendMessage_(GadgetID(#Combo0), #CB_SETMINVISIBLE, 10, 0)
Egypt my love
Post Reply