3

I am using Delphi XE5. I think i have a problem with my laptop. After a while, it returns wrong value to Screen.Width and GetSystemMetrics(SM_CXSCREEN) (same for Height). My OS is Windows 7 64-bit.

My laptop's screen res is 1920x1080 (1080p) however my app says it is 1280x720 (720p). I don't think there is a DPI problem as the problem goes when i reboot and starts after a while. Also Compatibality settings are off. Did anyone have this problem before? Or do you know a solution? I have also added the manifest below but didn't help

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

here is how i compiled it

1 24 "mf.txt"

EDIT:

Ok I wrote this function which is tricky way to fix it. I prefer Screen.Width return correct value:

function ScreenSize(var x, y: integer): boolean;
const
  ENUM_CURRENT_SETTINGS =  -1;
  ENUM_REGISTRY_SETTINGS = -2;
var
  dm: TDevMode;
begin
  Result := False;
  x := 0;
  y := 0;
  ZeroMemory(@dm, sizeof(dm));
  if EnumDisplaySettings(nil, Cardinal(ENUM_CURRENT_SETTINGS), dm) then
  begin
    Result := True;
    x := dm.dmPelsWidth;
    y := dm.dmPelsHeight;
  end else
  begin
    x := GetSystemMetrics(SM_CXSCREEN);
    y := GetSystemMetrics(SM_CYSCREEN);
  end;
end;

EDIT 2:

I have found SetProcessDPIAware solved my problem but it doesn't work in XP

blacksun
  • 733
  • 7
  • 24
  • You'd get that sort of behaviour if you had a high dpi scaling set and your app was not dpi aware. – David Heffernan Feb 05 '15 at 08:27
  • My text DPI is scaled 150% and that was why it happened. I have edited the question with a solution which is tricky – blacksun Feb 05 '15 at 08:59
  • Post your answer as an answer, instead of adding it to the question. – CodesInChaos Feb 05 '15 at 09:13
  • I'm not sure how your edit will help you. If you are running under DPI virtualization, you cannot use the non-virtualizaed coordinate space. Yes you can report the numbers to the user but there's not much else that you could do. – David Heffernan Feb 05 '15 at 09:16
  • SetProcessDPIAware works great but it doesn't support XP – blacksun Feb 05 '15 at 09:17
  • There is no DPI virtualization on XP. Anyway, don't use `SetProcessDPIAware`. Put it in the manifest. I suggest that you slow down a little and follow the steps in my answer more carefully. Step 1, identify the manifest that is being linked to your application. It's not what you think it is. – David Heffernan Feb 05 '15 at 09:27
  • @CodesInChaos I don't want to misdirect users. That's why i didn't answer as an answer. David's solution seems better – blacksun Feb 05 '15 at 09:46

1 Answers1

5

You state that your system is running at 150% font scaling. If your application runs with DPI virtualization then this virtualization explains the behaviour you observe. Note that 1920 / 1.5 = 1280 and 1080 / 1.5 = 720.

The only reasonable explanation for the behaviour that you report is that the process is running under DPI virtualization. Applying the DPI aware manifest option will stop DPI virtualization. So, it would seem most likely that the manifest is not being linked to your application correctly, or the manifest is not valid.

I suspect that your application might have two manifest linked to it. The second one of which would be discarded. That would happen if you used the default application settings in your Delphi project. The next step for you is to look at the actual resources linked to your executable file by using a resource viewer. That's the sure fire way to see what has been linked.

Probably the solution will be to use the custom manifest option in the Application node of the Delphi Project Options and supply the complete application manifest. This will need to specify comctl32 v6 to enable themes, the requireAdministrator option of asInvoker, and the DPI aware option.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I think i have the correct manifest. I have also tried to add it from Project->Add to project menu. It didn't help... – blacksun Feb 05 '15 at 09:24
  • `Project -> Add` isn't the way to do this. Look in the Project Options under the Application node. Under Runtime Themes select custom manifest and there supply a complete manifest. – David Heffernan Feb 05 '15 at 09:28
  • David it works when i do it there but i am not sure what i loose here. I mean what is missing in my project after i choose this way? – blacksun Feb 05 '15 at 09:43
  • Well, take a look at the manifest that you get with Enable runtime themes. That's going to need you to use a resource editor. There are many available. My guess is that the default manifest will have `asInvoker` and the comctl32 v6 components, plus product details. You need all of that and to add the dpi aware option. – David Heffernan Feb 05 '15 at 09:46
  • i have tried to download a ResEditor which changed all settings (browser's home page and etc.). Do you know a good one? – blacksun Feb 05 '15 at 10:11
  • 1
    ResourceHacker and XNResourceEditor are the two that I have used – David Heffernan Feb 05 '15 at 10:11
  • David thank you very much. It works perfect. And also thank you for your recommending res editor. :) – blacksun Feb 05 '15 at 10:21