How to Alter the Icon of a COMBO drop control

Here is a small program that shows two COMBO controls on a screen.
I wrote a small procedure that enumerates the controls and finds the Combo:CreateButton control for a given combo
From there, I alter the ICON on the Combo Control

Note: this program also shows multiple columns in the drop lists

  PROGRAM
  MAP
  END

Q QUEUE
Descr   STRING(20)
Row     LONG
END 

ComboValue STRING(20)
ComboValue2 STRING(20)
QuickWindow WINDOW('Combo Suggest'),AT(,,417,130),CENTER,GRAY,IMM,SYSTEM,|
    FONT('Segoe UI',8,,FONT:regular,CHARSET:ANSI),TIMER(1),RESIZE

    COMBO(@s20),AT(31,28,314),USE(ComboValue),DROP(4),FROM(Q), |
      FORMAT('155L(2)|M~Description~@S20' & |
              '@20L(2)|M~Row~@N2@')

    BUTTON('Button1'),AT(30,100),USE(?BUTTON1)

    COMBO(@s20),AT(31,58,313,15),USE(ComboValue2),DROP(4),FROM(Q),|
      FORMAT('155L(2)|M~Description~@S20' & |
              '@20L(2)|M~Row~@N2@') 
END

 INCLUDE('debuger.inc'),ONCE
DBG Debuger

FEQ EQUATE(SIGNED)
  MAP
ComboButtonFEQ   PROCEDURE(FEQ xComboFEQ),FEQ
SetComboIcon     PROCEDURE(FEQ xComboFEQ, STRING xNewIcon)
  END
  CODE  
  dbg.mg_init('ComboSuggest')

  DO FillQ
  GET(Q, 5); ComboValue = Q.Descr
  GET(Q, 3); ComboValue2= Q.Descr

  OPEN(QuickWindow)

  dbg.DumpControls() ! see DebugViewPP for OutputDebugString output


  !  SetComboIcon( ?ComboValue, ICON:Exclamation)
  SetComboIcon( ?ComboValue2, ICON:Ellipsis) !<<<<<<<<<<<
  
  ACCEPT
  END 

FillQ ROUTINE
    LOOP 20 TIMES
       Q.Descr = ALL(CHR(65 + RECORDS(Q)))
       Q.Row   = RECORDS(Q)+1
       ADD(Q)
    END 


SetComboIcon    PROCEDURE(FEQ xComboFEQ, STRING xNewIcon)
    CODE
    ComboButtonFEQ(xComboFEQ){PROP:Icon} = xNewIcon

ComboButtonFEQ   PROCEDURE(FEQ xComboFEQ)
CurrFEQ                FEQ(0)
ComboFieldName        ANY
CREATE:_ComboButton   EQUATE(CREATE:combo + 0100H)  !see NG:  Softvelocity.clarion.documentation  Thread:"What is {prop:type}=271"  Sept-18-2006
    CODE 
    ComboFieldName = DBG.GetFEQDescr(xComboFEQ)

    LOOP 
        CurrFEQ = 0{PROP:NextField, CurrFEQ}
        IF     CurrFEQ{PROP:Type} = CREATE:_ComboButton   |
           AND DBG.GetFEQDescr(CurrFEQ) = ComboFieldName  |
        THEN 
           RETURN CurrFEQ
        END         
    WHILE CurrFEQ <> 0

    RETURN 0

Here is the output of DBG.DumpControls, that I used to write the ComboButtonFEQ(FEQ) procedure.
Make sure you scroll horizontally to notice that the xDescr of the CREATE:ComboButton shows the same information as it’s parent control, the xDescr value is set by DBG.GetFEQDescr(FEQ) which is just a wrapper for the undocumented RTL command Cla$FIELDNAME

debugerGetFieldName(SIGNED FEQ),*CSTRING,RAW,NAME(‘Cla$FIELDNAME’)

