2011-08-19 37 views
7

Tôi có TScrollBox có một RichEdit lớn hơn hộp cuộn, vì vậy cả thanh cuộn bên xuất hiện trong hộp cuộn. Sau đó, tôi có chức năng DoTask gọi RichEdit.SetFocus.Làm cách nào để vô hiệu hóa hành vi cuộn vào chế độ xem của TScrollBox?

Khi tôi cuộn xuống đến nơi tôi muốn xem một phần của điều khiển văn bản và sau đó gọi DoTask, ScrollBox sẽ tự động cuộn lên đầu RichEdit. Làm thế nào tôi có thể tránh điều đó?

+0

Vâng, rõ ràng. –

+1

không sử dụng hộp cuộn có vẻ là giải pháp hiển nhiên vì bạn có nhiều thanh cuộn hơn cần thiết –

+0

@David: nếu RichEdit là thành phần duy nhất trên hộp cuộn, tôi đồng ý. Tất nhiên chúng tôi không biết nếu nó là. Đặt một thành phần duy nhất có thanh cuộn riêng của nó trên một hộp cuộn sẽ có một chút ... lạ thật đấy. –

Trả lời

6

Như bạn muốn, sau đây là một số gợi ý:

  • Override SetFocusedControl theo hình thức:

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

    Hoặc:

    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; 
    
  • xen 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; 
    

    Hoặc:

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

Hoặc sử dụng bất kỳ sự kết hợp sáng tạo của tất cả những điều trên. Làm thế nào và khi bạn thích nó được cuộn chỉ bạn biết.

+0

Tôi đoán một trợ giúp lớp cho TScrollBox, thay vì một interposer, cũng sẽ làm các trick. Tuy nhiên, không thể kiểm tra điều đó. –

+1

Tôi không nghĩ điều đó sẽ hiệu quả, @Rudy. Bạn không thể ghi đè các phương thức ảo với người trợ giúp lớp học. Trang web cuộc gọi ban đầu của phương thức không biết trình trợ giúp lớp tồn tại, vì vậy nó sẽ tiếp tục gọi phương thức gốc. –

+0

@Rob: Bạn nói đúng. Trang web cuộc gọi ban đầu sẽ không sử dụng phương thức trợ giúp. –

2

giải pháp đơn giản nhất sẽ là

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

Không xâm nhập vào VCL/phát sinh thành phần tùy chỉnh chỉ có một giải pháp - TForm.SetFocusedControl ghi đè + cài đặt lại vị trí của thanh cuộn như đã nói ở trên. Một điều tôi thêm vào là vô hiệu hóa/kích hoạt cửa sổ vẽ lại để tránh các bước nhảy xấu xí. Đây là đoạn cuối cùng của tôi:

sbContainer là TScrollBox và NoScrCtrl là một điều khiển nằm bên trong nó được lấy tiêu điểm nhưng chúng tôi không muốn nó được cuộn vào chế độ xem.

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; 
Các vấn đề liên quan