Как было отмечено в комментариях, вы можете рисовать прямо на экране. GetDC предложения вернуть соответствующий контекст устройства:
HWND [в]
Дескриптор окна которого DC должен быть восстановлен. Если это значение равно NULL, GetDC получает DC для всего экрана.
Rendering непосредственно на экран создает по меньшей мере, две проблемы, которые необходимо решить:
- Экран DC является общим ресурсом. Всякий раз, когда кто-то другой отображается на экране (например, когда отображается окно), эта часть экрана перезаписывается.
- Рендеринг является разрушительным. При рендеринге в контексте устройства исходное содержимое перезаписывается. Чтобы реализовать эффект постепенного исчезновения, вам нужно будет сохранить исходное содержимое (и динамически обновлять его, когда отображаются другие окна).
Обе проблемы могут быть решены путем создания окна вместо этого. Окно не требуется для того, чтобы иметь границу, заголовок, системное меню или кнопки минимизации/максимизации/закрытия. Соответствующими Window Styles являются WS_POPUP | WS_VISIBLE
.
Чтобы окно выглядело перед всем остальным, оно должно быть помечено как самое верхнее (с использованием WS_EX_TOPMOST
Extended Window Style). Обратите внимание, что это помещает окно выше всех других не самых верхних окон в Z-порядке. Вам все равно придется сражаться с другими самыми верхними окнами (гонка вооружений, которую вы не можете выиграть).
Для обеспечения прозрачности окно должно иметь расширенный стиль окна WS_EX_LAYERED
, а также для создания Layered Window. Затем активируется альфа-прозрачность, вызывающая SetLayeredWindowAttributes. Чтобы фон окна полностью прозрачный, независимо от прозрачности окна, вам также необходимо включить цветную клавиатуру. Простой способ сделать это - установить hbrBackground
член WNDCLASSEX structure на (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
является шаблонные окна кода приложения.
::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 message, чтобы обеспечить простой способ перетаскивать окно по экрану с помощью мыши или другого указывающего устройства. Обратите внимание, что вход мыши передается в окно внизу для всех областей, которые полностью прозрачны.
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;
Создание окна было бы нормальным способом для этого. Windows может быть прозрачной и не обязательно иметь видимый фрейм и т. Д., Если это то, что вас отталкивает от использования. –
Прозрачное окно верхнего уровня лучше всего, но если вам абсолютно необходимо писать на экране напрямую, вы можете использовать 'GetDC (0)', чтобы получить дескриптор холста 'HDC' для экрана, а затем вы можете нарисовать его по мере необходимости. –
Спасибо. Думаю, я пойду за окном – divB