2016-06-18 17 views
0

私はをTScrollBoxに入力してテキストを表示し、先頭にTLabelをヘッダ情報として使用します。メモはスクロールボックスよりも広い場合があり、もちろんHorizontal scroll barを使ってメモのテキストを左右にスクロールすることができます。 私はいつもボックスを表示領域にスクロールするために中央にヘッダーとしてラベルを持っている。私はLabel1.Left:= (Scrollbox1.Width div 2) - (Label1.Width div 2);を設定することでこれを行うことができますが、それは動作しますが、それはちらつきのようなもので、前後にスクロールするときに揺れます。メモはスムーズに動いて、ラベルは動かない。ラベルをスクロールボックスの中央にスムーズに保つにはどうすればいいですか?

enter image description here

ここ単位です:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

type 

    TScrollBox=Class(VCL.Forms.TScrollBox) 
    procedure WMHScroll(var Message: TWMHScroll); message WM_HSCROLL; 
    private 
    FOnScrollHorz: TNotifyEvent; 
    public 
    Property OnScrollHorz:TNotifyEvent read FOnScrollHorz Write FonScrollHorz; 
    End; 

    TForm1 = class(TForm) 
    ScrollBox1: TScrollBox; 
    Label1: TLabel; 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure ScrollBox1Resize(Sender: TObject); 
    private 
    procedure MyScrollHorz(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TScrollBox.WMHScroll(var Message: TWMHScroll); 
begin 
    inherited; 
    if Assigned(FOnScrollHorz) then FOnScrollHorz(Self); 
end; 

procedure TForm1.MyScrollHorz(Sender: TObject); 
begin 
    Label1.Left:= (Scrollbox1.Width div 2) - (Label1.Width div 2); 
end; 

procedure TForm1.ScrollBox1Resize(Sender: TObject); 
begin 
    Label1.Left:= (Scrollbox1.Width div 2) - (Label1.Width div 2); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    ScrollBox1.OnScrollHorz := MyScrollHorz; 
end; 

end. 

とDFM:

object Form1: TForm1 
    Left = 0 
    Top = 0 
    Caption = 'Form1' 
    ClientHeight = 212 
    ClientWidth = 458 
    Color = clBtnFace 
    DoubleBuffered = True 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    OnCreate = FormCreate 
    PixelsPerInch = 96 
    TextHeight = 13 
    object ScrollBox1: TScrollBox 
    Left = 0 
    Top = 0 
    Width = 458 
    Height = 212 
    HorzScrollBar.Smooth = True 
    HorzScrollBar.Tracking = True 
    Align = alClient 
    BiDiMode = bdLeftToRight 
    DoubleBuffered = True 
    ParentBiDiMode = False 
    ParentDoubleBuffered = False 
    TabOrder = 0 
    OnResize = ScrollBox1Resize 
    ExplicitHeight = 337 
    object Label1: TLabel 
     Left = 192 
     Top = 30 
     Width = 69 
     Height = 13 
     BiDiMode = bdLeftToRight 
     Caption = 'Details header' 
     ParentBiDiMode = False 
    end 
    object Memo1: TMemo 
     Left = 24 
     Top = 70 
     Width = 700 
     Height = 89 
     Lines.Strings = (
     'Details...') 
     TabOrder = 0 
    end 
    end 
end 

私はDoubleBufferedを使用してみましたが、助けにはなりません。

スクロールするときにMemo1と同じようにスムーズに、ちらつき/揺らさずにLabel1を移動する方法はありますか?


EDIT:

設計は、最終的に、私は、フォーム上の3又はscrollboxesを有し、それぞれがヘッダと3枚のメモまで含まれていることであろう。同じスクロールボックス内のすべてのメモを同時にスクロールする必要があるため、スクロールはスクロールボックスで行う必要があります。それが意味私は外scrollboxes、それはフォーム上に、フォームまたはパネル上のラベルを置くとでどのように動作するかを見ていない:

enter image description here


EDIT 2:DO以下

の回答良い解決策を提供しますが、Scrollboxの中心にあるLabelsを置いてFormに置く必要があります。 Scrollbox'sscroll barsまたはscroll barsのいずれかに直接移動します(Form)。これは望ましい効果を得ますが、LabelsにはもうScrollboxの一部ではないという少しの不便が加わります。

+1

スクロールボックスにラベルを貼る必要はありません。パネルをコンテナとして使用し、ラベルをパネルの上に置き、スクロールボックスをクライアントコンポーネントとしてパネルに配置します。 – sddk

+1

メモをスクロールするには、スクロールバーを使用してスクロールバーを使用してスクロールすることができます(皮肉なことに、TMemo.Scrollbarsプロパティを使用)。その内蔵スクロールを使用する場合、スクロールボックスはまったく必要なく、ラベルを移動する必要はありません。 –

+0

@KenWhite、sddk:フォームには最大4つのスクロールボックス、各スクロールボックスにはヘッダー付きで最大3つのメモを持つことができます。だから彼らはグループ化されたスクロールボックスに入る必要があります。私はフォーム/パネルにそれらを配置し、関連するグループ化された情報をスクロールして必要なデザインを維持する方法を見ていません。質問の編集を参照してください。 –

答えて

2

からは、「メモがスムーズに動く、ラベルがない」あなたが移動しないようにしようとしているためだ

OnScrollHorzハンドラを取り外すと、ラベルがスムーズに移動します。しかし、それはあなたが望むものではなく、それはもはやフォームに集中しません。

inheritedWM_HSCROLL)の呼び出し中に、ラベルがメモとともに移動する問題があります。デフォルトの処理の後で、ラベルの位置を変えます。そのため、フリッカーが発生します。

