wpf 在不同DPI下如何在DrawingVisual中画出清晰的图形
- WPF单位,系统DPI,显示器DPI三者的定义及关系
- WPF单位:一种与设备无关的单位,以1/96逻辑英寸为一个单位,也就是说如果将一个对象的长度设为96,那么在任何设备上WPF都会试图将其显示为1逻辑英寸长.
- 系统DPI:将多少个显示器的像素点定义为1逻辑英寸,默认是96个点
- 显示器DPI:每实际英寸有多少个像素点. 大多数显示器每逻辑英寸可显示96个点,不过近年开始流行的高分辨率屏可能会高出很多.
WPF单位决定可视元素的尺寸是多少逻辑英寸,但逻辑每英寸是多少则由系统DPI决定.(此处的"逻辑英寸"已不是生活中的那个绝对不变的单位了,而是由系统DPI决定,只不过默认是与实际英寸一致的)在默认情况下:WPF的一个单位=1/96逻辑英寸=1/96实际英寸 =显示器的1个像素.此时完美点对点,所以不会模糊.但如果在系统中更改了DPI设置,比如144(150%)DPI,此时WPF的一个单位=1/96逻辑英寸=1.5/96实际英寸=显示器的1.5个像素.此时点对点被破坏,所以模糊.
- DrawingVisual如何才能做到与显示器点对点?
- 所有的绘图参数都需要根据系统DPI进行调整,比如在96系统DPI环境下的宽度为1的Pen对象,想要在144系统DPI下继续精确保持1个像素的宽度,那么就要将其缩小为1/(144/96)≈ 0.66666
- 当WPF对DrawingVisual进行渲染时,渲染DPI设置要与系统DPI一致.如果不一致则WPF会先以渲染设置的DPI进行渲染 ,再缩放到系统DPI,一旦缩放就破坏了点对点,进而导致模糊.比如下面通过RenderTargetBitmap对象来使用DrawingVisual,其中的144就是要与系统DPI一致.
Dim RenderTargetBitmap As New RenderTargetBitmap(1920, 1080, 144, 144,PixelFormats.Pbgra32)
RenderTargetBitmap.Render(drawingVisual)
- 例子
Public Class Window1 Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim drawingVisual As New DrawingVisual()
Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()
Dim Thickness As Double = 1 '线宽1个单位,此处等同于1个像素
Dim HalfThickness As Double = Thickness * 0.5
drawingContext.DrawLine(New Pen(Brushes.Black, Thickness),
New Point(0, 100 - HalfThickness),
New Point(1920, 100 - HalfThickness)
)
drawingContext.Close() Dim RenderTargetBitmap As New RenderTargetBitmap(1920, 1080, 96, 96, PixelFormats.Pbgra32) '注意这里创建的是96DPI的图像对象
RenderTargetBitmap.Render(drawingVisual) Dim image As New Image
image.Source = RenderTargetBitmap Canvas1.Children.Add(image)
End Sub End Class
<Window
x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp3"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Window1"
Width="300"
Height="300"
mc:Ignorable="d" Loaded="Window_Loaded">
<Canvas x:Name="Canvas1">
</Canvas>
</Window>
运行结果:线是清晰锐利的
接下来把系统DPI改为150%(修改后别忘了注销windows的当前用户后重新登入以使DPI的修改生效),仍然是要求在相同位置画出一条一个像素宽的清晰横线.
Public Class Window1 Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim drawingVisual As New DrawingVisual()
Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()
Dim Thickness As Double = 1 / 1.5 '在144(150%)DPI的情况下,线宽1个像素
Dim HalfThickness As Double = Thickness * 0.5
drawingContext.DrawLine(New Pen(Brushes.Black, Thickness),
New Point(0, 100 / 1.5 - HalfThickness),
New Point(1920, 100 / 1.5 - HalfThickness)
)
drawingContext.Close() Dim RenderTargetBitmap As New RenderTargetBitmap(1920, 1080, 144, 144, PixelFormats.Pbgra32) '注意这里创建的是144DPI的图像对象
RenderTargetBitmap.Render(drawingVisual) Dim image As New Image
image.Source = RenderTargetBitmap Canvas1.Children.Add(image)
End Sub End Class
运行结果:线依然是是清晰锐利的
- 其它

