眼见为实,找到了代码,上半部分是对左右键四个事件的处理,下半部分是我的Trayicon代理的实现: procedure Tmain.wndProc(var Msg: TMessage) ;//重载并自定义消息 var poss:TPoint;CurrentTime :longint; Para:array [0..MAX_PATH] of char; begin GetCursorPos(Poss); //得到当前鼠标位置 with msg do begin if msg =wm_MyCall then Begin if WParam=0 then //这是程序的主图标消息 begin CurrentTime:=gettickcount;//得到当前开机时间 case LParam of WM_LBUTTONDBLCLK: begin Mine.Tag :=1;// 双击事件时不处理单击 MineClick(nil); //双击事件为窗口是否显示的切换 end; wm_LButtonDown: begin Mine.Tag:=0; while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do application.ProcessMessages; if Mine.Tag=0 then TrackPopupMenu(mn.handle,tpm_BottomAlign or tpm_RightAlign,Poss.X,Poss.Y,0,handle,nil); //PopMenu(self); // timClk.Enabled:=true;//将处理单击的时钟激活,到时处理单击 end; WM_RBUTTONDBLCLK: begin //FowTimTimer(self);//如字符跟踪则将活动窗口Caption还原 Mine.Tag :=1;// 双击事件时不处理单击 MnexitClick(nil); halt; end; wm_RButtonDown: begin Mine.Tag:=0; while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do application.ProcessMessages; if Mine.Tag=0 then TrackPopupMenu(mnrun.handle,tpm_BottomAlign or tpm_RightAlign,Poss.X,Poss.Y,0,handle,nil); end; End; end else //这是程序表生成的图标消息 begin case LParam of wm_LButtonDown: for CurrentTime:=0 to prglist.Items.Count-1 do begin if prglist.Items[CurrentTime].ImageIndex<>WParam-1 then continue; N8Click(mnrun.Items[CurrentTime]); break; end; wm_RButtonDown:shellabout(handle,Myname,'火鸟软件出品 [email protected]',application.icon.handle); end; end; end else begin if msg=ReCall then//这是由新运行的程序传来的,高字节是命令行及参数,低字节是长度 begin if WParam>0 then begin //para:=strAlloc(LParam); GlobalGetAtomName(WParam,@para,LParam); GlobalDeleteAtom(WParam); if (wordat(para,':2')=2) or (wordat(para,':2')=3) then messagebox(handle,'请先将运行中的超人关闭',myname,mb_ok+MB_ICONINFORMATION) else begin //para:=pchar(copy(para,wordat(para,':2')-1,LParam)); //if filesafe(para) then FileOper(para,handle); if main.icosva.Hint='' then if filesafe(copy(para,wordat(para,':2')-1,LParam)) then FileOper(copy(para,wordat(para,':2')-1,LParam),screen.ActiveForm.handle); end; //StrDispose(para); end else begin if top=-1000 then MineClick(Nil); SetForegroundWindow(application.handle); FlashWindow(handle,false); delay(0.1); FlashWindow(handle,true); Refresh ; end; end; case WParam of //WM_SYSCOMMAND Hot_Lock: fmlock.showmodal; Hot_Key: begin if top=-1000 then MineClick(Nil); SetForegroundWindow(application.handle); Refresh ; end; SC_MINIMIZE: begin MineClick(self); exit; end; { SC_MAXIMIZE,SC_RESTORE: begin LogPopClick(TopOn); exit; end;} end; end; end; inherited wndProc(Msg); //继承 end;
是的,谢谢,好象就是这句话 while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do application.ProcessMessages; 就是判断2次点击的时间的间隔如果在双击范围内,那就application.ProcessMessages;//这句话应该是跳过的意思。
trayicon在你鼠标左键双击时会先收到一条WM_LButtonDown、
紧接着会收到WM_LBUTTONDBLCLK说明用户是双击而非单击
所以你在LButtonDown中的处理不应该是直接的单击处理,而是一个类似超时处理的循环,其时间长短会用到API GetDoubleClickTime(触发双击的最大时间间隔,再大了就是单击两次了),当已超时而未触发LBUTTONDBLCLK时说明真是单击,否则是因为双击而触发的,就只执行LBUTTONDBLCLK而不招待LButtonDown好了
procedure Tmain.wndProc(var Msg: TMessage) ;//重载并自定义消息
var poss:TPoint;CurrentTime :longint;
Para:array [0..MAX_PATH] of char;
begin
GetCursorPos(Poss); //得到当前鼠标位置
with msg do
begin
if msg =wm_MyCall then
Begin
if WParam=0 then //这是程序的主图标消息
begin
CurrentTime:=gettickcount;//得到当前开机时间
case LParam of
WM_LBUTTONDBLCLK:
begin
Mine.Tag :=1;// 双击事件时不处理单击
MineClick(nil); //双击事件为窗口是否显示的切换
end;
wm_LButtonDown:
begin
Mine.Tag:=0;
while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do
application.ProcessMessages;
if Mine.Tag=0 then TrackPopupMenu(mn.handle,tpm_BottomAlign or tpm_RightAlign,Poss.X,Poss.Y,0,handle,nil);
//PopMenu(self);
// timClk.Enabled:=true;//将处理单击的时钟激活,到时处理单击
end;
WM_RBUTTONDBLCLK:
begin
//FowTimTimer(self);//如字符跟踪则将活动窗口Caption还原
Mine.Tag :=1;// 双击事件时不处理单击
MnexitClick(nil);
halt;
end;
wm_RButtonDown:
begin
Mine.Tag:=0;
while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do
application.ProcessMessages;
if Mine.Tag=0 then TrackPopupMenu(mnrun.handle,tpm_BottomAlign or tpm_RightAlign,Poss.X,Poss.Y,0,handle,nil);
end;
End;
end
else //这是程序表生成的图标消息
begin
case LParam of
wm_LButtonDown:
for CurrentTime:=0 to prglist.Items.Count-1 do
begin
if prglist.Items[CurrentTime].ImageIndex<>WParam-1 then continue;
N8Click(mnrun.Items[CurrentTime]);
break;
end;
wm_RButtonDown:shellabout(handle,Myname,'火鸟软件出品 [email protected]',application.icon.handle);
end;
end;
end
else
begin
if msg=ReCall then//这是由新运行的程序传来的,高字节是命令行及参数,低字节是长度
begin
if WParam>0 then
begin
//para:=strAlloc(LParam);
GlobalGetAtomName(WParam,@para,LParam);
GlobalDeleteAtom(WParam);
if (wordat(para,':2')=2) or (wordat(para,':2')=3) then messagebox(handle,'请先将运行中的超人关闭',myname,mb_ok+MB_ICONINFORMATION)
else
begin
//para:=pchar(copy(para,wordat(para,':2')-1,LParam));
//if filesafe(para) then FileOper(para,handle);
if main.icosva.Hint='' then
if filesafe(copy(para,wordat(para,':2')-1,LParam)) then
FileOper(copy(para,wordat(para,':2')-1,LParam),screen.ActiveForm.handle);
end;
//StrDispose(para);
end
else
begin
if top=-1000 then MineClick(Nil);
SetForegroundWindow(application.handle);
FlashWindow(handle,false);
delay(0.1);
FlashWindow(handle,true);
Refresh ;
end;
end; case WParam of //WM_SYSCOMMAND
Hot_Lock:
fmlock.showmodal;
Hot_Key:
begin
if top=-1000 then MineClick(Nil);
SetForegroundWindow(application.handle);
Refresh ;
end;
SC_MINIMIZE:
begin
MineClick(self);
exit;
end;
{ SC_MAXIMIZE,SC_RESTORE:
begin
LogPopClick(TopOn);
exit;
end;}
end;
end;
end;
inherited wndProc(Msg); //继承
end;
互勉共进吧!
while ((gettickCount)<(CurrentTime+GetDoubleClickTime)) and (Mine.Tag=0) do
application.ProcessMessages;
就是判断2次点击的时间的间隔如果在双击范围内,那就application.ProcessMessages;//这句话应该是跳过的意思。