I
import
Unregistered / Unconfirmed
GUEST, unregistred user!
好像没有作用? 按照作者的说法,需要做成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
// 不要有非法企图啊
回复人: 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
// 不要有非法企图啊