Delphi Programming / Object Pascal

[掲載 2015年07月28日] [更新 2015年07月28日] Delphi サンプルプログラム集 |
| 073_TTreeView のスクロールバーの表示制御 |
| 動作確認等 |
Windows 7 U64(SP1) + Delphi XE(UP1) Pro |
 |
073_TTreeView_ScrollBar.zip [2,282 KB] 2015年07月28日版 (EXE 同梱) |
TTreeView のスクロールバーの表示制御関係のサンプルです。
TTreeView には、TStringGrid や TRichEdit のような、ScrollBars プロパティはありません。
TTreeView では、クライアント領域にデータが表示できなくなると、必要に応じて水平スクロールバーまたは垂直スクロールバーが表示されます。
本ページのサンプルは、TTreeView の継承クラス (コンポーネント) を作成し、これらのスクロールバーを強制的に表示したり、非表示にするサンプルです。
本ページのサンプルでは、継承クラスをコンポーネントとして登録 (インストール) しないで、[派生元のコンポーネントと交換する方法] で説明しているユニットを使用しています。
|
| 01_TTreeView のスクロールバーの表示と非表示を切り換え |
TTreeView の継承クラス (コンポーネント) を作成して、水平スクロールバー、垂直スクロールバーを常に表示または常に非表示するようにするサンプルです。
Button1 のクリックで表示と非表示を切り換えるようにしています。
TTreeView が生成、再生成すると RecreateWnd が実行されます。RecreateWnd は WM_NCCALCSIZE メッセージを発行します。このメッセージ処理内で表示スタイルを設定しています。
本サンプルでは、TTreeView の継承クラスに HideScrollBars というプロパティを実装して、このプロパティの値を Button1 で切り換えるようにしています。
垂直スクロールバーだけ、あるいは水平スクロールバーだけの表示制御は、スタイルの設定フラグによって変更できます。 |

|
図1
設計時の画面 |
 |
図2
実行開始画面
|
 |
図3
ノードの一部を閉じる
|
 |
