问题描述
我之前使用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,100
至200,200
处).而是返回100x100像素的正方形(在50,50
至100,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感知的屏幕截图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!