放大 API 概述

借助放大 API,辅助技术供应商可以开发在 Microsoft Windows 上运行的屏幕放大应用程序。 本主题介绍放大 API,并说明如何在应用程序中使用它。 它包含以下部分:

入门

Windows Vista 和更高版本的操作系统支持放大 API 的原始版本。 在 Windows 8 及更高版本中,API 支持其他功能,包括全屏放大和设置放大的系统光标的可见性。

Magnification.dll提供对放大 API 的支持。 若要编译应用程序,请包含 Magnification.h 并链接到 Magnification.lib。

注意

WOW64 不支持放大 API;也就是说,32 位放大镜应用程序无法在 64 位 Windows 上正常运行。

基本概念

本部分介绍放大 API 所基于的基本概念。 它包含以下部分:

放大镜的类型

API 支持两种类型的放大镜: 全屏放大镜放大镜控件。 全屏放大镜放大整个屏幕的内容,而放大镜控件放大屏幕特定区域的内容,并在窗口中显示内容。 对于这两个放大镜,图像和文本都能够控制放大量。 你还可以将颜色效果应用于放大的屏幕内容,使有颜色缺陷或需要颜色或多或少对比度的用户更容易看到。

重要

放大镜控制 API 在 Windows Vista 及更高版本的操作系统上可用,而全屏放大镜 API 仅在Windows 8及更高版本的操作系统上可用。

放大系数

全屏放大镜和放大镜控件都应用缩放转换来放大屏幕内容。 比例转换应用的放大量称为 放大因子。 它表示为浮点值,其中 1.0 对应于不放大,较大的值会导致相应的放大量。 例如,值为 1.5 会使屏幕内容增加 50%。 小于 1.0 的放大系数无效。

颜色效果

通过将 5x5 颜色转换矩阵应用于放大的屏幕内容的颜色来实现颜色效果。 矩阵确定内容的红色、蓝色、绿色和 alpha 分量强度。 有关详细信息,请参阅 Windows GDI+ 文档中 的 Using a Color Matrix to Transform a Single Color(使用颜色矩阵转换单一颜色 )。

源矩形

全屏放大镜将比例转换和颜色转换应用于整个屏幕。 另一方面,放大镜控件将屏幕的一个区域(称为 源矩形)复制到屏幕外位图。 接下来,控件将缩放转换和颜色转换(如果有)应用于屏幕外位图。 最后, 控件在放大镜控件窗口中显示缩放和颜色转换的位图。

筛选器列表

默认情况下,放大镜控件放大指定源矩形中的所有窗口。 但是,通过提供窗口句柄的 筛选器列表 ,可以控制哪些窗口包含在放大的内容中,哪些窗口不包含。 有关详细信息,请参阅 选择性放大

全屏放大镜不支持筛选器列表;它始终放大屏幕上的所有窗口。

输入转换

