我有一個比滾動框大的RichEdit的TScrollBox,所以兩個滾動條都出現在滾動框中。然後我有一個功能DoTask
,調用RichEdit.SetFocus
。如何禁用TScrollBox的滾動瀏覽行爲?
當我向下滾動到我想要看到的文本控件的一部分,然後調用DoTask
時,滾動框將自動滾動到RichEdit的頂部。我怎樣才能避免這種情況?
我有一個比滾動框大的RichEdit的TScrollBox,所以兩個滾動條都出現在滾動框中。然後我有一個功能DoTask
,調用RichEdit.SetFocus
。如何禁用TScrollBox的滾動瀏覽行爲?
當我向下滾動到我想要看到的文本控件的一部分,然後調用DoTask
時,滾動框將自動滾動到RichEdit的頂部。我怎樣才能避免這種情況?
如你所願,這裏有一些建議:
覆蓋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;
或者使用上述所有的創造性組合。如何和什麼時候你喜歡它滾動只有你知道。
我猜TScrollBox的類助手,而不是一個插入,也會做的伎倆。雖然不能檢查。 –
我不認爲這會奏效,@Rudy。你不能用類助手來覆蓋虛擬方法。該方法的原始調用網站不知道類助手是否存在,因此它將繼續調用原始方法。 –
@Rob:你說得對。原來的呼叫站點不會使用助手方法。 –
的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;
沒有黑客進入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;
是的,很明顯。 –
不使用滾動框似乎是顯而易見的解決方案,因爲你有更多的滾動條比需要 –
@David:如果RichEdit是滾動框中唯一的組件,我同意。當然,我們不知道它是否是。把一個單獨的組件放在一個滾動框上有它自己的滾動條會有點奇怪,確實如此。 –