Windows API:在屏幕显示时写入屏幕 [英] Windows API: write to screen as on screen display

查看:41
本文介绍了Windows API:在屏幕显示时写入屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a (very) small application which just performs some minor things at start and should write a message on the screen similar as for an on-screen-display: Big letters, without any window, above everything, visible for some moment and then fade away.

如果可能,我不想为它创建窗口.

If possible I do not want to create a window for it.

这样做的正确方法是什么?

What is the right way to do this?

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

(I hope there are no special toolkits like DirectX, direct graphics access etc. required)

推荐答案

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

As pointed out in the comments, you can draw directly to the screen. GetDC offers to return the appropriate device context:

hWnd [in]

要检索其 DC 的窗口的句柄.如果此值为 NULL,GetDC 将检索整个屏幕的 DC.

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

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

Rendering directly to the screen poses at least two problems that need to be addressed:

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

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

Both issues can be solved by creating a window instead. A window is not required to have a border, caption bar, system menu or minimize/maximize/close buttons. The appropriate Window Styles are WS_POPUP | WS_VISIBLE.

要使窗口显示在其他所有内容的前面,需要将其标记为最顶层(使用 WS_EX_TOPMOST 扩展窗口样式).请注意,这会将窗口置于 Z 顺序中所有其他非最顶层窗口的上方.你仍然需要与其他最顶层的窗口进行斗争(一场你赢不了的军备竞赛).

To make the window show up in front of everything else, it needs to be marked as topmost (using the WS_EX_TOPMOST Extended Window Style). Note, that this places the window above all other non-topmost windows in the Z-order. You still have to fight with other topmost windows (an arms race you cannot win).

要实现透明度,窗口还必须具有 WS_EX_LAYERED 扩展窗口样式以创建 分层窗口.然后调用 SetLayeredWindowAttributes 启用 Alpha 透明度.无论窗口的 alpha 透明度如何,要保持窗口背景完全透明,您还需要启用颜色键控.一个简单的方法是设置 hbrBackground 成员rel="noreferrer">WNDCLASSEX 结构(HBRUSH)GetStockObject(BLACK_BRUSH),并在调用 SetLayeredWindowAttributes<时指定 RGB(0, 0, 0) 作为 crKey 参数/代码>.


概念证明(为简洁起见省略了错误检查):

To implement transparency the window must have the WS_EX_LAYERED extended window style as well to create a Layered Window. Alpha transparency is then enabled calling SetLayeredWindowAttributes. To keep the window background fully transparent regardless of the window's alpha transparency you also need to enable color keying. A simple way to do this is to set the hbrBackground member of the WNDCLASSEX structure to (HBRUSH)GetStockObject(BLACK_BRUSH), and specify RGB(0, 0, 0) as the crKey argument in the call to SetLayeredWindowAttributes.


Proof of concept (error checking elided for brevity):

#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 成员.这控制了背景渲染,最终将完全透明.

First up is registering the main application window class. The important piece is the hbrBackground member. This controls background rendering, and will eventually be made fully transparent.

    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 透明度以准备淡出效果,同时颜色键控会遮蔽那些未渲染的窗口区域.

This is all the setup code required to instantiate a window, and adjust it's attributes. Alpha transparency is enabled to prepare for the fade-out effect, while color keying masks out those areas of the window that aren't rendered to.

    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 应用程序代码.

The remainder of wWinMain is boilerplate windows application code.

    ::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 消息,以提供一种使用鼠标或其他指针设备在屏幕上拖动窗口的简单方法.请注意,对于所有完全透明的区域,鼠标输入都会传递到下方的窗口.

The window procedure is performs simple rendering. To demonstrate both alpha and key color transparency the code renders a white ellipse with the client area as the bounding rectangle. In addition, the WM_NCHITTEST message is also handled, to provide a simple way to dragged the window accross the screen using the mouse or another pointing device. Note that mouse input is passed to the window underneath for all areas that are fully transparent.

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 处理程序,输出文本.使用与键颜色不同的文本颜色很重要.如果要使用黑色文本,则必须使用不同的键色.


Alternative WM_PAINT handler, that outputs text. It's important to use a text color different from the key color. If you want to use black text you will have to use a different key color.

    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:在屏幕显示时写入屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