 |
|
 |
having problem when adding "\n"
ex.
"A short \nwarning"
unleash the possibilities
|
|
|
|
 |
|
 |
Some Win32 mish-mash is needed, but nothing too hard. Here's the code in VB.NET:
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, _
ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const LB_SETITEMHEIGHT = &H1A0
Private Sub ListView1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListView1.SizeChanged
For i As Integer = 0 To sender.Items.Count - 1
Dim mi As New MeasureItemEventArgs(Graphics.FromImage(New Bitmap(1, 1)), i, sender.ItemHeight)
ListView1_MeasureItem(sender, mi)
SendMessage(sender.Handle, LB_SETITEMHEIGHT, i, mi.ItemHeight)
Next i
End Sub
Basically, you call SendMessage and pass it the handle of the ListView, the LB_SETITEMHEIGHT const, the index of the item you want to change the itemheight of, and finally the itemheight itself. In this case I've recycled my MeasureItem event... although it's VERY IMPORTANT TO NOTE IF YOU DO THIS that drawing on the graphics won't work, nor will getting the bounds of the graphic, etc. Only use this if you only use the .Index and only write to the .ItemHeight of the MeasureItemEventArgs in your event. Otherwise just make a new function to calculate the item height and call it from here and from your event.
|
|
|
|
 |
|
 |
I agree with your alternative solution.
I don't like unmanaged API calls, but in this case SendMessage is the lighter way to accomplish this task.
|
|
|
|
 |
|
 |
I see there's a problem when I try to scroll your control with the mouse wheel. And, more, there's also a problem when I try to scroll it by the last item, with either the mouse wheel or using the scrollbar.
If your code is doing a great job rendering the variable size items, I think you should spend some time providing the additional keyboard interface and fixing these scrolling problems. That would make it a great reusable control.
Nice work.
|
|
|
|
 |
|
 |
Well, I keep looking through your code, and I see some stuff that can be changed for performance tunning.
First, don't apply logic painting to all of the items in the list, just keep track somehow of the items that are visible and update just that.
Second, make some calculations and detect either an item is beeing selected/deselected (using the Ctrl key), and invalidate just the bounds of that item. In the situation when you have single select, just invalidate the item that was selected, and the one that is beeing selected right now. You can even make 2 separate calls to Control.Invalidate() and I think they're very close to eachother and the result will be a single WM_PAINT message sent to your control (speed). The more complicated way is to use regions.
Also, for this specific control, I don't know if the actual base class (Panel) helps you better. I would inherit from ScrollableControl. All you need is the AutoScroll feature, right?
I hope you'll update this control soon, then I will use it in my projects alot.
Ohh, and I forgot to ask you, are you a former MFC programmer?
Keep up the good work!
Adi
|
|
|
|
 |
|
 |
Hi Adi,
thanks for your input.
adi881 wrote:
I hope you'll update this control soon, then I will use it in my projects alot.
As you might have noticed the posting of that article was over 2 years ago. I don't have the time (don't know if this is good or bad ) to update all my old stuff.
Feel free to make the updates yourself and post a V2 version of that control in a new article here on CP. The everybody will benefit.
adi881 wrote:
Ohh, and I forgot to ask you, are you a former MFC programmer?
Yes. But that's even longer ago...
Cheers
Chris
|
|
|
|
 |
|
 |
Adi,
Some time ago I also updated this control and wrote a small article for it. Since Christian does not have time to update it, maybe I can.
However I also updated the painting logic and keep a list of what should be painted or not. The article name is 'An auto-resize C# ListBox (updated)'.
Hope that helps.
Best regards,
Robert
|
|
|
|
 |
|
|
 |
|
 |
Hello Christian Tratz,
Yesterday I downloaded your control (great control!) and made some minor adjustments to it:
- support for drawing text with '\n' characters
- sometimes words got to the right edge
- changed the ArrayList so that newly inserted items (e.g. not at the end) changes the SelectedItemsIndices-List. Marked items will now move to the bottom, practical for timed-messages.
- changed the Line in ParseMessageEventArgs into Header which makes it possible to draw other strings (times) as a header.
If you like I can send it to you. I could not find your email, since I would otherwise have done that instead of this message.
Best regards,
Robert
|
|
|
|
 |
