Windows Develop Bookmark and Share   
 index > Windows Forms General > issue with the List view scroll bar
 

issue with the List view scroll bar

Hi,

Anybody plase help me with this issue,

i am having two list views. Both these are having scroll bars.

What i want is that, i have to make only one scroll bar for both the listviews, so that if i am scrolling the scroll bar of the fisrt listview, both should get scrolled...

i have seen in one application that its possilbe, that is not in c#, its purely VS c++.

So please i need a help for this.

Thanks in Advance,

Nimesh

nimeshprabhakar  Monday, March 31, 2008 8:49 AM

Hi,

You can sub-class the ListView class and override its WndProc method to catch the WM_VSCROLL and WM_HSCROLL messages, andcreate a Scroll event for it. Then you can handle this Scroll event to send related scroll message to another ListView, see my sample below for the details

Code Snippet

partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

this.listView1.View = View.Details;

this.listView2.View = View.Details;

for (int j = 0; j < 10; j++)

{

this.listView1.Columns.Add("c" + j.ToString());

this.listView2.Columns.Add("c" + j.ToString());

}

for (int j = 0; j < 300; j++)

{

ListViewItem item = new ListViewItem("item" + j.ToString());

for (int k = 1; k < 10; k++)

{

item.SubItems.Add("sub item" + k.ToString());

}

this.listView1.Items.Add(item);

this.listView2.Items.Add(item.Clone() as ListViewItem);

}

this.listView1.Scroll += new ListViewEx.ScrollHandler(listView1_Scroll);

//this.listView2.Scroll += new ListViewEx.ScrollHandler(listView2_Scroll);

}

[DllImport("user32.dll")]

static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]

static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

private const int WM_HSCROLL = 0x114;

private const int WM_VSCROLL = 0x115;

private const int SBS_HORZ = 0;

private const int SBS_VERT = 1;

void listView1_Scroll(object sender, MyScrollEventArgs e)

