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;
|