星云电脑教程
您现在的位置: 星云电脑教程 >> 电脑教程 >> 经验共享 >> 操作系统 >> WinXP专栏 >> 正文
XP中屏蔽 Ctrl+Alt+Del         ★★★

Windows XP系统中如何屏蔽 Ctrl+Alt+Del、Alt+Tab以及Ctrl+Esc键序列

星云电脑教程 文章来源:vckbase 作者:northtib… 更新时间:2006-6-17 10:12:36 【 有问必答

本文转自:星云电脑教程www.gonet8.com

//////////////////////////////////
// 低级键盘钩子
// 截获任务转换键:不传递直接返回
//
LRESULT CALLBACK MyTaskKeyHookLL(int nCode, WPARAM wp, LPARAM lp)
{
   KBDLLHOOKSTRUCT *pkh = (KBDLLHOOKSTRUCT *) lp;

   if (nCode==HC_ACTION) {
      BOOL bCtrlKeyDown =
         GetAsyncKeyState(VK_CONTROL)>>((sizeof(SHORT) * 8) - 1);

      if ((pkh->vkCode==VK_ESCAPE && bCtrlKeyDown) || // Ctrl+Esc
          // Alt+TAB
          (pkh->vkCode==VK_TAB && pkh->flags & LLKHF_ALTDOWN) ||   
          // Alt+Esc
          (pkh->vkCode==VK_ESCAPE && pkh->flags & LLKHF_ALTDOWN)|| 
          (pkh->vkCode==VK_LWIN || pkh->vkCode==VK_RWIN)) { // 开始菜单
         if (g_bBeep && (wp==WM_SYSKEYDOWN||wp==WM_KEYDOWN))
            MessageBeep(0); // 蜂鸣
         return 1; // 不再往CallNextHookEx传递,直接返回
      }
   }
   return CallNextHookEx(g_hHookKbdLL, nCode, wp, lp);
}

////////////////////////////////////////////////
// 是否屏蔽任务键序列——也就是说键盘钩子是否安装?
// 注:这里假设没有其它钩子做同样的事情
//
DLLEXPORT BOOL AreTaskKeysDisabled()
{
   return g_hHookKbdLL != NULL;
}

////////////////////////////////////////////////
// 屏蔽任务键:安装低级键盘构
// 返回当前是否屏蔽标志(TRUE/FALSE)
//
DLLEXPORT BOOL DisableTaskKeys(BOOL bDisable, BOOL bBeep)
{
   if (bDisable) {
      if (!g_hHookKbdLL) {
         g_hHookKbdLL = SetWindowsHookEx(WH_KEYBOARD_LL,
            MyTaskKeyHookLL, MyDll.m_hInstance, 0);
      }

   } else if (g_hHookKbdLL != NULL) {
      UnhookwindowsHookEx(g_hHookKbdLL);
      g_hHookKbdLL = NULL;
   }
   g_bBeep = bBeep;

   return AreTaskKeysDisabled();
}      

    TaskKeyHook 输出两个函数:DisableTaskKeys 和 AreTaskKeysDisabled。前者安装WH_KEYBOARD_LL 钩子;后者判断这个钩子是否安装。此键盘钩子的处理思路是截获Alt+Tab,Ctrl+Esc,Alt+Esc以及windows 键VK_LWIN/VK_RWIN,关于这两个键,稍候会有详细描述。当钩子碰到这些键时,它直接返回到调用者,而不是将处理传递给CallNextHookEx 。

