MeasureItem problem

G

Guest

I have a listbox that is set to OwnerDrawVariable. What i want to be able to
do is set the ItemHeight to a different value based on some run-time event.
I want to increase the size and draw something extra and later decrease the
size to the regular dimensions.

So whenever the user action takes place i called Refresh() on the listbox.
This forces a call to measureitem and i can verify that it sets the
ItemHeight and ItemWidth to the new values. But when DrawItem is called, the
bounds property does not reflect this. It still has the old width and
height. The bounds property simply does not have the right demensions for
the item.

Am i doing something wrong? I tried googling but could not find anything. If
i set the custom height at the begining then it works fine. I can set an
item to a different height, draw in the extra area only if i set it the
first time.

using Version 1.1
 
J

Jeffrey Tan[MSFT]

Hi cisco,

Thanks for your post.

Can you provide a little sample project to demonstrate out this issue? You
attach your demo sample in a further reply by Outlook Express. Then we can
understand the cause much better.

I will wait for your further feedback. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

Jeffrey,

How do you want me to send the sample project? Just post to the newsgroup?
I'll include the test code below but i can send the whole test project if
you would like. It's pretty much just one user control and a form.

The control has a hashtable that uses the index of the item as the
key. If the user double clicks(_listWits_DoubleClick) the item it
set's this value to true. The MeasureItem checks the hashtable in
order to set the new height. The DrawItem also checks this to see if
it should redraw it.

DebugOutput is putting out the correct height in the MeasureItem
method but DrawItem doesn't put out the correct Bounds.Size for it.



Cisco

[1]
private void _listWits_MeasureItem(object sender, MeasureItemEventArgs e) {
if( e.Index < 0 ) return ;
string data = _listWits.Items[e.Index].ToString();
Graphics g = e.Graphics;
SizeF size = g.MeasureString(data, _listWits.Font);
e.ItemWidth = (int)Math.Ceiling(size.Width);
int height = (int)Math.Ceiling(size.Height);
if( _hash[e.Index] != null ) {
height += (int)Math.Ceiling(Font.GetHeight(e.Graphics) * 2);
}
Debug.WriteLine("Measure Item: " + e.Index.ToString() + ", Height: " +
height);
e.ItemHeight = height;

}

/// <summary>
/// Draws the items. If the current item's value in the hashtable is true
/// then write more dummy information for it. This means i want to
increase it's size.
/// </summary>
private void _listWits_DrawItem(object sender, DrawItemEventArgs e) {

if( e.Index < 0 ) return ;

string text = _listWits.GetItemText(e.Index);


// print out the bounds for debugging
Debug.WriteLine("DrawItem: " + string.Format("Item {0}'s bound {1}",
e.Index, e.Bounds) );

Font currentFont = _listWits.Font;

Graphics g = e.Graphics;
if (((e.State & DrawItemState.Focus) == DrawItemState.Focus) && ((e.State
& DrawItemState.NoFocusRect) != DrawItemState.NoFocusRect)) {
ControlPaint.DrawFocusRectangle(g, e.Bounds, e.ForeColor, e.BackColor);
} else {
if( (e.Index + 1) % 2 != 0 ) {
Color color = Color.FromArgb(125, Color.LightBlue);
using( Brush rectBrush = new SolidBrush(color) ) {
g.FillRectangle( rectBrush, e.Bounds );
}
using( Pen rectPen = new Pen(Brushes.Black) ) {
rectPen.DashStyle = DashStyle.Dot;
Rectangle rect = new Rectangle(e.Bounds.Location, e.Bounds.Size);
rect.Size = new Size(e.Bounds.Width-1, e.Bounds.Height-1);
g.DrawRectangle(rectPen, rect);
}
} else {
e.DrawBackground();
}
}

// draw the first part
SizeF sizeFirst = g.MeasureString( text, currentFont );
using( Brush brsh = new SolidBrush(e.ForeColor) ) {
g.DrawString( text, currentFont, brsh, 0, e.Bounds.Top );
}

if( _hash[e.Index] != null ) {
g.DrawString(
e.Index.ToString().PadLeft(2, '0') + " " + DateTime.Now.ToString(),
currentFont, Brushes.Red, (int)Math.Ceiling(sizeFirst.Width),
e.Bounds.Top + currentFont.Height + currentFont.Height/2 );
}

}


private void _listWits_DoubleClick(object sender, System.EventArgs e) {
_hash[_listWits.SelectedIndex] = true;
// tried loading the data source again to see if it would reset the
// bounds
object source = _listWits.DataSource;
_listWits.DataSource = null;
if( source != null )
_listWits.DataSource = source;
_listWits.Refresh();
}


"Jeffrey Tan[MSFT]" said:
Hi cisco,

Thanks for your post.

Can you provide a little sample project to demonstrate out this issue? You
attach your demo sample in a further reply by Outlook Express. Then we can
understand the cause much better.

I will wait for your further feedback. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jeffrey Tan[MSFT]

C

cisco

Jeffrey said:
Hi Cisco,

It seems that this is a known bug. Please refer to the bug link below:
"Bug Details: Owner-draw Listbox With Non-Standard Font Size Get Incorrect
Item Heights In DrawItem Event"
http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackid=1
267dab9-aa0a-4591-9259-c777f5a51f08

Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Firewall at work didn't let me post earlier but Thanks for the help
Jeffrey. It's interesting though. I took out the font selection so that
it uses the parent font but i still get the same thing. I even set it in
code but still have the same issue. I don't think it's related to just
changing the font.

I am using VS 2003 and that bug is for 2005... but oh well. I think i'll
have to track the bounds myself :(

Appreciate it,
Cisco
 
B

Bob Powell [MVP]

Just as an experiment, try recreating the handle of the control when you
want the change to take effect.

I have a recollection of doing this before.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
C

cisco

Bob said:
Just as an experiment, try recreating the handle of the control when you
want the change to take effect.

I have a recollection of doing this before.

Bob,

It looks like that worked. The test class i have is working off events
so i set the RightToLeft value to recreate the handle. It seems like
recreating the handle works. I'll probably subclass it and call
recreatehandle() on the one i'll put in production code. RightToLeft is
an expensive call.

Thanks for the workaround bob!

Cisco
 
J

Jeffrey Tan[MSFT]

Hi Cisco,

I found that "Bob Powell [MVP]" has provided a workaround for this issue.
If you need further help, please feel free to post. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top