2011-08-19 60 views
7

我有一個比滾動框大的RichEdit的TScrollBox,所以兩個滾動條都出現在滾動框中。然後我有一個功能DoTask,調用RichEdit.SetFocus如何禁用TScrollBox的滾動瀏覽行爲?

當我向下滾動到我想要看到的文本控件的一部分,然後調用DoTask時,滾動框將自動滾動到RichEdit的頂部。我怎樣才能避免這種情況?

+0

是的,很明顯。 –

+1

不使用滾動框似乎是顯而易見的解決方案,因爲你有更多的滾動條比需要 –

+0

@David:如果RichEdit是滾動框中唯一的組件,我同意。當然,我們不知道它是否是。把一個單獨的組件放在一個滾動框上有它自己的滾動條會有點奇怪,確實如此。 –

回答

6

如你所願,這裏有一些建議:

  • 覆蓋SetFocusedControl形式:

    function TForm1.SetFocusedControl(Control: TWinControl): Boolean; 
    begin 
        if Control = RichEdit then 
        Result := True 
        else 
        Result := inherited SetFocusedControl(Control); 
    end; 
    

    或者:

    type 
        TCustomMemoAccess = class(TCustomMemo); 
    
    function TForm1.SetFocusedControl(Control: TWinControl): Boolean; 
    var 
        Memo: TCustomMemoAccess; 
        Scroller: TScrollingWinControl; 
        Pt: TPoint; 
    begin 
        Result := inherited SetFocusedControl(Control); 
        if (Control is TCustomMemo) and (Control.Parent <> nil) and 
        (Control.Parent is TScrollingWinControl) then 
        begin 
        Memo := TCustomMemoAccess(Control); 
        Scroller := TScrollingWinControl(Memo.Parent); 
        SendMessage(Memo.Handle, EM_POSFROMCHAR, Integer(@Pt), Memo.SelStart); 
        Scroller.VertScrollBar.Position := Scroller.VertScrollBar.Position + 
         Memo.Top + Pt.Y; 
        end; 
    end; 
    
  • TScrollBox

    type 
        TScrollBox = class(Forms.TScrollBox) 
        protected 
        procedure AutoScrollInView(AControl: TControl); override; 
        end; 
    
    procedure TScrollBox.AutoScrollInView(AControl: TControl); 
    begin 
        if not (AControl is TCustomMemo) then 
        inherited AutoScrollInView(AControl); 
    end; 
    

    或者:

    procedure TScrollBox.AutoScrollInView(AControl: TControl); 
    begin 
        if (AControl.Top > VertScrollBar.Position + ClientHeight) xor 
         (AControl.Top + AControl.Height < VertScrollBar.Position) then 
        inherited AutoScrollInView(AControl); 
    end; 
    

或者使用上述所有的創造性組合。如何和什麼時候你喜歡它滾動只有你知道。

+0

我猜TScrollBox的類助手,而不是一個插入,也會做的伎倆。雖然不能檢查。 –

+1

我不認爲這會奏效,@Rudy。你不能用類助手來覆蓋虛擬方法。該方法的原始調用網站不知道類助手是否存在,因此它將繼續調用原始方法。 –

+0

@Rob:你說得對。原來的呼叫站點不會使用助手方法。 –

2

的simpliest的解決辦法是

var a, b : Integer; 
begin 
    a := ScrollBox1.VertScrollBar.Position; 
    b := ScrollBox1.HorzScrollBar.Position; 
    richEdit1.SetFocus; 
    ScrollBox1.VertScrollBar.Position:=a ; 
    ScrollBox1.HorzScrollBar.Position:=b ; 
end; 
1

沒有黑客進入VCL /派生自定義組件只有一個解決方案 - TForm.SetFocusedControl覆蓋+重新設置滾動條的位置,如上所述。我添加的一件事是禁用/啓用窗口重繪,以避免醜陋的跳轉。 這裏是我的最後一個片段:

sbContainer是TScrollBox和NoScrCtrl是一個控制內部它獲得焦點,但我們不希望它被滾動在視圖中。

function TForm1.SetFocusedControl(Control: TWinControl): Boolean; 
var hpos, vpos: integer; 
begin 
    if Control = NoScrCtrl then 
    begin 
    sbContainer.Perform(WM_SETREDRAW, WPARAM(False), 0); 
    hpos := sbContainer.HorzScrollBar.Position; 
    vpos := sbContainer.VertScrollBar.Position; 
    Result := inherited SetFocusedControl(Control); 
    sbContainer.HorzScrollBar.Position := hpos; 
    sbContainer.VertScrollBar.Position := vpos; 
    sbContainer.Perform(WM_SETREDRAW, WPARAM(True), 0); 
    sbContainer.Refresh; 
    end 
    else 
    Result := inherited SetFocusedControl(Control); 
end;