デフォルトのスクロール(OnBeforeHorzScroll)の前に発生するイベントハンドラを公開し、発生時にラベルを非表示にすることができます。 はスムーズに中央に置かれます、それはラベルが一時的に消えるところで別の種類のちらつきを引き起こします。まだ満足できるものではないかもしれません。

溶液がフォームにペアレントされた制御、スクロールボックスに兄弟を使用することです。 TLabelをグラフィックコントロールとして使用することはできませんが、TStaticTextを使用することができます。 スタティックがデザイン時に誤ってスクロールボックスの後ろに来ると、IDEの「構造ペイン」が便利になることがあります。

+0

ああ、なぜそれがちらつくのかは分かりません。私の編集画面でデザインの図を参照してください。つまり、各スクロールボックスはすべてのグループ化されたメモコントロールをスクロールする必要があるため、フォームにヘッダーを付けるオプションはありません。 –

+1

私はあなたがまだ 'TStaticText's'を使うことができると思います。スクロールボックスに1つをドロップし、構造ペインを使用してフォームに移動し、親がフォームになります。フォームのOnResizeでの位置を計算します。試してみてください。合併症はないと思います。 –

+0

これはうまく動いているようですが、私はなぜそれがうまくいくのか驚いています。 –

2

あなたはこのようにそれを行うことができます。代わりに、スクロールボックスの

は、フォーム上のスクロールバーを置きます。整列を下に設定します(または列を増やしたい場合は手動でサイズや位置を設定するか、それぞれを独自のパネルに配置します)。次に、メモのサイズを設定し、ラベルをフォームの中央に配置します。メモのサイズを設定した後(おそらく動的にコードを経由して)、このコードを配置:

ScrollBar1.Min:=0-Memo1.Left; 
ScrollBar1.Max:=Memo1.Width-Form1.ClientWidth+Memo1.Left; 

最後の事は、スクロールバーOnChangeイベントを設定することです:

procedure TForm1.ScrollBar1Change(Sender: TObject); 
begin 
    Memo1.Left:=0-ScrollBar1.Position; 
    Memo2.Left:=0-ScrollBar1.Position; 
    ... 
    MemoXY.Left:=0-ScrollBar1.Position; 
end; 

あなたのフォームは次のようになります。完了

Scrollable memos

!安定した中心のラベルとスムーズにスクロール可能なメモがあります。

編集:

Vertical scroll

、全体のソースコード:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, ExtCtrls; 

