Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Rather than use SendMessage and mark your DLL as unsafe you can use the <code>GetScrollPos</code> and <code>SetScrollPos</code> functions from user32.dll.</p> <p>I've wrapped the code up into your MyTreeView class so it's nicely encapsulated.</p> <p>You just need to call the <code>AddLinkedTreeView</code> method like so:</p> <pre><code>treeView1.AddLinkedTreeView(treeView2); </code></pre> <p>Here's the source for the MyTreeView class.</p> <pre><code>public partial class MyTreeView : TreeView { public MyTreeView() : base() { } private List&lt;MyTreeView&gt; linkedTreeViews = new List&lt;MyTreeView&gt;(); /// &lt;summary&gt; /// Links the specified tree view to this tree view. Whenever either treeview /// scrolls, the other will scroll too. /// &lt;/summary&gt; /// &lt;param name="treeView"&gt;The TreeView to link.&lt;/param&gt; public void AddLinkedTreeView(MyTreeView treeView) { if (treeView == this) throw new ArgumentException("Cannot link a TreeView to itself!", "treeView"); if (!linkedTreeViews.Contains(treeView)) { //add the treeview to our list of linked treeviews linkedTreeViews.Add(treeView); //add this to the treeview's list of linked treeviews treeView.AddLinkedTreeView(this); //make sure the TreeView is linked to all of the other TreeViews that this TreeView is linked to for (int i = 0; i &lt; linkedTreeViews.Count; i++) { //get the linked treeview var linkedTreeView = linkedTreeViews[i]; //link the treeviews together if (linkedTreeView != treeView) linkedTreeView.AddLinkedTreeView(treeView); } } } /// &lt;summary&gt; /// Sets the destination's scroll positions to that of the source. /// &lt;/summary&gt; /// &lt;param name="source"&gt;The source of the scroll positions.&lt;/param&gt; /// &lt;param name="dest"&gt;The destinations to set the scroll positions for.&lt;/param&gt; private void SetScrollPositions(MyTreeView source, MyTreeView dest) { //get the scroll positions of the source int horizontal = User32.GetScrollPos(source.Handle, Orientation.Horizontal); int vertical = User32.GetScrollPos(source.Handle, Orientation.Vertical); //set the scroll positions of the destination User32.SetScrollPos(dest.Handle, Orientation.Horizontal, horizontal, true); User32.SetScrollPos(dest.Handle, Orientation.Vertical, vertical, true); } protected override void WndProc(ref Message m) { //process the message base.WndProc(ref m); //pass scroll messages onto any linked views if (m.Msg == User32.WM_VSCROLL || m.Msg == User32.WM_MOUSEWHEEL) { foreach (var linkedTreeView in linkedTreeViews) { //set the scroll positions of the linked tree view SetScrollPositions(this, linkedTreeView); //copy the windows message Message copy = new Message { HWnd = linkedTreeView.Handle, LParam = m.LParam, Msg = m.Msg, Result = m.Result, WParam = m.WParam }; //pass the message onto the linked tree view linkedTreeView.RecieveWndProc(ref copy); } } } /// &lt;summary&gt; /// Recieves a WndProc message without passing it onto any linked treeviews. This is useful to avoid infinite loops. /// &lt;/summary&gt; /// &lt;param name="m"&gt;The windows message.&lt;/param&gt; private void RecieveWndProc(ref Message m) { base.WndProc(ref m); } /// &lt;summary&gt; /// Imported functions from the User32.dll /// &lt;/summary&gt; private class User32 { public const int WM_VSCROLL = 0x115; public const int WM_MOUSEWHEEL = 0x020A; [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar); [DllImport("user32.dll")] public static extern int SetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar, int nPos, bool bRedraw); } } </code></pre> <p><strong>Edit</strong>: Added forwarding of the WM_MOUSEWHEEL message as per MinnesotaFat's suggestion.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload