Как указано в комментариях, вы можете рисовать прямо на экране. GetDC предлагает вернуть соответствующий контекст устройства:
hWnd [in]
Дескриптор окна, контроллер домена которого необходимо получить. Если это значение равно NULL, GetDC извлекает контроллер домена для всего экрана.
Рендеринг непосредственно на экран создает как минимум две проблемы, которые необходимо решить:
- Экран 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