2009-12-01 2 views

답변

15

나는 작은 프로젝트를 오래 전에 했었고, 여기 내가 찾은 단순한 해결책이있다.

하위 클래스를 RichTextBox하여 새 컨트롤 만들기 :

public class SynchronizedScrollRichTextBox : System.Windows.Forms.RichTextBox 
    { 
     public event vScrollEventHandler vScroll; 
     public delegate void vScrollEventHandler(System.Windows.Forms.Message message); 

     public const int WM_VSCROLL = 0x115; 

     protected override void WndProc(ref System.Windows.Forms.Message msg) { 
      if (msg.Msg == WM_VSCROLL) { 
       if (vScroll != null) { 
        vScroll(msg); 
       } 
      } 
      base.WndProc(ref msg); 
     } 

     public void PubWndProc(ref System.Windows.Forms.Message msg) { 
      base.WndProc(ref msg); 
     } 
    }  

이 양식과 각 컨트롤은 명시 적으로 vScroll 위치가 변경되었음을 컨트롤의 다른 인스턴스를 통지하기위한 새로운 컨트롤을 추가합니다. 이 같은 뭔가를해야만 :

private void scrollSyncTxtBox1_vScroll(Message msg) { 
    msg.HWnd = scrollSyncTxtBox2.Handle; 
    scrollSyncTxtBox2.PubWndProc(ref msg); 
} 

나는 모든 '연결'컨트롤 디스플레이 라인의 같은 번호가없는 경우이 코드는 문제가있다 생각합니다.

+0

이 메서드는 스크롤 막대를 움직여 스크롤하는 데 적합합니다. 그러나 스크롤 막대는 (1) 마우스 휠로 스크롤 (2) '페이지 아래로'또는 '페이지 위로'키로 스크롤 - 화살표 키를 눌러 스크롤 – twnaing

+0

@Jay riggs 'System.Windows.Forms.RichTextBox' 'PubWndProc'에 대한 정의가없고 'System.Windows.Forms.RichTextBox'유형의 첫 번째 인수를 허용하는 확장 메서드 'PubWndProc'이 없습니다 (지시어 또는 어셈블리 참조가 누락 되었습니까?) – Pomster

18

감사합니다. Jay 님의 답변입니다. 좀 더 검색 한 후에 나는 또한 here이라고 기술 된 방법을 발견했다. 관심있는 다른 사람들을 위해 아래에서 설명하겠습니다.


먼저 다음 열거 형을 선언

public enum ScrollBarType : uint { 
    SbHorz = 0, 
    SbVert = 1, 
    SbCtl = 2, 
    SbBoth = 3 
} 

public enum Message : uint { 
    WM_VSCROLL = 0x0115 
} 

public enum ScrollBarCommands : uint { 
    SB_THUMBPOSITION = 4 
} 

다음, GetScrollPosSendMessage에 외부 참조를 추가합니다.

[DllImport("User32.dll")] 
public extern static int GetScrollPos(IntPtr hWnd, int nBar); 

[DllImport("User32.dll")] 
public extern static int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); 

마지막으로, 적절한 RichTextBoxVScroll 이벤트에 대한 이벤트 핸들러를 추가

private void myRichTextBox1_VScroll(object sender, EventArgs e) 
{ 
    int nPos = GetScrollPos(richTextBox1.Handle, (int)ScrollBarType.SbVert); 
    nPos <<= 16; 
    uint wParam = (uint)ScrollBarCommands.SB_THUMBPOSITION | (uint)nPos; 
    SendMessage(richTextBox2.Handle, (int)Message.WM_VSCROLL, new IntPtr(wParam), new IntPtr(0)); 
} 

을이 경우 richTextBox2의 세로 스크롤 위치 richTextBox1와 동기화된다.

+0

요약 . 내 많은 시간을 절약했습니다. 고맙습니다! –

+1

WM_HSCROLL의 16 진 코드는 무엇이겠습니까? – Logerfo

1

Jay의 하위 클래스 접근 방식의 변형은 Joseph Kingry의 게시물에서 확인할 수 있습니다. Synchronizing Multiline Textbox Positions in C#. Joseph의 접근법은 하위 클래스이지만 _VScroll 이벤트 핸들러가 필요하지 않습니다. 나는이 방법을 사용하여 3 개의 박스 사이에 3-way 바인드를하고 WM_HSCROLL을 추가했습니다.

3

[비주얼 스튜디오 C의 # 2010 익스프레스, 윈도우 7 64 비트 설치에 v10.0.30319] 나는 도넛의 솔루션은 위의 게시, 그러나 많은 줄을 포함 RichTextBoxes의 끝으로 스크롤 할 때 문제가 발견 사용했습니다

.

GetScrollPos()의 결과가 >0x7FFF이면 nPos이 시프트되면 최상위 비트가 설정됩니다. 결과적으로 wParam 변수와 함께 IntPtr이 생성되면 OverflowException으로 실패합니다. 쉽게 (실패합니다 두 번째 줄) 다음으로이 테스트 할 수 있습니다

IntPtr ip = new IntPtr(0x7FFF0000); 
    IntPtr ip2 = new IntPtr(0x80000000); 

UIntPtr이 솔루션으로 나타납니다 사용하지만, 내가 그 일을 가져올 수 없습니다 SendMessage()의 버전.그래서, 나는 다음과 같은 사용했습니다 :

[DllImport("User32.dll")] 
    public extern static int SendMessage(IntPtr hWnd, uint msg, UInt32 wParam, UInt32 lParam); 

0xffff까지 잘해야하지만, 그 후 실패합니다. 나는 >0xffff 결과를 GetScrollPos()에서 아직 경험하지 못했고, User32.dll이 SendCommand()의 64 비트 버전을 가지고 있지 않다고 가정하지만, 그 문제에 대한 해결책은 매우 높이 평가 될 것입니다.

관련 문제