首页  编辑  

NT/Win2K下模拟按Ctrl+Alt+Del

Tags: /超级猛料/Hardware.硬件相关/键盘和鼠标/   Date Created:

好像没有作用?

按照作者的说法,需要做成Service,但是我做了,好像还是没有效果?不知道漏掉了什么地方?我Install Service之后还是不行。:(

回复人: edguo() (2002-1-14 23:59:40)  得0分

// 这是我以前写的一段代码,在NT/Win2k下可以工作

// 算你好运。

// 主要的trick是WindowsStation/Desktop和那句PostMessage

const

 DEF_ACT_WS: PChar = 'WinSta0';        // current user window station

 LOGON_DT: PChar = 'WinLogon';        // winlogon desktop

 DEFAULT_DT: PChar = 'Default';        // default desktop

const

 FLAG_OPEN_WS =

     WINSTA_ENUMDESKTOPS or WINSTA_READATTRIBUTES or

     WINSTA_ACCESSCLIPBOARD or WINSTA_CREATEDESKTOP or

     WINSTA_WRITEATTRIBUTES or WINSTA_ACCESSGLOBALATOMS or

     WINSTA_EXITWINDOWS or WINSTA_ENUMERATE or WINSTA_READSCREEN;

 FLAG_OPEN_DT =

     DESKTOP_READOBJECTS or DESKTOP_CREATEWINDOW or

     DESKTOP_CREATEMENU or DESKTOP_HOOKCONTROL or

     DESKTOP_JOURNALRECORD or DESKTOP_JOURNALPLAYBACK or

     DESKTOP_ENUMERATE or DESKTOP_WRITEOBJECTS or DESKTOP_SWITCHDESKTOP;

function OpenWSDT (pszWS, pszDT: PChar; var hOldWS: HWINSTA;

 var hOldDT: HDESK): Boolean;

var

 hNewWS: HWINSTA;

 hNewDT: HDESK;

begin

 Result := FALSE;

 hOldWS := GetProcessWindowStation;

 hOldDT := GetThreadDesktop (GetCurrentThreadID);

 hNewWS := 0;

 if pszWS<>nil then

 begin

   hNewWS := OpenWindowStation(pszWS,FALSE,FLAG_OPEN_WS);

   if hNewWS<>0 then

   begin

     if not SetProcessWindowStation(hNewWS) then

     begin

       CloseWindowStation(hNewWS);

       Exit;

     end;

   end else Exit;

 end;

 if pszDT=nil then

 hNewDT := OpenInputDesktop(0,FALSE,FLAG_OPEN_DT) else

 hNewDT := OpenDesktop (pszDT,0,FALSE,FLAG_OPEN_DT);

 if hNewDT<>0 then

 if not SetThreadDesktop (hNewDT) then

 begin

   CloseDesktop (hNewDT);

 end else Result := TRUE;

 if not Result then

 begin

     // Failed, close switched station

   if hNewWS<>0 then

   begin

     if SetProcessWindowStation(hOldWS) then

     begin

       CloseWindowStation (hNewWS);

     end;

   end;

 end;

end;

procedure SwitchWSDT(hWS: HWINSTA; hDT: HDESK);

var

 hCurWS: HWINSTA;

 hCurDT: HDESK;

begin

 if hWS<>0 then

 begin

   hCurWS := GetProcessWindowStation;

   if hWS<>hCurWS then

   if SetProcessWindowStation(hWS) then

   begin

     CloseWindowStation(hCurWS);

   end;

 end;

 if hDT<>0 then

 begin

   hCurDT := GetThreadDesktop (GetCurrentThreadID);

   if hCurDT<>hDT then

   if SetThreadDesktop(hDT) then

   begin

     CloseDesktop(hCurDT);

   end;

 end;

end;

procedure SimulateCtrlAltDel (bIsWinNT: Boolean);

var

 hOldWS: HWINSTA;

 hOldDT: HDESK;

begin

 if not OpenWSDT(DEF_ACT_WS,LOGON_DT,hOldWS,hOldDT) then hOldWS := 0;

 PostMessage(HWND_BROADCAST,WM_HOTKEY,0,

     MAKELONG(MOD_ALT or MOD_CONTROL, VK_DELETE));

 if hOldWS<>0 then SwitchWSDT(hOldWS,hOldDT);

end;

// HTH  

回复人: touhu(吐血) (2002-1-15 13:26:28)  得0分

你的意思是不是要捕捉CTRL+ALT+DEL,不让系统显示出原来的"关闭程序"的窗口,而是显示你自己的窗口?  

回复人: edguo() (2002-1-15 13:48:34)  得0分

工作在Service模式可以。

我在我们的产品的远程维护一直用着。

代码是对的。

在user模式下我没仔细研究过,抱歉。

我刚才看了一下,是OpenDesktop()失败,估计是权限还是什么原因,没时间研究。

Good luck.

回复人: edguo() (2002-1-15 14:01:36)  得0分

我注意到OpenDesktop()属于Service Functions,

如果你使用这段代码,说不好只能写Service,

到目前为止我还没见过不用Service就能这样做的软件

(除了Windows本身,其实我怀疑它是怎么做的)。

HTH.

回复人: edguo() (2002-1-15 14:10:36)  得0分

//这是段模拟按键的代码,也是我以前写的。

// 特殊按键通过SetShiftState()来做,例如SetShiftState(VK_MENU,TRUE);

procedure KeybdEvent (KeyCode: Byte; Flags: DWORD);

begin

 Keybd_Event(KeyCode, MapVirtualKey(KeyCode, 0), Flags, 0);

end;

procedure SetShiftState (Key: Byte; Down: Boolean);

var

 KeyState: Boolean;

 Flags: DWORD;

begin

 KeyState := GetAsyncKeyState(Key) and $8000<>0;

 if (KeyState and Down) or ((not KeyState)and(not Down)) then Exit;

 if Down then Flags := 0 else Flags := KEYEVENTF_KEYUP;

 KeybdEvent(Key,Flags);

end;

procedure SendKey (KeySym: Char; KeyDown: Boolean; bIsWinNT: Boolean);

var

 KeyVal: SmallInt;

 KeyCode, KeyMask: Byte;

 LShift,RShift,Ctrl,Alt, CapsLock: Boolean;

 Flags: DWORD;

begin

 KeyVal := VkKeyScan(Char(Byte(KeySym) and $FF));

 KeyCode := LOBYTE(KeyVal);

 KeyMask := HIBYTE(KeyVal);

 if KeyCode=$FF then Exit;

 CapsLock := (GetAsyncKeyState(VK_CAPITAL) and $8000)<>0;

 if CapsLock then KeyMask := KeyMask xor 1;

 if bIsWinNT then

 begin

   LShift := (GetAsyncKeyState(VK_LSHIFT) and $8000) <> 0;

   RShift := (GetAsyncKeyState(VK_RSHIFT) and $8000) <> 0;

   SetShiftState(VK_RSHIFT, FALSE);

   SetShiftState(VK_LSHIFT, FALSE);

   SetShiftState(VK_SHIFT, (KeyMask and $01)<>0);

   Ctrl := (GetAsyncKeyState(VK_LCONTROL) and $8000) <> 0;

   if (not Ctrl) then SetShiftState(VK_LCONTROL,(KeyMask and $02)<>0);

   Alt := (GetAsyncKeyState(VK_LMENU) and $8000) <> 0;

   if (not Alt) then SetShiftState(VK_LMENU,(KeyMask and $04)<>0);

 end else

 begin

   LShift := (GetAsyncKeyState(VK_SHIFT) and $8000) <> 0;

   RShift := FALSE;

   SetShiftState (VK_SHIFT, (KeyMask and $01)<>0);

   Ctrl := (GetAsyncKeyState(VK_CONTROL) and $8000) <> 0;

   if  (not Ctrl) then SetShiftState(VK_CONTROL, (Keymask and $02)<>0);

   Alt := (GetAsyncKeyState(VK_MENU) and $8000) <> 0;

   if (not Alt) then SetShiftState(VK_MENU,(KeyMask and $04)<>0);

 end;

 if KeyDown then Flags := 0 else Flags := KEYEVENTF_KEYUP;

 KeybdEvent(KeyCode and $FF,Flags);

 if bIsWinNT then

 begin

   SetShiftState(VK_LSHIFT, LShift);

   SetShiftState(VK_RSHIFT, RSHIFT);

   SetShiftState(VK_LCONTROL, CTRL);

   SetShiftState(VK_LMENU, ALT);

 end else

 begin

   SetShiftState(VK_SHIFT, LSHIFT);

   SetShiftState(VK_CONTROL, CTRL);

   SetShiftState(VK_MENU, ALT);

 end;

end;

// HTH

// 不要有非法企图啊