Winodws消息
procedure WMGetDlgCode(var Msg: TWMGetDlgCode); message WM_GETDLGCODE;
{说明:
可以拦截处理方向键,但是有更灵活的方法,介绍如下:
想要你的组件能够处理方向键,你必须要拦截 CM_WANTSPECIALKEY 组件讯息。 CM_WANTSP
ECIALKEY 组件讯息提供你比拦截 WM_GETDLGCODE 窗口讯息更容易且灵活的判断方法来决定
是否需要某些特殊键的讯息。当控件收到任何一个特殊键时就会送出CM_WANTSPECIALKEY 组
件讯息给控件。
CM_WANTSPECIALKEY 组件讯息比 WM_GETDLGCODE 讯息更具有弹性的地方在这儿。我们甚至
可以根据是按下的是哪个特殊键才决定是否处理这个键。例如,你的控件有三张影像,你可
以让使用者利用左右方向键来回检视它们,如果翻到最后一张影像再按向右键时,焦点就让
它离开组件,剩下的全部都让 Delphi 来处理。
举例:
procedure TCustomGrid.WMGetDlgCode(var Msg: TWMGetDlgCode);
begin
Msg.Result := DLGC_WANTARROWS; //在这说明要处理方向键
if goRowSelect in Options then Exit;
if goTabs in Options then Msg.Result := Msg.Result or DLGC_WANTTAB; //这里同样可以处理Tab键
if goEditing in Options then Msg.Result := Msg.Result or DLGC_WANTCHARS;
end;
相关:
VCL内部消息 CM_WANTSPECIALKEY
}
procedure WMMeasureItem(var Message: TWMMeasureItem); message WM_MEASUREITEM;
procedure WMDrawItem(var Message: TWMDrawItem); message WM_DRAWITEM;
{说明:
procedure WMMeasureItem(var Message: TWMMeasureItem); message WM_MEASUREITEM;
procedure WMDrawItem(var Message: TWMDrawItem); message WM_DRAWITEM;
这两个消息息息相关,一起做说明--
系统会在控件需要绘制的时候先发送一个WM_MEASUREITEM消息给当此控件的父窗体(注意这里要
注意,这是由于标准Win32开发方式决定的,由于原来大多数的控件都是在接收到主窗体的W
M_CREATE消息时候创建的,一个窗口过程是当时程序员可以编写代码唯一的机会,所有的消
息都发送到主线程的消息循环中,所以控件的消息自然发到这里来了!可没有这么频繁使用
子类化或者超类化的方式)来确定控件的绘制范围,然后接着发送WM_DRAWITEM给此控件的父
窗体,而我们要做一个独立的组件,它怎么知道什么时候该绘制呢?代码本来应该写在窗体
中才对啊!好在delphi在库中意见考虑到这个需求,只要你的控件是在delphi中使用的,那
么TForm窗体会将所有接收的消息发送给相应的窗口过程处理,TWinControl.WMDrawItem相关
代码如下(经过处理):
举例:
procedure TWinControl.WMDrawItem(var Message: TWMDrawItem);
begin
if not DoControlMsg(Message.DrawItemStruct^.CtlID, Message) then iherited;
end;
而DoControlMsg的实现很简单:
function DoControlMsg(ControlHandle: HWnd; var Message): Boolean;
var Control: TWinControl;
begin
DoControlMsg := False;
Control := FindControl(ControlHandle);
if Control <> nil then
with TMessage(Message) do
begin
Result := Control.Perform(Msg + CN_BASE, WParam, LParam);
DoControlMsg := True;
end;
end;
相关:
上述消息在主窗体中被处理,Delphi中主窗体接受到此消息后,就查找要接受该消息的子窗体。
找到控件后将该消息的标识加上CN_BASE发送给相应窗口就是了(CN_DRAWITEM=CN_BASE+WM_
DRAWITEM),所以这里是第二个注意点:在组件中截获WM_DRAWITEM消息是没有效果的,事实
上根本没有这个消息传送到组件的窗口过程,而应该截获的是CN_DRAWITEM,WM_MEASUREITE
M的消息处理过程是一样的,组件中应该截取CN_MEASUREITEM消息。两个Delphi自定义消息
声明如下:
procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
}