Windows触控板单击

后端开发 2026-07-10

我正在尝试以编程方式启用/禁用该选项:

设置 → 蓝牙与设备 → 触控板 → 轻触 → “用单指轻触实现单击”

当通过Windows设置手动切换时,效果是即时的。

然而,当我在以下注册表键下进行修改时:

HKCU\Software\Microsoft\Windows\CurrentVersion\PrecisionTouchPad

更改只有在执行完整系统重启后才会生效。

我已经尝试过:

  • 重启资源管理器(explorer.exe
  • 重启与输入相关的服务(如 hidservTabletInputService
  • 重新枚举设备(pnputil /scan-devices
  • 重启驱动程序(HID / 触控板)
  • 结束并重新打开 SystemSettings.exe

这些方法都不能让更改立即生效。


有没有办法:

  1. 强制Windows在不重启的情况下重新加载高精度触控板设置,或者
  2. 通过编程方式模拟切换操作(例如通过API、PowerShell或 UI自动化),使效果立即生效?

(20260414_204100) - 在问题中添加了最小可复现示例。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ttpd
{
    public partial class Form1 : Form
    {
        // SystemParametersInfo constants
        private const uint SPI_GETTOUCHPADPARAMETERS = 0x00AE;
        private const uint SPI_SETTOUCHPADPARAMETERS = 0x00AF;
        private const uint SPIF_UPDATEINIFILE = 0x01; // Save config to user .ini
        private const uint SPIF_SENDCHANGE = 0x02;    // Notify system change

        // Stores current Tap to Click state
        private bool touchpadClickEnabled;

        // UI controls (assumed from designer)
        private Label lblStatus;

        [StructLayout(LayoutKind.Sequential)]
        public struct TOUCHPAD_PARAMETERS_V1
        {
            public uint versionNumber;
            public uint maxSupportedContacts;
            public uint legacyTouchpadFeatures;
            public uint flags1;
            public uint flags2;
            public uint sensitivityLevel;
            public uint cursorSpeed;
            public uint feedbackIntensity;
            public uint clickForceSensitivity;
            public uint rightClickZoneWidth;
            public uint rightClickZoneHeight;

            // Access tapEnabled (bit 2 of flags2)
            public bool TapEnabled
            {
                get => ((flags2 >> 2) & 1) == 1;
                set
                {
                    if (value)
                        flags2 |= (1u << 2); // set bit
                    else
                        flags2 &= ~(1u << 2); // clear bit (uint safe)
                }
            }
        }

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SystemParametersInfo(
            uint uiAction,
            uint uiParam,
            ref TOUCHPAD_PARAMETERS_V1 pvParam,
            uint fWinIni);

        public static void ToggleTapToClick(bool enable)
        {
            TOUCHPAD_PARAMETERS_V1 touchpadParams = new TOUCHPAD_PARAMETERS_V1();
            touchpadParams.versionNumber = 1;

            // Get current settings
            if (SystemParametersInfo(SPI_GETTOUCHPADPARAMETERS, (uint)Marshal.SizeOf(touchpadParams), ref touchpadParams, 0))
            {
                Console.WriteLine($"Current Tap to Click: {touchpadParams.TapEnabled}");

                // Modify tapEnabled
                touchpadParams.TapEnabled = enable;

                // Apply new settings
                if (SystemParametersInfo(SPI_SETTOUCHPADPARAMETERS, (uint)Marshal.SizeOf(touchpadParams), ref touchpadParams, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE))
                {
                    Console.WriteLine($"Tap to Click set to: {enable}");
                }
                else
                {
                    Console.WriteLine($"Error setting Tap to Click: {Marshal.GetLastWin32Error()}");
                }
            }
            else
            {
                Console.WriteLine($"Error reading touchpad settings: {Marshal.GetLastWin32Error()}");
            }
        }

        public Form1()
        {
            InitializeComponent();
            UpdateTapToClickStatusAndButton();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ToggleTapToClick(!touchpadClickEnabled);
            UpdateTapToClickStatusAndButton();
        }

        private void UpdateTapToClickStatusAndButton()
        {
            TOUCHPAD_PARAMETERS_V1 touchpadParams = new TOUCHPAD_PARAMETERS_V1();
            touchpadParams.versionNumber = 1;

            if (SystemParametersInfo(SPI_GETTOUCHPADPARAMETERS, (uint)Marshal.SizeOf(touchpadParams), ref touchpadParams, 0))
            {
                touchpadClickEnabled = touchpadParams.TapEnabled;

                if (lblStatus != null)
                    lblStatus.Text = $"Tap to Click: {(touchpadClickEnabled ? "ENABLED" : "DISABLED")}";

                if (button1 != null)
                    button1.Text = touchpadClickEnabled ? "Disable Tap to Click" : "Enable Tap to Click";
            }
            else
            {
                if (lblStatus != null)
                    lblStatus.Text = $"Tap to Click: ERROR ({Marshal.GetLastWin32Error()})";

                if (button1 != null)
                    button1.Text = "Error reading status";
            }
        }
    }
}

解决方案

应用程序通过 WM_SETTINGCHANGE window message 来更新新设置。虽然你也可以自己实现,但有一种官方方法可以完成所有这些,通过 SystemParametersInfo

你需要以下定义:

[DllImport("user32.dll", SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfoW(
    uint uiAction, uint uiParam, ref TOUCHPAD_PARAMETERS_V1 pvParam, uint fWinIni);

private const uint SPI_GETTOUCHPADPARAMETERS = 0x00AE;
private const uint SPI_SETTOUCHPADPARAMETERS = 0x00AF;
private const uint SPIF_UPDATEINIFILE = 0x01;
private const uint SPIF_SENDCHANGE = 0x02;

[StructLayout(LayoutKind.Sequential)]
private struct TOUCHPAD_PARAMETERS_V1
{
    uint versionNumber = 1;
    public uint maxSupportedContacts;
    public LEGACY_TOUCHPAD_FEATURES legacyTouchpadFeatures;

    public TOUCHPAD_FLAGS1 flags1;
    public TOUCHPAD_FLAGS2 flags2;

    public TOUCHPAD_SENSITIVITY_LEVEL sensitivityLevel;
    public uint cursorSpeed;
    public uint feedbackIntensity;
    public uint clickForceSensitivity;
    public uint rightClickZoneWidth;
    public uint rightClickZoneHeight;
}

[Flags]
private enum TOUCHPAD_FLAGS1 : uint
{
    TouchpadPresent       = 1u << 0,
    LegacyTouchpadPresent = 1u << 1,
    ExternalMousePresent  = 1u << 2,
    TouchpadEnabled       = 1u << 3,
    TouchpadActive        = 1u << 4,
    FeedbackSupported     = 1u << 5,
    ClickForceSupported   = 1u << 6,
}

[Flags]
private enum TOUCHPAD_FLAGS2 : uint
{
    AllowActiveWhenMousePresent = 1u << 0,
    FeedbackEnabled             = 1u << 1,
    TapEnabled                  = 1u << 2,
    TapAndDragEnabled           = 1u << 3,
    TwoFingerTapEnabled         = 1u << 4,
    RightClickZoneEnabled       = 1u << 5,
    MouseAccelSettingHonored    = 1u << 6,
    PanEnabled                  = 1u << 7,
    ZoomEnabled                 = 1u << 8,
    ScrollDirectionReversed     = 1u << 9,
}

private enum LEGACY_TOUCHPAD_FEATURES
{
    LEGACY_TOUCHPAD_FEATURE_NONE = 0x00000000,
    LEGACY_TOUCHPAD_FEATURE_ENABLE_DISABLE = 0x00000001,
    LEGACY_TOUCHPAD_FEATURE_REVERSE_SCROLL_DIRECTION = 0x00000004
}

private enum TOUCHPAD_SENSITIVITY_LEVEL
{
    TOUCHPAD_SENSITIVITY_LEVEL_MOST_SENSITIVE = 0x00000000,
    TOUCHPAD_SENSITIVITY_LEVEL_HIGH_SENSITIVITY = 0x00000001,
    TOUCHPAD_SENSITIVITY_LEVEL_MEDIUM_SENSITIVITY = 0x00000002,
    TOUCHPAD_SENSITIVITY_LEVEL_LOW_SENSITIVITY = 0x00000003,
    TOUCHPAD_SENSITIVITY_LEVEL_LEAST_SENSITIVE = 0x00000004
}

Then get the current params, change the values you want and set back. The function sets the registry (if you use SPIF_UPDATEINIFILE or SPIF_SENDCHANGE) and fire a message (if you use SPIF_SENDCHANGE).

var touchParams = new TOUCHPAD_PARAMETERS_V1();
// get existing params
if (!SystemParametersInfoW(SPI_GETTOUCHPADPARAMETERS, Marshal.SizeOf<TOUCHPAD_PARAMETERS_V1>(), ref touchParams, 0))
    throw new Win32Exception(Marshal.GetLastPInvokeError());

touchParams.Flags2 |= TOUCHPAD_FLAGS2.TapEnabled;

// set new params and fire message
if (!SystemParametersInfoW(SPI_SETTOUCHPADPARAMETERS, Marshal.SizeOf<TOUCHPAD_PARAMETERS_V1>(), ref touchParams, SPIF_SENDCHANGE))
    throw new Win32Exception(Marshal.GetLastPInvokeError());
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章