如何控制音量?(100分)

  • 主题发起人 主题发起人 erdonme
  • 开始时间 开始时间
E

erdonme

Unregistered / Unconfirmed
GUEST, unregistred user!
如何控制音量?
 
var
v:longint;

//得到当前音量
WaveOutGetVolume(0,@v);
TrackBar1.Position:=hi(v);


//控制音量
procedure TForm1.TrackBar1Change(Sender: TObject);
var
t,v:longint;
begin

t:=TrackBar1.Position;
v:=(t shl 8) or (t shl 24);
WaveOutSetVolume(0,v);
end;

 
来自csdn的:

unit funVolume;

interface

uses MMSystem, Dialogs;

Type TDeviceName = (Master, Microphone, WaveOut, Synth);

function GetVolume(DN:TDeviceName) : Word
procedure SetVolume(DN:TDeviceName;
Value:Word);
function GetVolumeMute(DN:TDeviceName) : Boolean;
procedure SetVolumeMute(DN:TDeviceName;
Value:Boolean);

implementation

//获取音量
function GetVolume(DN:TDeviceName) : Word;
var
hMix: HMIXER;
mxlc: MIXERLINECONTROLS;
mxcd: TMIXERCONTROLDETAILS;
vol: TMIXERCONTROLDETAILS_UNSIGNED;
mxc: MIXERCONTROL;
mxl: TMixerLine;
intRet: Integer;
nMixerDevs: Integer;
begin

// Check if Mixer is available
nMixerDevs := mixerGetNumDevs();
if (nMixerDevs < 1) then

begin

Exit;
end;


// open the mixer
intRet := mixerOpen(@hMix, 0, 0, 0, 0);
if intRet = MMSYSERR_NOERROR then

begin

case DN of
Master : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
Microphone :
mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
WaveOut : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
Synth : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
end;

mxl.cbStruct := SizeOf(mxl);

// get line info
intRet := mixerGetLineInfo(hMix, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxlc, SizeOf(mxlc),0);
mxlc.cbStruct := SizeOf(mxlc);
mxlc.dwLineID := mxl.dwLineID;
mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls := 1;
mxlc.cbmxctrl := SizeOf(mxc);

mxlc.pamxctrl := @mxc;
intRet := mixerGetLineControls(hMix, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxcd, SizeOf(mxcd),0);
mxcd.dwControlID := mxc.dwControlID;
mxcd.cbStruct := SizeOf(mxcd);
mxcd.cMultipleItems := 0;
mxcd.cbDetails := SizeOf(Vol);
mxcd.paDetails := @vol;
mxcd.cChannels := 1;

intRet := mixerGetControlDetails(hMix, @mxcd,MIXER_SETCONTROLDETAILSF_VALUE);

Result := vol.dwValue

if intRet <> MMSYSERR_NOERROR then

ShowMessage('GetControlDetails Error');
end
else

ShowMessage('GetLineInfo Error');
end;

intRet := mixerClose(hMix);
end;

end;


//设置音量
procedure setVolume(DN:TDeviceName;
Value : Word);
var
hMix: HMIXER;
mxlc: MIXERLINECONTROLS;
mxcd: TMIXERCONTROLDETAILS;
vol: TMIXERCONTROLDETAILS_UNSIGNED;
mxc: MIXERCONTROL;
mxl: TMixerLine;
intRet: Integer;
nMixerDevs: Integer;
begin

// Check if Mixer is available
nMixerDevs := mixerGetNumDevs();
if (nMixerDevs < 1) then

begin

Exit;
end;


// open the mixer
intRet := mixerOpen(@hMix, 0, 0, 0, 0);
if intRet = MMSYSERR_NOERROR then

begin

case DN of
Master : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
Microphone :
mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
WaveOut : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
Synth : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
end;

mxl.cbStruct := SizeOf(mxl);

// get line info
intRet := mixerGetLineInfo(hMix, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxlc, SizeOf(mxlc),0);
mxlc.cbStruct := SizeOf(mxlc);
mxlc.dwLineID := mxl.dwLineID;
mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls := 1;
mxlc.cbmxctrl := SizeOf(mxc);

