お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





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

"ポップアップするリストボックス"



こんにちは、かとちんです。

コードエディタで、[Ctrl]+[Space] で出てくるポップアップリストボックス
が欲しいなぁと思ったんですが、Delphi-IDE のみ持っていてどこにも提供
されていない〜 (;_;) ので、作成しました。

但し,「フォームに直接貼り付けること」「フォームのAutoScrollはFalseで
あること」という条件下でしか使えません。(-_-、) 解決できなかったぁ。

unit PopupListBox;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TPopupCloseEvent = procedure (Sender: TObject; ActiveTo: TControl)
                     of object;

  TPopupListBox = class(TColumnListBox)
  private
    { Private 宣言 }
    FPopExecuteNow: Boolean;
    FPopupNow: Boolean;
    FOnPopupClose: TPopupCloseEvent;
    procedure WMKillFocus(var Message: TWMKillFocus); message
                                                        WM_KILLFOCUS;
    procedure CMCancelMode(var Message: TCMCancelMode); message
                                                       CM_CANCELMODE;
  protected
    { Protected 宣言 }
    procedure Loaded; override;
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
                      X, Y: Integer); override;
    procedure SetParent(AParent: TWinControl); override;
  public
    { Public 宣言 }
    constructor Create(AOwner: TComponent); override;
    procedure Popup(X, Y: Integer);
    procedure PopupCancel;
  published
    property Ctl3D default False;
    property OnPopupClose: TPopupCloseEvent read FOnPopupClose
                                            write FOnPopupClose;
  end;

procedure Register;
begin
  RegisterComponents('Samples', [TPopupListBox]);
end;

{ TPopupListBox }

constructor TPopupListBox.Create(AOwner: TComponent);
begin
  if not (AOwner is TForm) then
    raise Exception.Create('TPopupListBox:Owner must be a Form');
  inherited Create(AOwner);
  Ctl3D := False;
  ParentCtl3D := False;
  IntegralHeight := True;
end;

procedure TPopupListBox.Loaded;
begin
  inherited;
  if not (csDesigning in ComponentState) then
  begin
    Visible := False;
    SetBounds(-10000,-10000, Width, Height);
  end;
end;

procedure TPopupListBox.CMCancelMode(var Message: TCMCancelMode);
var
  C: TControl;
begin
  inherited;
  if FPopExecuteNow then Exit;
  if (Message.Sender <> Self) then
  begin
    if PopupMenu <> nil then
    begin
      // PopupMenu が表示されると Sender=nil で送られてくるので
      if (Message.Sender = nil) then Exit;
    end;
    C := Message.Sender;
    if not Visible then C := nil;
    PopupCancel;
    if Assigned(FOnPopupClose) then FOnPopupClose(Self, C);
  end;
end;

procedure TPopupListBox.WMKillFocus(var Message: TWMKillFocus);
var
  C: TControl;
begin
  inherited;
  if FPopExecuteNow then exit;
  C := FindControl(Message.FocusedWnd);
  if not Visible then C := nil;
  PopupCancel;
  if Assigned(FOnPopupClose) then FOnPopupClose(Self, C);
end;

procedure TPopupListBox.KeyDown(var Key: Word; Shift: TShiftState);
begin
  if (Key = VK_ESCAPE) or (Key = VK_RETURN) then
  begin
    PopupCancel;
    if Assigned(FOnPopupClose) then FOnPopupClose(Self, Self);
  end;
  inherited;
end;

procedure TPopupListBox.MouseUp(Button: TMouseButton; Shift:
TShiftState;
  X, Y: Integer);
begin
  if ItemAtPos(Point(X, Y), True) = ItemIndex then
  begin
    PopupCancel;
    if Assigned(FOnPopupClose) then FOnPopupClose(Self, Self);
  end;
  inherited;
end;

procedure TPopupListBox.Popup(X, Y: Integer);
begin
  if not (Owner is TForm) then Exit;
  PopupCancel;

  FPopExecuteNow := True;
  try
    Visible := True;
    TForm(Owner).ActiveControl := Self;

    if GetParent(Handle) = TForm(Owner).Handle then
    begin
      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle,
                     GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
      // デスクトップを親にする
      SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);

      // デスクトップにポップアップ表示
      if X + Width > Screen.Width then X := Screen.Width - Width;
      if Y + Height > Screen.Height then Y := Screen.Height - Height;
      SetWindowPos(Handle, HWND_TOP, X, Y, 0, 0, SWP_NOSIZE);
    end;
    Show;
    FPopupNow := True;
  finally
    FPopExecuteNow := False;
  end;
end;

procedure TPopupListBox.PopupCancel;
begin
  if not (Owner is TForm) then Exit;
  if not FPopupNow then Exit;

  FPopExecuteNow := True;
  try
    Visible := False;
    if GetParent(Handle) <> TForm(Owner).Handle then
    begin
      Windows.SetParent(Handle, TForm(Owner).Handle);
      FPopupNow := False;
      SetBounds(-10000, -10000, Width, Height);
    end;
  finally
    FPopExecuteNow := False;
  end;
end;

procedure TPopupListBox.SetParent(AParent: TWinControl);
begin
  if AParent <> nil then
    if not (AParent is TForm) then
      raise Exception.Create('TPopupListBox:Parent must be a Form')
    else
      if TForm(AParent).AutoScroll then
      begin
        ShowMessage(
          'TPopupListBox: Form''s AutoScroll must be False. Changed.'
        );
        TForm(AParent).AutoScroll := False;
      end;
  inherited;
end;


 ⌒ ⌒   2000/01/24(月)  午後 10:00  かとちん(JDX06162)
 ◎ ◎   mailto:tarochan.kato@nifty.ne.jp
∋ ▽ ∈  http://pc2.techno-ware-unet.ocn.ne.jp/~kato/

Original document by かとちん        氏 ID:(JDX06162)


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

Copyright 1996-2002 Delphi Users' Forum