using System; using System.IO; using System.Data; using System.Text; using System.Drawing; using System.Collections; using System.Windows.Forms; using System.Runtime.InteropServices; namespace TestMultiScroll { public class Form1 : System.Windows.Forms.Form { private System.ComponentModel.IContainer components = null; public System.Windows.Forms.RichTextBox RichTextBox1 = null; public System.Windows.Forms.RichTextBox RichTextBox2 = null; public System.Windows.Forms.RichTextBox RichTextBox3 = null; // =================================================================== // for NativeWindow and PostMessageA // =================================================================== private const int WM_HSCROLL = 0x114; private const int WM_VSCROLL = 0x115; private const int WM_MOUSEWHEEL = 0x20A; private const int WM_COMMAND = 0x111; // =================================================================== // for GetScroll and PostMessageA // =================================================================== private const int WM_USER = 0x400; private const int SBS_HORZ = 0; private const int SBS_VERT = 1; // =================================================================== // for SubClassing // =================================================================== private const int SB_THUMBPOSITION = 4; private Subclass sClass1 = null; private Subclass sClass2 = null; private Subclass sClass3 = null; public Form1() { InitializeComponent(); } protected void Dispose(bool disposing) { if (disposing) { if ( !( (components == null))) { components.Dispose(); } } base.Dispose(disposing); } #region Windows Form Designer generated code private void InitializeComponent() { this.RichTextBox1 = new System.Windows.Forms.RichTextBox (); this.RichTextBox2 = new System.Windows.Forms.RichTextBox (); this.RichTextBox3 = new System.Windows.Forms.RichTextBox (); this.SuspendLayout(); // // RichTextBox1 // this.RichTextBox1.Location = new System.Drawing.Point (24, 24); this.RichTextBox1.Name = "RichTextBox1"; this.RichTextBox1.Size = new System.Drawing.Size (128, 128); this.RichTextBox1.TabIndex = 0; this.RichTextBox1.Text = "RichTextBox1"; this.RichTextBox1.WordWrap = false; // // RichTextBox2 // this.RichTextBox2.Location = new System.Drawing.Point (160, 24); this.RichTextBox2.Name = "RichTextBox2"; this.RichTextBox2.Size = new System.Drawing.Size (128, 128); this.RichTextBox2.TabIndex = 1; this.RichTextBox2.Text = "RichTextBox2"; this.RichTextBox2.WordWrap = false; // // RichTextBox3 // this.RichTextBox3.Location = new System.Drawing.Point (296, 24); this.RichTextBox3.Name = "RichTextBox3"; this.RichTextBox3.Size = new System.Drawing.Size (128, 128); this.RichTextBox3.TabIndex = 3; this.RichTextBox3.Text = "RichTextBox3"; this.RichTextBox3.WordWrap = false; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size (5, 13); this.ClientSize = new System.Drawing.Size (448, 174); this.Controls.Add(this.RichTextBox3); this.Controls.Add(this.RichTextBox2); this.Controls.Add(this.RichTextBox1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); this.Load += new System.EventHandler (Form1_Load); this.RichTextBox1.VScroll += new System.EventHandler (RichTextBox1_VScroll); this.RichTextBox2.VScroll += new System.EventHandler (RichTextBox2_VScroll); this.RichTextBox3.VScroll += new System.EventHandler (RichTextBox3_VScroll); this.RichTextBox1.HScroll += new System.EventHandler (RichTextBox1_HScroll); this.RichTextBox2.HScroll += new System.EventHandler (RichTextBox2_HScroll); this.RichTextBox3.HScroll += new System.EventHandler (RichTextBox3_HScroll); } #endregion /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.Run(new Form1()); } private void Form1_Load(System.Object sender,System.EventArgs e) { sClass1 = new Subclass(RichTextBox1.Handle); sClass2 = new Subclass(RichTextBox2.Handle); sClass3 = new Subclass(RichTextBox3.Handle ); this.sClass1.NativeWindowsEvent += new Subclass.WindowsEventHandler (sClass_WindowProcedure); this.sClass2.NativeWindowsEvent += new Subclass.WindowsEventHandler (sClass_WindowProcedure); this.sClass3.NativeWindowsEvent += new Subclass.WindowsEventHandler (sClass_WindowProcedure); for (int i = 0; i <= 100; i++) { if (i % 4 == 0) { RichTextBox1.AppendText(" this is a longer string to force HScroll " + i + System.Environment.NewLine); RichTextBox2.AppendText(" this is a longer string to force HScroll " + i + System.Environment.NewLine); RichTextBox3.AppendText(" this is a longer string to force HScroll " + i + System.Environment.NewLine); } else { RichTextBox1.AppendText(" this is a string " + i + System.Environment.NewLine); RichTextBox2.AppendText(" this is a string " + i + System.Environment.NewLine); RichTextBox3.AppendText(" this is a string " + i + System.Environment.NewLine); } } } public void sClass_WindowProcedure(ref Message uMsg) { switch (uMsg.Msg) { case (WM_VSCROLL): if (uMsg.HWnd.Equals(RichTextBox1.Handle)) { ThumbScrollHandler(RichTextBox1, new RichTextBox[] {RichTextBox2, RichTextBox3}, ref uMsg); } if (uMsg.HWnd.Equals(RichTextBox2.Handle)) { ThumbScrollHandler(RichTextBox2, new RichTextBox[] {RichTextBox1, RichTextBox3}, ref uMsg); } if (uMsg.HWnd.Equals(RichTextBox3.Handle )) { ThumbScrollHandler(RichTextBox3, new RichTextBox[] {RichTextBox1, RichTextBox2}, ref uMsg); } break; case (WM_HSCROLL): if (uMsg.HWnd.Equals(RichTextBox1.Handle)) { ThumbScrollHandler(RichTextBox1, new RichTextBox[] {RichTextBox2, RichTextBox3}, ref uMsg); } if (uMsg.HWnd.Equals(RichTextBox2.Handle)) { ThumbScrollHandler(RichTextBox2, new RichTextBox[] {RichTextBox1, RichTextBox3}, ref uMsg); } if (uMsg.HWnd.Equals(RichTextBox3.Handle)) { ThumbScrollHandler(RichTextBox3, new RichTextBox[] {RichTextBox1, RichTextBox2}, ref uMsg); } break; } } private void ThumbScrollHandler(RichTextBox sender, RichTextBox[] receivers, ref Message uMsg) { sClass2.NativeWindowsEvent -= new Subclass.WindowsEventHandler(ref sClass_WindowProcedure); foreach (RichTextBox receiver in receivers) { Message msg = Message.Create(receiver.Handle, uMsg.Msg, uMsg.WParam, uMsg.LParam); sClass2.SendWndProc(ref msg); } sClass2.NativeWindowsEvent += new Subclass.WindowsEventHandler(ref sClass_WindowProcedure); } private void RichTextBox1_VScroll(object sender,System.EventArgs e) { VerticalScroll(RichTextBox1, new RichTextBox[2] {RichTextBox2, RichTextBox3}); } private void RichTextBox2_VScroll(object sender, System.EventArgs e) { VerticalScroll(RichTextBox2, new RichTextBox[2] {RichTextBox1, RichTextBox3}); } private void RichTextBox3_VScroll(object sender,System.EventArgs e) { VerticalScroll(RichTextBox3, new RichTextBox[2] {RichTextBox1, RichTextBox2}); } private void RichTextBox1_HScroll(object sender,System.EventArgs e) { HorizontalScroll(RichTextBox1, new RichTextBox[2] {RichTextBox2, RichTextBox3}); } private void RichTextBox2_HScroll(object sender, System.EventArgs e) { HorizontalScroll(RichTextBox2, new RichTextBox[2] {RichTextBox1, RichTextBox3}); } private void RichTextBox3_HScroll(object sender,System.EventArgs e) { HorizontalScroll(RichTextBox3, new RichTextBox[2] {RichTextBox1, RichTextBox2}); } private void VerticalScroll(RichTextBox sender, RichTextBox[] receivers) { int position = GetScrollPos(sender.Handle, SBS_VERT); foreach (RichTextBox receiver in receivers) { PostMessageA( receiver.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * position, 0); } } private void HorizontalScroll(RichTextBox sender, RichTextBox[] receivers) { int position = GetScrollPos(sender.Handle , SBS_HORZ); foreach(RichTextBox receiver in receivers) { PostMessageA(receiver.Handle, WM_HSCROLL, SB_THUMBPOSITION + 0x10000 * position, 0); } } // =================================================================== // API Function: GetScrollPos() // =================================================================== [DllImport("user32.dll")] private static extern int GetScrollPos(IntPtr hWnd, int nBar); // =================================================================== // API Function: PostMessageA() // =================================================================== [DllImport("user32.dll ")] private static extern bool PostMessageA(IntPtr hwnd, int wMsg, int wParam, int lParam); } // =================================================================== // NativeWindow Subclassing // =================================================================== public class Subclass : System.Windows.Forms.NativeWindow { public event WindowsEventHandler NativeWindowsEvent; public delegate void WindowsEventHandler(ref Message uMsg); public Subclass(IntPtr pWindowHandle):base() { base.AssignHandle(pWindowHandle); } protected override void WndProc(ref System.Windows.Forms.Message uMsg) { base.WndProc(ref uMsg); if (NativeWindowsEvent != null) NativeWindowsEvent(ref uMsg); } public void SendWndProc(ref System.Windows.Forms.Message uMsg) { base.WndProc(ref uMsg); } } }