type 
    TForm1 = class(TForm) 
    Panel1: TPanel; 
    Panel2: TPanel; 
    Panel3: TPanel; 
    Label1: TLabel; 
    Label2: TLabel; 
    Label3: TLabel; 
    Label4: TLabel; 
    Label5: TLabel; 
    Label6: TLabel; 
    Memo1: TMemo; 
    Memo2: TMemo; 
    Memo3: TMemo; 
    Memo4: TMemo; 
    Memo5: TMemo; 
    Memo6: TMemo; 
    ScrollBar1: TScrollBar; 
    ScrollBar2: TScrollBar; 
    ScrollBar3: TScrollBar; 
    ScrollBar4: TScrollBar; 
    ScrollBar5: TScrollBar; 
    ScrollBar6: TScrollBar; 
    procedure FormCreate(Sender: TObject); 
    procedure ScrollBarHChange(Sender: TObject); 
    procedure ScrollBarVChange(Sender: TObject); 
    procedure FormResize(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
var cycle: Integer; 
begin 
    //GENERATE YOUR COMPONENTS HERE 

    //sets every components tag to its default top position 
    //(you can do this in any other way for example using array) 
    for cycle:=0 to Form1.ComponentCount-1 do 
    begin 
    if(Form1.Components[cycle] is TControl)then 
     Form1.Components[cycle].Tag:=(Form1.Components[cycle] as TControl).Top 
    end; 
end; 

procedure TForm1.FormResize(Sender: TObject); 
begin 
    //changes the panels sizes and positions 
    Panel1.Width:=Form1.ClientWidth div 3; 
    Panel2.Width:=Form1.ClientWidth div 3; 
    Panel3.Width:=Form1.ClientWidth div 3; 
    Panel2.Left:=Panel1.Width+1; 
    Panel3.Left:=Panel1.Width+Panel2.Width+1; 

    //if you dont want all scrollbars to reset on window resize, you need to handle the positioning of elements when window (and panels) size is changing 
    ScrollBar1.Position:=ScrollBar1.Min; 
    ScrollBar2.Position:=ScrollBar2.Min; 
    ScrollBar3.Position:=ScrollBar3.Min; 
    ScrollBar4.Position:=ScrollBar4.Min; 
    ScrollBar5.Position:=ScrollBar5.Min; 
    ScrollBar6.Position:=ScrollBar6.Min; 

    //make these tests on the widest element of each panel (8 is just a margin so the memo has some space on the right) 
    if((Memo1.Left+Memo1.Width)>(Panel1.ClientWidth-ScrollBar4.Width-8))then 
    begin 
    ScrollBar1.Enabled:=true; 
    ScrollBar1.Max:=Memo1.Width-Panel1.ClientWidth+Memo1.Left+ScrollBar4.Width+8; 
    end 
    else 
    ScrollBar1.Enabled:=false; 

    if((Memo3.Left+Memo3.Width)>(Panel2.ClientWidth-ScrollBar5.Width-8))then 
    begin 
    ScrollBar2.Enabled:=true; 
    ScrollBar2.Max:=Memo3.Width-Panel1.ClientWidth+Memo3.Left+ScrollBar5.Width+8; 
    end 
    else 
    begin 
    ScrollBar2.Position:=ScrollBar2.Min; 
    ScrollBar2.Enabled:=false; 
    end; 

    if((Memo5.Left+Memo5.Width)>(Panel3.ClientWidth-ScrollBar6.Width-8))then 
    begin 
    ScrollBar3.Enabled:=true; 
    ScrollBar3.Max:=Memo5.Width-Panel1.ClientWidth+Memo5.Left+ScrollBar6.Width+8; 
    end 
    else 
    ScrollBar3.Enabled:=false; 

    //make these tests on the bottom element of each panel (16 is just a margin so the memo has some space on the bottom) 
    if((Memo2.Top+Memo2.Height)>(Panel1.ClientHeight-ScrollBar1.Height-16))then 
    begin 
    ScrollBar4.Enabled:=true; 
    ScrollBar4.Max:=Memo2.Top+Memo2.Height-Panel1.ClientHeight+ScrollBar1.Height+16; 
    end 
    else 
    ScrollBar4.Enabled:=false; 

    if((Memo4.Top+Memo4.Height)>(Panel2.ClientHeight-ScrollBar2.Height-16))then 
    begin 
    ScrollBar5.Enabled:=true; 
    ScrollBar5.Max:=Memo4.Top+Memo4.Height-Panel2.ClientHeight+ScrollBar2.Height+16; 
    end 
    else 
    ScrollBar5.Enabled:=false; 

    if((Memo6.Top+Memo6.Height)>(Panel3.ClientHeight-ScrollBar3.Height-16))then 
    begin 
    ScrollBar6.Enabled:=true; 
    ScrollBar6.Max:=Memo6.Top+Memo6.Height-Panel3.ClientHeight+ScrollBar3.Height+16; 
    end 
    else 
    ScrollBar6.Enabled:=false; 
end; 

procedure TForm1.ScrollBarHChange(Sender: TObject); 
var cycle: Integer; 
begin 
    for cycle:=0 to ((Sender as TScrollBar).Parent as TPanel).ControlCount-1 do 
    begin 
    if(((Sender as TScrollBar).Parent as TPanel).Controls[cycle] is TMemo)then 
     (((Sender as TScrollBar).Parent as TPanel).Controls[cycle] as TMemo).Left:=0-(Sender as TScrollBar).Position+8; 
    end; 
end; 

procedure TForm1.ScrollBarVChange(Sender: TObject); 
var cycle: Integer; 
begin 
    for cycle:=0 to ((Sender as TScrollBar).Parent as TPanel).ControlCount-1 do 
    begin 
    if(not (((Sender as TScrollBar).Parent as TPanel).Controls[cycle] is TScrollBar))then 
     (((Sender as TScrollBar).Parent as TPanel).Controls[cycle] as TControl).Top:=(((Sender as TScrollBar).Parent as TPanel).Controls[cycle] as TControl).Tag-(Sender as TScrollBar).Position; 
    end; 
end; 

end. 
ここ

は彼自身のパネルでも垂直スクロールバーと3列それぞれにバージョンです。

そして.DFM:

つのスクロールボックスを使用しないのはなぜ
object Form1: TForm1 
    Left = 0 
    Top = 0 
    Caption = 'Form1' 
    ClientHeight = 473 
    ClientWidth = 769 
    Color = clBtnFace 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    OnCreate = FormCreate 
    OnResize = FormResize 
    DesignSize = (
    769 
    473) 
    PixelsPerInch = 96 
    TextHeight = 13 
    object Panel1: TPanel 
    Left = 0 
    Top = 0 
    Width = 257 
    Height = 473 
    Anchors = [akLeft, akTop, akBottom] 
    BevelOuter = bvNone 
    BorderStyle = bsSingle 
    TabOrder = 0 
    object Label1: TLabel 
     Left = 104 
     Top = 16 
     Width = 31 
     Height = 13 
     Caption = 'Label1' 
    end 
    object Label2: TLabel 
     Left = 104 
     Top = 152 
     Width = 31 
     Height = 13 
     Caption = 'Label2' 
    end 
    object Memo1: TMemo 
     Left = 8 
     Top = 32 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo1') 
     TabOrder = 0 
    end 
    object Memo2: TMemo 
     Left = 8 
     Top = 168 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo2') 
     TabOrder = 1 
    end 
    object ScrollBar1: TScrollBar 
     AlignWithMargins = True 
     Left = 0 
     Top = 452 
     Width = 236 
     Height = 17 
     Margins.Left = 0 
     Margins.Top = 0 
     Margins.Right = 17 
     Margins.Bottom = 0 
     Align = alBottom 
     PageSize = 0 
     TabOrder = 2 
     OnChange = ScrollBarHChange 
     ExplicitWidth = 253 
    end 
    object ScrollBar4: TScrollBar 
     Left = 236 
     Top = 0 
     Width = 17 
     Height = 452 
     Align = alRight 
     Enabled = False 
     Kind = sbVertical 
     PageSize = 0 
     TabOrder = 3 
     OnChange = ScrollBarVChange 
     ExplicitTop = 248 
     ExplicitHeight = 121 
    end 
    end 
    object Panel2: TPanel 
    Left = 256 
    Top = 0 
    Width = 257 
    Height = 473 
    Anchors = [akLeft, akTop, akBottom] 
    BevelOuter = bvNone 
    BorderStyle = bsSingle 
    TabOrder = 1 
    object Label3: TLabel 
     Left = 104 
     Top = 16 
     Width = 31 
     Height = 13 
     Caption = 'Label3' 
    end 
    object Label4: TLabel 
     Left = 104 
     Top = 152 
     Width = 31 
     Height = 13 
     Caption = 'Label4' 
    end 
    object Memo3: TMemo 
     Left = 8 
     Top = 32 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo3') 
     TabOrder = 0 
    end 
    object Memo4: TMemo 
     Left = 8 
     Top = 168 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo4') 
     TabOrder = 1 
    end 
    object ScrollBar2: TScrollBar 
     AlignWithMargins = True 
     Left = 0 
     Top = 452 
     Width = 236 
     Height = 17 
     Margins.Left = 0 
     Margins.Top = 0 
     Margins.Right = 17 
     Margins.Bottom = 0 
     Align = alBottom 
     PageSize = 0 
     TabOrder = 2 
     OnChange = ScrollBarHChange 
     ExplicitWidth = 253 
    end 
    object ScrollBar5: TScrollBar 
     Left = 236 
     Top = 0 
     Width = 17 
     Height = 452 
     Align = alRight 
     Enabled = False 
     Kind = sbVertical 
     PageSize = 0 
     TabOrder = 3 
     OnChange = ScrollBarVChange 
     ExplicitTop = 248 
     ExplicitHeight = 121 
    end 
    end 
    object Panel3: TPanel 
    Left = 512 
    Top = 0 
    Width = 257 
    Height = 473 
    Anchors = [akLeft, akTop, akBottom] 
    BevelOuter = bvNone 
    BorderStyle = bsSingle 
    TabOrder = 2 
    object Label5: TLabel 
     Left = 104 
     Top = 16 
     Width = 31 
     Height = 13 
     Caption = 'Label5' 
    end 
    object Label6: TLabel 
     Left = 104 
     Top = 152 
     Width = 31 
     Height = 13 
     Caption = 'Label6' 
    end 
    object Memo5: TMemo 
     Left = 8 
     Top = 32 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo5') 
     TabOrder = 0 
    end 
    object Memo6: TMemo 
     Left = 8 
     Top = 168 
     Width = 497 
     Height = 89 
     Lines.Strings = (
     'Memo6') 
     TabOrder = 1 
    end 
    object ScrollBar3: TScrollBar 
     AlignWithMargins = True 
     Left = 0 
     Top = 452 
     Width = 236 
     Height = 17 
     Margins.Left = 0 
     Margins.Top = 0 
     Margins.Right = 17 
     Margins.Bottom = 0 
     Align = alBottom 
     PageSize = 0 
     TabOrder = 2 
     OnChange = ScrollBarHChange 
     ExplicitWidth = 253 
    end 
    object ScrollBar6: TScrollBar 
     Left = 236 
     Top = 0 
     Width = 17 
     Height = 452 
     Align = alRight 
     Enabled = False 
     Kind = sbVertical 
     PageSize = 0 
     TabOrder = 3 
     OnChange = ScrollBarVChange 
     ExplicitTop = 248 
     ExplicitHeight = 121 
    end 
    end 
end 
+0

ありがとう!フォームの高さが垂直スクロールバーが必要となるようにサイズが変更されたとき、どのように問題を解決しますか?ラベルはフォームから「スクロール」する必要がありますか? –

+1

私は2番目の例が完全に機能する垂直スクロールバーを持つように投稿を編集しました。欠点は、ユーザーがウィンドウサイズを変更したときに両方のスクロールバーが自動的にリセットされることです(これは大きな問題ではありません)。また、各パネルの右下隅に小さい四角形があり、下のコンポーネントを見ることができますこの小さな四角形をパネルなどで非表示にする)。 – jano152