図4
Button1 をクリック
- 未表示のデータがあってもスクロールバーが非表示となる
|
リスト1
TTreeView のスクロールバーの表示と非表示を切り換え |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls, ComCtrls;
type
TplTreeView = class(TTreeView)
private
FHideScrollBars : Boolean;
procedure SetHideScrollBars(const Value: Boolean);
protected
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
public
property HideScrollBars : Boolean read FHideScrollBars write SetHideScrollBars;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
plTreeView1 : TplTreeView;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
plChgCompo,
CommCtrl;
{$R *.dfm}
//=============================================================================
// フォームのOnCreateイベント処理
// TTreeViewの派生クラス(コンポーネント)を生成
// すぐにテストできるようにテスト用のデータをセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
j : Integer;
k : Integer;
LText1 : String;
LText2 : String;
LNode1 : TTreeNode;
LNode2 : TTreeNode;
begin
//フォーム作成時にコンポーネントの入れ替え
plTreeView1 := TplTreeView(ChangeComponent(TreeView1, TplTreeView));
plTreeView1.Items.BeginUpdate;
for i := 0 to 2 do begin
LText1 := Format('%.5d',[i + 1]);
LNode1 := TreeView1.Items.Add(nil, LText1);
for j := 0 to 2 do begin
LText2 := LText1 + '-' + Format('%.5d',[j + 1]);
LNode2 := plTreeView1.Items.AddChild(LNode1, LText2);
if i = 2 then begin
for k := 0 to 2 do begin
plTreeView1.Items.AddChild(LNode2, LText2 + '-' + Format('%.10d',[k + 1]));
end;
end;
end;
end;
plTreeView1.FullExpand;
plTreeView1.Items.EndUpdate;
LNode1 := plTreeView1.Items.GetFirstNode;
LNode1.MakeVisible;
LNode1.Selected := True;
ActiveControl := plTreeView1;
end;
//=============================================================================
// TTreeViewの継承クラスに実装したHideScrollBarsプロパティをトグル操作
// HideScrollBarsがTrueだと水平、垂直スクロールバーは共に非表示(Hide)になる
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
plTreeView1.HideScrollBars := not plTreeView1.HideScrollBars;
end;
{ TplTreeView }
//-----------------------------------------------------------------------------
// TTreeViewの継承クラスに実装したHideScrollBarsプロパティの設定メソッド
// 変更したらRecreateWndを実行する
// RecreateWndを実行するとWM_NCCALCSIZEメッセージが発生する
//-----------------------------------------------------------------------------
procedure TplTreeView.SetHideScrollBars(const Value: Boolean);
begin
if FHideScrollBars <> Value then begin
FHideScrollBars := Value;
RecreateWnd;
end;
end;
//=============================================================================
// WM_NCCALCSIZEメッセージ処理
// スクロールバー表示のフラグを強制的に変更
//=============================================================================
procedure TplTreeView.WMNCCalcSize(var Message: TWMNCCalcSize);
var
LStyle : Integer;
begin
LStyle := GetWindowLong(Handle, GWL_STYLE);
if FHideScrollBars then begin
LStyle := LStyle and not WS_HSCROLL and not WS_VSCROLL;
end else begin
LStyle := LStyle or WS_HSCROLL or WS_VSCROLL;
end;
SetWindowLong(Handle, GWL_STYLE, LStyle);
inherited;
end;
end.
| 02_TTreeView のスクロールバーの無効化表示 |
TTreeView のスクロールバーは、操作不可の状態になっても、無効化の表示とはなりません。
これを無効化の表示状態にするサンプルです。
GetScrollInfo 関数で、表示データがクライアント領域に収まらない状態でスクロールの Range を取得すると、水平スクロールの範囲としてのピクセル数が、垂直のスクロール範囲として表示可能なノード数が取得できます。表示可能なノード数には、展開していないノードは含まれていません。
データがクライアント領域に全て表示されている時は、これらの値は 0 です。
このことを利用しています。
リサイズ以外にも、ノードの追加、削除、あるいはノードを展開した時やノードを閉じた時もチェックが必要です。これらをチェックする処理も追加してみました。
|
[備考]
TTreeView のメッセージとして、MSDN の [Tree View Messages] の記事に TVM_XXXX という形式がありますが、これらのメッセージは、情報の取得や設定に使用するメッセージです。TVM_XXX 処理のメッセージを受信するには、TVM_XXX 受信用のプロシージャーを実装します。
もし、すでに VCL 内で TVM_XXX 受信用のプロシージャーが実装されている場合は、inherited 処理が必要です。
処理の結果としてのメッセージは、[Tree View Notifications]
の記事にある TVN_XXXX 等の通知メッセージが利用できます。TVN_XXXX の通知メッセージは CN_NOTIFY メッセージで受信できます。
|

|
図5
EXE の実行開始画面 |
 |
図6
一部のノードを閉じる
- データが全てクライアント領域内にある状態
- スクロールバーが無効化の表示になる
|
 |
