2011-08-19 6 views
7

Possiedo un TScrollBox con un RichEdit più grande della casella di scorrimento, quindi entrambe le barre di scorrimento laterali vengono visualizzate nella casella di scorrimento. Quindi ho una funzione DoTask che chiama RichEdit.SetFocus.Come si disabilita il comportamento di scorrimento in vista di TScrollBox?

Quando si scorre verso il basso a cui voglio vedere parte del controllo testo, e quindi chiamare DoTask, ScrollBox scorrerà automaticamente verso l'alto di RichEdit. Come posso evitarlo?

+0

Sì, è chiaro. –

+1

non utilizzare la casella di scorrimento sembra essere la soluzione più ovvia poiché si dispone di più barre di scorrimento del necessario. –

+0

@David: se RichEdit è l'unico componente della casella di scorrimento, sono d'accordo. Certo che non sappiamo se lo è. Mettere un singolo componente che ha le sue barre di scorrimento su una casella di scorrimento sarebbe un po '... strano, davvero. –

risposta

6

Come desideri, ecco alcuni suggerimenti:

  • Override SetFocusedControl nella forma:

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

    Oppure:

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

    Oppure:

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

o utilizzare alcun combinazione creativa di tutto quanto sopra. Come e quando ti piace che scorra solo tu sai.

+0

Immagino che un aiutante di classe per TScrollBox, invece di un interposer, farebbe anche il trucco. Non posso controllare, comunque. –

+1

Non penso che funzionerebbe, @Rudy. Non è possibile sovrascrivere i metodi virtuali con gli helper di classe. Il sito di chiamata originale del metodo non sa che l'helper di classe esiste, quindi continuerà a chiamare il metodo originale. –

+0

@Rob: hai ragione. Il sito di chiamata originale non utilizzerà il metodo di supporto. –

2

la soluzione più semplice sarebbe

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

Senza hacking in VCL/derivazione di componenti personalizzati, c'è una sola soluzione: TForm.SetFocusedControl esegue l'override + re-imposta le posizioni delle barre di scorrimento come sopra detto. Una cosa che ho aggiunto è disabilitare/abilitare il ridisegno della finestra per evitare brutti salti. Ecco il mio ultimo frammento:

sbContainer è TScrollBox e NoScrCtrl è un controllo che si trova al suo interno che ottiene lo stato attivo ma non vogliamo che venga visualizzato in modalità a scorrimento.

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; 
Problemi correlati