通常,放大的屏幕内容对于用户笔或触摸输入是“不可见的”。 例如,如果用户点击控件的放大图像,则系统不一定将输入传递给控件。 相反,如果任何) 驻留在未放大的桌面上的点击屏幕坐标上,系统会将输入传递给任何项 (。 使用 MagSetInputTransform 函数可以指定一个输入转换,该转换将放大的屏幕内容的坐标空间映射到实际 (未放大) 屏幕坐标空间。 这使系统能够将放大屏幕内容中输入的笔或触摸输入传递到屏幕上的正确 UI 元素。

注意

调用进程必须具有 UIAccess 权限才能设置输入转换。 有关详细信息,请参阅UI 自动化安全注意事项/MANIFESTUAC (在清单) 中嵌入 UAC 信息

系统光标

MagShowSystemCursor 函数可用于显示或隐藏系统光标。 如果在全屏放大镜处于活动状态时显示系统光标,则系统光标始终与屏幕内容的其余部分一起放大。 如果在全屏放大镜处于活动状态时隐藏系统光标,则系统光标根本不可见。

使用放大镜控件时, MagShowSystemCursor 函数显示或隐藏未放大的系统光标,但对放大的系统光标没有影响。 放大的系统光标的可见性取决于放大镜控件是否具有 MS_SHOWMAGNIFIEDCURSOR 样式。 如果具有此样式,则每当系统光标进入源矩形时,放大镜控件将显示放大的系统光标以及放大的屏幕内容。

初始化放大镜运行时库

在调用任何其他放大镜 API 函数之前,必须通过调用 MagInitialize 函数来创建和初始化放大镜运行时对象。 同样,使用完放大镜 API 后,调用 MagUninitialize 函数以销毁放大镜运行时对象并释放关联的系统资源。

使用Full-Screen放大镜

若要使用全屏放大镜,请调用 MagSetFullscreenTransform 函数。 magLevel 参数指定放大系数。 xOffsetyOffset 参数指定如何相对于屏幕定位放大的屏幕内容。

当屏幕内容被放大时,它变得大于屏幕本身。 内容的某些部分超出了屏幕边缘,对用户不可见。 MagSetFullscreenTransform 函数的 xOffsetyOffset 参数确定屏幕上显示放大屏幕内容的哪一部分。 参数共同指定未放大的屏幕内容中某个点的坐标。 当内容被放大时,它将与屏幕左上角的指定点一起定位。

以下示例设置全屏放大镜的放大系数,并将放大的屏幕内容的中心置于屏幕中心。

BOOL SetZoom(float magnificationFactor)
{
    // A magnification factor less than 1.0 is not valid.
    if (magnificationFactor < 1.0)
    {
        return FALSE;
    }

    // Calculate offsets such that the center of the magnified screen content 
    // is at the center of the screen. The offsets are relative to the 
    // unmagnified screen content.
    int xDlg = (int)((float)GetSystemMetrics(
            SM_CXSCREEN) * (1.0 - (1.0 / magnificationFactor)) / 2.0);
    int yDlg = (int)((float)GetSystemMetrics(
            SM_CYSCREEN) * (1.0 - (1.0 / magnificationFactor)) / 2.0);

    return MagSetFullscreenTransform(magnificationFactor, xDlg, yDlg);
}

使用 MagSetFullscreenColorEffect 函数通过设置应用程序定义的颜色转换矩阵将颜色效果应用于全屏内容。 例如,以下示例设置将颜色转换为灰度的颜色转换矩阵。

// Initialize color transformation matrices used to apply grayscale and to 
// restore the original screen color.
MAGCOLOREFFECT g_MagEffectGrayscale = {0.3f,  0.3f,  0.3f,  0.0f,  0.0f,
                                       0.6f,  0.6f,  0.6f,  0.0f,  0.0f,
                                       0.1f,  0.1f,  0.1f,  0.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
                                       0.0f,  0.0f,  0.0f,  0.0f,  1.0f};

MAGCOLOREFFECT g_MagEffectIdentity = {1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
                                      0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
                                      0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
                                      0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
                                      0.0f,  0.0f,  0.0f,  0.0f,  1.0f};

BOOL SetColorGrayscale(__in BOOL fGrayscaleOn)
{
    // Apply the color matrix required to either apply grayscale to the screen 
    // colors or to show the regular colors.
    PMAGCOLOREFFECT pEffect = 
                (fGrayscaleOn ? &amp;g_MagEffectGrayscale : &amp;g_MagEffectIdentity);

    return MagSetFullscreenColorEffect(pEffect);
}

可以通过调用 MagGetFullscreenTransform 函数来检索当前放大因子和偏移值。 可以通过调用 MagGetFullscreenColorEffect 函数来检索当前颜色转换矩阵。

使用放大镜控件

放大镜控件放大屏幕特定区域的内容,并在窗口中显示内容。 本部分介绍如何使用放大镜控件。 它包含以下部分:

创建放大镜控件

放大镜控件必须承载于使用 WS_EX_LAYERED 扩展样式创建的窗口中。 创建主机窗口后,调用 SetLayeredWindowAttributes 以设置主机窗口的不透明度。 主机窗口通常设置为完全不透明度,以防止基础屏幕内容显示。 以下示例演示如何将主机窗口设置为完全不透明度:

SetLayeredWindowAttributes(hwndHost, NULL, 255, LWA_ALPHA);

如果将 WS_EX_TRANSPARENT 样式应用于主机窗口,鼠标单击将传递到位于鼠标光标位置的主机窗口后面的任何对象。 请注意,由于主机窗口不处理鼠标单击,因此用户将无法使用鼠标移动缩放窗口或调整其大小。

必须 WC_MAGNIFIER放大镜控件窗口的窗口类。 如果应用 MS_SHOWMAGNIFIEDCURSOR 样式,则放大镜控件将系统光标包含在放大的屏幕内容中,光标将随屏幕内容一起放大。

创建放大镜控件后,保留窗口句柄,以便将其传递给其他函数。

以下示例演示如何创建放大镜控件。

// Description: 
//   Registers the host window class, creates the host window, sets the layered
//   window attributes, and creates the magnifier control. 
// Parameters:
//   hInstance - Instance handle of the application.
// Variables:
//   HostWndProc - Window procedure of the host window.
//   WindowClassName - Name of the window class.
//   WindowTitle - Title of the host window.
// Constants and global variables:
//   hwndHost - Handle of the host window.
//   hwndMag - Handle of the magnifier window.
//   LENS_WIDTH - Width of the magnifier window.
//   LENS_HEIGHT - Height of the magnifier window.
// 
BOOL CreateMagnifier(HINSTANCE hInstance)
{
   // Register the host window class.
    WNDCLASSEX wcex = {};
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style          = 0;
    wcex.lpfnWndProc    = HostWndProc;
    wcex.hInstance      = hInstance;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(1 + COLOR_BTNFACE);
    wcex.lpszClassName  = WindowClassName;
    
    if (RegisterClassEx(&amp;wcex) == 0)
        return FALSE;

    // Create the host window. 
    hwndHost = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, 
        WindowClassName, WindowTitle, 
        WS_CLIPCHILDREN,
        0, 0, 0, 0,
        NULL, NULL, hInstance, NULL);
    if (!hwndHost)
    {
        return FALSE;
    }

    // Make the window opaque.
    SetLayeredWindowAttributes(hwndHost, 0, 255, LWA_ALPHA);

    // Create a magnifier control that fills the client area.
    hwndMag = CreateWindow(WC_MAGNIFIER, TEXT("MagnifierWindow"), 
        WS_CHILD | MS_SHOWMAGNIFIEDCURSOR | WS_VISIBLE,
        0, 0, 
        LENS_WIDTH, 
        LENS_HEIGHT, 
        hwndHost, NULL, hInstance, NULL );
    if (!hwndMag)
    {
        return FALSE;
    }

    return TRUE;
}

