本文介绍了DPI感知的屏幕截图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我之前使用AutoIt的_ScreenCapture_Capture()没有任何麻烦.但是在具有4k分辨率屏幕的Windows 10上,我使用的DPI缩放比例为200%. _ScreenCapture_capture()现在可以将内容放大2倍,并且是我要求的位置的一半.

I used AutoIt's _ScreenCapture_Capture() before without any trouble. But on Windows 10 with a 4k resolution screen I'm using DPI scaling at 200%. _ScreenCapture_capture() now gets something 2x zoomed in and half the location I asked for.

例如:

 _ScreenCapture_Capture("c:\a.bmp", 100, 100, 200, 200)
;                             Path,  X1,  Y1,  X2,  Y2

不返回屏幕的100x100像素正方形(在100,100200,200处).而是返回100x100像素的正方形(在50,50100,100处).

Does not return a 100x100 pixel square of the screen (at 100,100 to 200,200). It returns a 100x100 pixel square (at 50,50 to 100,100) instead.

我确实找到了解决方法:

I did find a solution :

DllCall("User32.dll", "bool", "SetProcessDPIAware")

但是,这弄糟了GUI的外观.因此,我随后发现了此代码:

However this screws up the GUI looks. So I then found this code:

GUISetFont(8.5 * _GDIPlus_GraphicsGetDPIRatio()[0])
Func _GDIPlus_GraphicsGetDPIRatio($iDPIDef = 96)
  Local $aResults[2] = [1, 1]
  _GDIPlus_Startup()
  Local $hGfx = _GDIPlus_GraphicsCreateFromHWND(0)
  If @error Then Return SetError(1, @extended, $aResults)
  #forcedef $__g_hGDIPDll, $ghGDIPDll
  $aResult = DllCall($__g_hGDIPDll, "int", "GdipGetDpiX", "handle", $hGfx, "float*", 0)
  If @error Then Return SetError(2, @extended, $aResults)
  Local $iDPI = $aResult[2]
  Local $aresults[2] = [$iDPIDef / $iDPI, $iDPI / $iDPIDef]
  _GDIPlus_GraphicsDispose($hGfx)
  _GDIPlus_Shutdown()
  Return $aresults
EndFunc   ;==>_GDIPlus_GraphicsGetDPIRatio

对于GUI而言,这很有效,但对于_ScreenCapture_Capture()调用却无济于事.看来我可以拥有一个美观或运行良好的程序,而不是两者兼具.

Which works great for the GUI but doesn't help for _ScreenCapture_Capture() calls. Seems I can either have a good looking- or a functioning program, not both.

我如何结合这两种解决方案来获得良好的GUI和正常运行的程序?如果我知道如何做相反的事情:

How could I combine these two solutions to get both a good GUI and a functioning program? If I knew how to do the opposite of :

DllCall("User32.dll", "bool", "SetProcessDPIAware")

然后,当我需要捕获屏幕部分时,可以打开兼容性,然后在捕获完成后立即将其关闭.但是我不知道如何"UNsetprocessdpiaware".

Then when I need to capture a screen portion I could turn on compatibility, then immediately turn it off when done capturing. But I don't know how to 'UNsetprocessdpiaware'.

推荐答案

如果您使用的是Windows 10 A更新(10.0.14393),则可以启动一个单独的线程,并使每个线程单独监视每个Monitor DPI,并保留您的不知道dpi的主GUI.

If you are using Windows 10 A update (10.0.14393) you can spin up a separate thread and make the thread alone Per Monitor DPI aware, and leave your main GUI as dpi unaware.

请参见

SetThreadDpiAwarenessContext函数

如果要在2015年之前使用Visual Studio版本进行构建,则可以声明指向函数原型的指针

If you are building using a version of visual studio before 2015 you can declare a pointer to the function prototype

DPI_AWARENESS_CONTEXT WINAPI SetThreadDpiAwarenessContext(
  _In_  DPI_AWARENESS_CONTEXT  dpiContext
);

,并在调用函数之前使用GetProcAddress测试该函数是否存在.如果您使用过该线程中的任何内容,都会为您提供原始的物理信息

and use GetProcAddress to test for the presence of the function before you call it. Anything in that thread will give you raw physical information if you used

DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE

请注意,此功能在Windows 10 10.0.10586上不可用.您必须测试其可用性.

Note that this function is not available on Windows 10 10.0.10586. You must test for its availability.

这篇关于DPI感知的屏幕截图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 02:26