図7
ノードを全て展開して縦方向にリサイズ
|
リスト2
TTreeView のスクロールバーの無効化表示 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls, ComCtrls, CommCtrl;
type
TplTreeView = class(TTreeView)
private
procedure Available_Disable_ScrollBars;
protected
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
procedure CNNotify(var Message: TWMNotifyTV); message CN_NOTIFY;
procedure Added(Node: TTreeNode); override;
procedure Resize; override;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
plTreeView1 : TplTreeView;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
plChgCompo;
{$R *.dfm}
//=============================================================================
// フォームのOnCreateイベント処理
// TTreeViewの派生クラス(コンポーネント)を生成
// すぐにテストできるようにテスト用のデータをセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
j : Integer;
k : Integer;
LText1 : String;
LText2 : String;
LNode1 : TTreeNode;
LNode2 : TTreeNode;
begin
//フォーム作成時にコンポーネントの入れ替え
plTreeView1 := TplTreeView(ChangeComponent(TreeView1, TplTreeView));
plTreeView1.Items.BeginUpdate;
for i := 0 to 2 do begin
LText1 := Format('%.5d',[i + 1]);
LNode1 := plTreeView1.Items.Add(nil, LText1);
for j := 0 to 2 do begin
LText2 := LText1 + '-' + Format('%.5d',[j + 1]);
LNode2 := plTreeView1.Items.AddChild(LNode1, LText2);
if i = 2 then begin
for k := 0 to 2 do begin
plTreeView1.Items.AddChild(LNode2, LText2 + '-' + Format('%.15d',[k + 1]));
end;
end;
end;
end;
plTreeView1.FullExpand;
plTreeView1.Items.EndUpdate;
LNode1 := plTreeView1.Items.GetFirstNode;
LNode1.MakeVisible;
LNode1.Selected := True;
end;
{ TplTreeView }
//-----------------------------------------------------------------------------
// スクロールバーの有効化表示と無効化表示の制御用メソッド
//-----------------------------------------------------------------------------
procedure TplTreeView.Available_Disable_ScrollBars;
var
LScrollInfo : TScrollInfo;
begin
LScrollInfo.cbSize := SizeOf(LScrollInfo);
LScrollInfo.fMask := SIF_ALL;
//垂直スクロールバーの有効化表示、無効化表示の処理
GetScrollInfo(Handle, SB_VERT, LScrollInfo);
if LScrollInfo.nMax > 0 then begin
EnableScrollBar(Handle, SB_VERT, ESB_ENABLE_BOTH);
end else begin
EnableScrollBar(Handle, SB_VERT, ESB_DISABLE_BOTH);
end;
//水平スクロールバーの有効化表示、無効化表示の処理
GetScrollInfo(Handle, SB_HORZ, LScrollInfo);
if LScrollInfo.nMax > 0 then begin
EnableScrollBar(Handle, SB_HORZ, ESB_ENABLE_BOTH);
end else begin
EnableScrollBar(Handle, SB_HORZ, ESB_DISABLE_BOTH);
end;
end;
//=============================================================================
// Resizeメソッド
// コントロールがリサイズされると自動的に実行されるメソッド
//=============================================================================
procedure TplTreeView.Resize;
begin
inherited;
Available_Disable_ScrollBars;
end;
//=============================================================================
// Addedメソッド
// ノードが追加された時に自動的に実行されるメソッド
//=============================================================================
procedure TplTreeView.Added(Node: TTreeNode);
begin
inherited;
Available_Disable_ScrollBars;
end;
//=============================================================================
// CN_NOTIFYメッセージ処理
// TVN_XXX等はCN_NOTIFYメッセージで受信できる
// CN_NOTIFYの引数の型は、コード補完機能を使用するとTMessage型となる
// これをTWMNotifyTV型に変更して使用
//
// TVN_XXXの使用にはusesにCommCtrlが必要
//=============================================================================
procedure TplTreeView.CNNotify(var Message: TWMNotifyTV);
var
LCode : Integer;
begin
inherited;
LCode := Message.NMHdr.code;
case LCode of
TVN_ENDLABELEDIT,
TVN_DELETEITEM,
TVN_ITEMEXPANDED:
begin
Available_Disable_ScrollBars;
end;
end;
end;
//=============================================================================
// WM_NCCALCSIZEメッセージ処理
// スクロールバー表示のフラグを強制的に変更
//=============================================================================
procedure TplTreeView.WMNCCalcSize(var Message: TWMNCCalcSize);
var
LStyle : Integer;
begin
LStyle := GetWindowLong(Handle, GWL_STYLE);
SetWindowLong(Handle, GWL_STYLE, LStyle or WS_HSCROLL or WS_VSCROLL);
inherited;
end;
end.
| 03_TTreeView のスクロールバーのコンテキストメニュー |
TTreeView のスクロールバー上で、マウスの右ボタンをクリックすると、下図のようなコンテキストメニューが現れます。このコンテキストメニューを表示しないようにする方法です。
コンテキストメニューが表示する際、WM_CONTEXTMENU メッセージが発生します。このメッセージ処理内で何もしなければコンテキストメニューは現れません。
何もしないと、TTreeView で TPopupMenue コンポーネント等を使用していると、そのポップアップメニューも表示しなくなってしまいます。そこで、マウスクリックの位置が、TListView のクライアント領域の時は、WM_CONTEXTMENU メッセージ本来の処理を実行するようにしています。
|