LRESULT CALLBACK MyTaskKeyHookLL(...)
{
   if (/* 任务键*)
      return 1; // 立即返回
   return CallNextHookEx(...);
}      

    TaskKeyHook的大部分实现都很简单。只有一个地方用到了一点小技巧:既使用#pragma data_seg 命名包含全程数据的数据段,并且用#pragma comment (linker...)告诉链接器让这个数据段为共享段。实现细节请参考源代码。 本文附带的例子程序(TrapKeys.exe)汇集了上述几个有关屏蔽键盘按键序列的功能,除此之外,它还有一个功能就是禁用任务栏。因为既然禁用了任务转换键,那么一般来说,也必然要禁用任务栏,否则禁用任务转换键就没有意义了。禁用任务栏的具体方法如下:

HWND hwnd = FindWindow("Shell_traywnd", NULL);//找到任务栏
EnableWindow(hwnd, FALSE); // 禁用任务栏

如图四是例子程序运行画面: 

 
图四 TrapKeys程序运行画面

以下是TrapKeys程序的实现代码:

/////////////////////////////////////////////////
// TrapKeys.cpp
//
#include "stdafx.h"
#include "resource.h"
#include "StatLink.h"
#include "TaskKeyMgr.h"

////////////////////
// 主对话框
//
class CMyDialog : public CDialog {
public:
   CMyDialog(CWnd* pParent = NULL) : CDialog(IDD_MYDIALOG, pParent) { }

protected:
   HICON m_hIcon;
   CStaticLink m_wndLink1;
   CStaticLink m_wndLink2;
   CStaticLink m_wndLink3;

   virtual BOOL OnInitDialog();

   // 命令/UI 的更新处理
   afx_msg void OnDisableTaskMgr();
   afx_msg void OnDisableTaskKeys();
   afx_msg void OnDisableTaskbar();
   afx_msg void OnUpdateDisableTaskMgr(CCmdUI* pCmdUI);
   afx_msg void OnUpdateDisableTaskKeys(CCmdUI* pCmdUI);
   afx_msg void OnUpdateDisableTaskbar(CCmdUI* pCmdUI);
   afx_msg LRESULT OnKickIdle(WPARAM,LPARAM);

   DECLARE_MESSAGE_MAP()
};

///////////////////////////////////////////////////////
// 标准的MFC 对话框应用类代码。
//
class CMyApp : public CWinApp {
public:
   virtual BOOL InitInstance() {
      // 初始化app:运行对话框
      CMyDialog dlg;
      m_pMainWnd = &dlg;
      dlg.DoModal();
      return FALSE;
   }
   virtual int ExitInstance() {
      // 为了按全起见,在退出程序的时候,将所有禁用的项目复原
      CTaskKeyMgr::Disable(CTaskKeyMgr::ALL, FALSE);
      return 0;
   }
} theApp;

BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
   ON_COMMAND(IDC_DISABLE_TASKKEYS,OnDisableTaskKeys)
   ON_COMMAND(IDC_DISABLE_TASKBAR, OnDisableTaskbar)
   ON_COMMAND(IDC_DISABLE_TASKMGR, OnDisableTaskMgr)
   ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKKEYS, OnUpdateDisableTaskKeys)
   ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKBAR, OnUpdateDisableTaskbar)
   ON_UPDATE_COMMAND_UI(IDC_DISABLE_TASKMGR, OnUpdateDisableTaskMgr)
   ON_MESSAGE(WM_KICKIDLE,OnKickIdle)
END_MESSAGE_MAP()

///////////////////////////////////////////////
// 初始化对话框:子类化超链接柄加栽图标
//
BOOL CMyDialog::OnInitDialog()
{
   CDialog::OnInitDialog();

   // 初始化超链接
   m_wndLink1.SubclassDlgItem(IDC_EMAIL,this);
   m_wndLink2.SubclassDlgItem(IDC_VCKBASEURL,this);
   m_wndLink3.SubclassDlgItem(IDC_VCKBASELINK,this);

   // 自己设置对话框图标。MFC不会为对话框应用程序设置它
   m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   SetIcon(m_hIcon, TRUE);       // 打图标
   SetIcon(m_hIcon, FALSE);      // 小图标
   
   return TRUE;
}

////////////////////////////////////////////////////////
// 命令/UI 更新处理:写这些东西应该很轻松。

void CMyDialog::OnDisableTaskKeys()
{
   CTaskKeyMgr::Disable(CTaskKeyMgr::TASKKEYS,
      !CTaskKeyMgr::AreTaskKeysDisabled(), TRUE); // 蜂鸣
}
void CMyDialog::OnUpdateDisableTaskKeys(CCmdUI* pCmdUI)
{
   pCmdUI->SetCheck(CTaskKeyMgr::AreTaskKeysDisabled());
}
void CMyDialog::OnDisableTaskbar()
{
   CTaskKeyMgr::Disable(CTaskKeyMgr::TASKBAR,
      !CTaskKeyMgr::IsTaskBarDisabled());
}
void CMyDialog::OnUpdateDisableTaskbar(CCmdUI* pCmdUI)
{
   pCmdUI->SetCheck(CTaskKeyMgr::IsTaskBarDisabled());
}
void CMyDialog::OnDisableTaskMgr()
{
   CTaskKeyMgr::Disable(CTaskKeyMgr::TASKMGR,
      !CTaskKeyMgr::IsTaskMgrDisabled());
}
void CMyDialog::OnUpdateDisableTaskMgr(CCmdUI* pCmdUI)
{
   pCmdUI->SetCheck(CTaskKeyMgr::IsTaskMgrDisabled());
}

////////////////////////////////////////////////////////
// 要想让ON_UPDATE_COMMAND_UI正常工作,这是必需的。
// 
LRESULT CMyDialog::OnKickIdle(WPARAM wp, LPARAM lCount)
{
   UpdateDialogControls(this, TRUE);
   return 0;
}      

   按上述方法尽管禁用了任务栏,但是还有一个机关没有处理,那就是按下Windows键仍然可以弹出“开始”菜单。显然在处理VK_LWIN之前,任务栏不会检查是否被启用。一般来讲,如果某个窗口被屏蔽掉,那么它就不再会处理用户在这个窗口的输入——这就是所谓的禁用(Disable)的含义。通常调用EnableWindow(FALSE)后自然就达到了这个目的。但是处理VK_LWIN/VK_RWIN按键的代码决不会去检查任务栏启用/禁用状态。对此,本文的处理办法仍然是利用键盘钩子。修改一下TaskKeyHook实现,增加对windows键的捕获。这样按下“开始”菜单键之后什么也不会发生。希望没有漏掉其它的按键。如果哪位读者发现漏掉了什么键,请和我联系,以便把它加到键盘钩子中去。为了简单起见,我在类CTaskKeyMgr中封装了所有禁用的函数。下面是这个类的定义击实现文件:

TaskKeyMgr
////////////////////////////////////////
// TaskKeyMgr.h
//
#pragma once
#include "TaskKeyHook.h"

/////////////////////////////////////////////////////////////////////
// 使用这个类禁用任务键,任务管理器或任务栏。
// 用相应的标志调用Disable,如:CTaskMgrKeys::Disable(CTaskMgrKeys::ALL);
// 
class CTaskKeyMgr {
public:
   enum {
      TASKMGR  = 0x01,  // 禁用任务管理器(Ctrl+Alt+Del)
      TASKKEYS = 0x02,  //禁用任务转换键(Alt-TAB, etc)
      TASKBAR  = 0x04,  //禁用任务栏
      ALL=0xFFFF        //禁用所有东西L
   };
   static void Disable(DWord dwItem,BOOL bDisable,BOOL bBeep=FALSE);

   static BOOL IsTaskMgrDisabled();
   static BOOL IsTaskBarDisabled();
   static BOOL AreTaskKeysDisabled() {
      return ::AreTaskKeysDisabled(); // 调用 DLL 
   }
};

CPP实现
////////////////////////////////////////////////////////////////
// TaskKeyMgr.cpp
//
#include "StdAfx.h"
#include "TaskKeyMgr.h"

#define HKCU HKEY_CURRENT_USER

// 用于禁用任务管理器策略的注册表键值对
LPCTSTR KEY_DisableTaskMgr =
   "Software\\Microsoft\\windows\\CurrentVersion\\Policies\\System";
LPCTSTR VAL_DisableTaskMgr = "DisableTaskMgr";

///////////////////////////////////////////
// 禁用相关的任务键
// 
// dwFlags   =  表示禁用什么
// bDisable   = 禁用为 (TRUE) ,否则为启用 (FALSE)
// bBeep    =  按下非法键是否蜂鸣(指针对任务键)
//
void CTaskKeyMgr::Disable(DWORD dwFlags, BOOL bDisable, BOOL bBeep)
{
   // 任务管理器 (Ctrl+Alt+Del)
   if (dwFlags & TASKMGR) {
      HKEY hk;
      if (RegOpenKey(HKCU, KEY_DisableTaskMgr,&hk)!=ERROR_SUCCESS)
         RegCreateKey(HKCU, KEY_DisableTaskMgr, &hk);

      if (bDisable) { // 禁用任务管理器(disable TM): set policy = 1
         DWORD val=1;
         RegSetValueEx(hk, VAL_DisableTaskMgr, NULL,
            REG_DWORD, (BYTE*)&val, sizeof(val));

      } else { // 启用任务管理器(enable TM)
         RegDeleteValue(hk,VAL_DisableTaskMgr);
      }
   }

   // 任务键 (Alt-TAB etc)
   if (dwFlags & TASKKEYS)
      ::DisableTaskKeys(bDisable,bBeep); // 安装键盘钩

   // 任务栏
   if (dwFlags & TASKBAR) {
      HWND hwnd = FindWindow("Shell_traywnd", NULL);
      EnableWindow(hwnd, !bDisable);
   }
}

BOOL CTaskKeyMgr::IsTaskBarDisabled()
{
   HWND hwnd = FindWindow("Shell_traywnd", NULL);
   return IsWindow(hwnd) ? !IsWindowEnabled(hwnd) : TRUE;
}

BOOL CTaskKeyMgr::IsTaskMgrDisabled()
{
   HKEY hk;
   if (RegOpenKey(HKCU, KEY_DisableTaskMgr, &hk)!=ERROR_SUCCESS)
      return FALSE; // 没有此键,不禁用

   DWORD val=0;
   DWord len=4;
   return RegQueryValueEx(hk, VAL_DisableTaskMgr,
      NULL, NULL, (BYTE*)&val, &len)==ERROR_SUCCESS && val==1;
}      

    这个类中的函数都是静态的,实际上CTaskKeyMgr完全就是一个名字空间。你可以在自己的程序中随心所欲地使用它。例如,禁用任务转换按键和任务栏,但是不禁用Ctrl+Alt+Del:

CTaskKeyMgr::Disable(CTaskKeyMgr::TASKKEYS |
                     CTaskKeyMgr::TASKBAR, TRUE);      

    此外,还有几个函数是用来检查当前禁用了哪些东西,甚至可以在用户按下禁用键时发出蜂鸣声……自己去享受Paul的源代码吧!

上一页  [1] [2] 

点击查看更多“Windows XP系统中如何屏蔽 Ctrl+Alt+Del、Alt+Tab以及Ctrl+Esc键序列”相关文章

教程录入:星云    责任编辑:星云 
相关文章
专 题 栏 目
让Vista和XP双系统共享虚拟
用Win XP组策略修改系统配
XP自带故障恢复控制台应用
活用Windows故障恢复控制台
Windows恢复控制台技巧及应
Windows XP控制台命令详解
Windows XP控制台命令详解
Windows XP控制台命令详解
用脚本恢复Windows XP的用
XP中巧妙去掉多余的安全删

Copyright © 2004-2008 星云电脑教程 GONET8.COM All Rights Reserved 豫ICP备05000636号 站长:星云