gpt4 book ai didi

c# - 使用 User32.ChangeDisplaySettings 设置分辨率仅在最大分辨率 ('badmode' 错误时失败)

转载 作者:行者123 更新时间:2023-12-01 18:33:50 27 4
gpt4 key购买 nike

所以我想做的是使用 ChangeDisplaySettings 在 C# 中的主显示器上设置屏幕分辨率。我已经在我拥有的多台 Windows 7 计算机上对此进行了测试,结果始终相同:任何*有效的分辨率(右键单击桌面时在“屏幕分辨率”菜单中列出的分辨率)都可以正常工作,除了用于在该菜单中选择的最大分辨率,这将导致 User32.ChangeDisplaySettings 返回 -2,即 DISP_CHANGE_BADMODE,意味着请求的显示模式无效。

*在一些具有较大主显示器的计算机上,我没有费心测试每个分辨率,只是选择了一些任意较小的分辨率和最大分辨率,因为有太多的分辨率无法在每个分辨率上进行测试。我对我的测试有足够的信心,可以说最大分辨率总是失败,而较小的分辨率通常/总是成功(无论如何,在我的测试期间,它们中的任何一个都没有失败)。

有关 ChangeDisplaySettings 的文档:http://msdn.microsoft.com/en-us/library/dd183411%28VS.85%29.aspx

有关其使用的 DEVMODE 结构的文档:http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx

举个例子,假设我在 1920x1080 显示屏上运行。

我手动(或以编程方式)将分辨率设置为其他值,无论它是什么或如何更改,然后运行以下代码:

DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
if (User32.EnumDisplaySettings(null, User32.ENUM_CURRENT_SETTINGS, ref dm) != 0)
{
dm.dmPelsWidth = 1920;
dm.dmPelsHeight = 1080;
Console.WriteLine("" + User32.ChangeDisplaySettings(ref dm, User32.CDS_UPDATEREGISTRY) + "\n");
}

*请注意,这实际上并不是程序中的代码。我只是制作了这个简化版本,将其简化为最基本的必要条件来说明这一点。

程序将打印出:

-2

如前所述,这是DISP_CHANGE_BADMODE的值,分辨率将无法更改。

现在,如果我将 1080 和 1920 的值分别更改为 900 和 1600(该显示器上支持的另一个分辨率),然后将分辨率设置为 1600x900 以外的其他值,然后运行该程序,它实际上会更改分辨率改为1600x900,并返回DISP_CHANGE_SUCCESSFUL。

请注意,使用其他标志(例如 CDS_RESET(0x40000000 或 1073741824))代替 CDS_UPDATEREGISTRY 也会导致相同的错误。

这是我发现可以帮助我入门的教程:

www.codeproject.com/Articles/6810/Dynamic-Screen-Resolution

[由于明显的垃圾邮件预防系统,我删除了超链接。有点愚蠢,因为第一个是 msdn.microsoft 链接,这是一个代码项目链接,但是,w/e]

请注意,在评论部分,似乎有人直接使用提供的源文件,并且遇到了类似的问题。引用他们的话:

hello , i'm using Resolution.cs on my c# application and it doesn't work with high resolutions like " 1366*768 " & " 1280*720 " can any one help ???

但是,尽管教程似乎经常推荐 ChangeDisplaySettings,但我找不到任何有关解决此问题的信息(这很可能是特定于操作系统的,但我目前缺乏任何非 Windows 7 计算机来测试) ,即使我这样做了,也无法解决在 Windows 7 计算机上无法运行的问题)

最佳答案

事实证明,我使用的教程假设在分辨率较低时不会将任何显示模式参数更改为无效的内容(例如提高刷新率,即限制在显示器一侧。由于我使用相同的两台显示器进行测试,并且最大分辨率的最大刷新率低于任何其他分辨率,因此我会遇到此问题。)

比教程中介绍的更安全的方法是使用显示模式的索引或仅使用 EnumDisplayModes,并且永远不要触摸 DEVMODE 结构内的数据。

