0

テキストを表示するためにTMemoinを使用し、ヘッダー情報として on top を使用します。メモがスクロールボックスよりも広い場合もあります。もちろん、メモを左右にスクロールしてメモ内のテキストを表示することもできます。スクロールボックスの表示領域の中央に常にヘッダーとしてラベルを付けたいと思います。設定でこれを行うことができますが、動作しますが、前後にスクロールするとちらつき、揺れます。メモはスムーズに動きますが、ラベルは動きません。TScrollBoxTLabelHorizontal scroll barLabel1.Left:= (Scrollbox1.Width div 2) - (Label1.Width div 2);

ここに画像の説明を入力

単位は次のとおりです。

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 をちらつきや揺れなく動かす方法について何か提案はありますか?


編集:

最終的には、フォームに 3 つ以上のスクロールボックスがあり、それぞれにヘッダー付きのメモが最大 3 つ含まれているという設計になります。また、同じスクロールボックス内のすべてのメモを同時にスクロールする必要があるため、スクロールはスクロールボックスで行う必要があります。つまり、フォームまたはパネルにラベルを付けてから、スクロールボックスの外側のフォームにラベルを付ける方法がわかりません。

ここに画像の説明を入力


編集2:

以下の回答は良い解決策を提供しますが、Labels中央に配置されている を の外にScrollbox配置し、それ自体の上に置く必要がありFormます。そして、 によって、Scrollbox's scroll barsまたは によってscroll bars直接移動しますFormLabelsこれにより、望ましい効果が得られますが、の一部ではないという不便さが少し加わりScrollboxます。

4

3 に答える 3

2

次のように実行できます。

ScrollBox の代わりに ScrollBar をフォームに配置します。その配置を下に設定します(または、列を増やしたい場合、または各列を独自のパネルに配置できる場合は、サイズと位置を手動で設定します)。次に、メモのサイズを設定し、ラベルをフォームの中央に配置します。メモのサイズを設定した後 (おそらくコードを介して動的に)、次のコードを配置します。

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

最後に、ScrollBar OnChange イベントを設定します。

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

フォームは次のようになります。

スクロール可能なメモ

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

編集:

これは、独自のパネルにそれぞれ 3 つの列があり、垂直スクロールバーもあるバージョンです。

縦スクロール

そしてソースコード全体:

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.

そして.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
于 2016-06-19T21:18:01.587 に答える
1

2 つのスクロール ボックスを使用してみませんか。

1 つを垂直スクロールに使用します。その上に、ラベルとメモを入れた 2 つ目のスクロール ボックスを置きます。

この 2 番目のスクロール ボックスは、必要に応じて水平スクロールに使用されます。

あるいは、TMemo を、独自のスクロールバーが実装されている TRichEdit などの他のコントロールに置き換えることも、より良い解決策かもしれません。したがって、現在のようにスクロール ボックスは 1 つしかなく、TRichEdit はテキストが広すぎる場合に独自のスクロールを処理します。

于 2016-06-20T13:57:07.303 に答える