认为是API高手的才入吧,到目前还没有办法解决的! (200分)

  • 主题发起人 主题发起人 lfpsoft
  • 开始时间 开始时间
L

lfpsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
如下图:例如任务栏上有“Delphi 6"、"我的程序”、“12.片片枫叶情 - ...”这三项。<br>在我的程序里如何知道鼠标是在其中的一项里,并且得到按的是右键或是左键呢?<br>我的最终的目的就是如果鼠标是在“我的程序”上,如果按下的是右键,系统就会弹出<br>一个系统级的菜单,我就是要屏闭它,弹出的是自己的菜单或者响应我的其他的事件。<br>不要说使用InsertMenu等添加或修改系统的菜单,这个我都会。<br><br>
20026232340324121.jpg
 
Applicaton的OnMessage不知道能不能捕获这个消息<br><br>-----<br>http://www.8421.org
 
不能,我用HOOK已得到这个消息,但是就是不知道如何判断是在“我的程序”上
 
有点难度<br>试试那些shell接口吧
 
你研究一下TabControl吧,或许能有帮助。我觉得可以通过向他发送消息来<br>获得需要的数据
 
你是不是一定需要在任务栏上显示你的程序,如果不需要的话,<br>在 FormCreate 加 &nbsp;SetWindowLong( Application.Handle, GWL_EXSTYLE,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;GetWindowLong(Application.Handle, GWL_EXSTYLE) or<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);<br>就可以隐藏任务栏图标
 
因为WINAMP 3可以在任务栏上弹出自己画的菜单,并不是系统的菜单<br>我想VC能做的,DELPHI应该也可以做吧。为了求个明白,不惜失去200分呀。<br>如果能做出来,还可以加分!
 
到这里看看吧!我在这里也问了这个问题<br>http://www.csdn.net/Expert/TopicView1.asp?id=825020
 
这个菜单应该是Application对象的系统菜单,很难替换。<br>winamp是VC做的,没有跟Delphi一样的Application窗口,显示的直接就是主窗口,<br>也就是说,弹出的是主窗口的菜单。<br><br>我做不出来,不过知道这些理由。
 
但WINAMP3 的菜单是自己画的,并不是系统的菜单.<br>既然VC能做,DELPHI就不能做了?
 
Delphi应该也能做,截取WM_SYSCOMMAND消息,弹出自己的菜单。
 
那个菜单就是系统菜单,只不过Winamp做了些手脚而已。用得着这么麻烦吗?<br>int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)<br>{<br> if (CFrameWnd::OnCreate(lpCreateStruct) == -1)<br> return -1;<br><br>&nbsp; &nbsp; CMenu* pMenu = GetSystemMenu(FALSE);<br>&nbsp; &nbsp; ASSERT(pMenu);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_MOVE, MF_BYCOMMAND);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_SIZE, MF_BYCOMMAND);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_RESTORE, MF_BYCOMMAND);<br>&nbsp; &nbsp; // pMenu-&gt;ModifyMenu(SC_CLOSE, MF_BYCOMMAND | MF_OWNERDRAW, SC_CLOSE, (LPCTSTR)NULL);<br>&nbsp; &nbsp; pMenu-&gt;DeleteMenu(SC_CLOSE, MF_BYCOMMAND);<br>&nbsp; &nbsp; pMenu-&gt;AppendMenu(MF_OWNERDRAW, MyMenuID, (LPCTSTR)NULL);<br> return 0;<br>}<br>然后自己处理WM_MEASUREITEM和WM_DRAWITEM就是了。
 
下载个WINAMP3看下是不是像你们说的那样吧。<br>http://www8.pconline.com.cn/download/download.phtml?id=93720
 
这个应该是你想要的,试了之后再说好不好用[:)]:<br><br>&nbsp; hMenuHandle:=GetSystemMenu([red]Application.Handle[/red],false);<br>&nbsp; AppendMenu(hMenuHandle,MF_POPUP,[blue]MySysMenu[/blue].Handle,'Hello');<br>&nbsp; <br>几点说明:<br>1.请注意红色部分的代码,一般在用GetSystemMenu的时候,很多人的做法是:<br> hMenuHandle:=GetSystemMenu(Form1.Handle,false); &nbsp;<br> 而这个时候所取得的系统菜单是MainForm的,而[red]不是[/red]任务按钮上的系统菜单!<br>2.MySysMenu是一个普通的popup menu<br>
 
