CxGrid 的加强右键菜单实现方法
2013-10-05 14:37
501 查看
目标:
希望在DBGridEh的标题栏上按右键弹出菜单,并且弹出的菜单,能针对刚刚按右键那列进行专有处理.
比如说,对某列进行排序,只要在此列上按右键,点排序即可对此列进行排序.
分析问题点:
1.必须判断是在标题栏上点击
2.必须判断是点击的右键,因为左键还有其他功能,所以必须分开
[第一次写这样的文章,也没有经过检查,如果不妥,请见谅了]
尝试方法一:在onTitleClick事件中处理
结果:不成功
原因:虽然OnTitleClick事件中有Column参数,但是这个函数中不能区分左右鼠标事件
尝试方法二:OnMouseDown或OnMouseUp事件+OnTitleClick
结果:不成功
本想在窗口中先定议一个全局变量LastMouseButton:TMouseButton
然后在OnMouseDown事件中把LastMouseButton:=Button;
然后在OntitleClick事件中再判断LastMouseButton事件的值
但奇怪的是,dbgrideh的onmousedown事件中,根本就不会有button=mbRight的时候不管你按的是左键还是右键,button都是mbLeft
这个不知道是不是dbgrideh的bug,反而dbgrid是可以的
尝试方法三:用Columneh.popmenu属性来实现,判断其PopupComponent即可
结果:不成功
原因:本来以为找到了门路,但偏偏这个popupcomponent这时却是dbgrideh,
而不是我要的column,所以暂是还是失败
有人要问,不可以每个column给一个不同的popmenu不就中以了,我现在要做一是一个通用的方法,让每个界面的功能都要一样处理,再来
尝试方法四:还是用columneh.popmenu属性
结果:成功
描述:在查popupcomponent为什么是dbgrideh,而不是columneh时,不经发现了一些代码
procedure TCustomDBGridEh.DefaultHandler(var Message);
var
P: TPopupMenu;
Cell: TGridCoord;
WinMessage: TMessage;
begin
inherited DefaultHandler(Message);
WinMessage := UnwrapMessageEh(Message);
if TMessage(WinMessage).Msg = wm_RButtonUp then
{$IFDEF CIL}
with TWMRButtonUp.Create(WinMessage) do
{$ELSE}
with TWMRButtonUp(Message) do
{$ENDIF}
begin
Cell := MouseCoord(XPos, YPos);
if (Cell.X < FIndicatorOffset) or (Cell.Y < 0) then Exit;
P := Columns[RawToDataColumn(Cell.X)].PopupMenu;//这句很重要,这个函数很NB
if (P <> nil) and P.AutoPopup then
begin
SendCancelMode(nil);
P.PopupComponent := Self;
with ClientToScreen(SmallPointToPoint(Pos)) do
P.Popup(X, Y);
Result := 1;
end;
end;
end;
看到没有,原来它本身就也是通过鼠标位置来判断当前的columneh的,并且触发它的popupmenu
那我们跟它一样的做法不就得了,有了思路,那就好办了!
关键函数RawToDataColumn是protected的,没办法直接访问,那好办,用我们的绝招HackClass哈
下面是实现的代码
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, GridsEh, DBGridEh, ExtCtrls, DBCtrls,Ehlibado, StdCtrls, Menus;
type
THackGrid= class (TCustomDBGridEh);
TForm1 = class(TForm)
DBNavigator1: TDBNavigator;
DBGridEh1: TDBGridEh;
DataSource1: TDataSource;
ADODataSet1: TADODataSet;
Button1: TButton;
Label1: TLabel;
PopupMenu1: TPopupMenu;
PopupMenu2: TPopupMenu;
M11: TMenuItem;
M21: TMenuItem;
PopupMenu3: TPopupMenu;
M31: TMenuItem;
procedure PopupMenu1Popup(Sender: TObject);
private
{ Private declarations }
lastmousebutton:TMouseButton;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.PopupMenu1Popup(Sender: TObject);
var Cell: TGridCoord;
point:TPoint;
i:integer;
begin
point:=mouse.CursorPos;
Point:=DBGridEh1.ScreenToClient(point);
cell:=DBGridEh1.MouseCoord(point.X,point.Y);
i:=THackGrid(DBGridEh1).RawToDataColumn(cell.X);
//至此,I已经取得了dbgrideh1中的columneh的序号
//想要FIELD就,dbgrideh1.columneh[i].field 随你了
end;
end.
从开始动手找资料,到一步一步实验,到找到答案,我这笨蛋搞了三个小时,
并且一度失去信心,以为搞不出来,
但回过头来再看看答案,原来真是它妈的简单,原兄弟们都不要再走我的弯路喽
希望在DBGridEh的标题栏上按右键弹出菜单,并且弹出的菜单,能针对刚刚按右键那列进行专有处理.
比如说,对某列进行排序,只要在此列上按右键,点排序即可对此列进行排序.
分析问题点:
1.必须判断是在标题栏上点击
2.必须判断是点击的右键,因为左键还有其他功能,所以必须分开
[第一次写这样的文章,也没有经过检查,如果不妥,请见谅了]
尝试方法一:在onTitleClick事件中处理
结果:不成功
原因:虽然OnTitleClick事件中有Column参数,但是这个函数中不能区分左右鼠标事件
尝试方法二:OnMouseDown或OnMouseUp事件+OnTitleClick
结果:不成功
本想在窗口中先定议一个全局变量LastMouseButton:TMouseButton
然后在OnMouseDown事件中把LastMouseButton:=Button;
然后在OntitleClick事件中再判断LastMouseButton事件的值
但奇怪的是,dbgrideh的onmousedown事件中,根本就不会有button=mbRight的时候不管你按的是左键还是右键,button都是mbLeft
这个不知道是不是dbgrideh的bug,反而dbgrid是可以的
尝试方法三:用Columneh.popmenu属性来实现,判断其PopupComponent即可
结果:不成功
原因:本来以为找到了门路,但偏偏这个popupcomponent这时却是dbgrideh,
而不是我要的column,所以暂是还是失败
有人要问,不可以每个column给一个不同的popmenu不就中以了,我现在要做一是一个通用的方法,让每个界面的功能都要一样处理,再来
尝试方法四:还是用columneh.popmenu属性
结果:成功
描述:在查popupcomponent为什么是dbgrideh,而不是columneh时,不经发现了一些代码
procedure TCustomDBGridEh.DefaultHandler(var Message);
var
P: TPopupMenu;
Cell: TGridCoord;
WinMessage: TMessage;
begin
inherited DefaultHandler(Message);
WinMessage := UnwrapMessageEh(Message);
if TMessage(WinMessage).Msg = wm_RButtonUp then
{$IFDEF CIL}
with TWMRButtonUp.Create(WinMessage) do
{$ELSE}
with TWMRButtonUp(Message) do
{$ENDIF}
begin
Cell := MouseCoord(XPos, YPos);
if (Cell.X < FIndicatorOffset) or (Cell.Y < 0) then Exit;
P := Columns[RawToDataColumn(Cell.X)].PopupMenu;//这句很重要,这个函数很NB
if (P <> nil) and P.AutoPopup then
begin
SendCancelMode(nil);
P.PopupComponent := Self;
with ClientToScreen(SmallPointToPoint(Pos)) do
P.Popup(X, Y);
Result := 1;
end;
end;
end;
看到没有,原来它本身就也是通过鼠标位置来判断当前的columneh的,并且触发它的popupmenu
那我们跟它一样的做法不就得了,有了思路,那就好办了!
关键函数RawToDataColumn是protected的,没办法直接访问,那好办,用我们的绝招HackClass哈
下面是实现的代码
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, GridsEh, DBGridEh, ExtCtrls, DBCtrls,Ehlibado, StdCtrls, Menus;
type
THackGrid= class (TCustomDBGridEh);
TForm1 = class(TForm)
DBNavigator1: TDBNavigator;
DBGridEh1: TDBGridEh;
DataSource1: TDataSource;
ADODataSet1: TADODataSet;
Button1: TButton;
Label1: TLabel;
PopupMenu1: TPopupMenu;
PopupMenu2: TPopupMenu;
M11: TMenuItem;
M21: TMenuItem;
PopupMenu3: TPopupMenu;
M31: TMenuItem;
procedure PopupMenu1Popup(Sender: TObject);
private
{ Private declarations }
lastmousebutton:TMouseButton;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.PopupMenu1Popup(Sender: TObject);
var Cell: TGridCoord;
point:TPoint;
i:integer;
begin
point:=mouse.CursorPos;
Point:=DBGridEh1.ScreenToClient(point);
cell:=DBGridEh1.MouseCoord(point.X,point.Y);
i:=THackGrid(DBGridEh1).RawToDataColumn(cell.X);
//至此,I已经取得了dbgrideh1中的columneh的序号
//想要FIELD就,dbgrideh1.columneh[i].field 随你了
end;
end.
从开始动手找资料,到一步一步实验,到找到答案,我这笨蛋搞了三个小时,
并且一度失去信心,以为搞不出来,
但回过头来再看看答案,原来真是它妈的简单,原兄弟们都不要再走我的弯路喽
相关文章推荐
- Oracle死锁查询及处理
- 1208. Legendary Teams Contest(dfs)
- 如何在64位win7中使用未有签名的驱动程序
- cocos2d-x游戏开发(十七)NDK+ant编译暗黑世界
- UBuntu安装配置记录
- 第四章2
- 存储管理,设备管理
- HTTP消息头
- 20131005国庆作业例5-8,5-9
- LeetCode: Single Number
- hdu1166敌兵布阵
- c#的飞信fetion短信API接口使用实例
- ABAP屏幕开发-屏幕插入图片
- 算法导论入手!
- java applet程序实例 运行
- 飞信 .net接口
- windows下用wampServer 为wordpress 搭建本地服务器运行环境
- 网络子系统37_网桥、端口定时器
- RUN Facebook in ur Android Phone
- CXGrid的使用技巧