Както е посочено в коментарите, можете да рисувате директно на екрана. GetDC предлага да върне подходящия контекст на устройството:
hWnd [in]
Манипулатор на прозореца, чийто DC трябва да бъде извлечен. Ако тази стойност е NULL, GetDC извлича DC за целия екран.
Изобразяването директно на екрана създава поне два проблема, които трябва да бъдат решени:
- Екранът DC е споделен ресурс. Всеки път, когато някой друг рендира на екрана (напр. когато се показва прозорец), тази част от екрана се презаписва.
- Рендирането е разрушително. При изобразяване в контекст на устройство, оригиналното съдържание се презаписва. За да приложите ефект на избледняване, ще трябва да запазите оригиналното съдържание (и да го актуализирате динамично, докато се показват други прозорци).
И двата проблема могат да бъдат решени чрез създаване на прозорец вместо това. Не е необходимо прозорецът да има рамка, лента с надписи, системно меню или бутони за минимизиране/увеличаване/затваряне. Подходящите стилове на прозорци са WS_POPUP | WS_VISIBLE
.
За да накарате прозореца да се показва пред всичко останало, той трябва да бъде маркиран като най-горния (с помощта на WS_EX_TOPMOST
Разширен стил на прозорец). Обърнете внимание, че това поставя прозореца над всички други не-горни прозорци в Z-реда. Все още трябва да се биете с други най-горни прозорци (надпревара във въоръжаването, която не можете да спечелите).
За прилагане на прозрачност прозорецът трябва да има WS_EX_LAYERED
разширения стил на прозореца, както и за създаване на слоест прозорец. След това алфа прозрачността се активира чрез извикване на SetLayeredWindowAttributes. За да запазите фона на прозореца напълно прозрачен, независимо от алфа прозрачността на прозореца, вие също трябва да активирате цветовия манипулатор. Лесен начин да направите това е да зададете член hbrBackground
на WNDCLASSEX структура към (HBRUSH)GetStockObject(BLACK_BRUSH)
и посочете RGB(0, 0, 0)
като аргумент crKey
в обаждането до SetLayeredWindowAttributes
.
Доказателство за концепцията (проверката за грешки е изключена за краткост):
#define STRICT 1
#define WIN32_LEAN_AND_MEAN
#include <SDKDDKVer.h>
#include <windows.h>
// Forward declarations
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
// Entry point
int APIENTRY wWinMain( HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/,
int nCmdShow ) {
Първо е регистриране на класа на основния прозорец на приложението. Важното е членът hbrBackground
. Това контролира изобразяването на фона и в крайна сметка ще стане напълно прозрачно.
const wchar_t k_WndClassName[] = L"OverlayWindowClass";
// Register window class
WNDCLASSEXW wcex = { 0 };
wcex.cbSize = sizeof( wcex );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = ::LoadCursorW( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)::GetStockObject( BLACK_BRUSH );
wcex.lpszClassName = k_WndClassName;
::RegisterClassExW( &wcex );
Това е целият код за настройка, необходим за създаване на прозорец и коригиране на неговите атрибути. Алфа прозрачността е активирана, за да се подготви за ефекта на избледняване, докато цветовият манипулатор маскира онези области от прозореца, които не са изобразени.
HWND hWnd = ::CreateWindowExW( WS_EX_TOPMOST | WS_EX_LAYERED,
k_WndClassName,
L"Overlay Window",
WS_POPUP | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
800, 600,
NULL, NULL,
hInstance,
NULL );
// Make window semi-transparent, and mask out background color
::SetLayeredWindowAttributes( hWnd, RGB( 0, 0, 0 ), 128, LWA_ALPHA | LWA_COLORKEY );
Останалата част от wWinMain
е шаблонен код на Windows приложение.
::ShowWindow( hWnd, nCmdShow );
::UpdateWindow( hWnd );
// Main message loop:
MSG msg = { 0 };
while ( ::GetMessageW( &msg, NULL, 0, 0 ) > 0 )
{
::TranslateMessage( &msg );
::DispatchMessageW( &msg );
}
return (int)msg.wParam;
}
Процедурата на прозореца изпълнява просто изобразяване. За да демонстрира прозрачност на алфа и ключовия цвят, кодът изобразява бяла елипса с клиентската област като ограничаващ правоъгълник. Освен това съобщението WM_NCHITTEST също се обработва, за предоставя лесен начин за плъзгане на прозореца през екрана с помощта на мишката или друго посочващо устройство. Имайте предвид, че въвеждането на мишката се предава на прозореца отдолу за всички области, които са напълно прозрачни.
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_PAINT:
{
PAINTSTRUCT ps = { 0 };
HDC hDC = ::BeginPaint( hWnd, &ps );
RECT rc = { 0 };
::GetClientRect( hWnd, &rc );
HBRUSH hbrOld = (HBRUSH)::SelectObject( hDC,
::GetStockObject( WHITE_BRUSH ) );
::Ellipse( hDC, rc.left, rc.top, rc.right, rc.bottom );
::SelectObject( hDC, hbrOld );
::EndPaint( hWnd, &ps );
}
return 0;
case WM_NCHITTEST:
return HTCAPTION;
case WM_DESTROY:
::PostQuitMessage( 0 );
return 0;
default:
break;
}
return ::DefWindowProc( hWnd, message, wParam, lParam );
}
Алтернативен манипулатор
WM_PAINT
, който извежда текст. Важно е да използвате цвят на текста, различен от цвета на ключа. Ако искате да използвате черен текст, ще трябва да използвате различен цвят на клавиша.
case WM_PAINT:
{
PAINTSTRUCT ps = { 0 };
HDC hDC = ::BeginPaint( hWnd, &ps );
RECT rc = { 0 };
::GetClientRect( hWnd, &rc );
::SetTextColor( hDC, RGB( 255, 255, 255 ) );
::SetBkMode( hDC, TRANSPARENT );
::DrawTextExW( hDC, L"Hello, World!", -1, &rc,
DT_SINGLELINE | DT_CENTER | DT_VCENTER, NULL );
::EndPaint( hWnd, &ps );
}
return 0;
person
IInspectable
schedule
17.03.2015
GetDC(0)
, за да получитеHDC
манипулатора на платното за екрана, и след това можете да рисувате върху него, ако е необходимо. - person Remy Lebeau   schedule 17.03.2015