我正在尝试创建一个与Windows UAC like shown in this tutorial类似的屏幕锁定器。我无法创建背景最大化窗口,减少光线,以及桌面的屏幕截图。
以下是我到目前为止所尝试的所有代码:
program Project1;
uses
Winapi.Windows, Winapi.Messages, Vcl.Graphics, Vcl.Forms;
function MainWndProc(hWindow: HWND; Msg: UINT; wParam: wParam;
lParam: lParam): LRESULT;
var
ps: TPaintStruct;
ScreenDC: HDC;
ScreenHandle: HWnd;
ScreenBitmap: TBitmap;
begin
Result := 0;
case Msg of
WM_PAINT:
begin
BeginPaint(hWindow, ps);
ScreenHandle := GetDeskTopWindow;
ScreenDC := GetDC(ScreenHandle);
try
ScreenBitmap := TBitMap.Create;
try
ScreenBitmap.Width := Screen.Width;
ScreenBitmap.Height := Screen.Height;
BitBlt(ScreenBitmap.Canvas.Handle, 0, 0,
Screen.Width, Screen.Height, ScreenDC, 0, 0, SRCCOPY);
finally
ScreenBitmap.Free
end
finally
ReleaseDC(ScreenHandle, ScreenDC)
end;
EndPaint(hWindow, ps);
end;
WM_DESTROY: PostQuitMessage(0);
else
begin
Result := DefWindowProc(hWindow, Msg, wParam, lParam);
Exit;
end;
end;
end;
var
wc: TWndClass;
hWindow: HWND;
Msg: TMsg;
begin
wc.lpszClassName := 'App';
wc.lpfnWndProc := @MainWndProc;
wc.Style := CS_VREDRAW or CS_HREDRAW;
wc.hInstance := hInstance;
wc.hIcon := LoadIcon(0, IDI_APPLICATION);
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.hbrBackground := (COLOR_WINDOW + 1);
wc.lpszMenuName := nil;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
RegisterClass(wc);
hWindow := CreateWindowEx(WS_EX_CONTROLPARENT or WS_EX_WINDOWEDGE,
'AppClass',
'CREATE_WND',
WS_VISIBLE or WS_CLIPSIBLINGS or
WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
400, 300,
0,
0,
hInstance,
nil);
ShowWindow(hWindow, CmdShow);
UpDateWindow(hWindow);
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Halt(Msg.wParam);
end.
答案 0 :(得分:0)
创建背景最大化窗口 - 非常简单
CreateWindowExW(WS_EX_TOPMOST, L"myclassname", 0, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), HWND_DESKTOP, 0, (HINSTANCE)&__ImageBase, this);
在WM_NCCREATE
我们需要捕获屏幕
//HDC _hDC; - class member
//HGDIOBJ _o;
BOOL Capture()
{
BOOL fOk = FALSE;
if (HDC hdc = GetDC(HWND_DESKTOP))
{
if (_hDC = CreateCompatibleDC(hdc))
{
int cx = GetSystemMetrics(SM_CXSCREEN), cy = GetSystemMetrics(SM_CYSCREEN);
if (HBITMAP hbmp = CreateCompatibleBitmap(hdc, cx, cy))
{
_o = SelectObject(_hDC, hbmp);
static BLENDFUNCTION bf = { AC_SRC_OVER, 0, 0x80, AC_SRC_ALPHA };// 0x80 -> 50%
fOk = AlphaBlend(_hDC, 0, 0, cx, cy, hdc, 0, 0, cx, cy, bf);
}
}
ReleaseDC(HWND_DESKTOP, hdc);
}
return fOk;
}
WindowProc就足够了
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NCDESTROY:
if (_hDC)
{
if (_o)
{
DeleteObject(SelectObject(_hDC, _o));
}
DeleteDC(_hDC);
}
//Release();
break;
case WM_NCCREATE:
//AddRef();
if (!Capture()) return FALSE;
break;
case WM_CLOSE:
return 0;// prevent from close
case WM_ERASEBKGND:
return TRUE;
case WM_PAINT:
{
PAINTSTRUCT ps;
if (BeginPaint(hwnd, &ps))
{
BitBlt(ps.hdc,
ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.top,
_hDC, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
EndPaint(hwnd, &ps);
}
}
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
static LRESULT CALLBACK _WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CScreenLocker* This;
if (uMsg == WM_NCCREATE)
{
This = reinterpret_cast<CScreenLocker*>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams);
SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(This));
}
else
{
This = reinterpret_cast<CScreenLocker*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
}
if (This)
{
//This->AddRef();
LRESULT r = This->WindowProc(hwnd, uMsg, wParam, lParam);
//This->Release();
return r;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
然后,在创建背景最大化窗口 - hwnd之后,需要使用hwnd作为父对象创建对话框。说
ShowWindow(hwnd, SW_SHOW);
MessageBoxW(hwnd,...);
DestroyWindow(hwnd);