• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1045
  • Last Modified:

Tab stops in CListBox (with owner draw)

Hi,

I have a CListBox with owner draw, ie. I have overwritten DrawItem. But, when I set the tabs using the method SetTabStops on my CListBox, it does not have any effect. It uses CDC::DrawText to draw the text in the DrawItem method, and I am already using the DT_EXPANDTABS format, but it doesn't work - it uses the standard fixed tab stops - how can I make the CDC::DrawItem / DrawText methods to accept the tab stops settings specified by the SetTabStops method?
0
Brian_HP
Asked:
Brian_HP
  • 5
  • 4
  • 2
1 Solution
 
ZoppoCommented:
Hi Brian_HP,

I've tried it and it works perfect ... have you tried if it works when it's not ownerdrawn? Are you sure the LBS_USETABSTOPS style is set (it's the 'Use Tabstops' check box of the 'Styles' page of the list box properies dialog)?

ZOPPO
0
 
Brian_HPAuthor Commented:
Hi Zoppo,

It works fine when it is not ownerdrawn. Then I can use the tab stops I like, but when it is ownerdrawn it uses some fixed tab stops. I have set up the style correctly, but DrawItem ignores the tab stops specified by SetTabStops !
  I have also tried some color example from CodeGuru - it had the same problem.

/Brian
0
 
ZoppoCommented:
Yes, now I see what you mean, sorry ...

The only way I found is following: Use an array of int's for SetTabStops(), store this array anywhere in you combobox class and use this array with CDC::TabbedTextOut() to draw the text. I've tried it and it seems to work.

hope that helps,

ZOPPO
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
migelCommented:
Hi!
I agree with ZOPPO
to store array of the tabs you can handle LB_SETTABSTOPS message (to emulate standard control bechavior)
that is:
declare in the your ListBox derived class method:
LRESULT OnLBSetTabstops(WPARAM, LPARAM);
in the message map add following entry:
ON_MESSAGE(LB_SETTABSTOPS, OnLBSetTabstops)

// assume your class name CMyListBox:
LRESULT CMyListBox::OnLBSetTabstops(WPARAM wPar, LPARAM lPar)
{
int ccTabs = wPar;
int* pTabs = (int*) lPar;
/* now we must store this info in the our class members let it be int* m_arTabs and int m_nTabsSize;*/
if (m_arTabs)
   delete m_arTabs;
m_arTabs = new int [ccTabs];
if (m_arTabs)
m_nTabsSize = ccTabs;
}

// now in the OnDrawItem you can wrote same code:
pDC-> TabbedTextOut( ..., m_nTabsSize, m_arTabs, 0);
0
 
Brian_HPAuthor Commented:
Thanks for the help both of you! I just have one question. What is the difference in catching the message (LB_SETTABSTOPS) and inheriting the virtual method SetTabStops(..) of CListBox?

You have both given two good (but almost similar) answers - how can I split the points between you?

PS. Migel, you have forgotton to copy the tab stops from pTabs into m_arTabs :)

/Brian
0
 
ZoppoCommented:
Hi Brian_HP,

Both solution works, but I think the more elegant solution is migel's one, because with my suggestion you have to store the tab stop positions by yourself and take care you do it every time SetTabStops() is called, and migel's solution simply catches the message sent to the list control whenever SetTabStops() is called and stores the tab positions automatically.

ZOPPO
0
 
Brian_HPAuthor Commented:
Hi Zoppo,

I think I agree with you, but in migel's solution I also have to store the tab stops.

/Brian
0
 
ZoppoCommented:
Yes, of course, this is needed, because it seems there's no possibility to recieve a list box's tabstop positions after setting them. The difference between mine and migel's solution is just that one that migel's one stores the tabs automatically. I don't think there's another solution than storing the tab stops for use with TabbedTextOut() ...

ZOPPO
0
 
migelCommented:
Hi!
hmm
override non virtual method of the base class by the virtual one in the derived is not good idea.
for example:
you derive class ->
CMyLisBox:public CListBox
{
//...
virtual SetTabStops(...);
///..
};

and somewhere create object :
CMyLisBox m_wndMyListBox....
now you can pass pointer to this object to the some function that want work with  native CListBox
(let it be SomeFunction(CListBox& box,....))

{
// somewhere in the code
SomeFunction(m_wndMyListBox,....); // <- compiler accept it and doesn`t generate any warning;
}
// example code for the SomeFunction()
....SomeFunction(CListBox& wndBox,...)
{
//....
wndBox.SetTabStops(...);// <-- OOPS what function will be called???
// right answer - function of the base class!!!
//....
}
0
 
Brian_HPAuthor Commented:
Hi migel,

I see your point, I just didn't know that SetTabStops wasn't virtual ...

/Brian
0
 
Brian_HPAuthor Commented:
Migel's solution has solved my problem, but thanks to both of you.

/Brian
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 5
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now