wpf 在不同DPI下如何在DrawingVisual中画出清晰的图形的更多相关文章
- 如何在canvas中画出一个太极图
先放一个效果图: 代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /&g ...
- 如何在 Linux 中找出最近或今天被修改的文件
1. 使用 ls 命令,只列出你的 home 文件夹中今天的文件. ls -al --time-style=+%D | grep `date +%D` 其中: -a- 列出所有文件,包括隐藏文件 -l ...
- Windows平台下如何在C#中调用Python
最近迷上了Python,发现它能够做很多C#无法完成的事情,比如,调用CMD或者在CMD中执行一个exe文件命令行并获得输出的结果.过程简单,处理起来也非常方便,但如果要用C#调用Python文件呢, ...
- linux系统下如何在vscode中调试C++代码
本篇博客以一个简单的hello world程序,介绍在vscode中调试C++代码的配置过程. 1. 安装编译器 vscode是一个轻量的代码编辑器,并不具备代码编译功能,代码编译需要交给编译器完成. ...
- 如何在 Linux 中找出 CPU 占用高的进程
1) 怎样使用 top 命令找出 Linux 中 CPU 占用高的进程 在所有监控 Linux 系统性能的工具中,Linux 的 top 命令是最好的也是最知名的一个.top 命令提供了 Linux ...
- 如何在shell中打印出带颜色的字符?
先看如下的效果: 方法: 先看如下的脚本sh3.sh: #!/bin/bash echo "peng" echo "$(color bold yellow) ------ ...
- 如何在word中写出赏心悦目的代码
短学期的VHDL终于结束了,虽然代码并不是很难,但是框框条条的规矩很多,也算折腾了一会,最后要写一个技术手册,结题报告类似物.考虑到word毕竟套主题比较方便,所以也就没有用LaTeX写,但是很快就发 ...
- 如何在EXCEL中找出第一列中不包含的第二列数据
1.找出第一列中不包含的第二列数据:=IFERROR(VLOOKUP(A:A,B:B,1,0),"无") 2.A列相同,B列相加:=SUMIF(G:G,G1,J:J)
- 如何在Unity中画抛物线
using UnityEngine; using System.Collections; using System.Collections.Generic; [ExecuteInEditMode] p ...
随机推荐
- MVCAdmin项目知识点记录
1.在过滤器中,用ViewBag类似的东西,要((ViewResult)filterContext.Result).ViewBag. 2.Controller中自己定义的非Action方法中(包括构造 ...
- Angular:使用service进行http请求的简单封装
①使用ng g service services/storage创建一个服务组件 ②在app.module.ts 中引入HttpClientModule模块 ③在app.module.ts 中引入创建 ...
- 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- 访问控制列表ACL应用
ACL的应用的场景 应用在三层接口 • Nat地址转换 Nat(network address translation,地址转换)是将数据报报头中的ip地址转换为另一个ip地址的过程,主要用于实现内部 ...
- Unity 游戏的暂停,继续,重开,退出
1.暂停游戏. Time.timeScale = 0; 2.继续游戏. Time.timeScale = 1; Time.timeScale = 0可以暂停游戏,Time.timeSc ...
- 2020-2021-1 20209307《Linux内核原理与分析》第一周作业
一.Linux基础命令操作 1.查看目录.新建文件.复制移除文件等 ls[选项] [文件或目录] -a 显示所有文件 包含隐藏文件 -l显示详细信息 -d查看目录属性 pwd显示当前目录 mkdir ...
- css 04-CSS选择器:伪类
04-CSS选择器:伪类 #伪类(伪类选择器) 伪类:同一个标签,根据其不同的种状态,有不同的样式.这就叫做"伪类".伪类用冒号来表示. 比如div是属于box类,这一点很明确,就 ...
- 走进 Python 类的内部
这篇文章和大家一起聊一聊 Python 3.8 中类和对象背后的一些概念和实现原理,主要尝试解释 Python 类和对象属性的存储,函数和方法,描述器,对象内存占用的优化支持,以及继承与属性查找等相关 ...
- HCIP----静态实验
要求: 1.全网可达 2.拓扑中所需地址全部基于192.168.0.0/24划分所得 3.使用静态路由 4.R1有三个环回,需要汇总 5.PC1与PC3属于同一VLAN,PC2和PC4属于同一VLAN ...
- 【红日安全-VulnStack】ATT&CK实战系列——红队实战(二)
一.环境搭建 1.1 靶场下载 靶场下载地址:http://vulnstack.qiyuanxuetang.net/vuln/detail/3/ 靶机通用密码: 1qaz@WSX 1.2 环境配置 ...