+1

ScrollBarChangeイベントはユニバーサルなので、多くの異なるコンポーネントをパネルに追加することができます。同様の方法で、FormResizeで最高の左+幅と最高+上の高さを持つコンポーネントを見つけ出し、それを普遍的なものにすることもできます。次に、somコンポーネントを作成するだけで毎回動作します。 FormResizeイベントをユニバーサルにするのに役立つ必要がある場合は、それを手助けすることもできます。 – jano152

1

あなたは垂直方向のスクロールのための1つを使用します。それにラベルと2枚目のスクロールボックスをメモとともに貼り付けます。必要なときに

この第2スクロールボックスは、水平スクロールに使用されます。

それとも、より良いソリューションを実現し、独自のスクロールバーを持っているTRichEditのようないくつかの他のコントロールとTMemoオブジェクトを置き換えることであろう。したがって、今のようなスクロールボックスは1つしかなく、TRichEditはテキストが幅広いときに独自のスクロール処理を行います。

+0

これは、複数のTMemo(またはTRichEdit)を結合ビューでグループ化し、単一のスクロールバーを使用してコンテンツをビューにスクロールする目的でSrollboxの目的を無効にします。右? –

+1

申し訳ありません私はあなたのメモの3つを同時にスクロールしたいと気づいていません。これは少し複雑です。そのようなシナリオのために@ jano152答えはおそらく最高のものです。 – SilverWarior

関連する問題