自己做的一个用鼠标滚轮调节系统音量的程序(Win32编程),拿出来跟大家分享.
只要把鼠标移到屏幕上方(或下方)滚动鼠标中键就可以调节音量大小
程序: WheelVolume.zip(请不要使用迅雷直接下载)
源程序:WheelVolume_source.zip(在VC6下编译通过) (请不要使用迅雷直接下载)
备注: 以上为xp下的程序和源代码,win7 版本的 请到qq邮箱里下载
vcshare@ qq.com(密码:share88)
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include "resource.h"
//调节音量的函数需要winmm.lib
#include <mmsystem.h>
#define _WIN32_WINNT 0x0500
#pragma comment(lib,"winmm.lib")
//当中建滚动时,向窗口发送此消息以使窗口显示当前音量值
#define WM_ADJUSTVOLUME WM_USER+100
//音量分20个值
#define TOTAL_PERCENT 20
//窗口大小
#define WIDTH 300
#define HEIGHT 28
//绘制每一小格的大小
#define EACH_WIDTH (WIDTH-51)/TOTAL_PERCENT
#define EACH_HEIGHT HEIGHT-4
//最低音量和最高音量分20个值
#define INTERVAL 20
int MousePos=0; //标志位
HWND g_hWnd; //窗口句柄
HHOOK g_hMouse=NULL; //钩子句柄
bool WINAPI SetVolume(LONG vol); //设置音量值
unsigned WINAPI GetVolume(); //获得音量值
//鼠标钩子,捕获中键滚动的消息
LRESULT CALLBACK MouseProc(int nCode,WPARAM wParam, LPARAM lParam)
{
if (nCode<0 )
return CallNextHookEx(g_hMouse,nCode,wParam,lParam); //传递钩子信息
if (wParam==WM_MOUSEWHEEL)
{
POINT point=(POINT)((MSLLHOOKSTRUCT *)lParam)->pt;
//鼠标是否在指定的地方滚动中建
if ( unsigned(point.y-MousePos)<20 )
{
int zDelta= (int)(((MSLLHOOKSTRUCT *)lParam)->mouseData );
(int(zDelta)>0) ? zDelta=-1 : zDelta=1;
//重新设置音量
int volume=GetVolume()+zDelta;
//假如音量超出0-20,则设为0或20
if (volume<0) volume=0;
if (volume>INTERVAL) volume=INTERVAL;
//设置音量
SetVolume(volume);
//假如窗口隐藏了,显示窗口
if (!IsWindowVisible(g_hWnd))
{
::SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); //保证窗口在最顶层
ShowWindow(g_hWnd,SW_SHOWNOACTIVATE); //显示窗口
}
//绘制音量图形
PostMessage(g_hWnd,WM_ADJUSTVOLUME,volume,0);
//避免WM_MOUSEWHEEL向下钩子传递
return 1;
}
}
return CallNextHookEx(g_hMouse,nCode,wParam,lParam); //传递钩子信息
}
//主窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
//假如已经有一个实例在运行,则显示已经运行的实例
HANDLE m_hMutex = CreateMutex(NULL,FALSE,"efe3ty34twgr4235325efwrwgrdgrg"); //记得在程序末尾调用CloseHandle( m_hMutex )
if (GetLastError()==ERROR_ALREADY_EXISTS)
{
HWND PreWnd=FindWindow(NULL,"WheelVolume");
ShowWindow(PreWnd,SW_SHOWNOACTIVATE);
RECT rect;
GetWindowRect(PreWnd,&rect);
SetCursorPos(rect.left+10,rect.top+10);
PostMessage(PreWnd,WM_RBUTTONDOWN,0,0);
CloseHandle( m_hMutex );
return FALSE;
}
//窗口类
WNDCLASS wndclass;
wndclass.lpszClassName="MyClass"; // window class name
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON));
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=WndProc;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
RegisterClass(&wndclass);
//加载设置
char buf[10]={0};
GetProfileString("WheelVolume","MousePos","0",buf,10);
MousePos=atoi(buf);
//获得显示窗口的X y 坐标
char Xbuf[10]={0};
char Ybuf[10]={0};
GetProfileString("WheelVolume","Postion_X","0",Xbuf,10);
GetProfileString("WheelVolume","Postion_Y","0",Ybuf,10);
int x=atoi(Xbuf);
int y=atoi(Ybuf);
if ( x<0 || y<0 || x>GetSystemMetrics(SM_CXSCREEN) || y>GetSystemMetrics(SM_CYSCREEN) )
{
x=0;
y=0;
}
//创建窗口
g_hWnd= CreateWindowEx( WS_EX_TOOLWINDOW|WS_EX_TOPMOST,"MyClass","WheelVolume",WS_POPUP | WS_CLIPSIBLINGS |WS_BORDER,x,y,WIDTH,HEIGHT,NULL,NULL,hInstance,NULL) ;
//启动鼠标低级钩子
g_hMouse=SetWindowsHookEx(WH_MOUSE_LL,MouseProc,GetModuleHandle(NULL),0);//这里用GetModuleHandle(NULL)来把自身作为一个保存钩子处理函数的dll
//消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0)) {TranslateMessage(&msg);DispatchMessage(&msg);} return msg.wParam ;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static int CurrentValue=0;
switch(message)
{
case WM_CREATE:
{
//判断是否第一次运行
char buf[4]={0};
GetProfileString("WheelVolume","IsFirstExcute","0",buf,4);
if (!strcmp(buf,"0"))
{
WriteProfileString("WheelVolume","IsFirstExcute","1"); //修改参数
::MessageBox(hWnd,TEXT("EasyVolume第一次运行"),"提示",MB_OK);
ShowWindow(hWnd,SW_SHOWNOACTIVATE);
RECT rect;
GetWindowRect(hWnd,&rect);
SetCursorPos(rect.left+10,rect.top+10);
PostMessage(hWnd,WM_RBUTTONDOWN,0,0);
}
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc= BeginPaint(hWnd, &ps);
{
//画界面
HDC hdc=::GetDC(g_hWnd);
HBRUSH brush=CreateSolidBrush(RGB(200,23,23)); //颜色
SelectObject (hdc,brush) ;
for (int i=0;i<CurrentValue;i++) //画音量界面
::Rectangle(hdc,2+i*EACH_WIDTH,2,(i+1)*EACH_WIDTH,EACH_HEIGHT);
DeleteObject(brush);
::ReleaseDC(g_hWnd,hdc) ;
}
//画百分数
char buf[10]={0};
sprintf(buf,"%d %%",100/TOTAL_PERCENT*CurrentValue);
::SetBkMode(hdc,TRANSPARENT);
RECT rect={WIDTH-50,0,WIDTH,HEIGHT};
::DrawText (hdc,buf, -1,&rect,DT_SINGLELINE | DT_LEFT | DT_VCENTER |DT_END_ELLIPSIS ) ;
EndPaint(hWnd, &ps);
SetTimer(g_hWnd,1,1000,NULL);
}
break;
case WM_ADJUSTVOLUME:
{
CurrentValue=wParam;
RECT rect={ 2+CurrentValue*EACH_WIDTH,2,WIDTH,EACH_HEIGHT}; //无效区域
InvalidateRect(g_hWnd,&rect,true); //更新
}
break;
case WM_TIMER:
ShowWindow(g_hWnd,SW_HIDE);
break;
case WM_LBUTTONDOWN:
{
KillTimer(hWnd,1);
//移动窗口
POINT point;
point.x= LOWORD (lParam) ;
point.y= HIWORD (lParam) ;
SendMessage(hWnd,WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y)); //在LBUTTONDOWN里加,可以移动窗口
//获得当前窗口的大小
RECT rect;
GetWindowRect(hWnd,&rect);
//假如窗口超过窗口边界,调整之
if (rect.left<0) rect.left=0;
if (rect.top<0) rect.top=0;
if (rect.right>GetSystemMetrics(SM_CXSCREEN)) rect.left=GetSystemMetrics(SM_CXSCREEN)-(rect.right-rect.left);
if (rect.bottom>GetSystemMetrics(SM_CYSCREEN)) rect.top=GetSystemMetrics(SM_CYSCREEN)-(rect.bottom-rect.top);
//重新设置窗口位置
SetWindowPos(hWnd,NULL,rect.left,rect.top,0,0,SWP_NOSIZE);
char buf[10];
//保存窗口
WriteProfileString("WheelVolume","Postion_X",itoa(rect.left,buf,10));
WriteProfileString("WheelVolume","Postion_Y",itoa(rect.top,buf,10));
SetTimer(hWnd,1,1000,0);
}
break;
case WM_RBUTTONDOWN:
{
//打开菜单时停止自动隐藏功能
KillTimer(hWnd,1);
//创建菜单
HMENU hMenuPopup = CreatePopupMenu () ;
AppendMenu (hMenuPopup, MF_STRING, 0, "当鼠标接近屏幕上方时使用滚轮调节音量");
AppendMenu (hMenuPopup, MF_STRING, 1, "当鼠标接近屏幕下方时使用滚轮调节音量");
AppendMenu (hMenuPopup, MF_STRING, 2, "开机时自动启动");
AppendMenu (hMenuPopup, MF_STRING, 3, "退出程序");
AppendMenu (hMenuPopup, MF_STRING, 4, "下载源程序");
AppendMenu (hMenuPopup, MF_STRING, 5, "说明:左键拖动可改变窗口位置,按右键可弹出设置菜单");
EnableMenuItem(hMenuPopup,5,MF_BYPOSITION | MF_DISABLED|MF_GRAYED);
//对应的启动方式(上方 或 下方)选项前打勾
if(MousePos==0)
CheckMenuItem(hMenuPopup,0,MF_BYPOSITION | MF_CHECKED);
else
CheckMenuItem(hMenuPopup,1,MF_BYPOSITION | MF_CHECKED);
//假如开机自动启动,着在"开机时自动启动"菜单前打勾标记
HKEY RegEntry;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",0, KEY_READ,&RegEntry);
char filename[MAX_PATH]={0};
DWORD WordType=REG_SZ;
DWORD WordData=sizeof(filename);
long ret=RegQueryValueEx(RegEntry,"VolumeChange",0,&WordType,(LPBYTE)filename,&WordData);
if (ret == ERROR_SUCCESS)
CheckMenuItem(hMenuPopup,2,MF_BYPOSITION | MF_CHECKED);
RegCloseKey(RegEntry);
//打开右键菜单
POINT point;
GetCursorPos(&point);
TrackPopupMenu (hMenuPopup, TPM_RIGHTBUTTON,point.x,point.y, 0, hWnd, NULL) ;
DestroyMenu (hMenuPopup);
SetTimer(hWnd,1,1000,0);
}
break;
case WM_COMMAND:
switch (LOWORD (wParam))
{
case 0: //设置"当鼠标接近屏幕上方时使用滚轮调节音量"
MousePos=0;
WriteProfileString("WheelVolume","MousePos","0");
::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOACTIVATE);
break;
case 1: //设置"当鼠标接近屏幕下方时使用滚轮调节音量"
char buf[10];
MousePos=GetSystemMetrics(SM_CYSCREEN)-20;
WriteProfileString("WheelVolume","MousePos",itoa(MousePos,buf,10)); //保存设置
::SetWindowPos(hWnd,HWND_TOPMOST,0,GetSystemMetrics(SM_CYSCREEN)-HEIGHT,0,0,SWP_NOSIZE|SWP_NOACTIVATE);
break;
case 2: //判断并修改"开机自动启动选项"
{
HKEY RegEntry;
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",0, KEY_ALL_ACCESS,&RegEntry);
char FilePath[MAX_PATH]={0};
DWORD WordType=REG_SZ;
DWORD WordData=sizeof(FilePath);
long ret=RegQueryValueEx(RegEntry,"VolumeChange",0,&WordType,(LPBYTE)FilePath,&WordData);
if (ret == ERROR_SUCCESS)
RegDeleteValue(RegEntry,"VolumeChange");
else
{
GetModuleFileName(NULL, FilePath, sizeof(FilePath));
RegSetValueEx(RegEntry,"VolumeChange",0,REG_SZ,(LPBYTE)FilePath,sizeof(FilePath)) ;
}
RegCloseKey(RegEntry);
}
break;
case 3: //推出程序
UnhookWindowsHookEx(g_hMouse) ;
PostQuitMessage(0);
break;
case 4:
ShellExecute(hWnd, "open", "http://sites.google.com/site/qiujiejia1/Home/WheelVolume_source.zip", NULL, NULL, SW_SHOWNORMAL);
}
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 0;
}
bool GetVolumeControl(HMIXER hmixer ,long componentType,long ctrlType,MIXERCONTROL* mxc)
{
MIXERLINECONTROLS mxlc;
MIXERLINE mxl;
mxl.cbStruct = sizeof(mxl);
mxl.dwComponentType = componentType;
if(!mixerGetLineInfo((HMIXEROBJ)hmixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE))
{
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = ctrlType;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(MIXERCONTROL);
mxlc.pamxctrl = mxc;
if(mixerGetLineControls((HMIXEROBJ)hmixer,&mxlc,MIXER_GETLINECONTROLSF_ONEBYTYPE))
return 0;
else
return 1;
}
return 0;
}
unsigned GetVolumeValue(HMIXER hmixer ,MIXERCONTROL *mxc)
{
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED vol; vol.dwValue=0;
mxcd.hwndOwner = 0;
mxcd.cbStruct = sizeof(mxcd);
mxcd.dwControlID = mxc->dwControlID;
mxcd.cbDetails = sizeof(vol);
mxcd.paDetails = &vol;
mxcd.cChannels = 1;
if(mixerGetControlDetails((HMIXEROBJ)hmixer, &mxcd, MIXER_OBJECTF_HMIXER|MIXER_GETCONTROLDETAILSF_VALUE))
return -1;
return vol.dwValue;
}
bool SetVolumeValue(HMIXER hmixer ,MIXERCONTROL *mxc, long volume)
{
MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED vol;vol.dwValue = volume;
mxcd.hwndOwner = 0;
mxcd.dwControlID = mxc->dwControlID;
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(vol);
mxcd.paDetails = &vol;
mxcd.cChannels = 1;
if(mixerSetControlDetails((HMIXEROBJ)hmixer, &mxcd, MIXER_OBJECTF_HMIXER|MIXER_SETCONTROLDETAILSF_VALUE))
return 0;
return 1;
}
//设置音量值
bool WINAPI SetVolume(LONG vol)
{
bool Result=false; //用于判断函数是否执行成功
MIXERCONTROL volCtrl;
HMIXER hmixer;
if(mixerOpen(&hmixer, 0, 0, 0, 0)) return 0;
if(GetVolumeControl(hmixer,MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,MIXERCONTROL_CONTROLTYPE_VOLUME,&volCtrl))
{
int ChangeValue=volCtrl.Bounds.lMaximum/INTERVAL;
int TotalValue=ChangeValue*vol;
if(SetVolumeValue(hmixer,&volCtrl,TotalValue))
Result=true;
}
mixerClose(hmixer);
return Result;
}
//返回音量值
unsigned WINAPI GetVolume()
{
unsigned rt=0;
MIXERCONTROL volCtrl;
HMIXER hmixer;
if(mixerOpen(&hmixer, 0, 0, 0, 0)) return 0;
if(!GetVolumeControl(hmixer,MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,MIXERCONTROL_CONTROLTYPE_VOLUME,&volCtrl))
return 0;
int ChangeValue=volCtrl.Bounds.lMaximum/INTERVAL; //每一次调用函数改变的音量值
rt=GetVolumeValue(hmixer,&volCtrl)/ChangeValue; //GetVolumeValue得到的是具体值
mixerClose(hmixer);
return rt;
}
`
`
大方广 http://www.dfg.cn/gb/学习圣贤之道
《幸福人生讲座》http://www.dfg.cn/gb/djjsh/pxcj/cailaoshi/20041120hk.htm