以下是我编写的示例程序的摘录,该程序将分辨率更改为指定参数,然后再更改回来。

            int selB, selG, selF, selH, selW;
... //these values get defined, etc.
DEVMODE OSpecs = new DEVMODE();
getCurrentRes(ref OSpecs);
int Ondx = getDMbySpecs(OSpecs.dmPelsHeight, OSpecs.dmPelsWidth, OSpecs.dmDisplayFrequency, OSpecs.dmDisplayFlags, OSpecs.dmBitsPerPel, ref OSpecs);
Screen Srn = Screen.PrimaryScreen;
Console.WriteLine("Current res is " + OSpecs.dmPelsHeight + " by " + OSpecs.dmPelsWidth + "\n");
DEVMODE NSpecs = new DEVMODE();
int Nndx = getDMbySpecs(selH, selW, selF, selG, selB, ref NSpecs);
//Note that this function sets both the DEVMODE to the selected display mode and returns the index value of this display mode. It returns -1 if it fails (-1 is the value of ENUM_CURRENT_SETTINGS), and sets the DEVMODE to the current display mode.
if (Nndx == -1)
{
Console.WriteLine("Could not find specified mode");
}
else if (setDisplayMode(ref NSpecs) || setDisplayMode(Nndx)) //This is just to illustrate both ways of doing it. One or the other may be more convenient (ie, the latter if you are getting this from a file, the former if you already have the DEVMODE in your program, etc.)
{
//reset display mode to original after waiting long enough to see it changed
Console.WriteLine("Successful change. Waiting 4 seconds.");
Thread.Sleep(4000);
if (setDisplayMode(ref OSpecs) || setDisplayMode(Ondx))
{
//success!
Console.WriteLine("Mode reversion succeeded.");
}
else
{
Console.WriteLine("Mode reversion failed. Manual reset required.");
}
}
else
{
//return
Console.WriteLine("Resolution change failed. Aborting");
}

这里使用的函数如下:

    static bool setDisplayMode(int i)
{
DEVMODE DM = new DEVMODE();
DM.dmSize = (short)Marshal.SizeOf(DM);
User32.EnumDisplaySettings(null, i, ref DM);
if (User32.ChangeDisplaySettings(ref DM, User32.CDS_TEST) == 0 && User32.ChangeDisplaySettings(ref DM, User32.CDS_UPDATEREGISTRY) == 0)
{
return true;
}
else
{
return false;
}
}
static bool setDisplayMode(ref DEVMODE DM)
{
if (User32.ChangeDisplaySettings(ref DM, User32.CDS_TEST) == 0 && User32.ChangeDisplaySettings(ref DM, User32.CDS_UPDATEREGISTRY) == 0)
{
return true;
}
else
{
return false;
}
}
static int getDMbySpecs(int H, int W, int F, int G, int B, ref DEVMODE DM)
{
DM.dmSize = (short)Marshal.SizeOf(DM);
DEVMODE SelDM = new DEVMODE();
SelDM.dmSize = (short)Marshal.SizeOf(SelDM);
int iOMI = 0;
for (iOMI = 0; User32.EnumDisplaySettings(null, iOMI, ref SelDM) != 0; iOMI++)
{
if (( B == -1 || B == SelDM.dmBitsPerPel) && ( H == -1 || H == SelDM.dmPelsHeight) && ( W == -1 || W == SelDM.dmPelsWidth) && ( G == -1 || G == SelDM.dmDisplayFlags) && ( F == -1 || F == SelDM.dmDisplayFrequency))

break;
}
if (User32.EnumDisplaySettings(null, iOMI, ref DM) == 0)
{
iOMI = -1;
getCurrentRes(ref DM);
}
return iOMI;
}
static void getCurrentRes(ref DEVMODE dm)
{
dm = new DEVMODE();
dm.dmSize = (short)Marshal.SizeOf(dm);
User32.EnumDisplaySettings(null, User32.ENUM_CURRENT_SETTINGS, ref dm);
return;
}

关于c# - 使用 User32.ChangeDisplaySettings 设置分辨率仅在最大分辨率 ('badmode' 错误时失败),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9756416/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com