mxlc.pamxctrl := @mxc;
intRet := mixerGetLineControls(hMix, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxcd, SizeOf(mxcd),0);
mxcd.dwControlID := mxc.dwControlID;
mxcd.cbStruct := SizeOf(mxcd);
mxcd.cMultipleItems := 0;
mxcd.cbDetails := SizeOf(Vol);
mxcd.paDetails := @vol;
mxcd.cChannels := 1;

vol.dwValue := Value;

intRet := mixerSetControlDetails(hMix, @mxcd,MIXER_SETCONTROLDETAILSF_VALUE);

if intRet <> MMSYSERR_NOERROR then

ShowMessage('SetControlDetails Error');
end
else

ShowMessage('GetLineInfo Error');
end;

intRet := mixerClose(hMix);
end;

end;


//获取静音
function GetVolumeMute(DN:TDeviceName) : Boolean;
var
hMix: HMIXER;
mxlc: MIXERLINECONTROLS;
mxcd: TMIXERCONTROLDETAILS;
vol: TMIXERCONTROLDETAILS_UNSIGNED;
mxc: MIXERCONTROL;
mxl: TMixerLine;
intRet: Integer;
nMixerDevs: Integer;
mcdMute: MIXERCONTROLDETAILS_BOOLEAN;
begin

// Check if Mixer is available
nMixerDevs := mixerGetNumDevs();
if (nMixerDevs < 1) then

begin

Exit;
end;


// open the mixer
intRet := mixerOpen(@hMix, 0, 0, 0, 0);
if intRet = MMSYSERR_NOERROR then

begin

case DN of
Master : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
Microphone :
mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
WaveOut : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
Synth : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
end;

mxl.cbStruct := SizeOf(mxl);

// mixerline info
intRet := mixerGetLineInfo(hMix, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxlc, SizeOf(mxlc),0);
mxlc.cbStruct := SizeOf(mxlc);
mxlc.dwLineID := mxl.dwLineID;
mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_MUTE;
mxlc.cControls := 1;
mxlc.cbmxctrl := SizeOf(mxc);
mxlc.pamxctrl := @mxc;

