お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"THintDragObject しょの1"





--------  キリトリ  -------------------------------------------------
unit HintDrag;

{********************************************************************

ドラッグ時にヒント表示を行い、メッセージ処理を自由に行うためのユニット

※注意
BeginHintDrag で開始したドラッグを中断させる場合は、CancelHintDrag
あるいは EndHintDrag を使用する。ドラッグしているかどうかの判別には
HintDragging を使用する。OnStartDrag イベントハンドラで、新しいドラッ
グオブジェクトを生成する場合は、THintDragObject から派生したものにする。

※使用例
uses
  HintDrag;

procedure TForm1.ListBox1MouseDown(Sender: TObject; Button:
    TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Index: Integer;
begin
  Index := ListBox1.ItemAtPos(Point(X, Y), True);
  if (Index >= 0) and (Button = mbLeft) then
    BeginHintDrag(ListBox1, False, ListBox1.Items[Index]);
end;

※メッセージ処理について
マウスメッセージは THintDragObject.MouseMsg で処理する。
キーメッセージは、TDragHintWindow.WMKeyDown で処理する。

キーメッセージを処理するためには、ヒントウィンドに Parent 設定と
SetFocus 処理が必要なので、メインフォームのフォーカスは失われる。
ドラッグ対象コントロールにスクロールメッセージなどを送る場合には
メインフォームにちらつきが出て見苦しい。

キーメッセージの処理は対象コンポーネントの WndProc を override
することを推奨する。

例
type
  TMyListBox = class(TListBox)
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

implementation

uses
  HintDrag;

procedure TMyListBox.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_KEYDOWN then
    if (TWMKey(Message).CharCode = VK_ESCAPE) and
      HintDragging(Self) then
      CancelHintDrag;
  inherited WndProc(Message);
end;

※コンパイル指令

したがって、このユニットでは、デフォルトでキーメッセージを処理しない
仕様になっている。
キーメッセージの処理を行う場合は、$UNDEF KEYMESSAGE の行を削除
すること
*********************************************************************}

{$DEFINE KEYMESSAGE}
{$UNDEF KEYMESSAGE}

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, Forms;

type
  THintDragObject = class(TDragControlObject)
  protected
    function Capture: HWND; virtual;
    procedure ReleaseCapture(Handle: HWND); virtual;
    procedure MouseMsg(var Message: TMessage); virtual;
  end;

  TDragHintWindow = class(THintWindow)
  private
    {$IFDEF KEYMESSAGE}
    procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
    {$ENDIF}
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    {$IFDEF VER90}
    function CalcHintRect(const AHint: string): TRect;
    {$ENDIF}
    procedure ShowDragHint; virtual;
    procedure HideDragHint; virtual;
  end;

procedure BeginHintDrag(Control: TControl; Immediate: Boolean;
    HintText: String);
procedure EndHintDrag(Control: TControl; Drop: Boolean);
function HintDragging(Control: TControl): Boolean;
procedure CancelHintDrag;

implementation

uses
  Consts;

var
  DragHintWindow: TDragHintWindow;
  HintDragControl: TControl;
  HintDragObject: TDragObject;
  HintDragFreeObject: Boolean;
  HintDragTarget: Pointer;
  HintDragHandle: HWND;
  HintDragCapture: HWND;
  HintDragStartPos: TPoint;
  HintDragPos: TPoint;
  HintDragSaveCursor: HCURSOR;
  HintDragActive: Boolean;
  HintDragText: String;

procedure HintDragTo(const Pos: TPoint); forward;
procedure HintDragDone(Drop: Boolean); forward;

{ drag and drop functions }

function HintDragMessage(Handle: HWND; Msg: TDragMessage;
  Source: TDragObject; Target: Pointer; const Pos: TPoint): Longint;
var
  DragRec: TDragRec;
begin
  Result := 0;
  if Handle <> 0 then
  begin
    DragRec.Pos := Pos;
    DragRec.Target := Target;
    DragRec.Source := Source;
    Result := SendMessage(Handle, CM_DRAG, Longint(Msg),
                                           Longint(@DragRec));
  end;
end;

function HintDoDragOver(DragMsg: TDragMessage): Boolean;
begin
  Result := False;
  if HintDragTarget <> nil then
    Result :=  LongBool(HintDragMessage(HintDragHandle, DragMsg,
                        HintDragObject, HintDragTarget, HintDragPos));
end;

procedure HintDragTo(const Pos: TPoint);
const
  Threshold = 5;
var
  DragCursor: TCursor;
  Target: TControl;
  TargetHandle: HWND;
  WinControl: TWinControl;
begin
  if HintDragActive or
    (Abs(HintDragStartPos.X - Pos.X) >= Threshold) or
    (Abs(HintDragStartPos.Y - Pos.Y) >= Threshold) then
  begin
    HintDragActive := True;
    Target := FindDragTarget(Pos, False); // controls.pas
    WinControl := FindVCLWindow(Pos);     // controls.pas
    if WinControl <> nil then
      TargetHandle := WinControl.Handle
    else
      TargetHandle := 0;
    if Target <> HintDragTarget then
    begin
      HintDoDragOver(dmDragLeave);
      HintDragTarget := Target;
      HintDragHandle := TargetHandle;
      HintDragPos := Pos;
      HintDoDragOver(dmDragEnter);
    end;
    HintDragPos := Pos;
    DragCursor := THintDragObject(HintDragObject).GetDragCursor(
                      HintDoDragOver(dmDragMove), Pos.X, Pos.Y);
    Windows.SetCursor(Screen.Cursors[DragCursor]);
    if HintDragText <> '' then
      if HintDragObject is THintDragObject then
        DragHintWindow.ShowDragHint;
  end;
end;

procedure HintDragInit(ADragObject: TDragObject; Immediate: Boolean);
begin
  HintDragObject := ADragObject;
  HintDragTarget := nil;
  GetCursorPos(HintDragStartPos);
  HintDragSaveCursor := Windows.GetCursor;
  HintDragActive := Immediate;
  HintDragCapture := THintDragObject(HintDragObject).Capture;
  if HintDragActive then HintDragTo(HintDragStartPos);
end;

--------  キリトリ  下の発言に続きます-------------------------------
                                                   本田勝彦

Original document by 本田勝彦        氏 ID:(VYR01647)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum