如何从TMemo控件中获取滚动条通知?

4

我有一个VCL TMemo 控件,需要在文本滚动时得到通知。没有 OnScroll 事件,而且滚动消息似乎不会向上传播到父窗体。

有什么办法可以获得通知吗? 如果万不得已,我可以放置一个外部的 TScrollBar 并在 OnScroll 事件中更新 TMemo,但这样我必须在移动光标或滚动鼠标轮时保持它们同步...


据我所知,你需要编写自己的子类并覆盖“WndProc”以捕获“WM_VSCROLL”和“WM_HSCROLL”消息,然后根据需要做出响应。 - Ken White
@KenWhite,这不是一个Delphi应用程序...我已经改回了标签。 - Max Kielland
你的标签一开始并没有表明它不是Delphi。它只是说VCL,而VCL Delphi。不过答案是一样的。 - Ken White
1
好的,VCL也是C++ Builder ;) - Max Kielland
好的,不是。它可以从C ++ Builder中使用,但是VCL的所有源代码都是用Delphi编写的。 - Ken White
2个回答

3
你可以使用一个拦截器类来处理 WM_VSCROLLWM_HSCROLL 消息以及通过 WM_COMMAND 消息暴露的 EN_VSCROLLEN_HSCROLL 通知代码。请尝试此示例。
type
  TMemo  = class(Vcl.StdCtrls.TMemo)
  private
   procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
   procedure WMVScroll(var Msg: TWMHScroll); message WM_VSCROLL;
   procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
  end;

  TForm16 = class(TForm)
    Memo1: TMemo;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form16: TForm16;

implementation

{$R *.dfm}


{ TMemo }

procedure TMemo.CNCommand(var Message: TWMCommand);
begin
   case Message.NotifyCode of
    EN_VSCROLL : OutputDebugString('EN_VSCROLL');
    EN_HSCROLL : OutputDebugString('EN_HSCROLL');
   end;

   inherited ;
end;

procedure TMemo.WMHScroll(var Msg: TWMHScroll);
begin
   OutputDebugString('WM_HSCROLL') ;
   inherited;
end;

procedure TMemo.WMVScroll(var Msg: TWMHScroll);
begin
   OutputDebugString('WM_HSCROLL') ;
   inherited;
end;

抱歉,我忘了提到我正在使用C++ Builder,但我会尝试翻译你的示例... - Max Kielland
дёӯй—ҙ件зұ»еңЁC++дёӯдёҚиө·дҪңз”ЁгҖӮдҪҶжҳҜжӮЁеҸҜд»ҘеңЁиҝҗиЎҢж—¶еҜ№ж ҮеҮҶзҡ„TMemo组件зҡ„WindowProcеұһжҖ§иҝӣиЎҢеӯҗзұ»еҢ–гҖӮ - Remy Lebeau
只需要进行微小的更正:在TMemo.WMVScroll过程中,将WM_VSCROLL更改为WM_HSCROLL - Interface Unknown

2
你可以在运行时通过子类化Memo的WindowProc属性来捕获发送到Memo的所有消息,例如:
private:
    TWndMethod PrevMemoWndProc;
    void __fastcall MemoWndProc(TMessage &Message);

__fastcall TMyForm::TMyForm(TComponent *Owner)
    : TForm(Owner)
{
    PrevMemoWndProc = Memo1->WindowProc;
    Memo1->WindowProc = MemoWndProc;
}

void __fastcall TMyForm::MemoWndProc(TMessage &Message)
{
    switch (Message.Msg)
    {
        case CN_COMMAND:
        {
            switch (reinterpret_cast<TWMCommand&>(Message).NotifyCode)
            {
                case EN_VSCROLL:
                {
                    //...
                    break;
                }

                case EN_HSCROLL:
                {
                    //...
                    break;
                }
            }

            break;
        }

        case WM_HSCROLL:
        {
            //...
            break;
        }

        case WM_VSCROLL:
        {
            //...
            break;
        }
    }

    PrevMemoWndProc(Message);
}

我确实收到了一些消息,但它们中没有任何滚动消息。如果我按下备忘录滚动条的上下按钮,我会收到Notifycode 0x0602(WParamHi),但不会有其他CN_COMMANDS。 - Max Kielland
@MaxKielland’╝ÜNotifyCode 0x0602 µś» EN_VSCROLL’╝łEN_HSCROLL µś» 0x0601’╝ēŃĆé - Remy Lebeau
谢谢!某些原因导致代码被优化了。当我进行更合适的实现时,它就可以正常工作了。通过使用 WM_xSCROLL 消息,我捕获了所有滚动条的行为,而不仅仅是箭头按钮。但是,有没有办法也捕获由于光标移动而导致备忘录滚动的情况?滚动条已经更新,但我没有收到任何滚动条消息。我尝试监听 SBM_SETPOS,但我想它是直接发送到嵌入式滚动条。在最坏的情况下,我想我必须监听按键按下事件。 - Max Kielland
使用TWinControlWindowProc属性的好例子。 - Wolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接