{

ListViewEx listVw = sender as ListViewEx;

Int16 hi = (Int16)((int)e.WParam >> 16);//position

Int16 lo = (Int16)e.WParam;//scroll type

if (e.Orientation == ScrollOrientation.VerticalScroll)

{

if (lo == 5) //SB_THUMBTRACK

{

if (SetScrollPos(this.listView2.Handle, SBS_VERT, hi, true) != 0)

{

SendMessage(this.listView2.Handle, WM_VSCROLL,
(IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);

}

}

else

{

SendMessage(this.listView2.Handle, WM_VSCROLL, e.WParam, IntPtr.Zero);

}

}

if (e.Orientation == ScrollOrientation.HorizontalScroll)

{

if (lo == 5)//SB_THUMBTRACK

{

SetScrollPos(this.listView2.Handle, SBS_HORZ, hi, true);

SendMessage(this.listView2.Handle, WM_HSCROLL,
(IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);

}

else

{

SendMessage(this.listView2.Handle, WM_HSCROLL, e.WParam, IntPtr.Zero);

}

}

}

}

Code Snippet

public class ListViewEx : ListView

{

public delegate void ScrollHandler(object sender, MyScrollEventArgs e);

public event ScrollHandler Scroll;

public void OnScroll(MyScrollEventArgs e)

{

if (Scroll != null)

{

Scroll(this, e);

}

}

private const int WM_HSCROLL = 0x114;

private const int WM_VSCROLL = 0x115;

protected override void WndProc(ref Message m)

{

if (m.Msg == WM_VSCROLL)

{

MyScrollEventArgs e = new MyScrollEventArgs();

e.WParam = m.WParam;

e.Orientation = ScrollOrientation.VerticalScroll;

OnScroll(e);

}

if (m.Msg == WM_HSCROLL)

{

MyScrollEventArgs e = new MyScrollEventArgs();

e.WParam = m.WParam;

e.Orientation = ScrollOrientation.HorizontalScroll;

OnScroll(e);

}

base.WndProc(ref m);

}

}

public class MyScrollEventArgs : EventArgs

{

private ScrollOrientation orientation;

private IntPtr wParam;

public IntPtr WParam

{

get { return wParam; }

set { wParam = value; }

}

public ScrollOrientation Orientation

{

get { return orientation; }

set { orientation = value; }

}

}

Zhi-Xin Ye  Thursday, April 03, 2008 10:43 AM

It's certainly possible, but there are things to consider...and you would need to create your own control that derrives from the ListView control to handle the events properly.

You would also have to marshal the ScrollEvent args in your new event.

Are you wanting to scroll both vertically and horizontally?

Are the contents/items in both views identical in size?


Steve

яeverser  Monday, March 31, 2008 9:50 AM

Hi Steve!

Thanks for that quick response!

Well, Yes, I need to perform the sync in both, the horizontal and the vertical bars. I am nearly done with every other part that the listviews are to perform. How can i customize these listviews in order to get them to sync? I am a little too raw with customizing the controls. Where can i create/capture the scroll events for the controls?

Hoping for another response from you.

-

Thanking you,

Nimesh

nimeshprabhakar  Monday, March 31, 2008 9:55 AM

Nimesh,

Without derriving your own control and overriding the WndProc to get the scroll event messages and marshal the pointers it receives, I don't think you'll be able to do it. (I could be wrong)

An easier solution might be to use a DataGridView and modify it's look to take on the appearance of a ListView control.

It won't be exact, but you will then have access to the events you need for this type of approach.

I can't say its recommended, as there could be problems to doing this if the contents of each control varies in size.

Scaling the scrollvalues to compensate for differences in content sizemight be a workaround, but it's not a solidapproach to solving a UI problem as I see it.


Is there no other way to present your data using a different approach?

яeverser  Monday, March 31, 2008 10:03 AM

Steve,

The other way that I performed my tasks earlier for a while was with the ListBox control. The use was pretty good until i came to hit a few blocks with the implementation of the project. I was losing out on a lot of my funtionality and so had to move to the ListView control.

You mentioned deriving my own control, well can you show me a 'how' on that? WndProc that i could manage overriding was when there was an Event available to override. There doesnt seem to be an event that I can override for the ListView control.(Well, I could be looking at it in a wrong way, but if that is so, where else can i look for it, or create my custom event handler for the ListView controls?)

-

Thanks again,

Nimesh

nimeshprabhakar  Monday, March 31, 2008 10:21 AM

Hi,

You can sub-class the ListView class and override its WndProc method to catch the WM_VSCROLL and WM_HSCROLL messages, andcreate a Scroll event for it. Then you can handle this Scroll event to send related scroll message to another ListView, see my sample below for the details

Code Snippet

partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

this.listView1.View = View.Details;

this.listView2.View = View.Details;

for (int j = 0; j < 10; j++)

{

this.listView1.Columns.Add("c" + j.ToString());

this.listView2.Columns.Add("c" + j.ToString());

}

for (int j = 0; j < 300; j++)

{

ListViewItem item = new ListViewItem("item" + j.ToString());

for (int k = 1; k < 10; k++)

{

item.SubItems.Add("sub item" + k.ToString());

}

this.listView1.Items.Add(item);

this.listView2.Items.Add(item.Clone() as ListViewItem);

}

this.listView1.Scroll += new ListViewEx.ScrollHandler(listView1_Scroll);

//this.listView2.Scroll += new ListViewEx.ScrollHandler(listView2_Scroll);

}

[DllImport("user32.dll")]

static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]

static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);

private const int WM_HSCROLL = 0x114;

private const int WM_VSCROLL = 0x115;

private const int SBS_HORZ = 0;

private const int SBS_VERT = 1;

void listView1_Scroll(object sender, MyScrollEventArgs e)

{

ListViewEx listVw = sender as ListViewEx;

Int16 hi = (Int16)((int)e.WParam >> 16);//position

Int16 lo = (Int16)e.WParam;//scroll type

if (e.Orientation == ScrollOrientation.VerticalScroll)

{

if (lo == 5) //SB_THUMBTRACK

{

if (SetScrollPos(this.listView2.Handle, SBS_VERT, hi, true) != 0)

{

SendMessage(this.listView2.Handle, WM_VSCROLL,
(IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);

}

}

else

{

SendMessage(this.listView2.Handle, WM_VSCROLL, e.WParam, IntPtr.Zero);

}

}

if (e.Orientation == ScrollOrientation.HorizontalScroll)

{

if (lo == 5)//SB_THUMBTRACK

{

SetScrollPos(this.listView2.Handle, SBS_HORZ, hi, true);

SendMessage(this.listView2.Handle, WM_HSCROLL,
(IntPtr)(4 + 0x10000 * hi), IntPtr.Zero);

}

else

{

SendMessage(this.listView2.Handle, WM_HSCROLL, e.WParam, IntPtr.Zero);

}

}

}

}

