gpt4 book ai didi

Windows API : write to screen as on screen display

转载 作者:可可西里 更新时间:2023-11-01 10:54:33 24 4
gpt4 key购买 nike

我正在编写一个(非常)小的应用程序,它在开始时只执行一些小的事情,并且应该在屏幕上写一条类似于屏幕显示的消息:大字母,没有任何窗口,高于一切,可见片刻然后消失。

如果可能我不想为它创建一个窗口。

正确的做法是什么?

(我希望不需要像 DirectX、直接图形访问等特殊工具包)

最佳答案

正如评论中所指出的,您可以直接在屏幕上绘图。 GetDC 提供返回适当的设备上下文:

hWnd [in]

A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC retrieves the DC for the entire screen.

直接渲染到屏幕会带来至少两个需要解决的问题:

  1. 屏幕 DC 是共享资源。每当其他人呈现到屏幕上时(例如,当显示窗口时),屏幕的那部分就会被覆盖。
  2. 渲染是破坏性的。当呈现到设备上下文中时,原始内容会被覆盖。要实现淡出效果,您必须保存原始内容(并在显示其他窗口时动态更新它们)。

这两个问题都可以通过创建一个窗口来解决。窗口不需要有边框、标题栏、系统菜单或最小化/最大化/关闭按钮。合适的 Window StylesWS_POPUP | WS_VISIBLE.

要使窗口显示在其他所有内容的前面,需要将其标记为最顶层(使用 WS_EX_TOPMOST Extended Window Style )。请注意,这会将窗口置于 Z 顺序中所有其他非最顶层窗口之上。您仍然必须与其他最顶层的窗口进行战斗(一场您无法赢得的军备竞赛)。

要实现透明度,窗口必须具有 WS_EX_LAYERED 扩展窗口样式以及创建 Layered Window 。然后调用 SetLayeredWindowAttributes 启用 Alpha 透明度。无论窗口的 alpha 透明度如何,要保持窗口背景完全透明,您还需要启用颜色键控。一个简单的方法是将 WNDCLASSEX structurehbrBackground 成员设置为 (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 );

这是实例化窗口和调整其属性所需的所有设置代码。启用 Alpha 透明度可为淡出效果做准备,同时颜色键控会屏蔽掉未渲染到的窗口区域。

    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;
}

窗口过程执行简单的渲染。为了演示 alpha 和关键颜色透明度,代码呈现了一个白色椭圆,其中客户区作为边界矩形。此外,还处理了 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 API : write to screen as on screen display,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29091028/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com