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

How to synchronize two RichEdit's scrolling position?

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

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

我尝试过的第二种方法是使用计时器并按时间定期与 LINESCROLL 同步(< 10 毫秒更好)。这在大多数情况下都很好,但有时仍然存在未对齐的问题。

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

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

感谢您的帮助。我找到了一个简单的解决方案来满足我的短期需求。

正如我之前提到的,第二个 RichEdit 的滚动条应该启用以接收 WM_MOUSEWHEEL 消息,但我不喜欢两个编辑都显示滚动条。出于这个原因,我使用 EM_LINESCROLL 代替鼠标滚轮消息。我写了一个子 class 派生 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 中的文本垂直偏移对齐。不过我觉得肯定有更好的解决办法,我会继续研究改进的。