お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





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

"THintDragObject しょの2"





--------  キリトリ  上の発言からの続きです -------------------------

type
  TDmy = class(TControl);

procedure HintDragInitControl(Control: TControl; Immediate: Boolean);
var
  ADragObject: TDragObject;
begin
  HintDragControl := Control;
  try
    ADragObject := nil;
    HintDragFreeObject := False;
    if Assigned(TDmy(Control).OnStartDrag) then
      TDmy(Control).OnStartDrag(Control, ADragObject);
    if ADragObject = nil then
    begin
      ADragObject := THintDragObject.Create(Control);
      HintDragFreeObject := True;
    end;
    HintDragInit(ADragObject, Immediate);
  except
    HintDragControl := nil;
    raise;
  end;
end;

procedure HintDragDone(Drop: Boolean);
var
  DragSave: TDragObject;
  Accepted: Boolean;
  DragMsg: TDragMessage;
  TargetPos: TPoint;
begin
  DragSave := nil;
  HintDragControl := nil;
  try
    THintDragObject(HintDragObject).ReleaseCapture(HintDragCapture);
    DragSave := HintDragObject;
    Windows.SetCursor(HintDragSaveCursor);
    try
      if TObject(HintDragTarget) is TControl then
        TargetPos := TControl(HintDragTarget).ScreenToClient(HintDragPos)
      else
        TargetPos := HintDragPos;
      Accepted := HintDragActive and
                  HintDoDragOver(dmDragLeave) and Drop;
      HintDragObject := nil;
      DragMsg := dmDragDrop;
      if not Accepted then
      begin
        DragMsg := dmDragCancel;
        HintDragPos.X := 0;
        HintDragPos.Y := 0;
        TargetPos.X := 0;
        TargetPos.Y := 0;
      end;
      HintDragMessage(HintDragHandle, DragMsg, DragSave,
                      HintDragTarget, HintDragPos);
      THintDragObject(DragSave).Finished(HintDragTarget, TargetPos.X,
                                         TargetPos.Y, Accepted);
      HintDragTarget := nil;
    finally
      HintDragObject := nil;
    end;
  finally
    DragHintWindow.HideDragHint;
    if HintDragFreeObject then
      DragSave.Free;
  end;
end;

{ interfaced procedure & function }

procedure CancelHintDrag;
begin
  if HintDragObject <> nil then
    HintDragDone(False);
  HintDragControl := nil;
end;

function HintDragging(Control: TControl): Boolean;
begin
  Result := HintDragControl = Control;
end;

procedure EndHintDrag(Control: TControl; Drop: Boolean);
begin
  if HintDragging(Control) then
    HintDragDone(Drop);
end;

procedure BeginHintDrag(Control: TControl; Immediate: Boolean;
    HintText: String);
var
  P: TPoint;
begin
  if Control is TForm then
    raise EInvalidOperation.CreateRes(SCannotDragForm);
  if HintDragControl = nil then
  begin
    HintDragControl := Control;
    if csLButtonDown in Control.ControlState then
    begin
      GetCursorPos(P);
      P := Control.ScreenToClient(P);
      Control.Perform(WM_LBUTTONUP, 0, Longint(PointToSmallPoint(P)));
    end;
    if HintDragControl = Control then
      HintDragInitControl(Control, Immediate);
    HintDragText := HintText;
  end;
end;

{ THintDragObject }

function THintDragObject.Capture: HWND;
begin
  Result := AllocateHWnd(MouseMsg);
  SetCapture(Result);
end;

procedure THintDragObject.ReleaseCapture(Handle: HWND);
begin
  Windows.ReleaseCapture;
  DeallocateHWND(Handle);
end;

procedure THintDragObject.MouseMsg(var Message: TMessage);
var
  P: TPoint;
begin
  try
    case Message.Msg of
      WM_MOUSEMOVE:
        begin
          P := SmallPointToPoint(TWMMouse(Message).Pos);
          Windows.ClientToScreen(HintDragCapture, P);
          HintDragTo(P);
        end;
      WM_LBUTTONUP:
        HintDragDone(True);
      WM_RBUTTONDOWN:
        HintDragDone(False);
    end;
  except
    if HintDragControl <> nil then HintDragDone(False);
    raise;
  end;
end;

{ TDragHintWindow }

procedure TDragHintWindow.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  {$IFDEF KEYMESSAGE}
  Params.Style := WS_POPUP;
  {$ELSE}
  Params.Style := WS_POPUP or WS_DISABLED;
  {$ENDIF}
end;

{$IFDEF KEYMESSAGE}
procedure TDragHintWindow.WMKeyDown(var Message: TWMKeyDown);
begin
  if TWMKeyDown(Message).CharCode = VK_ESCAPE then
    CancelHintDrag;
end;
{$ENDIF}

{$IFDEF VER90}
function TDragHintWindow.CalcHintRect(const AHint: string): TRect;
begin
  Result := Rect(0, 0, Screen.Width, 0);
  DrawText(Canvas.Handle, PChar(AHint), -1, Result,
    DT_CALCRECT or DT_LEFT or DT_WORDBREAK or DT_NOPREFIX);
  Inc(Result.Right, 6);
  Inc(Result.Bottom, 2);
end;
{$ENDIF}

procedure TDragHintWindow.ShowDragHint;
var
  CursorHeight, CursorWidth, CaptionHeight: Integer;
  HintPos: TPoint;
  HintWinRect: TRect;
begin
  if not HandleAllocated then
    HandleNeeded;
  CaptionHeight := GetSystemMetrics(SM_CYCAPTION);
  CursorHeight := GetSystemMetrics(SM_CYCURSOR);
  CursorWidth := GetSystemMetrics(SM_CXCURSOR);
  HintPos := HintDragPos;
  Inc(HintPos.Y, CursorHeight - CaptionHeight);
  Inc(HintPos.X, CursorWidth - CaptionHeight + 3);
  HintWinRect := CalcHintRect(HintDragText);
  OffsetRect(HintWinRect, HintPos.X, HintPos.Y);
  { ActivateHint no adjust }
  Caption := HintDragText;
  BoundsRect := HintWinRect;
  SetWindowPos(Handle, HWND_TOPMOST, HintWinRect.Left, HintWinRect.Top,
    0, 0, SWP_SHOWWINDOW or SWP_NOACTIVATE or SWP_NOSIZE);
  {$IFDEF KEYMESSAGE}
  if HintDragControl is TWinControl then
    Parent := TWinControl(HintDragControl);
  SetFocus;
  {$ENDIF}
end;

procedure TDragHintWindow.HideDragHint;
begin
  {$IFDEF KEYMESSAGE}
  Parent := nil;
  {$ENDIF}
  if HandleAllocated then
    ReleaseHandle;
end;

initialization
  DragHintWindow := TDragHintWindow.Create(Application);

finalization
  DragHIntWindow.Free;

end.
--------  キリトリ  -------------------------------------------------
                                                   本田勝彦

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


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

Copyright 1996-2002 Delphi Users' Forum