C# WPF 分辨率独立性?
我正在使用 C# 在 WPF 中开发地图控件。 我正在使用画布控件,例如 400 x 200,它被分配了例如 2,000mx 1,000m 的地图区域。
地图比例为:canvas_size_in_meters / real_size_in_meters。
我想找到canvas_size_in_meters。
canvas.ActualWidth 以 DIU(设备独立单位)为单位给出宽度。 因此,400 DIU 为 400/96 = 4,17 英寸,假设我的显示器的物理分辨率为 96 dpi。
然而,使用尺子,我发现我的显示器的物理分辨率是87 dpi。 (只有少数显示器实际上具有 96 物理 dpi)
该 DPI 差异 (10%) 转化为屏幕上实际地图控件宽度的 +10% 差异。
如何准确测量 WPF 控件的尺寸(以英寸为单位),而不管屏幕分辨率和 DPI 设置如何?
I am developing a map control in WPF with C#. I am using a canvas control e.g. 400 x 200 which is assigned a map area of e.g. 2,000m x 1,000m.
The scale of the map would be: canvas_size_in_meters / real_size_in_meters.
I want to find the canvas_size_in_meters.
The canvas.ActualWidth gives the Width in DIU's (Device Independant Units). So, 400 DIU's is 400/96 = 4,17 inches, PROVIDED that the physical resolution of my monitor is 96 dpi.
However, using a ruler, I found that the physical resolution of my monitor is 87 dpi. (There are only few monitors that ACTUALLY have 96 physical dpi)
That DPI difference (10%) translates to a +10% difference in the actual map control width on screen.
How do I measure the size of a WPF control in inches EXACTLY and regardless of screen resolution and DPI setting ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这实际上是不可能的,因为要使其工作,WPF 必须知道显示器的分辨率(以 DPI 表示)。 理论上听起来不错,但实际上 Windows 并不知道这些信息。 这就是为什么Windows本身总是盲目地假设96dpi而不是更聪明地假设它。
即使有某种方法可以手动告诉它,或者如果您的特定显示器有一个自定义驱动程序可以将正确的信息传递给 Windows,这也不会在其他任何人的计算机上工作,因此 Windows 不会将此信息传递给到任何应用程序。
你能做的最好的事情就是像谷歌地图一样绘制比例尺。 您知道 1 像素 == 1 英里,因此您可以在地图上绘制一条 50 像素的线,并附上标签“这条线等于 50 英里”
This isn't actually possible, because for it to work, WPF would have to know the resolution (in terms of DPI) of your monitor. Sounds nice in theory, but in practice windows doesn't know this information. This is why windows itself always assumes 96dpi blindly instead of being smarter about it.
Even if there were some way to manually tell it, or if your particular monitor has a custom driver that does pass the correct information to windows, this isn't going to work on anyone else's computer, so windows doesn't pass this information on to any applications.
The best you can do is draw a scale like google maps does. You know that 1 pixel == 1 mile, so you can draw a 50 pixel line on your map, with a label saying "this line equals 50 miles"
有办法计算当前像素大小(以毫米或英寸为单位)。 正如之前的帖子中提到的,它不是一个固定值,会根据当前分辨率和显示器尺寸而变化。
首先获取当前分辨率。 假设它是 1280x1024
现在使用 GetDeviceCaps 函数获取显示器宽度(以毫米为单位)。 它是一个标准的 Windows 库函数。
int widthmm = GetDeviceCaps(deviceContext, HORZSIZE);
我的显示器宽度是 362mm
所以像素大小 = 362/1280 = 0.282 mm
此方法的准确性取决于显示区域完全覆盖显示器宽度的假设。
因此,要回答最初的问题,400 x 200 像素的画布大小将是
显示在我的显示器上时,以米为单位(400 * 0.282/1000)x(200 * 0.282/1000)。
There is way to compute current pixel size in mm or inches. As mentioned in the earlier posts, it is not a fixed value and would vary depending on the current resolution and monitor size.
First get the current resolution. Assume it is 1280x1024
Now get the monitor width in mm using GetDeviceCaps function. Its a standard windows library function.
int widthmm = GetDeviceCaps(deviceContext, HORZSIZE);
My monitor width is 362mm
So pixel size = 362/1280 = 0.282 mm
The accuracy of this method depends on the assumption that the display area covers the width of the monitor exactly.
So to answer the original question, the canvas size of 400 x 200 pixels would be
(400 * 0.282/1000) x (200 * 0.282/1000) in meters when shown on my monitor.
感谢您的及时回复。
我完全同意,但我一开始就不想相信。 您会看到,如果地图用于显示不同图层的地图数据(取决于比例),则必须对地图比例进行近似计算。
大多数应用程序使用具有例如 10 个离散地图级别的滑块控件来设置“比例”。
拥有绝对比例对于应用程序来说并不重要,最好显示一个指示性比例,例如 1:15,000。
绝对缩放需要一个额外的变量 monitorPhysicalDPI (最初设置为 96),如果用户选择更改,则会提供稍微更好的缩放(同样,这并不重要)。 地图控件的大小为:
map.ActualWidth * (96/monitorPhysicalDPI) *inchsPerDIU,inchesPerDIU 为 1/96
同样,这些都是装饰性的。如果 Windows 知道 ACTUAL,那不是很好吗?控件的尺寸? (用户必须提供有关操作系统设置的屏幕尺寸的信息,或者只需安装显示器 INF 文件)
Thank you for you prompt reply.
I totally agree, but I didn't want to believe it in the first place. You see, there has to be an approximate calculation of the scale of the map if the map is used to display different layers of map data (scale dependant).
Most applications use a slider control with e.g. 10 discrete map levels to set the "scale".
Having an absolute scale is not crucial for the application, it would be nice to display an indicative scale, like 1:15,000.
An absolute scale would require for an extra variable monitorPhysicalDPI (initially set to 96) that if the uses chooses to change would give slightly better scaling (again it's not crucial). The size of the map control would be:
map.ActualWidth * (96/monitorPhysicalDPI) * inchesPerDIU, inchesPerDIU is 1/96
Again these are cosmetics.. Wouldn't it be nice if Windows knew the ACTUAL control's dimensions? (user would have to give information about the screen dimensions on OS setup, or simply installing the monitor INF file)