9
votes

Comment puis-je désactiver le comportement de défilement de TscrollBox?

J'ai un tscrollbox qui a un richedit plus gros que le Scrollebox, de sorte que les deux barres de défilement latérales apparaissent dans le défilement. Ensuite, j'ai une fonction dotask qui appelle richedit.setfocus .

Lorsque je fais défiler jusqu'à où je veux voir une partie de la commande de texte, puis appelle dotask , la touche Scrollez-vous automatiquement faire défiler automatiquement jusqu'au sommet de la sommet. Comment puis-je éviter ça?


3 commentaires

N'utilisez pas la boîte de défilement semble être la solution évidente car vous avez plus de barres de défilement que nécessaire


@David: Si le richedit est le seul composant sur le Scrollebox, je suis d'accord. Bien sûr, nous ne savons pas si c'est. Mettre un composant unique qui a ses propres barres de défilement sur une touche de défilement serait un peu ... bizarre, en effet.


Oui, il y a beaucoup de contrôles à part richedit.


4 Réponses :


2
votes

La solution la plus simple serait

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


0 commentaires

8
votes

Comme vous le souhaitez, voici quelques suggestions:

  • remplacement setFocususcontrol code> dans le formulaire: p>

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

    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;
    


3 commentaires

Je suppose qu'un assistant de classe pour TscrollBox, au lieu d'un interposeur, ferait également le tour. Je ne peux pas vérifier cela, cependant.


Je ne pense pas que cela fonctionnerait, @rudy. Vous ne pouvez pas remplacer les méthodes virtuelles avec les aides de classe. Le site d'appel d'origine de la méthode ne connaît pas l'aide de la classe existant, il continuera donc à appeler la méthode d'origine.


@Rob: Vous avez raison. Le site d'appel d'origine n'utilisera pas la méthode de l'assistance.



2
votes

sans piratage dans VCL / dériver des composants personnalisés Il n'y a qu'une solution - Tform.SeSetFocoingControl de remplacement + redéfinir les positions des barres de défilement comme indiqué ci-dessus. Une chose que j'ai ajoutée est désactivée / permet à la fenêtre redessinée d'éviter les sauts laids. Voici mon extrait final:

SBContainer est TScrollBox et NoscrCtrl est une commande de contrôle à l'intérieur, qui se concentre, mais nous ne voulons pas qu'il soit défilé en vue. P>

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;


0 commentaires

0
votes

Pour désactiver le comportement de défilement à la suite de ma forme principale, j'ai utilisé cette solution: (C ++ Builder)

bool __fastcall TMainForm::SetFocusedControl(TWinControl *Control) {
    LockWindowUpdate(Handle);
    int vpos = VertScrollBar->Position;
    int hpos = HorzScrollBar->Position;
    bool result = TForm::SetFocusedControl(Control);
    if (VertScrollBar->Position != vpos) {
        VertScrollBar->Position = vpos;
    }
    if (HorzScrollBar->Position != hpos) {
        HorzScrollBar->Position = hpos;
    }
    LockWindowUpdate(0);
    return result;
}


0 commentaires