X
xuxiaohan
Unregistered / Unconfirmed
GUEST, unregistred user!
这次真的要请高手来解决了, SubClass 无法拦截 CM_CANCELMODE ??? 真晕!300分!不管能不能解决,解释清楚就给分。 ( 积分: 100 )<br />我的目的是做一个PopWindow, 利用 CM_CANCELMODE 和 WM_KILLFOCUS 隐藏 popWindow.
因为有机会在很多不同的 控件上 下拉这个 popWindow, 所以我用SubClass拦截 popWindow的parent 的消息 CM_CANCELMODE 和 WM_KILLFOCUS , WM_KILLFOCUS 能够拦截到,CM_CANCELMODE 不能拦截到, why????。
下面是所有代码, 包括一个Form(测试用)。
TPopupWindow = class(TCustomControl)
private
FButton: TWinControl;
FoldBtnProc: TFarProc;
FBtnProc : TFarProc;
procedure btnWndProc(var message: TMessage);
procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
protected
procedure CreateParams(var Params: TCreateParams); override;
function GetValue: Variant; virtual; abstract;
procedure SetValue(const Value: Variant); virtual; abstract;
procedure CloseUp(Accept: Boolean); virtual;
public
constructor Create(AOwner: TComponent); override;
function GetPopupText: string; virtual;
procedure Hide;
procedure Show(Origin: TPoint);
end;
procedure TPopupWindow.btnWndProc(var message: TMessage);
var
s: string;
begin
with message do
begin
s:=inttohex(Msg, 8)+' ';
windows.TextOut(getDC(0), 10, 10, pchar(s), length(s));
case Msg of
[blue] CM_CANCELMODE : hide; // WHY ????[/blue]
WM_KILLFOCUS : hide;//hide;
end;
Result := CallWindowProc(FoldBtnProc, FButton.Handle, Msg, wParam, lParam);
end;
end;
procedure TPopupWindow.CloseUp(Accept: Boolean);
begin
end;
constructor TPopupWindow.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FButton := TWinControl(AOwner);
ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable,
csAcceptsControls];
Ctl3D := False;
ParentCtl3D := False;
Visible := False;
Parent := FButton;
width:=160;
height:=160;
FoldBtnProc:=Pointer(GetWindowLong(Fbutton.Handle, GWL_WNDPROC));
FBtnProc:=MakeObjectInstance(btnWndProc);
SetWindowLong(FButton.Handle, GWL_WNDPROC, LongInt(FBtnProc));
end;
procedure TPopupWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do begin
Style := WS_POPUP or WS_BORDER or WS_CLIPCHILDREN;
ExStyle := WS_EX_TOOLWINDOW;
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
end;
end;
function TPopupWindow.GetPopupText: string;
begin
end;
procedure TPopupWindow.Hide;
begin
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
Visible := False;
end;
procedure TPopupWindow.Show(Origin: TPoint);
begin
SetWindowPos(Handle, HWND_TOP, Origin.X, Origin.Y, 0, 0,
SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
Visible := True;
end;
procedure TPopupWindow.WMMouseActivate(var Message: TMessage);
begin
Message.Result := MA_NOACTIVATE;
end;
...
unit testFace;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, myControls, srToolButton, StdCtrls, Mask, ToolEdit, ImgList;
type
txButton = class(TButton)
private
FFace: TPopupWindow;
procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
public
procedure click; override;
procedure PopupDropDown(DisableEdit: Boolean); virtual;
constructor create(Aowner: TComponent); override;
end;
TForm1 = class(TForm)
Button1: TButton;
ImageList1: TImageList;
srToolButton2: TsrToolButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
Fbutton: TxButton;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Fbutton:=TxButton.create(self);
Fbutton.top:=10;
Fbutton.left:=10;
end;
{ txButton }
procedure txButton.click;
begin
inherited;
PopupDropDown(true);
end;
procedure txButton.CMCancelMode(var Message: TCMCancelMode);
begin
inherited;
// FFace.Hide; 这里可以响应;
end;
constructor txButton.create(Aowner: TComponent);
begin
inherited Create(AOwner);
parent:=TWincontrol(AOwner);
FFace:=TpopupWindow.Create(self);
end;
procedure txButton.PopupDropDown(DisableEdit: Boolean);
var
P: TPoint;
Y: Integer;
begin
begin
P := Parent.ClientToScreen(Point(Left, Top));
Y := P.Y + Height;
end;
if P.X &lt; 0 then P.X := 0 ;
FFace.Show(Point(P.X, Y));
end;
procedure txButton.WMKillFocus(var Message: TWMKillFocus);
begin
inherited;
// FFace.Hide;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
sendmessage(Fbutton.Handle, CM_CANCELMODE, 0, 0);
end;
end.
因为有机会在很多不同的 控件上 下拉这个 popWindow, 所以我用SubClass拦截 popWindow的parent 的消息 CM_CANCELMODE 和 WM_KILLFOCUS , WM_KILLFOCUS 能够拦截到,CM_CANCELMODE 不能拦截到, why????。
下面是所有代码, 包括一个Form(测试用)。
TPopupWindow = class(TCustomControl)
private
FButton: TWinControl;
FoldBtnProc: TFarProc;
FBtnProc : TFarProc;
procedure btnWndProc(var message: TMessage);
procedure WMMouseActivate(var Message: TMessage); message WM_MOUSEACTIVATE;
protected
procedure CreateParams(var Params: TCreateParams); override;
function GetValue: Variant; virtual; abstract;
procedure SetValue(const Value: Variant); virtual; abstract;
procedure CloseUp(Accept: Boolean); virtual;
public
constructor Create(AOwner: TComponent); override;
function GetPopupText: string; virtual;
procedure Hide;
procedure Show(Origin: TPoint);
end;
procedure TPopupWindow.btnWndProc(var message: TMessage);
var
s: string;
begin
with message do
begin
s:=inttohex(Msg, 8)+' ';
windows.TextOut(getDC(0), 10, 10, pchar(s), length(s));
case Msg of
[blue] CM_CANCELMODE : hide; // WHY ????[/blue]
WM_KILLFOCUS : hide;//hide;
end;
Result := CallWindowProc(FoldBtnProc, FButton.Handle, Msg, wParam, lParam);
end;
end;
procedure TPopupWindow.CloseUp(Accept: Boolean);
begin
end;
constructor TPopupWindow.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FButton := TWinControl(AOwner);
ControlStyle := ControlStyle + [csNoDesignVisible, csReplicatable,
csAcceptsControls];
Ctl3D := False;
ParentCtl3D := False;
Visible := False;
Parent := FButton;
width:=160;
height:=160;
FoldBtnProc:=Pointer(GetWindowLong(Fbutton.Handle, GWL_WNDPROC));
FBtnProc:=MakeObjectInstance(btnWndProc);
SetWindowLong(FButton.Handle, GWL_WNDPROC, LongInt(FBtnProc));
end;
procedure TPopupWindow.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do begin
Style := WS_POPUP or WS_BORDER or WS_CLIPCHILDREN;
ExStyle := WS_EX_TOOLWINDOW;
WindowClass.Style := WindowClass.Style or CS_SAVEBITS;
end;
end;
function TPopupWindow.GetPopupText: string;
begin
end;
procedure TPopupWindow.Hide;
begin
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER or
SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_HIDEWINDOW);
Visible := False;
end;
procedure TPopupWindow.Show(Origin: TPoint);
begin
SetWindowPos(Handle, HWND_TOP, Origin.X, Origin.Y, 0, 0,
SWP_NOACTIVATE or SWP_SHOWWINDOW or SWP_NOSIZE);
Visible := True;
end;
procedure TPopupWindow.WMMouseActivate(var Message: TMessage);
begin
Message.Result := MA_NOACTIVATE;
end;
...
unit testFace;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, myControls, srToolButton, StdCtrls, Mask, ToolEdit, ImgList;
type
txButton = class(TButton)
private
FFace: TPopupWindow;
procedure CMCancelMode(var Message: TCMCancelMode); message CM_CANCELMODE;
procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
public
procedure click; override;
procedure PopupDropDown(DisableEdit: Boolean); virtual;
constructor create(Aowner: TComponent); override;
end;
TForm1 = class(TForm)
Button1: TButton;
ImageList1: TImageList;
srToolButton2: TsrToolButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
Fbutton: TxButton;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Fbutton:=TxButton.create(self);
Fbutton.top:=10;
Fbutton.left:=10;
end;
{ txButton }
procedure txButton.click;
begin
inherited;
PopupDropDown(true);
end;
procedure txButton.CMCancelMode(var Message: TCMCancelMode);
begin
inherited;
// FFace.Hide; 这里可以响应;
end;
constructor txButton.create(Aowner: TComponent);
begin
inherited Create(AOwner);
parent:=TWincontrol(AOwner);
FFace:=TpopupWindow.Create(self);
end;
procedure txButton.PopupDropDown(DisableEdit: Boolean);
var
P: TPoint;
Y: Integer;
begin
begin
P := Parent.ClientToScreen(Point(Left, Top));
Y := P.Y + Height;
end;
if P.X &lt; 0 then P.X := 0 ;
FFace.Show(Point(P.X, Y));
end;
procedure txButton.WMKillFocus(var Message: TWMKillFocus);
begin
inherited;
// FFace.Hide;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
sendmessage(Fbutton.Handle, CM_CANCELMODE, 0, 0);
end;
end.