2016-03-21 4 views
4

Я пытаюсь получить реальное разрешение экрана (в пикселях) в приложении Windows C++. Когда изменится настройка точек на дюйм, я получаю виртуальное (скорректированное) разрешение вместо реального. Я попытался использовать SetProcessDPIAware, SetProcessDpiAwareness (со всеми тремя перечисляемыми значениями в качестве аргументов) и истинную настройку в манифесте. Во всех трех случаях код работает нормально (т. Е. Показывает реальное разрешение) на моем ПК с Windows 7, но не в Win 10 (здесь он игнорирует настройку DPI Aware и возвращает настроенное разрешение).SetProcessDPIAware, похоже, не работает под окнами 10

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 

// Windows Header Files: 
#include <windows.h> 
#include <winuser.h> 
#include <VersionHelpers.h> 
#include <ShellScalingAPI.h> 
#include <stdlib.h> 
#include <stdio.h> 

int APIENTRY WinMain(HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR  lpCmdLine, 
        int  nCmdShow) 
{ 
char *cBuffer2 ; 

    cBuffer2 = (char *)malloc(3000) ; 
    if (IsWindowsVistaOrGreater()) 
    { 
// SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); 
     int result = SetProcessDPIAware(); 

     sprintf(cBuffer2,"SetProcessDPIAware() result: [%i]\n",result) ; 

     int height = GetSystemMetrics(SM_CYSCREEN); 
     int width = GetSystemMetrics(SM_CXSCREEN); 
     sprintf(cBuffer2,"%s#1:\nHeight: [%i]\nwidth: [%i]\n",cBuffer2,height,width) ; 


     HWND hwnd = (HWND)atoi(lpCmdLine) ; 
     HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 
     MONITORINFO info; 
     info.cbSize = sizeof(MONITORINFO); 
     GetMonitorInfo(monitor, &info); 
     int monitor_width = info.rcMonitor.right - info.rcMonitor.left; 
     int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top; 
     sprintf(cBuffer2,"%s#2:\nHeight: [%i]\nwidth: [%i]\n",cBuffer2,monitor_height,monitor_width) ; 

    } 

    MessageBox(0,cBuffer2,"SHOWRES.EXE",MB_OK) ; 
    return 0 ; 
} 

манифеста Я попытался с помощью заключается в следующем:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > 
    <asmv3:application> 
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> 
     <dpiAware>true</dpiAware> 
    </asmv3:windowsSettings> 
    </asmv3:application> 
</assembly> 

Любые идеи?

+2

Очень сложно сказать, что вы здесь сделали. В то же время вы, кажется, много чего. Почему бы вам не выбрать один и придерживаться его. Я предлагаю вам использовать манифестный подход. Вы не сказали нам, что такое выход. –

+0

@ Давид Хеффернан: Да, я пробую много разных подходов, потому что никто не работает. Как я сказал в исходном сообщении, под Windows 7 я получаю ожидаемый результат (то есть реальное разрешение дисплея), но под окнами 10 я получаю виртуальный (я получаю без какой-либо настройки DPI). –

+1

Проблема в том, что мы не знаем, какой подход вам нужен, и что вы пробовали. Я бы предпочел, чтобы вы выбрали один подход и представили [mcve]. –

ответ

4

Я, наконец, узнал, что происходит с помощью Джонатана Поттера и Бармака Шеримани: Windows 10, в отличие от предыдущих версий окон, позволяет пользователю изменять настройки «на лету» без необходимости вести журнал и снова войдите в систему. Я запускал тесты на машине с выигрышем 10, которая обычно имеет стандартные (100%) настройки. Поэтому я бы изменил настройку на 150%, запустил приложение и получил неправильные результаты.

Ответы Джонатана и Бармака указывали, что в настройках конкретного компьютера есть что-то, а не в программе или вообще выиграно 10, что вызвало мои проблемы. Так что я попытался следующие:

- changed DPI settings to 150% 
- logged out 
- logged in again 
- ran the program 

И я получил правильные результаты (разрешение экрана в реальном, против отрегулировать один).

Таким образом, для того, чтобы SetProcessDPIAware (и связанные с ним подходы: SetProcessDpiAwareness() и manifest with true) работали правильно, нужно снова выйти из системы и войти в систему после изменения настройки DPI и перед запуском программы.

Еще раз спасибо, Джонатан и Бармак!

+0

Это может быть не очень полезно, но документация для SetProcessDpiAware() специально говорит о том, чтобы не использовать это в более поздних версиях Windows (в соответствии с разделом «Требования» в MSDN для этой функции) и что SetProcessDpiAwareness() следует использовать * вместо * (и что он должен вызываться не чаще одного - будь то манифестом или кодом). –

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