在手动修改了无障碍文本缩放的注册表项后,如何让Windows重新生效?

后端开发 2026-07-09

我想写一个程序,可以通过我的MOBA鼠标上的按钮触发,在Windows 11的“文本大小”设置(设置应用 > 无障碍 > 文本大小 > 页面顶部的滑块)之间来回切换,切到100% 和我偏好的数值。我通过大量Google搜索,找到了需要修改的注册表项(HKEY_CURRENT_USER\SOFTWARE\Microsoft\Accessibility\TextScaleFactor),以及如何用C++修改它(据我所知,这似乎是唯一拥有所有必需API的语言),但实现起来仍然不太对劲。

具体来说,通过设置应用更改该设置时,Windows会显示一个“请稍等”屏幕几秒钟,然后所有打开的窗口都会重新绘制以适应更改后的文本大小;但如果用我目前写的程序手动编辑注册表项,以上都不会发生,大多数窗口也无法识别这个变化,只有Microsoft Edge会重新绘制,但只有在我切换回它(例如用Alt-Tab)时才会重新绘制。

我读到需要在 [这个Reddit评论] 上广播一个 WM_SETTINGCHANGE 消息,并在它链接的Stack Overflow帖子中也广播同样的消息,我也尝试过,但似乎没有起到任何作用。我还在运行程序后尝试重新启动Windows资源管理器,但也没什么帮助。我还看到 [这个论坛帖子] 提到可能还需要关注其他一些注册表项,我做了测试,发现只有那份清单中与字体相关的条目(当然还有 TextScaleFactor 那条)在通过设置应用修改后才真正改变,因此也可以尝试修改这些注册表键值,但我已经被这件事搞得筋疲力尽(对C++经验也不丰富),只想尽快把事情做完。

我是不是做错了什么?甚至有一个更好的办法来实现我想做的事吗?

这是我的代码(使用Visual Studio 2022创建并测试):

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <malloc.h>
#include <iostream>

// ToggleTextScale.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

// Constants
constexpr auto PREFERRED_TEXT_SCALE = 175; // Should be replaced with a command line arg.
constexpr auto DEFAULT_TEXT_SCALE = 100;

int main()
{
    // Declaring a bunch of variables that I'm gonna need later.
    LONG lResult;
    DWORD dwRet;
    DWORD cbData;
    HKEY hKey;
    DWORD_PTR broadcastResult;
    LPBYTE textScaleFactor_ptr = (LPBYTE)malloc(sizeof REG_DWORD); // <- This is the important one!

    // Check for if the ptr is null so Visual Studio doesn't yell at me about it.
    if (textScaleFactor_ptr) {
        // Open the Reg key that has the value I need.
        lResult = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Accessibility"), 0, KEY_READ | KEY_SET_VALUE, &hKey);

        // Get the value.
        cbData = 4;
        dwRet = RegQueryValueEx(hKey, TEXT("TextScaleFactor"), NULL, NULL, textScaleFactor_ptr, &cbData);

        // If the text scaling is 100%, change to preferred value.
        // Otherwise, change to 100%.
        if ((int)*textScaleFactor_ptr == 100) {
            DWORD preferredVal = PREFERRED_TEXT_SCALE;
            lResult = RegSetValueEx(hKey, TEXT("TextScaleFactor"), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&preferredVal), sizeof(preferredVal));
        }
        else {
            DWORD defaultVal = DEFAULT_TEXT_SCALE;
            lResult = RegSetValueEx(hKey, TEXT("TextScaleFactor"), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&defaultVal), sizeof(defaultVal));
        }

        // Broadcast a message so Windows knows something changed and can do its thing.
        SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, (LPARAM)TEXT("TextScaleFactor"), 0, 1000, &broadcastResult);

        // Close the registry key.
        RegCloseKey(hKey);

        // Free the important pointer to clean up.
        free(textScaleFactor_ptr);

        // Final return.
        return ERROR_SUCCESS;
    }
    else {
        // Clean up if the important pointer didn't work.
        free(textScaleFactor_ptr);
        return ERROR_NOT_ENOUGH_MEMORY;
    }
}

解决方案

SetTextScaleFactor() 修改注册表项,然后调用一个未公开的函数来发送通知:

RtlPublishWnfStateData(WNF_EOA_UISETTINGS_CHANGED, 0, 0, 0, 0)

你也可以直接调用这个函数,但更简单的方式还是调用受支持的API。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章