关于HOOK的,已有点眉目了,进来看看,不会也UP下! 能解决的再加100大元 (40分)

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

lfpsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
如果用过WINAMP3的都知道,在Winamp 3中当右击任务栏的窗口标题时出现的不再是
系统的关闭,最小化,最大化,还原这几项的菜单,而是自己的菜单。
不知道在DELPHI里如何做也可以实现呢?
注意,不是在系统的菜单上添加自己的菜单项,而是弹出自己的菜单项。
 
UP下吧!
 
我猜:
没用标题栏吧
自己做的类似标题栏的的IMAGE?
 
贴一篇文章,也许是你要的:

----------------------------------------------
①、 如 何 把 用 户 菜 单 项 加 入 系 统
菜 单, ②、 如 何 才 能 响 应 这 一 菜 单 项。

---- 要 解 决 第 一 个 问 题, 就 需 要 获 取 系 统 菜 单 的 句 柄, 这 一 点 可 用 API 函 数
getsystemmenu() 来 获 取(getmenu() 只 能 获 取 用 户 菜 单 句 柄), 有 了 系 统 菜 单 句 柄, 便
可 以 用 API 函 数appendmenu() 向 系 统 菜 单 中 加 入 用 户 菜 单 选 项 了。

---- 要 解 决 第 二 个 问 题, 需 要 重 载 WM_SYSCOMMAND 或WM_MENUSELECT 消 息。 我 们
知 道, 当 用 户 从 菜 单 中 选 一 项 时, 系 统 便 会 发 出 WM_COMMMAND 消 息, 而 对
于 系 统 菜 单, 则 会 发 出 WM_SYSCOMMAND 消 息, 重 载 这 个 消 息, 并 判 断 选 中 菜
单 的 ID 值 是 否 为 用 户 设 定 值 便 可 以 了。Delphi 为 我 们 提 供 了 这 方 面 的 机 制, 使
我 们 能 方 便 的 实 现 这 一 功 能。 当 然, 为 实 现 这 一 功 能 我 们 还 可 以 利 用 子 类
或 为 系 统 加 消 息 钩 子 的 方 法 来 解 决。

---- 为 了 便 于 实 现, 在 这 里, 我 们 采 用 重 载 WM_SYSCOMMAND 消 息 和 填 写
WM_MENUSELECT 消 息 结 构 的 方 法 来 实 现 这 一 功 能。

---- 下 面 为 笔 者 为 实 现 这 一 功 能 而 开 发 的 实 例。

---- 程 序 在Delphi ver 1.0 下 调 试 通 过。

program Psysmenu;
uses
Forms,
Sysmenu in '/SYSMENU.PAS' {Form1};

{$R *.RES}
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

unit Sysmenu;

interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes,
Graphics, Controls,Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
procedure user_sysmenu(var msg:twmmenuselect);
message wm_syscommand;

public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}

procedure TForm1.user_sysmenu(var msg:TWMMENUSELECT);
begin
if msg.iditem=100 then
showmessage(' 响应系统菜单!')
{ 也 可 以setwindowpos()来实现处于最前端功能}
else
inherited; { 作缺省处理,必须调用这一过程}
end;

procedure TForm1.FormCreate(Sender: TObject);
var hmenu:integer;
begin
hmenu:=getsystemmenu(handle,false);
{获取系统菜单句柄}
appendmenu(hmenu,MF_SEPARATOR,0,nil);
appendmenu(hmenu,MF_STRING,100,'加入系统菜单');
{加入用户菜单}
end;
end.
////////////////////////////////////////////////////
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure WMSysCommand(var Msg: TWMSysCommand);
message WM_SYSCOMMAND;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

const
SC_MyMenuItem = WM_USER + 1;