// Get the mute control
intRet := mixerGetLineControls(hMix, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxcd, SizeOf(mxcd),0);
mxcd.cbStruct := SizeOf(TMIXERCONTROLDETAILS);
mxcd.dwControlID := mxc.dwControlID;
mxcd.cChannels := 1;
mxcd.cbDetails := SizeOf(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails := @mcdMute;

// Get mute
intRet := mixerGetControlDetails(hMix, @mxcd, MIXER_SETCONTROLDETAILSF_VALUE);

if mcdMute.fValue = 0 then
Result:=false
else
Result := True;

if intRet <> MMSYSERR_NOERROR then

ShowMessage('SetControlDetails Error');
end
else

ShowMessage('GetLineInfo Error');
end;


intRet := mixerClose(hMix);
end;

end;


//设置静音
procedure SetVolumeMute(DN:TDeviceName;
Value:Boolean);
var
hMix: HMIXER;
mxlc: MIXERLINECONTROLS;
mxcd: TMIXERCONTROLDETAILS;
vol: TMIXERCONTROLDETAILS_UNSIGNED;
mxc: MIXERCONTROL;
mxl: TMixerLine;
intRet: Integer;
nMixerDevs: Integer;
mcdMute: MIXERCONTROLDETAILS_BOOLEAN;
begin

// Check if Mixer is available
nMixerDevs := mixerGetNumDevs();
if (nMixerDevs < 1) then

begin

Exit;
end;


// open the mixer
intRet := mixerOpen(@hMix, 0, 0, 0, 0);
if intRet = MMSYSERR_NOERROR then

begin

case DN of
Master : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
Microphone :
mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
WaveOut : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
Synth : mxl.dwComponentType := MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
end;

mxl.cbStruct := SizeOf(mxl);

// mixerline info
intRet := mixerGetLineInfo(hMix, @mxl, MIXER_GETLINEINFOF_COMPONENTTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxlc, SizeOf(mxlc),0);
mxlc.cbStruct := SizeOf(mxlc);
mxlc.dwLineID := mxl.dwLineID;
mxlc.dwControlType := MIXERCONTROL_CONTROLTYPE_MUTE;
mxlc.cControls := 1;
mxlc.cbmxctrl := SizeOf(mxc);
mxlc.pamxctrl := @mxc;

// Get the mute control
intRet := mixerGetLineControls(hMix, @mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);

if intRet = MMSYSERR_NOERROR then

begin

FillChar(mxcd, SizeOf(mxcd),0);
mxcd.cbStruct := SizeOf(TMIXERCONTROLDETAILS);
mxcd.dwControlID := mxc.dwControlID;
mxcd.cChannels := 1;
mxcd.cbDetails := SizeOf(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails := @mcdMute;

// Set and UnSet mute
mcdMute.fValue := Ord(Value);
intRet := mixerSetControlDetails(hMix, @mxcd, MIXER_SETCONTROLDETAILSF_VALUE);

if intRet <> MMSYSERR_NOERROR then

ShowMessage('SetControlDetails Error');
end
else

ShowMessage('GetLineInfo Error');
end;


intRet := mixerClose(hMix);
end;

end;


end.


 
别人笔记里的东西,转:

音量控制程序制作手记 (及全部源码)
关键字: 音量 静音 api 经验
分类?: 开发经验
密级?: 参赛
(评分:★★★★ , 回复: 8, 阅读: 1277) &amp;raquo;&amp;raquo;

音量控制程序SmartVolume制作手记《上》
====================================
很久以来,我对Win2000的音量控制深恶痛绝。有时候音量不合适要调节的时候,我会单击托盘栏上的小喇叭,下一步不是拖动拉杆,而是耐心地等待......只听一阵硬盘哗哗作响,鼠标处的光标变成沙漏,大约五秒左右,会跳出那个小小的调整音量窗口。我长出一口气,感慨一番,做一次调整。每次都是如此,烦啊。

夜深人静的时候,有时候运行一个程序,会突然爆发出一阵巨大的声音,怕影响家人熟睡的我,就开始手忙脚乱了!前面的音量调节肯定是不能用了,因为反应太慢。我跳起来,去找音箱后面的开关。平时开关就难找得出奇,何况是这种紧急情况?于是拨音箱电源线。整个世界清静了。我坐下来喘口气,心里暗自庆幸没有错拨到主机电源线。

想起从前用win98的“好日子”。98下的音量调节出来得很快,不用有这等担心。可是也有一样不好,深夜里,想听听音乐,当然要把音量调得小而又小。可是,当我把那个TraceBar拉到最底端的时候,坏了!音量突然变成最大!又是一阵手忙脚乱,以及过后大骂微软。

下了无数次的决心,要找一个音量控制软件或者自己写一个。上网粗略地找了一下,没有合适的,还是自己写吧。这就是做程序员的好处。呵呵。

麻烦的是,我不知道控制音量的API。上网查吧。从google上找到一篇文章, 如何控制计算机系统音量http://gamepower.myst.com.cn/tech/vb_clvol.htm),一看,是VB源码,里面有几个API的声明和调用。好啊,这么容易就找到了。先看它用到什么API吧:auxGetNumDevs,auxGetDevCaps,auxSetVolume,auxGetVolume,看起来应该是这几个。

用windows自带的查找文件功能在所有Delphi源码和控件源码里查找有auxSetVolume的*.pas的文件,只有mmsystem.pas里有。打开一看,果然有相关的声明。怪我对delphi了解不够,竟然忘记了先查一下Delphi源程序。

可惜没有找到示例程序。查一下Delphi自带的Windows SDK帮助,好象不够详细;再上MSDN查一下,发现二者内容差不多。我试着在Delphi里运行这一句
ShowMessage(Inttostr(auxGetNumDevs));
// use mmsystem;
发现结果竟然是0。看来,这里还是有问题,aux就是辅助设备的意思,大概是这里不对。我要调整windows的主音量,而不是wave, midi,大概也不是aux。多媒体方面的知识我并不太了解,只能这样猜测。

印象中好象看到过有监视API的软件。如果真的能在调整音量的时候监视它调用了哪些API,不就解决了吗?于是用“监视 API”做关键字在Google上查。原来这个软件叫APIspy。国内的网站居然难以下载,用 apispydo
wnload继续查google。最终从国外站点下载了版本2.5。(http://madmat.hypermart.net/apis3225.exe)

APIspy可以指定并运行一个程序,在运行过程中监视API调用。怎么知道windows调节音量的程序名呢?

用Sound做关键字在MSDN里查询,找到一篇文章讲到
The SndVol32 program (sndvol32.exe) controls both the volume settings for various sound sources (such as wave, CD, and synthesizer) and the master volume setting.

原来是sndvol32.exe,我轻易地在system32里找到了它。用apispy打开,那个run按钮居然是灰的。我试着单击旁边的imports,出现一个对话框,显示sndvol32程序调用的各dll的api的名字。有advapi32.dll, comctl32.dll, ... 最后是winmm.dll。我只关心声音控制,当然是把双击每一个winmm的api把它们添加到监视列表里。

现在run按钮可用了。单击它,出现了Volume Control窗口,同时apispy显示出调用的那些api。我拉动主音量调节杆,监视窗口又有了变化。在监视结果里面,我发现了这样几个调用:mixerGetControlDetails, mixerGetLineInfo。Mixer是混音器的意思,有戏。

从MSDN上继续用新找到的API查,又找出了几个相关的来。

UINT mixerGetNumDevs(VOID);
MMRESULT mixerSetControlDetails(
HMIXEROBJ hmxobj,
LPMIXERCONTROLDETAILS pmxcd,
DWORD fdwDetails
);

好复杂啊!(详见 http://msdn.microsoft.com/library/default.asp?url=/library/EN-US/multimed/mmfunc_8hkf.asp)

试着在Delphi里调用mixerGetNumDevs,结果是1。运行下面代码
procedure TForm1.Button1Click(Sender: TObject);
var
NumDevs : integer;
dcaps : TAuxCaps;
i:integer;
begin

NumDevs := mixerGetNumDevs;
for i := 0 to NumDevs - 1do

begin

mixerGetDevCaps(i, @dcaps, sizeof(dcaps));
Listbox1.Items.Add(dcaps.szPname)
end;

end;


结果是SiS 7012 Wave,那是我的声卡。一切正确。

我试着用mixerSetControlDetails设置音量,却总是不能得其门而入。再次上网找示范用例吧。不知为什么,google上不去了,用百度查询mixerSetControlDetails,找到一篇文章,名字是《音量调节及静音》(http://www.csdn.net/develop/article/17/17257.shtm),作者是Haofei。往下一看,是一个完整的Delphi单元,有四个函数获取音量GetVolume(DN)、设置音量SetVolume(DN,Value)、获取静音GetVolumeMute(DN)及设置静音SetVolumeMute(DN,Value)。

放到自己程序里,写了两行代码,完全正确。

本来是想自己写的,想不到有人已经把事情做完了。既是高兴,又是失望。关于音量调整的技术探索,到此为止。

剩下的工作没有什么难度,很快就可以写出自己的音量控制程序了。

尾声:在搜索过程中,还找到了hubdog的主页上也有类似的一篇文章《Delphi 4下编写Audio Mixer Control》(http://hubdog.myrice.com/Recommend/rcAudioMixer.htm),看来,有不少人做过同样的尝试,我只是个迟到者。

本来,问题解决也就完了,但我在整个过程中,越来越想把自己的经历写出来,供初学的朋友参考吧。

----------------------------------------------------------------------

音量控制程序SmartVolume制作手记《下》
====================================


接下来,就到了实地编程的阶段了。

我所希望的功能是:
1. 按一个热键比如Ctrl-Alt-小键盘减号,会打开/关闭声音。
2. 按热键Ctrl-Alt-上、下方向键调节音量大小。

还有一个小小的难题需要解决,那就是全局热键。我知道LMD控件组里有LMDGlobalHotkey可以做到,不过这一次想试试自己解决这个问题。
我可以去LMD的源码或上网找资料,不过记得好象是Register打头的Api,从SDK帮助中一查,果然是RegisterHotKey和UnregisterHotKey,同时要用到消息WM_HOTKEY。

大体看了一下API帮助,再经过简单的分析,写了一段程序如下,运行通过。看来很简单嘛。自己以前把这些技术想得太复杂了:
procedure TForm1.Button2Click(Sender: TObject);
begin

RegisterHotKey(handle,1,MOD_ALT or MOD_CONTROL,VK_SUBTRACT);
//Ctrl-Alt-小键盘减号
RegisterHotKey(handle,2,MOD_ALT or MOD_CONTROL,VK_DOWN);
//Ctrl-Alt-方向键下
end;


procedure TForm1.WMHotKey(var Message: TWMHotkey);
begin

case Message.HotKey of
1: showmessage('1');
2: showmessage('2');
else

Showmessage(inttostr(message.HotKey));
end;

end;


procedure TForm1.Button3Click(Sender: TObject);
begin

UnregisterHotKey(handle,1);
UnregisterHotKey(handle,2);
end;


下一步是得到用户自己定义的HOTKEY。Delphi有一个原生的THotkey控件,就是做这件事的。不过看了帮助,THotkey是为TMenuItem服务的。要把它转成API使用的参数,还真的颇费一番周折。通过看THotkey的源码,加上一通试验,才算搞定。
procedure TForm1.Button2Click(Sender: TObject);
var
Modifiers:integer;
HK:longint;
begin

Modifiers:=0;
if hkShift in Hotkey1.Modifiers then

Modifiers:=Modifiers or MOD_SHIFT;
if hkCtrl in Hotkey1.Modifiers then

Modifiers:=Modifiers or MOD_CONTROL;
if hkAlt in Hotkey1.Modifiers then

Modifiers:=Modifiers or MOD_ALT;
HK := SendMessage(Hotkey1.Handle, HKM_GETHOTKEY, 0, 0);
// 从源码里学来的
Win32Check(RegisterHotKey(handle,1,Modifiers,HK and $FF));
end;


THotkey的参数保存应该很容易的。只需要保存两个数字 byte(Hotkey1.Modifiers) 和 Hotkey1.Hotkey。

想来想去,Delphi的THotkey用着还是不爽,自己写一个组件吧。名字叫TGlobalHotKey。

我写组件的经验很少,只是知道大体的方法。
比如这次在增删一些属性的时候,发现Object Inspector里没有及时反应出来。打开DclUser.dpk,编译一下,就有了。

哈哈,做完了。以下是GlobalHotKey控件源码


//------------------- GlobalHotKey.pas 开始 ----------------------
// 作者:安富国 http://anjo.delphibbs.com 2003.5

unit GlobalHotKey;

interface

uses
SysUtils, Classes, Controls, ComCtrls, IniFiles, Windows,
CommCtrl, Messages;

type
TGlobalHotKey = class(THotKey)
private
FGlobalID: integer;
FOnExecute: TNotifyEvent;
procedure SetGlobalID(const Value: integer);
{ Private declarations }
protected
{ Protected declarations }
procedure WMHotKey(var Message: TWMHotkey);
message WM_HOTKEY;
public
{ Public declarations }
// 保存hotkey到ini文件中
procedure LoadFromIni(Ini:TIniFile);

// 从ini文件里取出hotkey
procedure SaveToIni(Ini:TIniFile);

// 查询windows有没有注册过这个Hotkey。如果没有,返回true。
function QueryGlobalHotkey:boolean;

// 注册为全局Hotkey
function RegisterGlobalHotkey:boolean;

// 注销全局Hotkey
procedure UnregisterGlobalHotkey;

// 与另一个THotKey比较
function EqualTo(AHotKey:THotKey):boolean;
published
{ Published declarations }
property GlobalID:integer read FGlobalID write SetGlobalID default 1;
property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
end;


procedure Register;

implementation

procedure Register;
begin

RegisterComponents('System', [TGlobalHotKey]);
end;


{ TGlobalHotKey }

function TGlobalHotKey.EqualTo(AHotKey: THotKey): boolean;
begin

result:=(Modifiers=AHotKey.Modifiers) and (HotKey=AHotKey.HotKey);
end;


procedure TGlobalHotKey.LoadFromIni(Ini: TIniFile);
var
SectionName:string;
begin

SectionName:='GlobalKey_'+name;
Modifiers:=THKModifiers(byte(ini.ReadInteger(SectionName,'Modifiers',byte(Modifiers))));
HotKey:=ini.ReadInteger(SectionName,'Hotkey',HotKey);
end;


function TGlobalHotKey.QueryGlobalHotkey: boolean;
begin

result:=RegisterGlobalHotkey;
if result then

UnregisterGlobalHotkey;
end;


function TGlobalHotKey.RegisterGlobalHotkey: boolean;
var
AModifiers:integer;
HK:longint;
begin

AModifiers:=0;
if hkShift in Modifiers then

AModifiers:=AModifiers or MOD_SHIFT;
if hkCtrl in Modifiers then

AModifiers:=AModifiers or MOD_CONTROL;
if hkAlt in Modifiers then

AModifiers:=AModifiers or MOD_ALT;
HK := SendMessage(Handle, HKM_GETHOTKEY, 0, 0);
result:=RegisterHotKey(handle,GlobalID,AModifiers,HK and $FF);
end;


procedure TGlobalHotKey.SaveToIni(Ini: TIniFile);
var
SectionName:string;
begin

SectionName:='GlobalKey_'+name;
ini.WriteInteger(SectionName,'Modifiers',byte(Modifiers));
ini.WriteInteger(SectionName,'Hotkey',HotKey);
end;


procedure TGlobalHotKey.SetGlobalID(const Value: integer);
begin

FGlobalID := Value;
end;


procedure TGlobalHotKey.UnregisterGlobalHotkey;
begin

UnregisterHotKey(handle,GlobalID);
end;


procedure TGlobalHotKey.WMHotKey(var Message: TWMHotkey);
begin

if Assigned(FOnExecute) then
FOnExecute(Self);
end;


end.

//------------------- GlobalHotKey.pas 结束 ------------------------

在GlobalHotKey里面,我给原来的THotkey加了调用RegisterHotKey时用到的参数GlobalID和响应Hotkey按下的事件onExecute。
按理说,TGlobalHotKey也许应该做成非可视的控件,不过我想,如果不想看到它,可以把Visible属性设为False,效果也一样。

按照事先构想的SmartVolume的功能,它需要运行时缩小到右下角任务栏。这是一个标准的TrayIcon应用。有关TrayIcon的文章,自打学Delphi以来,就见到过无数篇,而我平时一般用Rxlib里的相应的控件RxTrayIcon,完善、方便。本想不用任何控件完成SmartVolume,看了看TrayIcon的资料,好麻烦!还是沿用Rxlib吧。

前后经过两天多的工作,程序完成了。完全实现了前面构想的两个功能,而且可以用户自定义热键,调用sndvol32.exe,每次热键调整后,窗口会自动出现三秒种后消失。

虽然本人生平编写过无数的程序,但是这一个我认为是最完美的……

:)



2003-5-18 22:49:00
发表评语&amp;raquo;&amp;raquo;&amp;raquo;


2003-5-21 19:38:24 源码(注:需要Rxlib v2.75 for D7)

源码

2003-5-21 19:55:41 设计截图


2003-5-21 20:36:44 源码安装说明有一点需要注意,应该将GlobalHotKey.pas注册为组件。否则会出错。
具体方法就不用我说了吧?
 
后退
顶部