Code Snippet

public class ListViewEx : ListView

{

public delegate void ScrollHandler(object sender, MyScrollEventArgs e);

public event ScrollHandler Scroll;

public void OnScroll(MyScrollEventArgs e)

{

if (Scroll != null)

{

Scroll(this, e);

}

}

private const int WM_HSCROLL = 0x114;

private const int WM_VSCROLL = 0x115;

protected override void WndProc(ref Message m)

{

if (m.Msg == WM_VSCROLL)

{

MyScrollEventArgs e = new MyScrollEventArgs();

e.WParam = m.WParam;

e.Orientation = ScrollOrientation.VerticalScroll;

OnScroll(e);

}

if (m.Msg == WM_HSCROLL)

{

MyScrollEventArgs e = new MyScrollEventArgs();

e.WParam = m.WParam;

e.Orientation = ScrollOrientation.HorizontalScroll;

OnScroll(e);

}

base.WndProc(ref m);

}

}

public class MyScrollEventArgs : EventArgs

{

private ScrollOrientation orientation;

private IntPtr wParam;

public IntPtr WParam

{

get { return wParam; }

set { wParam = value; }

}

public ScrollOrientation Orientation

{

get { return orientation; }

set { orientation = value; }

}

}

Zhi-Xin Ye  Thursday, April 03, 2008 10:43 AM

Dude! that was amazing!

But there's a place where i am stuck at with this.

this.listView1.Scroll += new ListViewEx.ScrollHandler(listView1_Scroll);

The above spot is where is face an error. It says System.Windows.Forms.ListView does not contain a definition for 'Scroll'

What do I do? I am getting desperate and scared now!

Please help!!!!

nimeshprabhakar  Thursday, April 03, 2008 3:39 PM
this.listView1 must be an instance of ListViewEx not ListView. Look for ListViewEx on your toolbar and use that instead.
JRQ  Thursday, April 03, 2008 4:00 PM
Hey there!

The post response you posted was really useful for me. I was looking for the very same thing for quite some time.
I managed to use the logic and code you provided till here. Now, if you wouldn't mind can you tell me as to how can i actually fire the scroll positions?
private void listViewEx1_Scroll(object Sender, MyScrollEventArgs e)
{
//what code here will fire the listViewEx2 to fire?
}

please respond! expecting that you will get me out of this situation.

Thanks a lot for the help already, and the next piece that you will be helping out with!

-
Roger
JigaX  Thursday, April 03, 2008 5:31 PM
The first code snippet shows you that. It will send a scroll message using SendMessage to listView2.

JRQ  Friday, April 04, 2008 7:10 PM
JRQ, Thanks for that correction! Was headed a different way. I was trying to use

Code Snippet

listViewEx2_Scroll(listViewEx1, e);



But that too failed.
Now with the correction that you posted I am getting a overflow exception here at the

Code Snippet

SendMessage(this.listViewEx2.Handle, WM_VSCROLL, e.WParam, IntPtr.Zero);

An unhandled exception of type 'System.StackOverflowException' occurred in Unknown Module.


How can I create a custom scroll for mouse scroll so that when one scrolls the other too scrolls

What am I do to fix this?

Thanking you in advance!


-

Roger
JigaX  Monday, April 07, 2008 6:19 AM

You can use google to search for other answers

Custom Search

More Threads

• Window Services question
• owned forms' visibility...
• Am I running multiple instances??
• SplitterControl inside a TabControl Resize issue
• PPC2003: Move Window
• Ending Backgroundworker
• Visual Studio C# 2005; Windows Form; Serial Port; Writeline() problems; worked and now doesn't; please help
• C# Independent WebBrowser
• ListView-Which event is called next
• How to access the data of Access that in the difference directory?