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

时间:2019-03-15 03:28:18

标签: c++ winapi c++builder vcl richedit

我在程序中添加了两个RichEdit,其中一个显示二进制内容,另一个显示字节的索引。我希望这两个编辑在滚动时/滚动后始终固定在同一位置。

image

一种可能的方法是处理主RichEdit的WM_VSCROLL和WM_MOUSEWHEEL消息,并将消息和参数传递给第二个RichEdit。我已经尝试过了,但是我发现两个编辑的对齐不是很好。另一个缺点是两个RichEdits的滚动条都需要启用,如果我仅启用一个,则另一个将无法接收WM_MOUSEWHEEL消息,但我希望仅显示一个滚动条。

image

我尝试的第二种方法是使用计时器,并在时间之前定期与LINESCROLL同步(<10ms更好)。在大多数情况下,此方法效果很好,但有时仍然存在无法解决的问题。

是否有更好的解决方案来处理这种需求?

//---------------------------------------------------------------------------
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;
}

1 个答案:

答案 0 :(得分:1)

感谢您的帮助。我已经找到了适合我短期需求的简单解决方案。

正如我之前提到的,应该启用第二个RichEdit的滚动条以接收WM_MOUSEWHEEL消息,但是我不喜欢两个编辑都显示滚动条。因此,我使用EM_LINESCROLL代替了鼠标滚轮消息。我编写一个派生TRichEdit的子类,并覆盖其WM_MOUSEWHEEL处理程序,然后将带有鼠标滚轮增量值的EM_LINESCROLL消息传递给两个RichEdits。

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中的文本垂直偏移对齐。但是我认为必须有更好的解决方案,我将继续研究以求改进。