65.9K
CodeProject 正在变化。 阅读更多。
Home

为不同用户提供不同的分辨率

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (5投票s)

2004年1月7日

4分钟阅读

viewsIcon

59684

downloadIcon

846

一个分辨率更改器,用于获取每个用户的分辨率设置

引言

Windows XP 包含许多辅助功能。视力略有困难的用户(例如,大多数老年人)可以通过多种设置来增大字体大小,包括(新添加的)字体大小设置、DPI 设置和桌面分辨率。然而,当计算机需要由视力受损和视力正常的用户的共享时,会产生一些问题。

  1. “桌面”控制面板小程序中的字体大小设置不会影响大多数对话框。因此,似乎无法使用它。
  2. DPI 设置需要重新启动系统才能完全生效。
  3. 桌面分辨率通常是最容易和最快更改的。然而,它在 Windows XP 中表现为系统范围的设置,而不是像 Windows 98 中那样按用户设置。

因此,您无法配置不同的用户帐户,使得用户 A 的所有字体都为标准大小,而用户 B 的所有字体都更大。市面上有几种“分辨率更改器”,包括 PJ Naughter 的一款,可在 CodeProject 上获得。不幸的是,似乎没有简单的方法可以在用户注销之前将分辨率切换回正常状态。(我尝试了注销脚本,但它们似乎运行得太晚了,Windows 拒绝更改显示设置。)过低的分辨率会使欢迎屏幕看起来很糟糕。在这里,我提供了一个部分解决方案,它对我来说有效,尽管存在一些缺点。我欢迎建议或改进。

Using the Code

此处提供的程序应放置在需要较低分辨率(较大字体)的用户的“启动”文件夹中。在其 InitInstance() 函数中,它会临时降低分辨率

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   hInst = hInstance; // Store instance handle in our global variable
   hWnd =  CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   if (!hWnd)
   {
      return FALSE;
   }
   //ShowWindow (hWnd, nCmdShow);
   //UpdateWindow (hWnd);
   ApplyTemporaryResolution();
   return TRUE;
}

您还会注意到,该程序会创建但不会显示任何窗口。它将保留在内存中,直到用户注销或关闭系统。然后它会拦截 WM_ENDSESSION 和其他消息来切换回分辨率。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, 
    WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;

    switch (message) 
    {
    // ...
    // Intercept program termination.
    case WM_CLOSE:
        ApplyDefaultResolution();
        return DefWindowProc(hWnd, message, wParam, lParam);
    case WM_QUIT:
        ApplyDefaultResolution();
        return DefWindowProc(hWnd, message, wParam, lParam);
    case WM_ENDSESSION:
        if (wParam)
            ApplyDefaultResolution();
        return DefWindowProc(hWnd, message, wParam, lParam);
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

ApplyTemporaryResolution()ApplyDefaultResolution() 函数通过调用 ChangeDisplaySettings() Windows API 函数来工作。目前,显示参数是硬编码的。您应该根据需要修改它们。

void ApplyTemporaryResolution()
{
    DEVMODE dm;
    ZeroMemory(&dm, sizeof(DEVMODE));
    dm.dmSize = sizeof(DEVMODE);
    dm.dmBitsPerPel = 32;
    dm.dmPelsWidth = 800;
    dm.dmPelsHeight = 600;
    dm.dmDisplayFrequency = 85;
    dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT 
        | DM_DISPLAYFREQUENCY;

    ChangeDisplaySettings(&dm, 0);
}

void ApplyDefaultResolution()
{
    DEVMODE dm;
    ZeroMemory(&dm, sizeof(DEVMODE));
    dm.dmSize = sizeof(DEVMODE);
    dm.dmBitsPerPel = 32;
    dm.dmPelsWidth = 1024;
    dm.dmPelsHeight = 768;
    dm.dmDisplayFrequency = 85;
    dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT 
        | DM_DISPLAYFREQUENCY;

    ChangeDisplaySettings(&dm, CDS_GLOBAL | CDS_UPDATEREGISTRY);
}

很诱人的是,第二个函数可以直接调用 ChangeDisplaySettings(0, 0),这应该可以在不提供特定参数的情况下切换到“默认”分辨率。然而,这似乎会引起问题——有时,临时分辨率会变成默认值。请注意,对 ChangeDisplaySettings() 的第二次调用使用了 CDS_GLOBAL | CDS_UPDATEREGISTRY 标志,以使应用的设置成为默认的、系统范围的设置。当我尝试不带标志(意味着:不在注册表中保存新值)时,系统会将先前设置的临时设置视为系统范围的默认值。

重要提示:在代码中设置显示设置之前,务必先使用 Windows 控制面板测试这两种模式的显示设置。否则,您可能什么都看不到,也无法将其更改回来。

关注点

此方法与快速用户切换不兼容。即使仅启用快速用户切换但未使用,默认分辨率也并非总是恢复,原因不明。使程序完全支持快速用户切换将是很好的。如果有人能告诉我如何使其工作,我愿意接受建议。您可以拦截用户切换消息(在文章附带的示例代码中已注释掉),但 ChangeDisplaySettings() 函数会返回 DISP_CHANGE_FAILED 错误。

此处描述问题的理想解决方案是再次使桌面分辨率成为每个用户设置。有趣的是,操作系统中已经存在该机制,但很难启用它!ChangeDisplaySettings() API 函数提供了选择应用设置是系统范围还是每个用户设置的参数。不幸的是,它们似乎不能按预期工作。看来 Windows 确实会记住一些每个用户的分辨率设置,但会在其之上应用系统范围的设置。

示例:为用户 A 选择较低的分辨率,切换到用户 B,选择较高的分辨率。当您切换回用户 A 时,您可能会注意到分辨率先变回较低,然后立即变回较高。至少在我的系统上,我可以看到这一点,其中已经应用了许多分辨率更改。

不幸的是,Platform SDK 文档没有解释这些设置如何工作,也没有解释它们存储在哪里。注册表在HKLM\SYSTEM 下包含许多分辨率设置,但它们似乎与用户配置文件没有直接关系。再次,我欢迎任何提示。

历史

  • 2004 年 1 月 - 发布第一个版本

结论

接下来要做的是让程序接受分辨率参数。我确信如果我可以在不链接资源的情况下做到这一点,它也可以大大减小。由于时间限制,我无法做到这些,但我欢迎贡献。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.