Delphi Programming / Object Pascal

[掲載 2015年07月23日] [更新 2015年07月27日] Delphi サンプルプログラム集 |
| 075_TScrollBox のスクロールバーの表示制御 |
| 動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
 |
075_TScrollBox_ScrollBar.zip [2,139 KB] 2015年07月27日版 (EXE 同梱) |
TScrollBox のスクロールバーの設定関係のサンプルです。
TScrollBox は、垂直スクロールバーと水平スクロールバーを独立して設定できます。
これらは TControlScrollBar 型の HorzScrollBar, VertScrollBar ですが、Visible プロパティの値を True にしても、TScrollBox のクライアント領域に全てのコントロールが表示されている状態だとスクスロールバーは表示されません。主に、これを強制的に表示するサンプルです。
|
| 01_TScrollBox のスクロールバーを常に表示 |
TScrollBox の継承クラス (コンポーネント) を作成して、WM_NCCALCSIZE メッセージ処理内で強制的に TScrollBox のスタイルに WS_VSCROLL を追加して、垂直スクロールバーを常に表示するようにしたサンプルです。
このサンプルでは、TScrollBox のクライアント領域にコントロール類が全て表示される状態になると、スクロールバーは操作できない状態になります。そこで、EnableScrollBar でスクロールバーを無効化します。
TScrollBox に配置しているコントロールの表示位置やサイズを変更した場合にも、スクロールバーの描画更新のために、Resize のコードと同じ処理が必要です。
|

|
図1
設計時の画面
- 継承クラス (コンポーネント) を実行時に生成するので、フォームには TScrollBox はない
|
 |
図2
実行開始画面
- TScrollBox に配置したコントロールが全て表示されている場合
- スクロールバーが見えているが、スクロール操作はできない
|
 |
図3
フォームをリサイズ
|
リスト1
TScrollBox の垂直スクロールバーを常に表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GIFImg, jpeg;
type
TplScrollBox = class(Forms.TScrollBox)
protected
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
procedure Resize; override;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
private
{ Private 宣言 }
plScrollBox1 : TplScrollBox;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// フォーム作成時の処理
// TScrollBoxの派生コンポーネントを生成
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
plScrollBox1 := TplScrollBox.Create(Self);
plScrollBox1.Parent := Self;
plScrollBox1.Align := alClient;
Image1.Parent := plScrollBox1;
Image1.Left := 10;
Image1.Top := 20;
end;
//=============================================================================
// Form1のOnMouseWheelイベント
// スクロールボックスをマウスホイールでスクロールさせる
//=============================================================================
procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
SB1 : TScrollBox;
begin
SB1 := plScrollBox1;
if FindVCLWindow(MousePos) = SB1 then begin
Handled := True;
SB1.VertScrollBar.Position := SB1.VertScrollBar.Position - WheelDelta div 5;
end;
end;
{ TplScrollBox }
//=============================================================================
// TplScrollBoxのResizeメソッド
// リサイズされると自動的に実行されるメソッド
// OnResizeイベントに相当する
//=============================================================================
procedure TplScrollBox.Resize;
var
i : Integer;
LBottom : Integer;
LScrollInfo : TScrollInfo;
begin
inherited;
//TScrollBox内に配置しているコントロールの表示高さを計算
LBottom := 0;
for i := 0 to ControlCount - 1 do begin
if LBottom <= (Controls[i].Top + Controls[i].Height) then begin
LBottom := Controls[i].Top + Controls[i].Height;
end;
end;
//下方に少しマージンをとってみる
LBottom := LBottom + 30;
VertScrollBar.Range := LBottom;
if LBottom < ClientHeight then begin
EnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH);
end else begin
EnableScrollBar(Handle, SB_VERT, ESB_ENABLE_BOTH);
end;
end;
//=============================================================================
// WM_NCCALCSIZEメッセージ処理
// 縦スクロールバー(WS_VSCROLL)を強制的に表示するスタイルに変更
//=============================================================================
procedure TplScrollBox.WMNCCalcSize(var Message: TWMNCCalcSize);
var
LStyle: Integer;
begin
LStyle := GetWindowLong(Handle, GWL_STYLE);
SetWindowLong(Handle, GWL_STYLE, LStyle or WS_VSCROLL);
//スクロールバーの表示を更新
Resize;
inherited;
end;
end.
| 02_TScrollBox のスクロールバーを常に非表示 |
TScrollBox のスクロールバーを常に非表示するには、水平スクロールバー、あるいは、垂直スクロールバーの Visible プロパティの値を False にします。
このことを確認するためのサンプルです。各ボタンは、水平、垂直スクロールバーの表示と非表示を切り換えるトグル動作となっています。
|
リスト2
TScrollBox のスクロールバーを常に非表示にする |
ScrollBox1.HorzScrollBar.Visible := False; //水平スクロールバーを常に非表示
ScrollBox1.VertScrollBar.Visible := False; //垂直スクロールバーを常に非表示

