VC实现系统热键激活后台服务程序
2008-03-08 21:39:29 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾剧懓顪冪€n亜顒㈡い鎰Г閹便劌顫滈崱妤€骞婄紓鍌氬€瑰銊╁箟缁嬫鍚嬮柛顐線缂冩洟姊婚崒娆戭槮婵犫偓闁秵鎯為幖娣妼缁愭鏌″搴′簽濞戞挸绉甸妵鍕冀椤愵澀娌梺缁樻尪閸庣敻寮婚敐澶婂嵆闁绘劖绁撮崑鎾诲捶椤撴稑浜炬慨妯煎亾鐎氾拷

核心提示:摘要: 本文给出了一种通过设置系统热键来呼出在系统后台隐藏运行的服务程序的一种方法,通过这种方法,VC实现系统热键激活后台服务程序,可以实现后台服务程序在必要的时候同用户的交互设置,引言通常情况下,非常有利于治理员和用户的治理与使用,本文所述程序在windows 2000 Professional下,用于后台监控的服务
摘要: 本文给出了一种通过设置系统热键来呼出在系统后台隐藏运行的服务程序的一种方法,通过这种方法,可以实现后台服务程序在必要的时候同用户的交互设置。
引言
通常情况下,用于后台监控的服务程序(Service)是没有界面的,甚至也没有提供任务栏图标,因此绝大多数情况下服务程序是无法同用户进行交互的。但是在实际应用中,这些服务程序虽然绝大多数时间是在后台运行,但是在某些必要的情况下还是需要用户的干预并同用户进行一些必要的交互操作。但是由于服务程序没有提供任何可供交互操作之用的界面,因此如何将其从后台激活(即呼出)成为解决此问题的一个要害。本文下面就给出一种通过设置系统热键的方法来激活运行于后台的服务程序。
设计思路
尽管从理论上可以有许多方法来激活后台运行的服务程序,比如可以通过寻找服务程序的窗口标题名而得到其窗口指针,然后再向此窗口发送消息使其出现到前台;也可以通过系统快照对当前系统进程进行枚举,然后再将其激活到前台。但是以上这些方法都需要另外编写应用程序,对后台服务程序的激活实际是再这些应用程序中进行的,这样的处理方式显然十分不便,最好的方法是对程序的激活和隐藏处理均在服务程序内部完成。因此可以考虑接收系统发出的消息,假如通过设置全局钩子对设置事件进行拦截捕捉,显然是相当烦琐的。在此考虑使用系统热键来激活后台服务程序,其实现过程非常简单,只需先向操作系统添加一个全局原子(Atom),然后再向操作系统登记一个热键,当程序在后台运行期间一旦有此热键按下,操作系统将会抛出系统消息WM_HOTKEY,所以服务程序只需在 WM_HOTKEY消息响应函数中添加相应代码即可实现服务程序的后台激活。
系统热键的注册
根据前面的介绍,不难写出为后台服务程序添加对系统热键响应的功能代码。首先通过函数GlobalFindAtom()查询本服务程序所对应的全局原子是否已存在于全局原子表中,假如发现,则说明系统中已经存在有此服务,程序退出。假如没有发现,则通过GlobalAddAtom()函数向全局原子表添加一个字串,并获取得到一个唯一标识此字串的原子。以上两函数原型分别为:
以下是引用片段: ATOM GlobalFindAtom(LPCTSTR lpString); ATOM GlobalAddAtom(LPCTSTR lpString); |
以下是引用片段: BOOL RegisterHotKey(HWND hWnd, // 接收热键响应的窗口句柄 int id, // 热键的标识 UINT fsModifiers, // 控制键标志 UINT vk // 虚拟键值 ); |
以下是引用片段: // 获取当前窗口句柄 HWND handle = GetSafeHwnd(); // 寻找HotKey对应的原子是否存在于原子列表 if(GlobalFindAtom("Hotkey") == 0) { // 假如没有存在于原子列表,则创建一个原子 id = GlobalAddAtom("Hotkey"); //注册全局热键Ctrl + Alt + R RegisterHotKey(handle, id, CONTROL + ALT, R); } else // 假如HotKey已经存在于原子列表,则终止程序运行 PostQuitMessage(0); |
以下是引用片段: 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); |
以下是引用片段: void CServiceDlg::OnHotKey(WPARAM wParam, LPARAM lParam) { // 判定是否是本服务程序设置的系统热键 if (wParam == id) { …… // 在此发送WM_PAINT消息,在OnPain()中通过 // ShowWindow(SW_SHOW)将界面设置为可视 PostMessage(WM_PAINT, 0, 0); } } |
赞助商链接