|
図8
スクロールバーのコンテキストメニュー
|
リスト3
TTreeView のスクロールバーのコンテキストメニューを表示しないようにする |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls, ComCtrls, Menus;
type
TplTreeView = class(TTreeView)
private
protected
procedure WMContextMenu(var Message: TWMContextMenu);
message WM_CONTEXTMENU;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
plTreeView1 : TplTreeView;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
plChgCompo;
{$R *.dfm}
//=============================================================================
// フォームのOnCreateイベント処理
// TTreeViewの派生クラス(コンポーネント)を生成
// すぐにテストできるようにテスト用のデータをセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
j : Integer;
k : Integer;
LText1 : String;
LText2 : String;
LNode1 : TTreeNode;
LNode2 : TTreeNode;
begin
//フォーム作成時にコンポーネントの入れ替え
plTreeView1 := TplTreeView(ChangeComponent(TreeView1, TplTreeView));
plTreeView1.Items.BeginUpdate;
for i := 0 to 2 do begin
LText1 := Format('%.5d',[i + 1]);
LNode1 := TreeView1.Items.Add(nil, LText1);
for j := 0 to 2 do begin
LText2 := LText1 + '-' + Format('%.5d',[j + 1]);
LNode2 := plTreeView1.Items.AddChild(LNode1, LText2);
if i = 2 then begin
for k := 0 to 2 do begin
plTreeView1.Items.AddChild(LNode2, LText2 + '-' + Format('%.10d',[k + 1]));
end;
end;
end;
end;
plTreeView1.FullExpand;
plTreeView1.Items.EndUpdate;
LNode1 := plTreeView1.Items.GetFirstNode;
LNode1.MakeVisible;
LNode1.Selected := True;
ActiveControl := plTreeView1;
end;
{ TplTreeView }
//=============================================================================
// WM_CONTEXTMENUメッセージ処理
// スクロールバーのコンテキストメニューを表示しないようにする
//=============================================================================
procedure TplTreeView.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;
end.
| 04_TTreeView のノードのテキストのツールチップを非表示 |
TTreeView のノードにマウスカーソルを移動します。この時、ノードのテキストがクライアントの右端に表示しきれない場合、下図のようなツールチップが現れます。
このツールチップが現れないようにする方法です。
方法は、スクロールバーの表示または非表示と同じで、ウィンドウのスタイルに TVS_NOTOOLTIPS フラグをセットします。実際にこの設定による動作を確認するためのサンプルです。
もし、上の方のサンプルのような TTreeView のウィンドウの再生成の処理を行わなければ、以下のように TreeView_SetToolTips メソッドで非表示にできます。
|
procedure TForm1.Button1Click(Sender: TObject);
begin
TreeView_SetToolTips(TreeView1.Handle, 0);
end;

|
図9
ノードのテキストのツールチップ
|
リスト4
TTreeView のノードのテキストのツールチップを表示しないようにする |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, Grids, StdCtrls, ComCtrls;
type
TplTreeView = class(TTreeView)
protected
procedure WMNCCalcSize(var Message: TWMNCCalcSize); message WM_NCCALCSIZE;
end;
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
TreeView1: TTreeView;
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
plTreeView1 : TplTreeView;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
plChgCompo,
CommCtrl;
{$R *.dfm}
//=============================================================================
// フォームのOnCreateイベント処理
// TTreeViewの派生クラス(コンポーネント)を生成
// すぐにテストできるようにテスト用のデータをセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
j : Integer;
k : Integer;
LText1 : String;
LText2 : String;
LNode1 : TTreeNode;
LNode2 : TTreeNode;
begin
//フォーム作成時にコンポーネントの入れ替え
plTreeView1 := TplTreeView(ChangeComponent(TreeView1, TplTreeView));
plTreeView1.Items.BeginUpdate;
for i := 0 to 2 do begin
LText1 := Format('%.5d',[i + 1]);
LNode1 := TreeView1.Items.Add(nil, LText1);
for j := 0 to 2 do begin
LText2 := LText1 + '-' + Format('%.5d',[j + 1]);
LNode2 := plTreeView1.Items.AddChild(LNode1, LText2);
if i = 2 then begin
for k := 0 to 2 do begin
plTreeView1.Items.AddChild(LNode2, LText2 + '-' + Format('%.10d',[k + 1]));
end;
end;
end;
end;
plTreeView1.FullExpand;
plTreeView1.Items.EndUpdate;
LNode1 := plTreeView1.Items.GetFirstNode;
LNode1.MakeVisible;
LNode1.Selected := True;
ActiveControl := plTreeView1;
end;
{ TplTreeView }
//=============================================================================
// WM_NCCALCSIZEメッセージ処理
// スクロールバー表示のフラグを強制的に変更
//
// 定数名TVS_XXXの使用にはusesにCommCtrlが必要
//=============================================================================
procedure TplTreeView.WMNCCalcSize(var Message: TWMNCCalcSize);
var
LStyle : Integer;
begin
LStyle := GetWindowLong(Handle, GWL_STYLE);
SetWindowLong(Handle, GWL_STYLE, LStyle or TVS_NOTOOLTIPS);
inherited;
end;
end.
|