DumpControls ===[start]==========================================
DumpControls for Window[Combo Suggest] FEQ Range[-2147483647 to 2147483647]
   FEQ[1]   Hide[] Disable[]   AT(31,28,314,12)   Type[15]=[create:COMBO]   Text[s20]  xDescr[?COMBOVALUE] Parent[0] Use [EEEEEEEEEEEEEEEEEEEE] UseAddress [134238016] Skip[] Trn[] IMM[]
   FEQ[2]   Hide[] Disable[]   AT(30,100,40,14)   Type[9]=[create:BUTTON]   Text[Button1]  xDescr[?BUTTON1] Parent[0] Use [] UseAddress [0] Skip[] Trn[] IMM[]
   FEQ[3]   Hide[] Disable[]   AT(31,58,313,15)   Type[15]=[create:COMBO]   Text[s20]  xDescr[?COMBOVALUE2] Parent[0] Use [CCCCCCCCCCCCCCCCCCCC] UseAddress [134237776] Skip[] Trn[] IMM[]
   FEQ[32768]   Hide[] Disable[]   AT(301,0,12,11)   Type[271]=[create:COMBOBUTTON]   Text[ ]  xDescr[?COMBOVALUE] Parent[0] Use [] UseAddress [0] Skip[] Trn[] IMM[]
   FEQ[32769]   Hide[] Disable[]   AT(-791,-545,303,43)   Type[270]=[create:SUBLIST]   Text[]  xDescr[?COMBOVALUE] Parent[0] Use [] UseAddress [0] Skip[1] Trn[] IMM[]
   FEQ[32770]   Hide[] Disable[]   AT(297,0,15,14)   Type[271]=[create:COMBOBUTTON]   Text[ ]  xDescr[?COMBOVALUE2] Parent[0] Use [] UseAddress [0] Skip[] Trn[] IMM[]
   FEQ[32771]   Hide[] Disable[]   AT(-791,-545,303,43)   Type[270]=[create:SUBLIST]   Text[]  xDescr[?COMBOVALUE2] Parent[0] Use [] UseAddress [0] Skip[1] Trn[] IMM[]
DumpControls ===[end]==========================================

Hey @MarkGoldberg, thanks for the demo!

I had a quick play around because I wanted to see what it looked like. For anyone else wanting to compile the example go and grab the dependencies from Marks github repo - ClarionCommunity
Specifically you want these:

  • debuger.inc
  • debuger.clw
  • TUFO.INT
  • FileAccessModes.EQU

…however your life might be easier if you just grab the whole repo and setup your RED to point to the appropriate paths!

I did notice one thing Mark, and I am curious to hear if you have any ideas about how to work around it or if it is an RTL issue. If you include a manifest then the ComboButton appears to no longer be OS themed after the icon change:

Notice how the ellipse icon button is no longer “flat”?

In my EXP I had:

MANIFEST VISTA WINDOWS7 combobutton.exe.manifest

And combobutton.exe.manifest was:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="x86"
    name="SoftVelocity.Clarion10.Application"
    type="win32"
  />
  <description>Clarion application.</description>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="x86"
        publicKeyToken="6595b64144ccf1df"
        language="*"
      />
    </dependentAssembly>
  </dependency>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application> 
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
      <!--The ID below indicates application support for Windows 7 -->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <!--The ID below indicates application support for Windows 8-1 -->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> 
      <!--The ID below indicates application support for Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    </application>
  </compatibility>
</assembly>

It is possible to re-theme the control using a function from the uxtheme.dll

I created a lib from the uxtheme.dll using lib maker exposing the function SetWindowsTheme and added the lib to the project.

In the map, added the following definition.

MODULE ('uxtheme.dll') 
  SetWindowTheme(unsigned hwnd, *CSTRING pszSubAppName, *CSTRING pszSubIdList),long, PASCAL,RAW,  NAME ('SetWindowTheme'),PROC!,DLL(__SetWindowTheme_)
END

Then changed the SetComboIcon Procedure as follows

SetComboIcon        PROCEDURE(FEQ xComboFEQ, STRING xNewIcon)
bParm  CSTRING(' ')
feq signed
   CODE
    feq = ComboButtonFEQ(xComboFEQ)
    feq{PROP:Icon} = xNewIcon
    SetWindowTheme(feq{PROP:Handle},bParm,bParm)

The control will now have it’s windows theme switched back on.

1 Like

Hey, that’s super neat! :star:
Got a screenshot?

Sorry Misleading, it doesn’t work :frowning:

I thought it did, but I think I just turned off theming for the whole control, so the button looked more flat.

Oh, that’s a bummer. Like never going to work or possibly worth messing around some more to figure it out?

I’ve played with it for an hour or so, I can’t get it to work.

1 Like

This is much simpler…

COMBO(@s60),AT(45,64,157,10),USE(COU:Country),VSCROLL,DROP(10),FORMAT(‘157L(2)@s60@’),FROM(Queue:FileDropCombo:1), |
IMM,MSG(‘Country Name’),TIP(‘Country Name’)

(?COU:Country{PROP:ButtonFEQ}){PROP:ICON} = ‘~CALENDAR.ICO’

3 Likes