c++ 如何同步两个RichEdit的滚动位置?

ef1yzkbh  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(78)

我添加了两个RichEdit,一个显示二进制内容,另一个显示字节的索引。我希望这两个编辑在滚动时/滚动后总是锚在同一位置。
x1c 0d1x的数据
一种可能的方法是处理主RichEdit的WM_VSCROLL和WM_MOUSEWHEEL消息,并将消息和参数传递给第二个RichEdit。我已经尝试过这种方法,但我发现这两个编辑对齐得不是很好。另一个缺点是两个RichEdit的滚动条都需要启用,如果我只启用一个,另一个不能接收WM_MOUSEWHEEL消息,但我希望只显示一个滚动条。



我尝试的第二种方法是使用定时器,并定期与LINESCROLL同步(<10 ms更好)。这在大多数情况下都很好用,但有时仍然存在未对齐的问题。
有没有更好的办法来满足这种需求?

//---------------------------------------------------------------------------
void __fastcall TBinaryEdit::Timer1Timer(TObject *Sender)
{
    int srcLine = 0;
    int trgLine = 0;

    if (Sender == Timer1) {
        srcLine = GetRichEditLineNo(MainEdit);
        trgLine = GetRichEditLineNo(IndexEdit);

        if (srcLine != trgLine) {
            SendMessage(IndexEdit->Handle, EM_LINESCROLL, 0, srcLine - trgLine);
        }
    }
}
//---------------------------------------------------------------------------
int TBinaryEdit::GetRichEditLineNo(TRichEdit* RE)
{
    int line;
    int wordpos;

    TRect rt;
    POINTL pt;

    SendMessage(RE->Handle, EM_GETRECT, 0, LPARAM(&rt));
    pt.x = RE->Left + rt.left;
    pt.y = RE->Top + rt.top;
    wordpos = SendMessage(RE->Handle, EM_CHARFROMPOS, 0, LPARAM(&pt));
    line = SendMessage(RE->Handle, EM_LINEFROMCHAR, wordpos, 0);

    return line;
}

字符串

e7arh2l6

e7arh2l61#

谢谢你的帮助。我找到了一个简单的方法来解决我的短期需求。
正如我之前提到的,第二个RichEdit的滚动条应该被启用以接收WM_MOUSEWHEEL消息,但是我不喜欢两个编辑都显示滚动条。出于这个原因,我使用EM_LINESCROLL代替鼠标滚轮消息。我写了一个子类派生TRichEdit并覆盖它的WM_MOUSEWHEEL处理程序,然后将EM_LINESCROLL消息与鼠标滚轮的delta值传递给两个RichEdit。

int zDelta = GET_WHEEL_DELTA_WPARAM(Message.WParam);
int scroll = zDelta == -120 ? 1 : -1;

SendMessage(MainEdit->Handle, EM_LINESCROLL, 0, scroll);
SendMessage(IndexEdit->Handle, EM_LINESCROLL, 0, scroll);

字符串
这使得RichEdits中的文本垂直偏移对齐。但我认为一定有更好的解决方案,我会继续研究改进。

k4ymrczo

k4ymrczo2#

迟早会有一个解决方案。我对c/c++的解决方案(你需要根据你的编程语言来调整):

case WM_MOUSEWHEEL:
        POINTL pt;
        SendMessage(hRichMain,EM_GETSCROLLPOS, 0, LPARAM(&pt));
        SendMessage(hRichComp,EM_SETSCROLLPOS,0,LPARAM(&pt));
        SendMessage(hRichOffset,EM_SETSCROLLPOS,0,LPARAM(&pt));
        SendMessage(hRichAscii,EM_SETSCROLLPOS,0,LPARAM(&pt));

    break;

字符串
EM_GETSCROLLPOS将滚动条位置从句柄hRichMain复制到ptEM_SETSCROLLPOS将位置信息从pt设置到hRichComp,hRichOffset, hRichAscii
甚至可以通过WM_COMMAND实现更精细的过滤:

case WM_COMMAND:
    {

///// RICH EDIT //////////////
      switch(HIWORD(wParam))
      {
          case EN_VSCROLL:
            if(LOWORD(wParam) == ID_RICHMAIN)
            {
                SendMessage(hRichMain,EM_GETSCROLLPOS, 0, LPARAM(&pt));
                SendMessage(hRichOffset,EM_SETSCROLLPOS,0,LPARAM(&pt));
                SendMessage(hRichAscii,EM_SETSCROLLPOS,0,LPARAM(&pt));
            //if (Button_GetCheck(hCheckScroll))
                SendMessage(hRichComp,EM_SETSCROLLPOS,0,LPARAM(&pt));

            }
            return TRUE;
      }

相关问题