系统热键的注册

系统热键的注册

  根据前面的介绍,不难写出为后台服务程序添加对系统热键响应的功能代码。首先通过函数GlobalFindAtom()查询本服务程序所对应的全局原子是否已存在于全局原子表中,如果发现,则说明系统中已经存在有此服务,程序退出。如果没有发现,则通过GlobalAddAtom()函数向全局原子表添加一个字串,并获取得到一个唯一标识此字串的原子。以上两函数原型分别为:

ATOM GlobalFindAtom(LPCTSTR lpString);
ATOM GlobalAddAtom(LPCTSTR lpString);

  其中,输入参数为一个描述原子的字符串,如果GlobalFindAtom()从全局原子表中找到了指定的字串,那么将返回此字串对应的原子,否则返回0。GlobalAddAtom()如果创建成功,将返回一个新创建的原子。
接下来,为了能在程序运行期间捕获到系统热键,需要通过RegisterHotKey()定义一个系统范围的热键。该函数原形如下:

BOOL RegisterHotKey(HWND hWnd, // 接收热键响应的窗口句柄
int id, // 热键的标识
UINT fsModifiers, // 控制键标志
UINT vk // 虚拟键值
);

  其中,热键标识id必须是一个范围在0xC000到0xFFFF之间的全局唯一的值,为了避免可能引起的热键冲突,通常把GlobalAddAtom()返回的原子作为参数传入,而且GlobalAddAtom()返回值的范围同id参数的允许范围是完全一致的。参数fsModifiers定义了同虚拟键值vk同时按下而产生出系统热键消息WM_HOTKEY的控制键组合,如MOD_ALT、MOD_CONTROL、MOD_SHIFT和MOD_WIN等。在本例中将要设定的系统热键为Alt+Ctrl+R,因此,参数fsModifiers和vk分别设置为MOD_ALT| MOD_CONTROL和VK_R。有关系统热键的注册实现方法可以整理如下:

// 获取当前窗口句柄
HWND handle = GetSafeHwnd();
// 寻找HotKey对应的原子是否存在于原子列表
if(GlobalFindAtom("Hotkey") == 0)
{
// 如果没有存在于原子列表,则创建一个原子
id = GlobalAddAtom("Hotkey");
//注册全局热键Ctrl + Alt + R
RegisterHotKey(handle, id, CONTROL + ALT, R);
}
else // 如果HotKey已经存在于原子列表,则终止程序运行

PostQuitMessage(0);



服务程序的隐藏与激活

  服务程序除了被激活后同用户的交互,绝大部分时间都是在后台隐藏运行的,不仅界面是不可视的,而且在任务列表中也不应当出现。关于界面的隐藏比较简单,可以通过向ShowWindow()函数设置SW_HIDE参数来实现,而在任务列表中的隐身则一般的做法是通过调用系统内核Kernel32.DLL的RegisterServiceProcess()函数将其设置成为一个服务进程,这样,在任务列表中也实现了隐身。但是RegisterServiceProcess()函数并非一个标准的API函数,使用起来有点烦琐。首先要通过GetModuleHandle()函数得到Kernel32.DLL模块的句柄,并由此通过GetProcAddress()函数进一步得出RegisterServiceProcess()函数在Kernel32.DLL中的入口地址,最后才能使用RegisterServiceProcess()函数。该函数原型声明如下:

DWORD RegisterServiceProcess(DWORD dwProcessId,DWORD dwType);

  其第一个参数指定了将要注册为服务进程的进程标识,参数dwType指定是去注册一个服务进程(为1时)还是去卸载一个服务进程(为0时)。其具体服务注册过程如下:

typedef DWORD (WINAPI *RSP)(DWORD dwProcessId,DWORD dwType);
// 获取Kernel32.DLL模块句柄
HMODULE m_hKernel = ::GetModuleHandle("Kernel32.DLL");
// 得到RegisterServiceProcess()函数入口地址
RSP m_rsp = (RSP)::GetProcAddress(m_hKernel, "RegisterServiceProcess");
// 注册当前进程为服务进程
m_rsp(::GetCurrentProcessId(),1);

  在服务程序后台运行期间,一旦有系统热键Alt+Ctrl+R按下,将发出系统热键消息WM_HOTKEY,该消息的消息响应函数不能通过ClassWizard来添加,而只能手工完成消息映射。在消息响应函数中,通过对消息参数 wParam的判断可以确定出是否是本服务程序所设定的系统热键,如果是,通过ShowWindow(SW_SHOW)将程序界面显示出来,以进行同用户的交互操作:

void CServiceDlg::OnHotKey(WPARAM wParam, LPARAM lParam)
{
// 判断是否是本服务程序设置的系统热键
if (wParam == id)
{
……
// 在此发送WM_PAINT消息,在OnPain()中通过
// ShowWindow(SW_SHOW)将界面设置为可视
PostMessage(WM_PAINT, 0, 0);
}
}




//////////////////////////////////////////////////////////////////////////////TEST CODE
  // testhotkey.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include "windows.h"
#define HOT_KEY_OPEN_DIR _T("hotkey_yong9")
UINT uHwnd=0x004F0B54;
HWND hStart=(HWND)uHwnd;
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_HOTKEY:
MessageBox(NULL,_T("CTL+ALT+F8"),"DDD",NULL);
return 0 ;


case WM_DESTROY:
if(!GlobalFindAtom(HOT_KEY_OPEN_DIR))
{
UnregisterHotKey(hStart,GlobalFindAtom(HOT_KEY_OPEN_DIR));
GlobalDeleteAtom(GlobalFindAtom(HOT_KEY_OPEN_DIR));
MessageBox(NULL,_T("destroy CTL+ALT+F8"),"DDD",NULL);
}


PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
int _tmain(int argc, _TCHAR* argv[])
{
/*if((hStart=FindWindow(_T("ConsoleWindowClass"),NULL))==NULL)
{
MessageBox(NULL,"ConsoleWindowClass find fail","ConsoleWindowClass find fail",NULL);
}*/
SetWindowText(hStart,_T("NINI"));
if(GlobalFindAtom(HOT_KEY_OPEN_DIR) == 0)
{
// 如果没有存在于原子列表,则创建一个原子
ATOM id = GlobalAddAtom(HOT_KEY_OPEN_DIR); 
//注册全局热键Ctrl + Alt + R
if (RegisterHotKey(hStart, id, 0, VK_F8))
{
MessageBox(NULL,_T("reg sucess"),"DDD",NULL); 
}
else
{


TCHAR sz[100];
_stprintf(sz,_T("fail id:%ld"),GetLastError());
MessageBox(NULL,sz,"DDD",NULL);
}



}
else
{
MessageBox(NULL,_T("exist"),"DDD",NULL); 
if(!GlobalFindAtom(HOT_KEY_OPEN_DIR))
{
UnregisterHotKey(hStart,GlobalFindAtom(HOT_KEY_OPEN_DIR));
GlobalDeleteAtom(GlobalFindAtom(HOT_KEY_OPEN_DIR));
MessageBox(NULL,_T("destroy CTL+ALT+F8"),"DDD",NULL);
}
}
bool bRet;
MSG msg;
while( (bRet = GetMessage( &msg, hStart, 0, 0 )) != 0) { // 注册消息循环体
if (bRet == -1) {   // handle the error and possibly exit
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值