初始化控件

创建放大镜控件后,必须调用 MagSetWindowTransform 函数以指定放大因子。 这只需将 矩阵指定为

(n、0.0、0.0)

(0.0、 n、0.0)

(0.0、0.0、1.0)

其中 n 是放大因子。

以下示例演示如何设置放大镜控件的放大系数。

// Description:
//   Sets the magnification factor for a magnifier control.
// Parameters:
//   hwndMag - Handle of the magnifier control.
//   magFactor - New magnification factor.
//
BOOL SetMagnificationFactor(HWND hwndMag, float magFactor)
{
    MAGTRANSFORM matrix;
    memset(&amp;matrix, 0, sizeof(matrix));
    matrix.v[0][0] = magFactor;
    matrix.v[1][1] = magFactor;
    matrix.v[2][2] = 1.0f;

    return MagSetWindowTransform(hwndMag, &amp;matrix);  
}

设置源矩形

当用户在屏幕上移动鼠标光标时,应用程序会调用 MagSetWindowSource 函数来指定要放大的基础屏幕的一部分。

下面的示例函数根据鼠标位置和放大镜窗口的尺寸除以放大系数) 计算源矩形 (的位置和尺寸,并相应地设置源矩形。 函数还会将主机窗口的工作区置于鼠标位置。 将每隔一段时间调用此函数以更新放大窗口。

// Description: 
//   Called by a timer to update the contents of the magnifier window and to set
//   the position of the host window. 
// Constants and global variables:
//   hwndHost - Handle of the host window.
//   hwndMag - Handle of the magnifier window.
//   LENS_WIDTH - Width of the magnifier window.
//   LENS_HEIGHT - Height of the magnifier window.
//   MAGFACTOR - The magnification factor.
//
void CALLBACK UpdateMagWindow(HWND /*hwnd*/, UINT /*uMsg*/, 
        UINT_PTR /*idEvent*/, DWORD /*dwTime*/)
{
    // Get the mouse coordinates.
    POINT mousePoint;
    GetCursorPos(&amp;mousePoint);

    // Calculate a source rectangle that is centered at the mouse coordinates. 
    // Size the rectangle so that it fits into the magnifier window (the lens).
    RECT sourceRect;
    int borderWidth = GetSystemMetrics(SM_CXFIXEDFRAME);
    int captionHeight = GetSystemMetrics(SM_CYCAPTION);
    sourceRect.left = (mousePoint.x - (int)((LENS_WIDTH / 2) / MAGFACTOR)) + 
             (int)(borderWidth / MAGFACTOR);
    sourceRect.top = (mousePoint.y - (int)((LENS_HEIGHT / 2) / MAGFACTOR)) + 
             (int)(captionHeight / MAGFACTOR) + (int)(borderWidth / MAGFACTOR); 
    sourceRect.right = LENS_WIDTH;
    sourceRect.bottom = LENS_HEIGHT;

    // Pass the source rectangle to the magnifier control.
    MagSetWindowSource(hwndMag, sourceRect);

    // Move the host window so that the origin of the client area lines up
    // with the origin of the magnified source rectangle.
    MoveWindow(hwndHost, 
        (mousePoint.x - LENS_WIDTH / 2), 
        (mousePoint.y - LENS_HEIGHT / 2), 
        LENS_WIDTH, 
        LENS_HEIGHT,
        FALSE);

    // Force the magnifier control to redraw itself.
    InvalidateRect(hwndMag, NULL, TRUE);

    return;
}

应用颜色效果

具有 MS_INVERTCOLORS 样式的放大镜控件应用内置颜色转换矩阵,该矩阵反转放大的屏幕内容的颜色。 下图显示了具有 MS_INVERTCOLORS 样式的放大镜控件中的屏幕内容。

放大内容并反转颜色的屏幕截图

使用 MagSetColorEffect 函数,可以通过设置应用程序定义的颜色转换矩阵来应用其他颜色效果。 例如,以下函数设置将颜色转换为灰度的颜色转换矩阵。

// Description:
//   Converts the colors displayed in the magnifier window to grayscale, or
//   returns the colors to normal.
// Parameters:
//   hwndMag - Handle of the magnifier control.
//   fInvert - TRUE to convert to grayscale, or FALSE for normal colors.
//
BOOL ConvertToGrayscale(HWND hwndMag, BOOL fConvert)
{
    // Convert the screen colors in the magnifier window.
    if (fConvert)
    {
        MAGCOLOREFFECT magEffectGrayscale = 
            {{ // MagEffectGrayscale
                {  0.3f,  0.3f,  0.3f,  0.0f,  0.0f },
                {  0.6f,  0.6f,  0.6f,  0.0f,  0.0f },
                {  0.1f,  0.1f,  0.1f,  0.0f,  0.0f },
                {  0.0f,  0.0f,  0.0f,  1.0f,  0.0f },
                {  0.0f,  0.0f,  0.0f,  0.0f,  1.0f } 
            }};

        return MagSetColorEffect(hwndMag, &amp;magEffectGrayscale);
    }

    // Return the colors to normal.
    else
    {
        return MagSetColorEffect(hwndMag, NULL);
    }
}

有关颜色转换工作原理的详细信息,请参阅 GDI+ 文档中 的使用颜色矩阵转换单一颜色

选择性放大

默认情况下,放大将应用于除放大窗口本身以外的所有窗口。 若要指定要放大的窗口,请调用 MagSetWindowFilterList 函数。 此方法采用窗口列表进行放大,或从放大中排除窗口列表。

放大 API