也许是win2k编程技术下的某个系统消息,象NC_

解决方案 »

  1.   

    Winamp 3可以实现这个功能的了。
      

  2.   

    SHAppBarMessage()或许是唯一的办法,我也没搞懂,看D5DG 807页,和WIN32API的帮助吧
      

  3.   

    谁有关于SHAppBarMessage()的资料?
      

  4.   

    我用HOOK已得到右键这个消息,
    但是就是不知道如何判断是在“我的程序”上
      

  5.   

    WINSHELLAPI UINT APIENTRY SHAppBarMessage(    DWORD dwMessage, 
        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.
      

  6.   

    那个地方实际是一个SysTabControl32控件,按理说截获它的窗口过程,然后处理消息WM_RUBTTONDOWN就可以了.不过奇怪地是我用WinSight监视了它的消息,当我在上面右击时,发现竟然没有WM_RBUTTONDOWN,WM_INITMENUPOPUP这些消息发送到它的窗口过程,那它是怎么显示那个菜单的?强烈关注!!!!!!!!
      

  7.   

    我用HOOK已得到右键这个消息,
    但是就是不知道如何判断是在“我的程序”上
    ------------------------------------
    使用TCM_GETITEM消息循环检测所有的Item,每一个Item都有一个字符串,检查那个字符串,看看是否是"我的程序"就可以了.
      

  8.   

    SHAppBarMessage好像不行。它不是干这一行的。
    找了一些资料,关于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.
      

  9.   

    代码不很长吧?
    上半段是HOOK.DLL的代码,下面的就是测试DLL的代码.
    下面是各个函数的说明。
    TGoData = record //这是一个结构,目的就是为了在内存中可以共享方便
        TargetWnd : Hwnd;//目标的句柄。这里是任务栏的句柄
        AppHwnd : THandle;//我的程序的句柄,目的是将程序的句柄加入去进行判断,但目前好像没有什么用处
        ghHook : HHook;//这个不用说了吧?
      end;  MyHookProc//这个也不用说,关键来的  SetHook //这个为安装钩子的函数
      EndHook //销掉钩子
      SetAppHandled //将应用程序的句柄传入DLL
      SetHandled //将目标句柄传入DLL 
    IntoShare//将GoData共享进内存里
      

  10.   

    使用消息TCM_GEITEM出现一点问题,想把我的代码贴出来和你一起探讨,愿意吗?
      

  11.   

    to:小网虫_L:我不是高手呀。我知道如果得到句柄就可以得到程序名。
    我就是不知道如何在HOOK里得到句柄呀。我只是在自己的程序里给DLL传
    个句柄而已。to:四大名捕之追杀令 
    好呀,你可以贴出来,或者发给我也可以。
    大家一起探讨探讨,应该会有收获的!
    [email protected]
      

  12.   

    下面是我的BCB代码(只贴出关键部分,其它免了),请指正:HWND HookWindowHandle;
    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;
    }
    //---------------------------------------------------------------------------
      

  13.   

    下面是我的BCB代码(只贴出关键部分,其它免了),请指正:HWND HookWindowHandle;
    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;
    }
    //---------------------------------------------------------------------------
      

  14.   

    if wP = WM_RBUTTONUP then
          if  (PMouseHookStruct(lp)^.hwnd   =GoData^.TargetWnd)  then
          begin
            MessageBeep(0);
            //关键就是在这里,应该如何判断呢?    你的这段程序是在你的程序中判断的,我认为WM_RBUTTONUP会引发系统的消息,如果你将其屏蔽的话,系统消息就会消失。
      

  15.   

    HitTest.pt.x:=P.x; 
    HitTest.pt.y:=P.y;
    我在DELPHI 6里上面的代码出错,说HitTest的P.X为只读.
    若不给它富值,则TabCtrl_HitTest的反回值始终为0.
    而在D6里也没有TabCtrl_GetItem这个函数。
    可能我对BCB不熟悉,看你的代码不清楚。
    不知你可以 否将你的代码转为DELPHI 的呢?
      

  16.   

    费了好大劲,才把它改成一个Delphi函数:function GetTabStr(HTaskBar:HWND; x:integer; y:integer; var ItemIndex:integer):String;
    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;
      

  17.   

    试过了,有个疑问,你为什么用:HTaskBar=FindWindowEx(HTaskBar,0,"SysTabControl32",NULL);而不用
    HTaskBar =FindWindowEx(HTaskBar,0,"ToolbarWindow32",NULL);呢?
    如果我用SysTabControl32就得不到任务栏的消息了。
    会不会是和操作系统有关?我用的是WINXP。再有,我在D6里试到执行:
    ItemIndex := TabCtrl_HitTest(HTaskBar, @HitTest);时
    ItemIndex的值都是0,这是为什么呢?
      

  18.   

    1、
    我贴出的代码是实际运行过的,我既然敢贴出代码,那肯定可以得到任务栏消息.你可以用WinSight查看一下,在MSTaskSwWClass下面只有SysTabControl32控件,没有ToolbarWindow32控件.2、不过为什么TabCtrl_HitTest返回值都是0,我用的是WIN2000,没有这个问题,难道是XP加强了安全性,不运行那样做? 建议你跟踪测试一下P变量的值得,
    看看它是否正常。
      

  19.   

    你不就是要修改系统菜单吗?不用那么复杂:
    用GetSystemMenu(Application.Handle,false)得到应用程序的系统菜单的句柄,用DeleteMenu和InsertMenu修改它,并编写自己的WM_SYSCOMMAND消息函数去响应它的消息。
      

  20.   

    我要的不是结果,而是实现的方法。
    用GetSystemMenu、DeleteMenu、InsertMenu不符合我的问题的要求.
      

  21.   

    我用WinSight查看在MSTaskSwWClass下面有ToolbarWindow32。
    可能真的操作系统的问题。
      

  22.   

    TabCtrl_HitTest是针对SysTabControl32的,XP没有这个控件只有ToolbarWindow32控件,怎么办?? 我们还怎么互相讨论?????????郁闷中.....
      

  23.   

    TabCtrl_HitTest是针对SysTabControl32的,XP没有这个控件只有ToolbarWindow32控件,怎么办?? 我们还怎么互相讨论?????????郁闷中.....
      

  24.   

    怎么说,绝对是不可能用hook的,
    hook会严重降低系统性能,nullsoft
    不会为了那么一个菜单就用hook。
      

  25.   

    up我没分了,请朋友们帮我回答一下这个好吗?谢谢了。
    http://www.csdn.net/Expert/TopicView1.asp?id=831786
      

  26.   

    to:四大名捕之追杀令
    不要担心,
    我现在正在找WIN2000,找到了就装上。
    之后我们就可以讨论了。如果不用HOOK,那NullSoft用的是什么呢?
    不如大家找个Winamp 3来分析分析吧。
      

  27.   

    不用担心,我现在正在找WIN2000,找到了我装上就可以再继续讨论了。如果NullSoft不用HOOK,那用什么呢?
    Shell接口有没有可能实现呢?
    有兴趣的下载个WINAMP 3回来研究研究吧!
    http://www8.pconline.com.cn/download/download.phtml?id=93720
      

  28.   

    大家都走偏了,这个应该你们想要的:  hMenuHandle:=GetSystemMenu(Application.Handle,false);
      AppendMenu(hMenuHandle,MF_POPUP,MySysMenu.Handle,'Hello');
      
    几点说明:
    1.请注意Application.Handle,一般在用GetSystemMenu的时候,很多人的做法是:
    hMenuHandle:=GetSystemMenu(Form1.Handle,false);  
    而这个时候所取得的系统菜单是MainForm的,而不是任务按钮上的系统菜单!
    2.MySysMenu是一个普通的popup menu
      

  29.   

    只需要修改你程序的系统菜单即可
    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;
      

  30.   

    用getsystemmenu,appendmenu等这些API函数我也会。
    这里讨论的不是这个,而是如何截住那个消息,在弹出菜单前把它钩住
    然后做我想做的事,不一定要弹出菜单。
    好不容易装了2000,发现2000和XP真的不同,一个是
    SysTabControl32,一个是ToolbarWindow32。
    在2000里ItenIndex的值能正确得到,可是TabStr的值不是空的就是
    一个乱码。原因是什么呢?
    对于ToolbarWindow32,又应该用什么函数呢?
      

  31.   

    我第一次没有添加下面语句时也出现乱妈
    TabItem.pszText := TabTextBuf;
    TabItem.cchTextMax := sizeof(TabTextBuf);添加后永远为空.实在搞不懂,为什么消息能发送成功,结果却不对?
      

  32.   

    今天也搞了一天,还是不行。
    不过我加了
    TabItem.pszText := TabTextBuf;
    TabItem.cchTextMax := sizeof(TabTextBuf);
    也会有乱码出现。希望有位高高手为我们指点迷律吧!