谢谢manfeel,如果只是为了弹出的菜单,你的是对的,我以前也用过这种方法。<br>但是我想要的就是如何得到这个消息,然后截住它,做我想做的事。<br>不一定要弹出菜单。
 
定制任务栏上的系统菜单 <br>云南昆明市 <br>吴中卫 <br>---- 通常,当我们在特定的场合或是在多应用的环境运行自己或其他的应用程序时,会在多窗口之间进行频繁的切换,以实施实时的交互得到所期望的结果,对于这样的“笨”办法,我们会不厌其烦地进行好多次,甚至是无数次。好在 Win 9x 在任务栏上显示了我们所运行或期望的程序,并配备了相应的右键系统弹出菜单,使我们在使用时方便多了。问题是那些都是缺省的系统菜单(命令),对于我们来说没有太大的帮助,下面我所介绍的就是利用 Win9x 为我们设定的任务栏系统菜单来达到快速、简捷的获取信息(执行命令)的目的。 <br><br>---- 提到系统菜单,就让我们联想到底层的 WIN32 系统调用:AppendMenu、Inert-Menu、ModifyMenu。仅此三个函数,就足可以让我们对缺省的系统菜单进行定制,应用自如了。为简单起见,本文就 AppendMenu 进行一些介绍,其余的请朋友们参见 WIN32API 帮助文件。 <br><br>&nbsp; &nbsp; 以下是 AppendMenu 函数原型: <br>&nbsp; &nbsp; BOOL AppendMenu(<br>&nbsp; &nbsp; HMENU hMenu, // 要定制的菜单句柄<br>&nbsp; &nbsp; UINT uFlags, // 怎样定制菜单项<br>&nbsp; &nbsp; UINT uIDNewItem, // 要定制的菜单项标识或子菜单句柄<br>&nbsp; &nbsp; LPCTSTR lpNewItem // 要定制的菜单项(字串)<br>&nbsp; &nbsp; );<br><br>---- 在 AppendMenu 函数里,lpNewItem 和 uIDNewItem 参数依赖 uFlags 的不同标志而有所变化,让我们来看一看 uFlags 到底有那一些定义值: <br><br>MF_BITMAP 指明该菜单项是一位图,在 lpNewItem 参数代表位图句柄<br>MF_CHECKED 在菜单项的前面放上一个“选中”标记<br>MF_DISABLED 屏蔽该菜单项,但不象平常那样变成灰色<br>MF_ENABLED 与 MF_DISABLED 相反<br>MF_GRAYED 除了有 MF_DISABLED 的作用以外,还把该菜单项变灰<br>MF_MENUBREAK &nbsp;把该菜单与现有菜单并排放在一起<br>MF_MENUBARBREAK &nbsp;与 MF_MENUBREAK 相同,除了在中间放一条竖线外<br>MF_OWNERDRAW 表明该菜单项为自绘菜单项,还必须处理一切的显示、更新<br>&nbsp;问题<br>MF_POPUP 该菜单项为一子菜单,uIDNewItem 参数代表其句柄<br>MF_SEPARATOR 与上一菜单项画上一分割线,系统将忽略 lpNewItem 和 <br>&nbsp;uIDNewItem 参数<br>MF_STRING 该菜单项是一文本字串,lpNewItem 是其内容<br>MF_UNCHECKED 取消该菜单项前面的“选中”标记<br><br>---- 我们看到,除了 MF_POPUP,MF_BITMAP,MF_OWNERDRAW 以外,MF_STRING 是最常用的菜单项定义方法,uIDNewItem 在这里是命令消息的 wParam 参数。朋友们还记得获取普通菜单的句柄用 GetMenu, 那么获取系统菜单的句柄就应该用 GetSyst-emMenu。这时有一个问题:程序怎么知道该获取的系统菜单是窗口上的系统菜单,还是任务栏上的系统菜单呢?这就依靠传递给 GetSystemMenu 的是哪一个参数。因为我们当前考虑的是任务栏,因此这个参数就必须是 Application.Handle。 <br>---- 如果这时候就着手编制一个 Project 检验一下,朋友们就会发现...“我”定义的菜单怎么没有反应!原来该菜单项根本没有在 Application 里处理过。显然,我们还得过滤一下传到 Application 的 WM_SYSCOMMAND 消息。 <br><br>---- 为了加深了解,我们首先追加一个简单的任务栏系统菜单: <br><br>&nbsp; &nbsp; Unit AddMenuDemo;<br>&nbsp; &nbsp; interface<br><br>uses Windows, Messages, SysUtils, Classes, <br>Graphics, Controls, Forms,<br>&nbsp; &nbsp; Dialogs,Menus;<br><br>&nbsp; &nbsp; type<br>&nbsp; &nbsp; &nbsp; &nbsp;TDemoForm = class(TForm)<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; &nbsp; private<br>&nbsp; &nbsp; &nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 我的消息过滤器<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;procedure OnAppMessage<br>(var Msg: TMsg; var Handled: Boolean);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; &nbsp; public<br>&nbsp; &nbsp; &nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; &nbsp;end;<br><br>&nbsp; &nbsp; var<br>&nbsp; &nbsp; &nbsp; &nbsp;DemoForm1: TDemoForm;<br><br>&nbsp; &nbsp; implementation<br><br>&nbsp; &nbsp; const<br>&nbsp; &nbsp; &nbsp; My_SimpleCMD1 = WM_USER + 1; <br>&nbsp; &nbsp; &nbsp;// 定义三个用户消息,用来处理菜单项被点击<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp;// 时相应的动作<br>&nbsp; &nbsp; &nbsp; My_SimpleCMD2 = WM_USER + 2;<br>&nbsp; &nbsp; &nbsp; My_SimpleCMD3 = WM_USER + 3;<br>&nbsp; &nbsp; ...<br><br>&nbsp; &nbsp; procedure TDemoForm1.FormCreate(Sender: TObject);<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp;Application.OnMessage := OnAppMessage; <br>&nbsp; &nbsp; &nbsp;//定义自己的消息处理过程<br><br>&nbsp; &nbsp; &nbsp;//定义了提交、反馈、处理三个菜单项<br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu<br>(Application.Handle, FALSE),MF_STRING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; My_SimpleCMD1,'提交');<br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu<br>(Application.Handle, FALSE),MF_STRING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; My_SimpleCMD2,'反馈');<br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu<br>(Application.Handle, FALSE),MF_SEPARATOR,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0, ''); // 定义一分割线<br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu<br>(Application.Handle, FALSE),MF_STRING,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; My_SimpleCMD3,'处理');<br>&nbsp; &nbsp; end; &nbsp;<br><br>procedure TDemoForm1.OnAppMessage<br>(var Msg: TMsg; var Handled: Boolean);<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp;// 定制自己的消息处理过程<br>&nbsp; &nbsp; &nbsp;if (Msg.message = WM_SYSCOMMAND) and <br>(Msg.wParam = My_SimpleCMD1) then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; ShowMessage('正在提交...');<br>&nbsp; &nbsp; &nbsp; &nbsp; Handled := True;<br>&nbsp; &nbsp; &nbsp; &nbsp; ...<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp;if (Msg.message = WM_SYSCOMMAND) and <br>(Msg.wParam = My_SimpleCMD2) then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; ShowMessage('正在反馈...');<br>&nbsp; &nbsp; &nbsp; &nbsp; Handled := True;<br>&nbsp; &nbsp; &nbsp; &nbsp; ...<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp;if (Msg.message = WM_SYSCOMMAND) and <br>(Msg.wParam = My_SimpleCMD3) then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; &nbsp; ShowMessage('正在处理...');<br>&nbsp; &nbsp; &nbsp; &nbsp; Handled := True;<br>&nbsp; &nbsp; &nbsp; &nbsp; ...<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp; ....<br><br>---- 当我们处理的事务比较多并且可分组,以上的做法就比较烦琐,这时就应该定义成多个 MF_POPUP ,其各个子菜单除了 uIDNewItem 传递这个子菜单的句柄外,另外独特之处在于消息过滤器的 Msg.wParam 是各个菜单项的 Command。这个 Command是在构建 TPopupMenu 时就定义了的。无论是否是 MenuItem 或 PopupMenu,其Command的值都是顺序递增的。以下是一范例: <br><br>&nbsp; &nbsp; &nbsp;unit Unit1;<br><br>&nbsp; &nbsp; &nbsp;interface<br><br>&nbsp; &nbsp; &nbsp;uses &nbsp;Windows, Messages, SysUtils, <br>Classes, Graphics, Controls, Forms, <br>&nbsp; &nbsp; &nbsp;Dialogs, Menus;<br><br>&nbsp; &nbsp; &nbsp;type<br>&nbsp; &nbsp; &nbsp; TForm1 = class(TForm)<br> PopupMenu1: TPopupMenu;<br> N1: TMenuItem; &nbsp;// Caption := '范例一';<br> N2: TMenuItem; &nbsp;// Caption := '范例二';<br> N3: TMenuItem; &nbsp;// Caption := '范例三';<br> procedure FormCreate(Sender: TObject);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; private<br>&nbsp; &nbsp; &nbsp; &nbsp; { Private declarations }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 我的消息过滤器<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;procedure OnAppMessage<br>(var Msg: TMsg; var Handled: Boolean);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; public<br>&nbsp; &nbsp; &nbsp; &nbsp; { Public declarations }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; ...<br><br>&nbsp; &nbsp; &nbsp;var<br>&nbsp; &nbsp; &nbsp; Form1: TForm1;<br><br>&nbsp; &nbsp; implementation<br>&nbsp; &nbsp; {$R *.DFM}<br><br>&nbsp; &nbsp; procedure TForm1.FormCreate(Sender: TObject);<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp;Application.OnMessage := OnAppMessage; <br>&nbsp; &nbsp; &nbsp;//定义自己的消息处理过程<br><br>&nbsp; &nbsp; &nbsp;// 定义一分割线 &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu(Application.Handle,<br>&nbsp;FALSE), MF_SEPARATOR, 0, '');<br><br>&nbsp; &nbsp; &nbsp;// 定义'提交'子菜单<br>&nbsp; &nbsp; &nbsp;AppendMenu(GetSystemMenu<br>(Application.Handle, FALSE), MF_POPUP,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PopupMenu1.Handle,'提交');<br>&nbsp; &nbsp; end;<br><br>procedure TForm1.OnAppMessage<br>(var Msg: TMsg; var Handled: Boolean);<br>&nbsp; &nbsp; begin<br><br>&nbsp; &nbsp; &nbsp;// 定制自己的消息处理过程<br>&nbsp; &nbsp; &nbsp;if (Msg.message = WM_SYSCOMMAND) <br>AND (Msg.wParam &lt; WM_USER) then<br>&nbsp; &nbsp; &nbsp;begin<br>&nbsp; &nbsp; &nbsp; Case Msg.wParam of<br>&nbsp; &nbsp; &nbsp; &nbsp; // N1.Command = 1<br>&nbsp; &nbsp; &nbsp; &nbsp; 1:ShowMessage<br>('范例一 Command:'+ IntToStr(N1.Command));<br>&nbsp; &nbsp; &nbsp; &nbsp; // N1.Command = 2<br>&nbsp; &nbsp; &nbsp; &nbsp; 2:ShowMessage<br>('范例二 Command:'+ IntToStr(N2.Command));<br>&nbsp; &nbsp; &nbsp; &nbsp; // N1.Command = 3<br>&nbsp; &nbsp; &nbsp; &nbsp; 3:ShowMessage<br>('范例三 Command:'+ IntToStr(N3.Command));<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; &nbsp; &nbsp; Handled := True;<br>&nbsp; &nbsp; &nbsp;end;<br>&nbsp; &nbsp; &nbsp;...<br>&nbsp; &nbsp; end;<br><br><br>---- 可以看出,MF_STRING 与 MF_POPUP 在消息处理机制上是稍微有点不同的,另外如果要在菜单前面加上图标的话,这在 Delphi 4.x、Delphi 5.x 版本下是不成问题,如果是在 Delphi 3.x 下的话,只要定义成自绘 MenuItem 即可,不过稍许复杂了一点。在应用过程中,需要提醒的是,这几组定义是不能一起使用: <br>* &nbsp;A. MF_DISABLED, MF_ENABLED, 和 MF_GRAYED <br>* &nbsp;B. MF_BITMAP, MF_STRING, 和 MF_OWNERDRAW <br>* &nbsp;C. MF_MENUBARBREAK 和 MF_MENUBREAK <br>* &nbsp;D. MF_CHECKED 和 MF_UNCHECKED &nbsp; <br><br>可能晚了
 
To : lfpsoft<br><br>已向你发了电子邮件,注意接收。
 
感谢BCB_FANS!<br>问题已得到解决!<br><br>http://bbs.soft163.com/uploadImages/2002772034334754.zip
 
后退
顶部