也许是win2k编程技术下的某个系统消息,象NC_
解决方案 »
- 各位兄弟,如果你发现了一个很有潜力的市场,别人还没有发现的,你怎么去捍卫自己的权益啊?
- 求打包工具
- 设为主键好一点,还是设为UNIQUE好一点呢?
- 如何可以判别字段的类型?(字符型还是数字型)
- 两个问题:DLL和焦点
- DLL中如何传DataSet?
- 有谁喜欢听R.E.M.的《Everybody Hurts》和R.Kelly的《I Believe I Can Fly》?
- 使用TMSCOMM控件時出錯信息:License information for TMSComm not found.You cannot user this Control in design mode.
- 一个关于调用vc++写的dll的问题
- 怎么回事?关于CASE语句的应用问题
- !!!很急,ADO连接数据库问题
- ADO怪现象~~~~~~~在线等待,谢谢……
但是就是不知道如何判断是在“我的程序”上
PAPPBARDATA pData
); ParametersdwMessageIdentifier of the appbar message to send. This parameter can be one of the following values:ABM_ACTIVATE Notifies the system that an appbar has been activated.
ABM_GETAUTOHIDEBAR Retrieves the handle of the autohide appbar associated with a particular edge of the screen.
ABM_GETSTATE Retrieves the autohide and always-on-top states of the Windows taskbar.
ABM_GETTASKBARPOS Retrieves the bounding rectangle of the Windows taskbar.
ABM_NEW Registers a new appbar and specifies the message identifier that the system should use to send notification messages to the appbar.
ABM_QUERYPOS Requests a size and screen position for an appbar.
ABM_REMOVE Unregisters an appbar, removing bar from the system's internal list.
ABM_SETAUTOHIDEBAR Registers or unregisters an autohide appbar for an edge of the screen.
ABM_SETPOS Sets the size and screen position of an appbar.
ABM_WINDOWPOSCHANGED Notifies the system when an appbar's position has changed.
pDataPointer to an APPBARDATA structure. The content of the structure depends on the value of dwMessage. Return ValuesReturns a message-dependent value. For more information, see the documentation for the individual appbar messages.
但是就是不知道如何判断是在“我的程序”上
------------------------------------
使用TCM_GETITEM消息循环检测所有的Item,每一个Item都有一个字符串,检查那个字符串,看看是否是"我的程序"就可以了.
找了一些资料,关于HOOK的。把它放出来,大家共同研究研究。
BCB_FANS,你能做个TCM_GETITEM的DEMO给我看看吗?library Hook;uses
SysUtils,
Classes,
HookProc in 'HookProc.pas';{$R *.RES}exports
SetHook,
EndHook,
SetAppHandled,
SetHandled;begin
IntoShare;
end.//HookProc.pas
unit HookProc;interfaceuses
SysUtils,
Windows,
Dialogs,
Messages;function MyHookProc(nCode: Integer; wp: wParam; lp: lParam): LResult; stdcall;
procedure SetHook;export;
procedure EndHook;export;
procedure IntoShare; stdcall;export;
procedure SetHandled( H: THandle );stdcall; export;
procedure SetAppHandled( H: THandle);stdcall; export;implementationtype
TGoData = record
TargetWnd : Hwnd;
AppHwnd : THandle;
ghHook : HHook;
end;
PGoData = ^TGoData;
var
GoData : PGoData;
MemFile : THandle;
aStr:String;
procedure SetHandled( H: THandle );stdcall; export;
begin
GoData^.TargetWnd := H;
end;procedure SetAppHandled( H: THandle);stdcall; export;
begin
GoData^.AppHwnd := H;end;
function MyHookProc(nCode: Integer; wp: wParam; lp: lParam): LResult; stdcall;
begin
if wP = WM_RBUTTONUP then
if (PMouseHookStruct(lp)^.hwnd =GoData^.TargetWnd) then
begin
MessageBeep(0);
//关键就是在这里,应该如何判断呢?
showmessage(inttostr(lp)+' '+inttostr(GoData^.AppHwnd)+' '+inttostr(PMouseHookStruct(lp)^.dwExtraInfo));
result :=1;
exit;
end;
Result := CallNextHookEx( GoData^.ghHook, nCode, wP, lP);
end;
procedure SetHook;export;
begin
GoData^.ghHook := SetWindowsHookEx(WH_MOUSE, @MyHookProc, hInstance, 0);
end;procedure EndHook;export;
begin
UnhookWindowsHookEx( GoData^.ghHook );
end;procedure IntoShare; stdcall;export;
begin
MemFile := OpenFileMapping( FILE_MAP_WRITE, False, 'JJYY' );
if MemFile = 0 then
MemFile:=CreateFileMapping( $FFFFFFFF, nil,
PAGE_READWRITE, 0, SizeOf( TGoData ), 'JJYY');
GoData := MapViewOfFile( MemFile, FILE_MAP_WRITE, 0, 0, 0 );
if MemFile = 0 then
FillChar( GoData^, SizeOf( TGoData ),0);
SetLength(aStr,255);
end;end.//测试
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
Ttest = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure SetHandled( H : THandle ); stdcall;external 'Hook.dll';procedure SetAppHandled( H : THandle); stdcall;external 'Hook.dll';procedure SetHook; stdcall;external 'Hook.dll';procedure EndHook; stdcall;external 'Hook.dll';var
test: Ttest;implementation{$R *.dfm}procedure Ttest.FormDestroy(Sender: TObject);
begin
EndHook;
end;procedure Ttest.FormCreate(Sender: TObject);
var
H : THandle;
begin
SetAppHandled(Handle);
H:= FindWindow('Shell_TrayWnd',nil);
H :=Findwindowex(H,0,'ReBarWindow32',nil);//得到任务栏的句柄
H :=Findwindowex(H,0,'MSTaskSwWClass',nil);//得到任务栏的句柄
H :=Findwindowex(H,0,'ToolbarWindow32',nil);//得到任务栏的句柄
SetHandled(H);
SetHook;end;end.
上半段是HOOK.DLL的代码,下面的就是测试DLL的代码.
下面是各个函数的说明。
TGoData = record //这是一个结构,目的就是为了在内存中可以共享方便
TargetWnd : Hwnd;//目标的句柄。这里是任务栏的句柄
AppHwnd : THandle;//我的程序的句柄,目的是将程序的句柄加入去进行判断,但目前好像没有什么用处
ghHook : HHook;//这个不用说了吧?
end; MyHookProc//这个也不用说,关键来的 SetHook //这个为安装钩子的函数
EndHook //销掉钩子
SetAppHandled //将应用程序的句柄传入DLL
SetHandled //将目标句柄传入DLL
IntoShare//将GoData共享进内存里
我就是不知道如何在HOOK里得到句柄呀。我只是在自己的程序里给DLL传
个句柄而已。to:四大名捕之追杀令
好呀,你可以贴出来,或者发给我也可以。
大家一起探讨探讨,应该会有收获的!
[email protected]
HWND AppWindow;AnsiString HookClassName="THookSysMsgForm";
HINSTANCE hInst;
HHOOK KeyHookID=NULL,MouseHookID=NULL,CBTHookID=NULL;
static int i=0;TRect SysTab32Rect;
HWND HTaskBar;int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
HTaskBar=FindWindow("Shell_TrayWnd",NULL);
HTaskBar=FindWindowEx(HTaskBar,0,"ReBarWindow32",NULL);//得到任务栏的句柄
HTaskBar=FindWindowEx(HTaskBar,0,"MSTaskSwWClass",NULL);//得到任务栏的句柄
// HTaskBar =FindWindowEx(HTaskBar,0,"ToolbarWindow32",NULL);//得到任务栏的句柄
HTaskBar=FindWindowEx(HTaskBar,0,"SysTabControl32",NULL);
GetWindowRect(HTaskBar,&SysTab32Rect);
hInst=hinst;
//若BCB支持共享数据段,以下代码是不必要的。
if(reason==DLL_PROCESS_ATTACH) FindHookWindow();
return 1;
}void FindHookWindow()
{
HookWindowHandle=FindWindow(HookClassName.c_str(),NULL);
}LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam)
{
if(nCode<0) return CallNextHookEx(MouseHookID,nCode,wParam,lParam); //HookWindowHandle是安装Hook的主程序.
if(HookWindowHandle==NULL)
{
HookWindowHandle=FindWindow(HookClassName.c_str(),NULL);
AppWindow=GetWindow(HookWindowHandle,GW_OWNER);
} MOUSEHOOKSTRUCT *mst=(MOUSEHOOKSTRUCT*)lParam; if(mst->hwnd==HTaskBar && (int)wParam==WM_RBUTTONUP)
{
//*/
TTCHitTestInfo HitTest;
int ItemIndex;
TPoint P; P.x=mst->pt.x;
P.y=mst->pt.y;
::ScreenToClient(HTaskBar,&P); HitTest.pt.x=P.x;
HitTest.pt.y=P.y;
ItemIndex=TabCtrl_HitTest(HTaskBar, &HitTest); if(ItemIndex >= 0)//得到在鼠标第几个程序图标上单击的索引,经过测试,能正确得到索引
{
//SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)AnsiString("ItemIndex="+IntToStr(ItemIndex)).c_str()); TC_ITEM TabItem;
char TabTextBuf[1024]; ZeroMemory(TabTextBuf,sizeof(TabTextBuf)); TabItem.mask=TCIF_TEXT;
TabItem.pszText=(LPSTR)TabTextBuf;
TabItem.cchTextMax=sizeof(TabTextBuf); ///
char Buf[64];
HWND hTT=TabCtrl_GetToolTips(HTaskBar);
if(hTT!=NULL)
{
GetWindowText(hTT,Buf,64);
} if(TabCtrl_GetItem(HTaskBar,ItemIndex,&TabItem))
{
//经过测试,发现消息明明已经成功发送,为什么TabStr却为空????????? AnsiString TabStr=AnsiString(TabTextBuf);
SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)AnsiString(" ToolTip="+AnsiString(Buf)+" ItemIndex="+IntToStr(ItemIndex)+" TabStr="+TabStr).c_str());
/*/
if(TabStr=="我的程序")
{
TrackPopupMenu(....); // 显示自己的菜单
return 1; // 不再显示系统菜单。
}
//*/
}
else
{
SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)"Error Call");
}
}
//*/
} return 0;
}
//---------------------------------------------------------------------------
HWND AppWindow;AnsiString HookClassName="THookSysMsgForm";
HINSTANCE hInst;
HHOOK KeyHookID=NULL,MouseHookID=NULL,CBTHookID=NULL;
static int i=0;TRect SysTab32Rect;
HWND HTaskBar;int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
HTaskBar=FindWindow("Shell_TrayWnd",NULL);
HTaskBar=FindWindowEx(HTaskBar,0,"ReBarWindow32",NULL);//得到任务栏的句柄
HTaskBar=FindWindowEx(HTaskBar,0,"MSTaskSwWClass",NULL);//得到任务栏的句柄
// HTaskBar =FindWindowEx(HTaskBar,0,"ToolbarWindow32",NULL);//得到任务栏的句柄
HTaskBar=FindWindowEx(HTaskBar,0,"SysTabControl32",NULL);
GetWindowRect(HTaskBar,&SysTab32Rect);
hInst=hinst;
//若BCB支持共享数据段,以下代码是不必要的。
if(reason==DLL_PROCESS_ATTACH) FindHookWindow();
return 1;
}void FindHookWindow()
{
HookWindowHandle=FindWindow(HookClassName.c_str(),NULL);
}LRESULT CALLBACK MouseHook(int nCode,WPARAM wParam,LPARAM lParam)
{
if(nCode<0) return CallNextHookEx(MouseHookID,nCode,wParam,lParam); //HookWindowHandle是安装Hook的主程序.
if(HookWindowHandle==NULL)
{
HookWindowHandle=FindWindow(HookClassName.c_str(),NULL);
AppWindow=GetWindow(HookWindowHandle,GW_OWNER);
} MOUSEHOOKSTRUCT *mst=(MOUSEHOOKSTRUCT*)lParam; if(mst->hwnd==HTaskBar && (int)wParam==WM_RBUTTONUP)
{
//*/
TTCHitTestInfo HitTest;
int ItemIndex;
TPoint P; P.x=mst->pt.x;
P.y=mst->pt.y;
::ScreenToClient(HTaskBar,&P); HitTest.pt.x=P.x;
HitTest.pt.y=P.y;
ItemIndex=TabCtrl_HitTest(HTaskBar, &HitTest); if(ItemIndex >= 0)//得到在鼠标第几个程序图标上单击的索引,经过测试,能正确得到索引
{
//SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)AnsiString("ItemIndex="+IntToStr(ItemIndex)).c_str()); TC_ITEM TabItem;
char TabTextBuf[1024]; ZeroMemory(TabTextBuf,sizeof(TabTextBuf)); TabItem.mask=TCIF_TEXT;
TabItem.pszText=(LPSTR)TabTextBuf;
TabItem.cchTextMax=sizeof(TabTextBuf); ///
char Buf[64];
HWND hTT=TabCtrl_GetToolTips(HTaskBar);
if(hTT!=NULL)
{
GetWindowText(hTT,Buf,64);
} if(TabCtrl_GetItem(HTaskBar,ItemIndex,&TabItem))
{
//经过测试,发现消息明明已经成功发送,为什么TabStr却为空????????? AnsiString TabStr=AnsiString(TabTextBuf);
SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)AnsiString(" ToolTip="+AnsiString(Buf)+" ItemIndex="+IntToStr(ItemIndex)+" TabStr="+TabStr).c_str());
/*/
if(TabStr=="我的程序")
{
TrackPopupMenu(....); // 显示自己的菜单
return 1; // 不再显示系统菜单。
}
//*/
}
else
{
SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)"Error Call");
}
}
//*/
} return 0;
}
//---------------------------------------------------------------------------
if (PMouseHookStruct(lp)^.hwnd =GoData^.TargetWnd) then
begin
MessageBeep(0);
//关键就是在这里,应该如何判断呢? 你的这段程序是在你的程序中判断的,我认为WM_RBUTTONUP会引发系统的消息,如果你将其屏蔽的话,系统消息就会消失。
HitTest.pt.y:=P.y;
我在DELPHI 6里上面的代码出错,说HitTest的P.X为只读.
若不给它富值,则TabCtrl_HitTest的反回值始终为0.
而在D6里也没有TabCtrl_GetItem这个函数。
可能我对BCB不熟悉,看你的代码不清楚。
不知你可以 否将你的代码转为DELPHI 的呢?
var
HitTest: TTCHitTestInfo;
P: TPoint;
TabItem: TC_ITEM;
TabTextBuf: array[0..1023] of Char;begin
Result := ''; P.x := x;
P.y := y;
Windows.ScreenToClient(HTaskBar,P); HitTest.pt.x := P.x;
HitTest.pt.y := P.y;
ItemIndex := TabCtrl_HitTest(HTaskBar, @HitTest); if ItemIndex >= 0 then
begin
TabItem.mask := TCIF_TEXT;
TabItem.pszText := TabTextBuf;
TabItem.cchTextMax := sizeof(TabTextBuf); if SendMessage(HTaskBar, TCM_GETITEM, ItemIndex,Longint(@TabItem)) = 0 then
begin
Result := TabItem.pszText;
end;
end;
end;---------
if(mst->hwnd==HTaskBar && (int)wParam==WM_RBUTTONUP)
{
AnsiString TabStr;
int ItemIndex; TabStr=GetTabStr(HTaskBar,mst->pt.x,mst->pt.y,ItemIndex); SendMessage(HookWindowHandle,WM_SETTEXT,0,(LPARAM)AnsiString("ItemIndex="+IntToStr(ItemIndex)+" TabStr="+TabStr).c_str()); //........
}
return 0;
HTaskBar =FindWindowEx(HTaskBar,0,"ToolbarWindow32",NULL);呢?
如果我用SysTabControl32就得不到任务栏的消息了。
会不会是和操作系统有关?我用的是WINXP。再有,我在D6里试到执行:
ItemIndex := TabCtrl_HitTest(HTaskBar, @HitTest);时
ItemIndex的值都是0,这是为什么呢?
我贴出的代码是实际运行过的,我既然敢贴出代码,那肯定可以得到任务栏消息.你可以用WinSight查看一下,在MSTaskSwWClass下面只有SysTabControl32控件,没有ToolbarWindow32控件.2、不过为什么TabCtrl_HitTest返回值都是0,我用的是WIN2000,没有这个问题,难道是XP加强了安全性,不运行那样做? 建议你跟踪测试一下P变量的值得,
看看它是否正常。
用GetSystemMenu(Application.Handle,false)得到应用程序的系统菜单的句柄,用DeleteMenu和InsertMenu修改它,并编写自己的WM_SYSCOMMAND消息函数去响应它的消息。
用GetSystemMenu、DeleteMenu、InsertMenu不符合我的问题的要求.
可能真的操作系统的问题。
hook会严重降低系统性能,nullsoft
不会为了那么一个菜单就用hook。
http://www.csdn.net/Expert/TopicView1.asp?id=831786
不要担心,
我现在正在找WIN2000,找到了就装上。
之后我们就可以讨论了。如果不用HOOK,那NullSoft用的是什么呢?
不如大家找个Winamp 3来分析分析吧。
Shell接口有没有可能实现呢?
有兴趣的下载个WINAMP 3回来研究研究吧!
http://www8.pconline.com.cn/download/download.phtml?id=93720
AppendMenu(hMenuHandle,MF_POPUP,MySysMenu.Handle,'Hello');
几点说明:
1.请注意Application.Handle,一般在用GetSystemMenu的时候,很多人的做法是:
hMenuHandle:=GetSystemMenu(Form1.Handle,false);
而这个时候所取得的系统菜单是MainForm的,而不是任务按钮上的系统菜单!
2.MySysMenu是一个普通的popup menu
id=100
appendmenu(getsystemmenu(handle,false),mf_separator,0,'');//添加分割线(窗口的)
appendmenu(getsystemmenu(Application.handle,false),mf_separator,0,'');//添加分割线(任务栏的)
appendmenu(getsystemmenu(handle,false),mf_string,id,'&About');添加一行
appendmenu(getsystemmenu(application.handle,false),mf_string,id,'&About');添加一行
在formcreate中加入application.onmessage:=appmessage;处理消息
procedure tform1.appmessage(var msg:tmsg;var handled:boolean);
begin
if (msg.message=wm_syscommand) and (msg.wParam=id)then
begin
messagebox(handle,'you clicked about','about',0);
handled:=true;
end;
end;
这里讨论的不是这个,而是如何截住那个消息,在弹出菜单前把它钩住
然后做我想做的事,不一定要弹出菜单。
好不容易装了2000,发现2000和XP真的不同,一个是
SysTabControl32,一个是ToolbarWindow32。
在2000里ItenIndex的值能正确得到,可是TabStr的值不是空的就是
一个乱码。原因是什么呢?
对于ToolbarWindow32,又应该用什么函数呢?
TabItem.pszText := TabTextBuf;
TabItem.cchTextMax := sizeof(TabTextBuf);添加后永远为空.实在搞不懂,为什么消息能发送成功,结果却不对?
不过我加了
TabItem.pszText := TabTextBuf;
TabItem.cchTextMax := sizeof(TabTextBuf);
也会有乱码出现。希望有位高高手为我们指点迷律吧!