【问题标题】:GetPixel returns incorrect valuesGetPixel 返回不正确的值
【发布时间】:2021-02-10 22:37:02
【问题描述】:

这是我在这个论坛上的第一个帖子,如果我没有在正确的地方发布它或者我做错了什么,请不要对我苛刻,我很少在论坛上发帖。所以,我对 GetPixel 函数有这个问题。基本上,它应该返回 x, y 处的颜色小数。我即将发布的代码在 Windows 7 32 位上完美运行,但最近我买了一台新的笔记本电脑 y50-70 和 Windows 8.1 64 位,相同的代码工作方式完全不同。我找不到任何解决问题的方法,甚至无法描述它。我认为这可能与桌面手柄、HDC、GetDC()、GetPixel() 有关,甚至可能与我的计算机分辨率、刷新率或类似的东西有关……我什至录制了一些视频,可以帮助您了解我遇到的问题是因为我什至无法正确描述它。这就像真正的颜色是 x = 219, y = 407 远离我的鼠标指向的地方。新笔记本电脑用了 3 周,我什至尝试过 1 次系统还原,但并没有解决问题。

请随意使用此代码,希望它对您有用:

#include <iostream>
#include <Windows.h>
using namespace std;

void Detect();

int main()
{
    Detect();

    return 0;
}

void Detect()
{
    POINT p;
    HDC hDC = GetDC(0);
    int x, y;

    while (!GetAsyncKeyState(VK_INSERT)) // Press insert to stop
    {
        GetCursorPos(&p);
        x = p.x;
        y = p.y;
        hDC = GetDC(0);
        cout << x << " " << y << " " << GetPixel(hDC, x, y) << endl;
        Sleep(50);
    }
    ReleaseDC(0, hDC);
}

以下问题的链接: https://youtu.be/q2H2M8WLHVI https://youtu.be/UcneHwXaGoM

如果有人至少能以某种方式提供帮助或告诉我该做什么、该去哪里,我会非常非常感激它。我开始编程的主要原因之一是因为这样的事情,使用颜色,条件等......现在我无法进一步前进,这真的很伤心。希望听到答复。谢谢。

【问题讨论】:

  • 我不认为这是问题所在,但是您应该从循环外部删除 GetDC 并将 ReleaseDC 移动到循环中。
  • 谢谢。我将ReleaseDC添加到循环中,我在外面添加GetDC的原因是因为它是未定义的,使用VisualStudio 2013,但这不是主要问题的解决方案。

标签: c++ getpixel


【解决方案1】:

这可能是 DPI 缩放的问题。

如果您的新显示器每英寸的点数高于平均水平,则默认情况下,Windows 会拉伸图形。默认情况下,Windows 假定程序忽略 DPI。如果 Windows 不拉伸图形,那么未针对 DPI 进行调整的程序将在高密度显示器的小窗口中显示小文本。

这有点小题大做。一些让您询问显示器和窗口的 Windows API 和消息将转换“平均”每英寸 96 像素与显示器的实际 DPI 之间的坐标。同样,让您调整大小的 API 进行相反的转换。所以这对程序来说在很大程度上是透明的。但这并不完美,因为并非所有 API 都能以一致的方式进行缩放。

所以我的猜测是你的笔记本电脑有一个高分辨率显示器,GetPixel 不会为 DPI 缩放转换坐标,而鼠标位置为 DPI 缩放转换。结果是您要求的像素与鼠标并不真正对齐。

我建议的解决方案是告诉窗口您的程序是“DPI 感知”的。有几种方法可以做到这一点。在您的情况下,最简单的方法可能是在程序开始时调用SetProcessDPIAware。您也可以在清单中标记您的程序。根据您使用的编译器,可能有一个命令行选项可以自动创建您需要的清单。

【讨论】:

  • 非常感谢! SetProcessDPIAware() 解决了它!我在 main() 函数中包含了这个函数,希望没问题。无论如何,我可以将您的帖子评为答案吗?只想再次说声谢谢。 :)
  • 由于 DPI 虚拟化,如果一个应用程序以不同的感知级别向另一个应用程序查询 DPI 相关信息,系统将自动缩放值以匹配调用者的感知级别。例如,如果您调用 GetWindowRect 并传入由另一个应用程序创建的窗口。使用上述情况,假设 PROCESS_DPI_UNAWARE 应用程序在显示器 C 上创建了一个 500 x 500 的窗口。如果您从不同的应用程序查询窗口矩形,矩形的大小将根据您的应用程序的 DPI 感知而有所不同。来自:bit.ly/1RpUnHx
  • @mikew:我不确定你想表达什么观点。这里没有进行应用程序间的通信。 Sakire Sileteik 使用的两个 API 中只有一个正在应用缩放。
  • 我只是在 MSDN 网站上发布该报价以供参考。我认为GetDCGetWindowRect 一样可以作为跨应用程序,但我不知道。我所知道的是,即使没有获得鼠标坐标,我也注意到了这个问题。我会发送硬编码的坐标,但仍然得到错误的结果。
【解决方案2】:

对我有用的另一种方法是更改​​控制面板中的设置,以禁用每设备 DPI 缩放。您正在运行多台显示器吗?

Win 8.1 在控制面板中引入了一项新设置,即“让我为所有显示器选择一个 DPI 缩放比例”。默认情况下,这是关闭的。打开它对我有用。

观看此视频以查找设置: https://www.youtube.com/watch?v=sE3IUTPy1WA

我很好奇,所以如果你不使用SetProccesDPIAware(),请告诉我这是否适合你

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-13
    • 2016-10-09
    • 2021-10-26
    • 2015-10-13
    • 2014-12-06
    • 2021-02-01
    相关资源
    最近更新 更多