如何通过编程将Windows 11 22H2从平板模式切换到桌面模式?

6

我的Lenovo Yoga 7i笔记本默认启动为平板模式,因此我会遇到大型桌面/任务栏图标和其他不愉快的UI瑕疵。

可以通过安装和运行专有的Lenovo服务(YMC.EXELenovo Yoga Mode Control for Windows来解决这个问题,但是该服务以其过度的CPU使用而臭名昭著。

在我的情况下,Windows服务管理器中将YMC设置为手动。要将Windows恢复为桌面模式,我必须手动从管理员控制台启动和停止YMC:net start ymc && net stop ymc每次系统重新启动时。

我正在寻找一种编程方式来执行YMC所做的任何操作,以将Windows 11切换到桌面模式,并将其封装为一个小型实用程序应用程序。

到目前为止,我找到的唯一相关答案是this one,提到了未记录的ITabletModeController

var pSP = (IServiceProvider)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_ImmersiveShell));
var pTMC = (ITabletModeController)pSP.QueryService(typeof(ITabletModeController).GUID, typeof(ITabletModeController).GUID);
if (pTMC != null)
{
    // 0 = Desktop, 1 = Tablet
    int nMode = 0;
    int nRet = pTMC.GetMode(ref nMode);
    nRet = pTMC.SetMode(nMode==0?1:0, 4);
}

我试过了,但没有成功。ChatGPT也没有帮上忙 :)


https://www.lifewire.com/use-tablet-mode-in-windows-11-5224864 - Hans Passant
1
你能把那个ymc.exe文件上传到某个地方吗? - Simon Mourier
1
嗨@SimonMourier,谢谢,好久不聊了:) 这是file,从这里下载的。 - noseratio - open to work
1
从exe文件来看,它似乎没有使用ITabletModelController(没有调用与guid相关的CoCreateInstance),但它与硬件特定的驱动程序进行通信,并使用带有自定义联想内容的WMI(https://github.com/alesya-h/linux_detect_tablet_mode和https://forums.lenovo.com/t5/Lenovo-Yoga-Series-Laptops/Lenovo-Yoga-7-gen-7-amd-14ARB7-tablet-mode-change-WMI-interfaces/m-p/5171832),因此它可能在某种程度上是在“Windows之外”工作。 - Simon Mourier
1
平板模式也随着Windows 11消失了,这可能解释了为什么ITabletModeController无法工作。https://learn.microsoft.com/en-us/uwp/api/windows.ui.viewmanagement.userinteractionmode?view=winrt-22621#tablet-mode-windows-10-only - Simon Mourier
显示剩余6条评论
1个回答

3

好的,我发表这篇回答是因为我认为它对于评论来说太多了。如果它与问题无关,请在评论中指出,以便我可以删除它。我没有Lenovo Yoga 7i,但我的Acer Travelmate Spin也有平板模式。

根据GetSystemMetrics GetSystemMetrics(SM_CONVERTIBLESLATEMODE); // 0x2003 ,我们似乎能够读取我们是否处于平板模式01,其中平板0=平板电脑平板1=笔记本电脑或其他设备,根据convertibleslatemode

文档声称:

反映笔记本电脑或平板模式的状态,0表示平板模式,非零表示其他模式。当系统度量值发生变化时,系统通过WM_SETTINGCHANGE发送广播消息,LPARAM中包含"ConvertibleSlateMode"。请注意,此系统度量值不适用于台式电脑。在这种情况下,请使用GetAutoRotationState来获取信息。
我尝试通过以下方式自己进行广播:
DWORD_PTR res;
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"ConvertibleSlateMode", SMTO_ABORTIFHUNG, 1000, &res);

没起作用。

然后我意识到这里有一个注册表键值:Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl,称为ConvertibleSlateMode,反映了之前提到的slate 0和1的值。

如果您处于平板电脑模式(slate 0)并将regkey的值设置为1,则会进入桌面模式。我不确定广播(上面提到的)是否必需,但对我而言,将regkey设置为0,然后设置为1就可以起作用(在平板电脑模式下)。

在C++中,可以使用以下代码完成此操作:

void setRegKey(const DWORD value) {
    HKEY hKey;
    LONG regStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\PriorityControl", 0, KEY_SET_VALUE, &hKey);

    if (regStatus != ERROR_SUCCESS) {
        std::cout << "Error opening registry key.\n";
        return;
    }

    const wchar_t* valueName = L"ConvertibleSlateMode";


    regStatus = RegSetValueExW(hKey, valueName, 0, REG_DWORD, (BYTE*)&value, sizeof(DWORD));

    if (regStatus != ERROR_SUCCESS) {
        std::cout << "Error setting registry value.\n";
        RegCloseKey(hKey);
        return;
    }

    RegCloseKey(hKey);

    std::cout << "Registry value set successfully.\n";
}

然后在主函数中:

int main() {
    setRegKey(0);
    setRegKey(1);
}

编辑:如@BenVoigt和@KeshavV所提到的,您很可能也可以按照以下步骤操作:Windows 10平板模式注册表设置:“当此设备自动切换平板模式开启或关闭”

更多相关链接:
GetSystemMetrics
WM_SETTINGCHANGE
SendMessageTimeout
convertibleslatemode


1
可能他所需要的就是设置“SigninMode”注册表键:https://stackoverflow.com/q/35187260/103167 - Ben Voigt
1
@darclander,感谢你的研究!我会尝试并在这里回报。 - noseratio - open to work
1
@darclander 这在我的联想Yoga上没有任何作用(与所链接的答案相同)。联想一定是通过他们的YMC.exe使用了一些专有的硬件协议。无论如何,我将奖励给你的答案作为研究的成果,除非有人发布更好的解决方案 - 谢谢! - noseratio - open to work
1
@noseratio 这真是不幸。 你也尝试在注册表中手动编写“0”->“1”了吗?(那是我找到的第一件事)我相信广播可以做些什么,但遗憾的是我对此经验不足,无法提供一个好的答案。 我会继续查找! - darclander
1
@darclander,是的,我已经用ChatGPT为我生成的一个快速PowerShell脚本尝试过了 :) 无论如何,感谢你的帮助,这是应得的赏金! - noseratio - open to work
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接