|
図4
スクロールバーが表示されている状態 |

|
図5
スクロールバーを非表示にした状態 |
本ページの最初のサンプルと同じ方法も使えます。
WM_NCCALCSIZE メッセージ処理内で、LStyle or WS_VSCROLL の部分を LStyle and not WS_VSCROLL とすると、垂直スクロールバーを常に表示しないようにできます。この設定をすると、VertScrollBar の Visible の値を True にしても垂直スクロールバーは表示できません。 |
procedure TplScrollBox.WMNCCalcSize(var Message: TWMNCCalcSize);
var
LStyle: Integer;
begin
LStyle := GetWindowLong(Handle, GWL_STYLE);
SetWindowLong(Handle, GWL_STYLE, LStyle and not WS_VSCROLL);
//スクロールバーの表示を更新
Resize;
inherited;
end;
| 03_TScrollBox のスクロールのトラッキング |
スクロールのトラッキング (追従) 機能の動作確認用サンプルです。
各々のボタンクリックは、水平または垂直スクロールのトラッキングを ON, OFF するトグル動作となっています。
スクロールバーのスクロールボックス (つまみ) をドラッグすると、スクロールボックス (つまみ) を放すまで、実際のスクロールはしません。これが TScrollBox のデフォルトの設定です。
VertScrollBar, HorzScrollBar (共に TControlScrollBar 型) の Tracking プロパティを True にすると、スクロールバーのドラッグに追従して TScrollBox に配置したコントロールがスクロールするようになります。
このスクロールのトラッキング (追従) を「滑らかなスクロール」と言うことがあるようです。 |

|
図6
VertScrollBar.Tracking = False の場合
- スクロールボックス (つまみ) を放すまではスクロールしない
|

|
図7
VertScrollBar.Tracking = True の場合
- スクロールボックス (つまみ) のドラッグと同時にスクロールする
|
リスト3
TScrollBox のスクロールのトラッキングの動作確認用サンプル |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GIFImg, jpeg;
type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
Button2: TButton;
ScrollBox1: TScrollBox;
Image1: TImage;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// 水平方向のスクロールのトラッキングのON,OFF切り換え
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ScrollBox1.HorzScrollBar.Tracking := not ScrollBox1.HorzScrollBar.Tracking;
end;
//=============================================================================
// 垂直方向のスクロールのトラッキングのON,OFF切り換え
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
ScrollBox1.VertScrollBar.Tracking := not ScrollBox1.VertScrollBar.Tracking;
end;
end.
| 04_TScrollBox のスクロールバーのコンテキストメニュー |
TScrollBox のスクロールバー上で、マウスの右ボタンをクリックすると、下図のようなコンテキストメニューが現れます。このコンテキストメニューを表示しないようにする方法です。
コンテキストメニューが表示する際、WM_CONTEXTMENU メッセージが発生します。このメッセージ処理内で何もしなければコンテキストメニューは現れません。何もしないと、TScrollBox で TPopupMenue コンポーネント等を使用していると、そのポップアップメニューも表示しなくなってしまいます。
そこで、マウスクリックの位置が、TScrollBox のクライアント領域の時は、WM_CONTEXTMENU メッセージ本来の処理を実行するようにしています。
|

|
図8
スクロールバーのコンテキストメニュー
|
リスト4
TScrollBox のスクロールバーのコンテキストメニューを表示しないようにする
TScrollBox の継承クラス (コンポーネント) を使用する場合 |
procedure TplScrollBox.WMContextMenu(var Message: TWMContextMenu);
var
LPos : TPoint;
begin
LPos := ScreenToClient(Point(Message.XPos, Message.YPos));
if PtInRect(ClientRect, LPos) then begin
inherited;
end else begin
Message.Result := 0;
end;
end;
|