Solved

Changing a CComboBox style to CBS_SORT

Posted on 2002-07-23
29
3,692 Views
Last Modified: 2013-11-20
Hi,

I'm trying to change the style of a CComboBox after it has been created.
I want to add & remove the CBS_SORT style.
I use the following code:
m_oCombo.ModifyStyleEx(0, CBS_SORT);
and
m_oCombo.ModifyStyleEx(CBS_SORT, 0);
But none of these lines seems to work.
Is the CBS_SORT style unchangeable after the combo has been created ?

If not, I guess I will have to implement an owner-draw combo-box, and override the CompareItem method.
Does anyone have an example of a DrawItem function for a regular combo-box ?

Thanks for your help.
0
Comment
Question by:gurly
  • 11
  • 10
  • 8
29 Comments
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
A few things that need clarification:

* Use
m_oCombo.ModifyStyle( 0, CBS_SORT );
to add the CBS_SORT style. It's not an extended style so don't use ModifyStyleEx
* I'm not sure whether this newly set style yields an  immediate response or if it applies only if you add new strings to the combobox.
* You are confusing owner-drawn controls with a derived class. Owner-drawn controls give you the ability to do the drawing of the items yourself. Deriving your own class inherits the entire functionality from the parent and gives you the opportunity to customize every single aspect without changing the rest. So this is what you are looking for, when you want to only change the CompareItem-method.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
A. You are right about the ModifyStyleEx. I also tried it with ModifyStyle and it didn't work (just didn't notice I haven't changed it back when I put the sample code here).

B. I change the style right after I call ResetContent and just before I fill the combo-box with new strings, and still - it doesn't work.

C. I know the difference between owner-drawn controls and derived classes. The fact is that in order to override the CompareItem method I have to derive my own class from CComboBox and change the control style to owner-drawn.
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
c.)

Where does it say so? The MSDN states that you have to implement CompareItem if you have an owner drawn combo-box. It doesn't say that you have to make it owner-drawn to override the CWnd::OnCompareItem-function.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
But if the control is not owner-drawn the CompareItem method is never called.
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
That's why I was referring to OnCompareItem...
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
Still - the OnCompareItem is also not called if the control is not owner-drawn.
From MSDN:
"The system sends the WM_COMPAREITEM message to determine the relative position of a new item in the sorted list of an owner-drawn combo box or list box. "
0
 
LVL 8

Accepted Solution

by:
fl0yd earned 50 total points
Comment Utility
You're right, I just found out myself. I guess I'm finally losing my sanity ;) Anyway, you can find information on the DRAWITEMSTRUCT as well as the CComboBox::DrawItem-function here:
http://msdn.microsoft.com/library/en-us/vcmfc98/html/_mfc_ccombobox.3a3a.drawitem.asp
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
Thanks for the link.
By now I implemented something similar myself.
I have one problem, though.
The lpDrawItemStruct->itemData doesn't hold the item text in case I called SetItemData for that item.
I don't want my item data to be a complicated struct holding the item text along with other data I need.
I just need to hold a number with the item.

Any ideas on how I can get the item text in the DrawItem & CompareItem functions ?
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
Hi!
CBS_SORT is the creation time style that is style that control use only during self creation and changing such styles after creation will not change control mode.
IMHO you need destroy existing control and recreate it again with needed style.
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
That's certainly not the way you want to go, migel. Deriving a class from CComcoBox, adding a private

BOOL m_bSort;

and a public member function

BOOL SetSort( BOOL b = TRUE ) { BOOL tmp = m_bSort; m_bSort = b; return tmp; }

will be clearly superior. In your CompareItem()-function add the following line at the very beginning:

if( !m_bSort )
    return;

This is definately a lot better concerning memory footprint, memory fragmentation and, possibly most important, runtime performance. Thinks about all those objects that have to be destroyed and recreated...
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
but for using CompareItem you have to use OWNERDRAW combo isn`t you?
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
And what is the big deal about it?
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
This methods called only when new item added into the combobox.
so if you will use your technique then you anyway will erase all elements and readd they again
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
This methods called only when new item added into the combobox.
so if you will use your technique then you anyway will erase all elements and readd they again
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 12

Expert Comment

by:migel
Comment Utility
This methods called only when new item added into the combobox.
so if you will use your technique then you anyway will erase all elements and readd they again
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
Even if that were the case then at least the entire window isn't destroyed. Think about how your suggestion will flicker... I doubt, that there is the need to re-insert the items though. An InvalidateRect( NULL, FALSE ); should be sufficient.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
I understand I will have to use an owner-drawn combo-box.
The only question left is:
How can I get the item text in the DrawItem / CopareItem methods, when the item is an actual DWORD set with SetItemData ?
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
did you try it by hand??
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
I understand I will have to use an owner-drawn combo-box.
The only question left is:
How can I get the item text in the DrawItem / CopareItem methods, when the item is an actual DWORD set with SetItemData ?
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
migel,
What do you mean ?
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
Since you called SetItemData, you would know what the DWORD_PTR points to.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
fl0yd,
You are correct, but as I said earlier, I don't want to save the item text in the data structure.
The DWORD_PTR is extra data for me, not an item identifier.
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
oops my prefious post is for fl0yd
1. Is your combo created with CBS_HASSTRINGS?
if  with than you can use CComboBox::GetLBText(id);
2 or you can use itemData member of the DRAWITEMSTRUCT passed into the DrawItem this member hold data you pass in the SetItemData call

void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

   LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData;
// rest of code
}
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
gurly,
    I assume that itemData points to the actual data you have some means to evaluate the string from there. If you don't want the combobox to store the string for you (which I think is a good choice) it is somewhere stored in the structure/class that itemData points to.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
migel,

1. LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData;
want get me the item text since it holds the item data.

2. When my combo has the style CBS_HASSTRINGS the CompareItem function is not called.
0
 
LVL 12

Expert Comment

by:migel
Comment Utility
so you need define struct (as fl0yd) that hodls both item string and item data and store pointers to the structs in the item data
you have no another choose
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
fl0yd,
I'm not sure I understand what you mean: how can the combo store the string for me ? Is it by the structure the item data points to (which I don't want to add the string to) ?
Or are you talking about something else ?
0
 
LVL 8

Expert Comment

by:fl0yd
Comment Utility
If you call CComboBox::AddString( LPCTSTR ), then the control stores the string for you. You can delete the c-string that you supplied for this function call after it returned since the control made a copy of it. I'm not sure, how you would get that string when doing the drawing. You will find information on that either from the link I provided above or you will have to look through this section in the msdn.
0
 
LVL 1

Author Comment

by:gurly
Comment Utility
Thanks for your help.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now