procedure TForm1.FormCreate(Sender: TObject);
begin
AppendMenu(GetSystemMenu(Handle, FALSE), MF_SEPARATOR, 0, '');
AppendMenu(GetSystemMenu(Handle, FALSE),
MF_STRING,
SC_MyMenuItem,
'My Menu Item');
end;

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = SC_MyMenuItem then
ShowMessage('Got the message') else
inherited;
end;
////////////////////////////////////////////////////////
这个过程可以:
procedure AppendToSystemMenu (Form: TForm;
Item: string; ItemID: Word);
{----------------------------------------------------------------}
{ Appends menu item to end of system menu of specified form and }
{ to system menu of application's minimized icon. To append a }
{ separator bar start the item with '-' (and use 0 for ItemID). }
{----------------------------------------------------------------}
var
NormalSysMenu, MinimizedMenu: HMenu;
AItem: array[0..255] of Char;
PItem: PChar;
begin
NormalSysMenu := GetSystemMenu(Form.Handle, false);

MinimizedMenu := GetSystemMenu(Application.Handle, false);
if StartsWith('-', Item) then
AppendMenu(NormalSysMenu, MF_SEPARATOR, 0, nil);
AppendMenu(MinimizedMenu, MF_SEPARATOR, 0, nil);
end
else
begin
PItem := StrPCopy(PChar(@AItem), Item);
AppendMenu(NormalSysMenu, MF_STRING, ItemID, PItem);
AppendMenu(MinimizedMenu, MF_STRING, ItemID, PItem);
end
end; {AppendToSystemMenu}
过程是如下定义:
function StartsWith (const StartString, theString: string)

: Boolean;
{-----------------------------------------------------------------}
{ Tests whether or not theString starts with the StartString. }
{ N.B. Case sensitive. }
{----------------------------------------------------------------}
begin
if Copy(theString, 1, length(StartString)) = StartString then
StartsWith := True
else
StartsWith := False
end; {StartsWith}
建立新FORM
type
TForm1 = class(TForm)
private
{ Private declarations }
public
procedure WinMsgHandler( var Msg : TMsg; var Handled : Boolean );

{ Public declarations }
end;
const
WM_ABOUT = WM_USER + 1; { About message }
IMPLEMENTATION
procedure TForm1.WinMsgHandler( var Msg : TMsg; var Handled : Boolean );
begin
If Msg.Message = WM_SYSCOMMAND then begin
if Msg.wParam = WM_ABOUT then Showmessage('Hello World!!');
end;
end;
你必须在窗体中加入以下方法:
Application.OnMessage := WinMsgHandler; {Use my message handler}
AppendMenu( GetSystemMenu( Self.Handle, False ),
MF_SEPARATOR, 0, ''); {Append our new value}
AppendMenu( GetSystemMenu(
rm1.FormCreate(Sender: TObject);

begin
AppendMenu(GetSystemMenu(Handle, False), { API call; see API Help }
MF_STRING, SC_UDF, '&About');
AppendMenu(GetSystemMenu(Application.Handle, False),
MF_STRING, SC_UDF, '&About');
Application.OnMessage := AppOnMessage;
end;
procedure TForm1.AppOnMessage(VAR Msg: TMsg; VAR Handled: BOolean);
VAR
Hf, Ha : hMenu;
Checkd : Boolean;
CONST
NuFlag : ARRAY[Boolean] OF Word = (MF_CHECKED, MF_UNCHECKED);
NuHWnd : ARRAY[Boolean] OF HWnd = (HWND_TOPMOST, HWND_NOTOPMOST);
BEGIN
IF Msg.Message WM_SYSCOMMAND THEN Exit;

IF Msg.wParam AND $FFF0 SC_UDF THEN Exit;
{ show your About Dialog }
END;
end.
 
她应该用的不是系统的标题兰而是自己作的
 
winamp是自已做的标题栏吧
 
我说的是指在windows开始菜单右边的任务栏上显示各个窗体CAPTION那里,击右键会
出现一条菜单,一般的DELPHI编译的程序只有最小化,还原,关闭这三项,而不是窗体
的标题栏。

而levinqm你的方法是在系统菜单项上加自己的菜单,这个方法我也会。
我想实现的是程序里做一个POPUPMENU,一按它就弹出POPUPMENU,而不是系统定理
的那几个菜单项。
 
我贴了张图,请各位看看。
如果有对其中的那个动画效果有兴趣的,大家一起研究下是如何实现也好呀!

200261614414852589.jpg

 
这样的效果,Mastering Delphi6有讲,贴一个瞧瞧

unit sysform;

interface

uses
SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs,
Menus, StdCtrls, AppEvnts;

type
TForm1 = class(TForm)
Button1: TButton;
MainMenu1: TMainMenu;
File1: TMenuItem;
Exit1: TMenuItem;
Edit1: TMenuItem;
Undo1: TMenuItem;
N1: TMenuItem;
Cut1: TMenuItem;
Copy1: TMenuItem;
Paste1: TMenuItem;
Help1: TMenuItem;
About1: TMenuItem;
New1: TMenuItem;
Open1: TMenuItem;
N2: TMenuItem;
ApplicationEvents1: TApplicationEvents;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure New1Click(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure Exit1Click(Sender: TObject);
procedure Undo1Click(Sender: TObject);
procedure Cut1Click(Sender: TObject);
procedure Copy1Click(Sender: TObject);
procedure Paste1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
public
procedure WMSysCommand (var Msg: TWMSysCommand);
message wm_SysCommand;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

const
idSysAbout = 100;

procedure TForm1.FormCreate(Sender: TObject);
begin
// add a separator and a menu item to the system menu
AppendMenu (GetSystemMenu (Handle, FALSE),
MF_SEPARATOR, 0, '');
AppendMenu (GetSystemMenu (Handle, FALSE),
MF_STRING, idSysAbout, '&About...');

// add the same items to the application system menu
AppendMenu (GetSystemMenu (Application.Handle, FALSE),
MF_SEPARATOR, 0, '');
AppendMenu (GetSystemMenu (Application.Handle, FALSE),
MF_STRING, idSysAbout, '&About...');
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if (Msg.Message = wm_SysCommand) and
(Msg.wParam = idSysAbout) then
begin
ShowMessage ('Mastering Delphi: SysMenu2 example');
Handled := True;
end;
end;

procedure TForm1.WMSysCommand (var Msg: TWMSysCommand);
var
Item: TMenuItem;
begin
// handle a specific command
if Msg.CmdType = idSysAbout then
ShowMessage ('Mastering Delphi: SysMenu2 example');

// activate standard menu handling code
Item := MainMenu1.FindItem (Msg.CmdType, fkCommand);
if not (Item = nil) then
Item.Click;

// default system menu commands
inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
// add a separator
AppendMenu (GetSystemMenu (Handle, FALSE), MF_SEPARATOR, 0, '');
// add the main menu to the system menu
with MainMenu1 do
for I := 0 to Items.Count - 1 do
AppendMenu (GetSystemMenu (Self.Handle, FALSE),
mf_Popup, Items.Handle, PChar (Items.Caption));
// disable the button
Button1.Enabled := False;
end;

procedure TForm1.New1Click(Sender: TObject);
begin
ShowMessage ('File New menu command');
end;

procedure TForm1.Open1Click(Sender: TObject);
begin
ShowMessage ('File Open menu command');
end;

procedure TForm1.Exit1Click(Sender: TObject);
begin
Close;
end;

procedure TForm1.Undo1Click(Sender: TObject);
begin
ShowMessage ('Edit Undo menu command');
end;

procedure TForm1.Cut1Click(Sender: TObject);
begin
ShowMessage ('Edit Cut menu command');
end;

procedure TForm1.Copy1Click(Sender: TObject);
begin
ShowMessage ('Edit Copy menu command');
end;

procedure TForm1.Paste1Click(Sender: TObject);
begin
ShowMessage ('Edit Paste menu command');
end;

procedure TForm1.About1Click(Sender: TObject);
begin
ShowMessage ('Mastering Delphi: SysMenu2 example');
end;

end.
 
我自认为是个菜鸟,但这个问题不太难,先找一个控件(TCoolTrayIcon)或自己调API也行,但功能可能没那么强大,
在你的主窗体中加入TCoolTrayIcon及弹出菜单,关联TCoolTrayIcon及弹出菜单,在TCoolTrayIcon的CLIC中K事件中加入你的代码就行。
 
可能是我的表达意思不清楚吧。
wangfu的代码就是在系统的菜单上添加自己的项呀。

而我需要的就是像上面图的画有红色的地方那里,击右键的时候
不弹出系统的那条菜单,而弹出我自己定义的菜单。
例如我用ExpressBars做了一个PopupMenu,我需要弹出它。
 
你可以把那些系统菜单,比如关闭,最小化,还原删除吧
然后添加自己的就可以吧,你自己试试
 
把关闭,最小化,还原删除,然后添加自己的这当然可以,以前我都做到了。
我要的是完全屏闭它,不是把它删除。
 
拦截任务栏的菜单消息。
估计不太难,我见过有个控件也是这样的,但没仔细研究。
什么时候有空我替你试一下,我现在暂时没空
 
那等你的消息了!
 
hamsoft说的没错。

这个问题没什么特别的
 
问题是没有特别,但为什么没有高手能帮帮我呢?
VC能做到(Winamp是VC做的吧??),DELPHI也能做到吧?

http://www.delphibbs.com/delphibbs/dispq.asp?lid=803445
 
我给你一个小程序吧,希望对你有帮助
qq:44079546
给我你的信箱
 
有意思!听课
 
后退
顶部