|
 |
This works for me, just refresh the items in the listbox when it's resized. Very simple and it seems to be fast:
private void listBox1_Resize(object sender, System.EventArgs e)
{
RefreshListBox(sender);
}
private void RefreshListBox(object sender)
{
ListBox listbox = (ListBox)sender;
object[] items = new object[listbox.Items.Count];
listbox.Items.CopyTo(items,0);
listbox.BeginUpdate();
listbox.Items.Clear();
listbox.Items.AddRange(items);
listbox.EndUpdate();
}
/I need a signature I guess
|
|
|
|
 |
|
 |
Dear Sir.
I Like your component but this code is not compiling in vs 2003.
what about perfomance of your list box.
did you find other way to redraw items when listbox resizing.
Thank you in advance.
Irakli Lomidze
|
|
|
|
 |
|
 |
This code was written when VS2003 was not available.
I still have the old VS.NET o I cannot tell you why it is not compiling.
Cheers
Chris
|
|
|
|
 |
|
 |
Yesterday I have downloaded this control and compiled it with VS 2003: no problems found.
|
|
|
|
 |
|
 |
Nice work and very helpful to me in a project I am working on. Unfortunately, the control using this code gets a lot of data and when I tried to view the data at the end of the list it wasn't displayed properly. I added one new variable () and two lines of code and modified one line of code to fix the problem in the following routine:
==============================================================================
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Graphics g = pe.Graphics;
Rectangle bounds = new Rectangle();
int posY = this.AutoScrollPosition.Y;
int totalPosY = 0;
//clear background
using ( Brush b = new SolidBrush(this.BackColor) )
{
// Fill background;
g.FillRectangle(b, this.ClientRectangle);
}
m_ItemHeights.Clear();
//draw our items
for(int i=0; i |
|
|
|
 |
|
 |
Yep, great work Christian.
Thanks for the fix Mike!
|
|
|
|
 |
|
 |
or...
this.AutoScrollMinSize = new Size(this.Width - 50, posY - this.AutoScrollPosition.Y);
|
|
|
|
 |
|
 |
If you wanted ListBox to call MeasureItem each time it called draw item...
doesn't setting the DrawMode property to DrawMode.OwnerDrawVariable accomplish that?
|
|
|
|
 |
|
 |
The problem with variable sized list box items is simply that the list box only calculates the size when the item is added. This is fine, if the height doesn't depend on the width - as the width can change when the list is resized. For wrapping text, this is essential.
One solution to this is to simply remove and then re-add each item every time the list is resized. This, however can get somewhat slow when there are many items in the list.
In straight Win32, the LB_SETITEMHEIGHT message can be used to modify the height of existing listbox items (this corresponds to the CListBox::SetItemHeight() method in MFC). I've used this technique, and found it acceptable. Unfortunately, Windows Forms doesn't seem to have a ListBox.SetItemHeight() method.
And so, the need for this class
--------
PMGRE --Shog9 --
|
|
|
|
 |
|
 |
The DrawMode.OwnerDrawVariable fires the MeasureItem event. But only once upon creation of the control. Not when the control is resized for example.
-Chris
|
|
|
|
 |
|
 |
ok, so i still don't see the need for a complete reimplementation.
couldn't you just hook into the OnFoo event raisers of the ones you want to raise the event for.. and do a
protected override void OnFoo( e ) {
OnMeasureItem(e);
base.(e);
}
???
|
|
|
|
 |
|
 |
The OnMeasureItem of the standard ListBox just fires the event. The whole ListBox class itself is (AFAIK) just a wrapper to the Win32 listbox. This control sends then the WM_MEASUREITEM message which is transformed to the .NET event.
As you set the item height within the event handler of that event, your only way to achieve the same behaviour would be to force the underlying control to send out these messages. I have not found a way to do that. If you know more let me know, because then you would be perfectly right.
-Chris
|
|
|
|
 |
|
 |
Thanks for sharing this great control. The only problem I experienced is that it will crash when resize to some minimum width.
Regards
|
|
|
|
 |
|
|
 |