我是参考了这段代码后修改成VC的代码,再去试试拦截 HCBT_CREATEWNDlibrary ShowHook;{ Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. }uses SysUtils, Classes, Windows, Messages;var hhook: Windows.HHOOK; oldWndProc: Integer;{$R *.res}function WindowProc(hwnd: HWND; msg: UINT; wp: WPARAM; lp: LPARAM): LRESULT; stdcall; var wndPos: PWindowPos; begin if msg = WM_WINDOWPOSCHANGING then begin wndPos := PWindowPos(lp); if (wndPos^.flags and SWP_SHOWWINDOW) <> 0 then begin wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW)); end; end; Result := CallWindowProc(TFNWndProc(oldWndProc), hwnd, msg, wp, lp); if msg = WM_WINDOWPOSCHANGING then begin SetWindowLong(hwnd, GWL_WNDPROC, Integer(oldWndProc)); end; end;function ShowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): Integer; stdcall; var cwp: PCwpStruct; wndPos: PWindowPos; clsName: array[0..31] of Char; str: WideString; begin if (nCode < 0) then // or (nCode = HC_NOREMOVE) begin Result := CallNextHookEx(hhook, nCode, wParam, lParam); exit; end; OutputDebugString('Hook procedure entered.'); cwp := PCwpStruct(lParam); if cwp^.message <> WM_WINDOWPOSCHANGING then begin Result := CallNextHookEx(hhook, nCode, wParam, lParam); exit; end; OutputDebugString('WM_WINDOWPOSCHANGING captured.'); wndPos := PWindowPos(cwp^.lParam); if (wndPos^.flags and SWP_SHOWWINDOW) = 0 then begin Result := CallNextHookEx(hhook, nCode, wParam, lParam); exit; end; OutputDebugString('SWP_SHOWWINDOW found.'); // 其他代码及记录日志 ...... if (wndPos^.hwnd <> 0) and IsWindow(wndPos^.hwnd) then begin OutputDebugString('Window handle is valid.'); if GetClassName(wndPos^.hwnd, clsName, 32) <> 0 then begin OutputDebugString('Window class name is: '); OutputDebugString(clsName); if CompareText(clsName, 'Notepad') = 0 then begin {$if false} MessageBox(0, 'Notepad will show.', nil, MB_OK); str := Format('0x%X', [wndPos^.flags]); MessageBox(0, PWideChar(str), nil, MB_OK); wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW)); str := Format('0x%X', [wndPos^.flags]); MessageBox(0, PWideChar(str), nil, MB_OK); Result := 0; exit; {$ifend} oldWndProc := SetWindowLong(wndPos^.hwnd, GWL_WNDPROC, Integer(@WindowProc)); end; end; end; Result := CallNextHookEx(hhook, nCode, wParam, lParam); end;procedure Hook(bEnable: Boolean); stdcall; export; begin if bEnable then begin if hhook = 0 then begin hhook := SetWindowsHookEx(WH_CALLWNDPROC, ShowHookProc, HInstance, 0); end; end else begin if hhook <> 0 then begin UnhookWindowsHookEx(hhook); hhook := 0; end; end; end;exports Hook;begin hhook := 0; oldWndProc := 0; end.
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }uses
SysUtils,
Classes,
Windows,
Messages;var
hhook: Windows.HHOOK;
oldWndProc: Integer;{$R *.res}function WindowProc(hwnd: HWND; msg: UINT; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;
var
wndPos: PWindowPos;
begin
if msg = WM_WINDOWPOSCHANGING then
begin
wndPos := PWindowPos(lp);
if (wndPos^.flags and SWP_SHOWWINDOW) <> 0 then
begin
wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW));
end;
end; Result := CallWindowProc(TFNWndProc(oldWndProc), hwnd, msg, wp, lp); if msg = WM_WINDOWPOSCHANGING then
begin
SetWindowLong(hwnd, GWL_WNDPROC, Integer(oldWndProc));
end;
end;function ShowHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
var
cwp: PCwpStruct;
wndPos: PWindowPos;
clsName: array[0..31] of Char; str: WideString;
begin
if (nCode < 0) then // or (nCode = HC_NOREMOVE)
begin
Result := CallNextHookEx(hhook, nCode, wParam, lParam);
exit;
end; OutputDebugString('Hook procedure entered.');
cwp := PCwpStruct(lParam);
if cwp^.message <> WM_WINDOWPOSCHANGING then
begin
Result := CallNextHookEx(hhook, nCode, wParam, lParam);
exit;
end; OutputDebugString('WM_WINDOWPOSCHANGING captured.');
wndPos := PWindowPos(cwp^.lParam);
if (wndPos^.flags and SWP_SHOWWINDOW) = 0 then
begin
Result := CallNextHookEx(hhook, nCode, wParam, lParam);
exit;
end; OutputDebugString('SWP_SHOWWINDOW found.'); // 其他代码及记录日志 ......
if (wndPos^.hwnd <> 0) and IsWindow(wndPos^.hwnd) then
begin
OutputDebugString('Window handle is valid.'); if GetClassName(wndPos^.hwnd, clsName, 32) <> 0 then
begin
OutputDebugString('Window class name is: ');
OutputDebugString(clsName); if CompareText(clsName, 'Notepad') = 0 then
begin
{$if false}
MessageBox(0, 'Notepad will show.', nil, MB_OK); str := Format('0x%X', [wndPos^.flags]);
MessageBox(0, PWideChar(str), nil, MB_OK); wndPos^.flags := (wndPos^.flags and (not SWP_SHOWWINDOW)); str := Format('0x%X', [wndPos^.flags]);
MessageBox(0, PWideChar(str), nil, MB_OK); Result := 0;
exit;
{$ifend}
oldWndProc := SetWindowLong(wndPos^.hwnd, GWL_WNDPROC, Integer(@WindowProc));
end;
end;
end;
Result := CallNextHookEx(hhook, nCode, wParam, lParam);
end;procedure Hook(bEnable: Boolean); stdcall; export;
begin
if bEnable then
begin
if hhook = 0 then
begin
hhook := SetWindowsHookEx(WH_CALLWNDPROC, ShowHookProc, HInstance, 0);
end;
end
else
begin
if hhook <> 0 then
begin
UnhookWindowsHookEx(hhook);
hhook := 0;
end;
end;
end;exports
Hook;begin
hhook := 0;
oldWndProc := 0;
end.
窗口初始化完毕,也就是他执行了UpdateWindow SHowWindow 之前隐藏了,这才是根本的方法。
先不说钩子不钩子
直接自己写的窗口想实现类似的功能一般是在OnNcPaint里
这样窗口不会闪
但是焦点还是会闪