2015-04-16 2 views
2

Это мой первый пост на этом форуме, пожалуйста, не беспокойтесь, если я не разместил его в нужном месте или не сделал что-то не так, я не публикую на форумах очень много. Итак, у меня есть эта проблема с функцией GetPixel. В принципе, он должен возвращать десятичное значение цвета в x, y. Код, который я собираюсь опубликовать, отлично работает на Windows 7 32bit, но недавно я купил новый ноутбук y50-70 с окнами 8.1 64 бит и тот же код работает совершенно по-другому. Я не могу найти решение проблемы, не могу даже описать ее. Я думаю, что это могло бы иметь что-то общее с дескриптором десктопа, HDC, GetDC(), GetPixel(), возможно даже с разрешением компьютера, частотой обновления или что-то в этом роде ... Я даже записал несколько видеороликов, которые могли бы помочь вам понять проблема у меня, потому что я не могу даже описать ее правильно. Это похоже на реальный цвет: x = 219, y = 407 от места, куда указывает моя мышь. Новый ноутбук 3 недели, я даже пытался сделать восстановление системы 1 раз, но это не решило проблему.GetPixel возвращает неправильные значения

Вы можете использовать этот код, надеюсь, что он будет хорошо работать для вас:

#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

Если кто-то мог по крайней мере, как-то помочь или сказать, что делать, куда идти, я бы очень, очень его умиротворил. Одна из основных причин, почему я начал программировать, - это что-то вроде этого, работа с цветами, условиями и т. Д. ... и теперь я не могу продвинуться дальше, что действительно грустно. Надеюсь услышать ответ. Спасибо.

+0

Я не думаю, что это проблема, но вы должны удалить «GetDC» извне цикла и переместить «ReleaseDC» в цикл. –

+0

Спасибо. Я добавлю ReleaseDC к циклу, и причина, по которой я добавил GetDC снаружи, был потому, что он был неопределенным, используя VisualStudio 2013, но это не решение основной проблемы. –

ответ

3

Возможно, это проблема с масштабированием DPI.

Если ваш новый монитор имеет более чем среднее число точек на дюйм, то Windows по умолчанию растягивает графику. По умолчанию Windows предполагает, что программы игнорируют DPI. Если Windows не растягивала графику, тогда программы, которые не настраивались для DPI, имели бы крошечный текст в крошечных окнах на дисплеях с высокой плотностью.

Это немного взломанный. Некоторые из API Windows и сообщений, которые позволяют вам спросить о дисплее и окнах, преобразуют координаты между «средним» 96 пикселями на дюйм и любым фактическим DPI для монитора. Аналогично, API-интерфейсы, которые позволяют вам делать измерения, делают противоположное преобразование. Так что это все в значительной степени прозрачно для программы. Но это не идеально, потому что не все API-интерфейсы могут масштабировать последовательно.

Итак, я предполагаю, что ваш ноутбук имеет дисплей с высоким разрешением, GetPixel не переводит координаты для масштабирования DPI, а позиция мыши - это, преобразованная для масштабирования DPI. В результате вы просите пиксель, который на самом деле не совпадает с мышью.

Мое предложенное решение - это сказать, что ваша программа «DPI-aware». Есть несколько способов сделать это. Самым простым в вашем случае может быть позвонить SetProcessDPIAware прямо в начале вашей программы. Вы также можете сделать это, указав свою программу в манифесте. В зависимости от используемого компилятора может возникнуть опция командной строки для автоматического создания манифеста.

+0

Большое вам спасибо! SetProcessDPIAware() решил это! Я включил эту функцию прямо в функцию main(), надеюсь, что все в порядке. В любом случае, я могу оценить ваш пост как ответ? Просто хочу еще раз поблагодарить вас. :) –

+0

Из-за виртуализации DPI, если одно приложение запрашивает другого с другим уровнем осведомленности для информации, зависящей от DPI, система автоматически масштабирует значения, чтобы они соответствовали уровню осведомленности вызывающего. Одним из примеров этого является вызов GetWindowRect и переход в окно, созданное другим приложением. Используя описанную выше ситуацию, предположите, что приложение PROCESS_DPI_UNAWARE создало окно размером 500 на 500 на дисплее C. Если вы запрашиваете прямое окно из другого приложения, размер прямоугольника будет меняться в зависимости от понимания DPI вашего приложения. От: http://bit.ly/1RpUnHx – mikew

+0

@mikew: Я не уверен, в какой момент вы пытаетесь это сделать. Здесь нет связи между приложениями. Только один из двух API, используемых Sakire Sileteik, применяется масштабирование. –

0

Другая альтернатива, которая сработала для меня, - это изменить настройку на панели управления, чтобы отключить масштабирование DPI для каждого устройства. Вы используете несколько мониторов?

Win 8.1 представил новую настройку на панели управления, в которой говорится: «Позвольте мне выбрать одно масштабирование DPI для всех дисплеев». По defualt это выключено. Повернув это, я работал на меня.

Смотрите это видео, чтобы найти настройки: https://www.youtube.com/watch?v=sE3IUTPy1WA

мне очень интересно, так что дайте мне знать, если это работает для вас, когда вы не используете SetProccesDPIAware()

Смежные вопросы