Delphi Programming / Object Pascal
[掲載 2012年08月04日] [更新 2014年04月09日] Delphi サンプルプログラム集 |
153_TGraphicControl を移動リサイズ |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE Pro |
|
153_ControlMoveResize.zip [1,297 KB] 2014年04月09日版 (EXE 同梱) |
- 2012年09月12日
- [157_移動リサイズ可能な TImage ラバーバンドとグラブハンドル] の記事掲載に伴い,移動とリサイズのサンプルを削除
- 2014年04月09日
- 移動とリサイズのサンプルを再掲
|
TImage 等の TGraphicControl の派生コントロールは,[152_WM_NCHITTEST によるコントロールの移動とリサイズ] のように,WM_NCHITTEST メッセージを使用したドラッグによる移動はできませんが,マウスイベントを使用すれば可能です.
以下は,TGraphicControl と TWinControl のどちらもドラッグによる移動ができるようにしたサンプルです.このサンプルコードであれば,TControl の派生コントロールは全てドラッグによる移動が可能です.
グラフィックコントロールは,BringToFront で,TWinControl の前面(上)には表示できません.この動作を実現するには,[152] の [04_移動リサイズ可能な画像] のサンプルのように,TPanel の上に配置した TGraphicControl に画像を表示することも考えられます. |
01_TControl のマウスドラッグによる移動 |
マウスのドラッグによる移動だけのテストです.OnMouseMove イベント内で,コントロールの位置を変更しているだけです.
同様のサンプルが [110_OnMouseMove イベントを使用したコントロールのドラッグ]にあります.[110] のサンプルは,TScrollBox 上にコントロールを配置しています.また,ドラッグ中にマウスカーソルが親コントロールの外側にも移動してしまいますが,下のコードでは,マウスカーソルの移動をクリップして,親コントロールであるフォームの外側には移動できないようにしています. |
|
図1
設計時画面
- TImage と TPanel を配置
- TImage の画像は設計時に読み込んでいる
|
|
図2
実行開始画面 |
|
図3
TImage をドラッグで移動中 |
リスト1
TControl のマウスドラッグによる移動 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Image1: TImage;
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private 宣言 }
DragMoveFlag : Boolean;
MouseStartY : Integer;
MouseStartX : Integer;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// Image1のOnMouseDownイベント
// 他のコントールのOnMouseDownイベントと共有
//
// マウスをDownしたらドラッグ開始
//=============================================================================
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
ARect : TRect;
DX : Integer;
begin
if Button = mbLeft then begin
DragMoveFlag := True;
MouseStartX := X;
MouseStartY := Y;
//マウスカーソルのクリップ
//フォームのクライアント領域の外側には移動できない(移動不可)にする
GetWindowRect(Self.Handle, ARect);
DX := ((ARect.Right - ARect.Left) - Self.ClientWidth) div 2;
InflateRect(ARect, -DX, -DX);
ARect.Top := ARect.Top + ((ARect.Bottom - ARect.Top) - Self.ClientHeight);
ClipCursor(@ARect);
end;
end;
//=============================================================================
// Image1のOnMouseMoveイベント
// 他のコントールのOnMouseMoveイベントと共有
//=============================================================================
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if not DragMoveFlag then exit;
//コントロールの位置を変更
TControl(Sender).Left := TControl(Sender).Left + X - MouseStartX;
TControl(Sender).Top := TControl(Sender).Top + Y - MouseStartY;
end;
//=============================================================================
// Image1のOnMouseUpイベント
// 他のコントールのOnMouseUpイベントと共有
//
// ドラッグ終了
//=============================================================================
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DragMoveFlag := False;
//マウスの移動範囲をスクリーン画面サイズに戻す
ClipCursor(nil);
end;
end.
上のサンプルのように,マウスのイベントを使用すれば TImage 等の TGraphicControl も移動可能になります.
リサイズは,マウスをドラッグして移動する際に,対象のコントロールをリサイズすればいいことになります.そのために,リサイズの開始操作をどの位置で行うかの判定が必要となります.そこで,次のサンプルでは,コントロールの端から一定の範囲内でマウスのドラッグを開始した場合,リサイズ開始とみなすことにしています.
TGraphicControl のリサイズで,ラバーバンドやグラブハンドルを描画したい場合は,コンポーネントにしないと無理があります.サンプル [157] に,TImage を移動リサイズ可能にしたコンポーネントを掲載しています. |
|
図4
設計時画面
- TImage と TPanel を配置
- TImage の画像は設計時に読み込み
|
|
図5
実行画面
|
リスト2
TControl の移動とリサイズ.TImage 等の TGraphicControl も移動リサイズ可能 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseLeave(Sender: TObject);
private
{ Private 宣言 }
DragMoveFlag : Boolean;
ResizeFlag : Byte;
MouseStartY : Integer;
MouseStartX : Integer;
OriginLeft : Integer;
OriginTop : Integer;
OriginWidth : Integer;
OriginHeight : Integer;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
resfNone = $00;
resfLeft = $01;
resfTop = $02;
resfRight = $04;
resfBottom = $08;
//=============================================================================
// フォーム作成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.DoubleBuffered := True;
end;
//=============================================================================
// Image1のOnMouseDownイベント
// 他のコントールのOnMouseDownイベントと共有
//
// マウスをDownしたらドラッグ開始
//=============================================================================
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
ARect : TRect;
DX : Integer;
begin
if Button = mbLeft then begin
DragMoveFlag := True;
//現在のマウスカーソルの位置
//これはParentコントロール内での座標
MouseStartX := X;
MouseStartY := Y;
//コントロールの現在の位置とサイズを退避しておく
OriginLeft := TControl(Sender).Left;
OriginTop := TControl(Sender).Top;
OriginWidth := TControl(Sender).Width;
OriginHeight := TControl(Sender).Height;
//マウスカーソルのクリップ
//フォームのクライアント領域の外側には移動できない(移動不可)にする
GetWindowRect(Self.Handle, ARect);
DX := ((ARect.Right - ARect.Left) - Self.ClientWidth) div 2;
InflateRect(ARect, -DX, -DX);
ARect.Top := ARect.Top + ((ARect.Bottom - ARect.Top) - Self.ClientHeight);
ClipCursor(@ARect);
end;
end;
//=============================================================================
// Image1のOnMouseMoveイベント
// 他のコントールのOnMouseMoveイベントと共有
//=============================================================================
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
DetectVal : Integer;
AControl : TControl;
NavValue : Integer;
LimitSize : Integer;
begin
AControl := TControl(Sender);
DetectVal := 5;
LimitSize := 50;
//まだ移動ドラッグまたはリサイズしていない時
if not DragMoveFlag then begin
ResizeFlag := resfNone;
//マウスカーソルの位置によって移動,リサイズの方向等を決定
if (X < DetectVal) then ResizeFlag := ResizeFlag or resfLeft;
if (Y < DetectVal) then ResizeFlag := ResizeFlag or resfTop;
if (AControl.Width - X) < DetectVal then ResizeFlag := ResizeFlag or resfRight;
if (AControl.Height - Y) < DetectVal then ResizeFlag := ResizeFlag or resfBottom;
//リサイズの方向によってマウスカーソルを変更する
if ResizeFlag = resfLeft or resfTop then Screen.Cursor := crSizeNWSE;
if ResizeFlag = resfLeft or resfBottom then Screen.Cursor := crSizeNESW;
if ResizeFlag = resfRight or resfTop then Screen.Cursor := crSizeNESW;
if ResizeFlag = resfRight or resfBottom then Screen.Cursor := crSizeNWSE;
if ResizeFlag = resfLeft then Screen.Cursor := crSizeWE;
if ResizeFlag = resfRight then Screen.Cursor := crSizeWE;
if ResizeFlag = resfTop then Screen.Cursor := crSizeNS;
if ResizeFlag = resfBottom then Screen.Cursor := crSizeNS;
if ResizeFlag = resfNone then Screen.Cursor := crDefault;
end;
if not DragMoveFlag then exit;
//移動リサイズの方向によって,コントロールの位置とサイズを変更
//サイズ変更の制限コード付き
//ResizeFlag = resfNoneは移動だけの場合
if ResizeFlag = resfNone then begin
AControl.Left := AControl.Left + X - MouseStartX;
AControl.Top := AControl.Top + Y - MouseStartY;
end else begin
//以下,リサイズの処理
if (ResizeFlag and resfLeft) = resfLeft then begin
NavValue := OriginWidth - (AControl.Left - OriginLeft);
if NavValue >= LimitSize then begin
AControl.Width := NavValue;
AControl.Left := AControl.Left + X - MouseStartX;
end;
end;
if (ResizeFlag and resfRight) = resfRight then begin
if X > LimitSize then begin
AControl.Width := OriginWidth + (X -MouseStartX);
end;
end;
if (ResizeFlag and resfTop) = resfTop then begin
NavValue := OriginHeight - (AControl.Top - OriginTop);
if NavValue >= LimitSize then begin
AControl.Height := NavValue;
AControl.Top := AControl.Top + Y - MouseStartY;
end;
end;
if (ResizeFlag and resfBottom) = resfBottom then begin
if Y > LimitSize then begin
AControl.Height := OriginHeight + Y -MouseStartY;
end;
end;
end;
end;
//=============================================================================
// Image1のOnMouseUpイベント
// 他のコントールのOnMouseUpイベントと共有
//
// ドラッグまたはリサイズ終了
//=============================================================================
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DragMoveFlag := False;
Screen.Cursor := crDefault;
//マウスの移動範囲をスクリーン画面サイズに戻す
ClipCursor(nil);
end;
//=============================================================================
// Image1のOnMouseLeaveイベント
// 他のコントールのOnMouseLeaveイベントと共有
//
// マウスカーソルがコントロールから離れたら,マウスカーソルをデフォルトの形に
//=============================================================================
procedure TForm1.Image1MouseLeave(Sender: TObject);
begin
Screen.Cursor := crDefault;
end;
end.
|