本文告诉大家如何修复 WPF 的 ContextMenu 在开启 PerMonitorV2 之后,在双屏不同的 DPI 的设备上,在副屏弹出的 ContextMenu 使用了主屏的 DPI 导致缩放错误的问题

关于什么是 PerMonitorV2 请参阅 支持 Windows 10 最新 PerMonitorV2 特性的 WPF 多屏高 DPI 应用开发 - walterlv

开启 PerMonitorV2 的 WPF 应用的 ContextMenu 将在多屏下,需要找到一个关联的屏幕来辅助计算所要显示的坐标。然而在 ContextMenu 创建出来时,是无法知道应该选用哪个屏幕。这就是导致 ContextMenu 视觉效果的 DPI 缩放不对的原因

修复方法就是给 ContextMenu 一个参考的控件,通过此参考控件,可以让 ContextMenu 进行多屏幕不同的 DPI 计算。给 ContextMenu 一个参考的控件的方法有两个

第一个方法是通过将 ContextMenu 设置给所要关联的控件的 ContextMenu 属性上,如此即可让 ContextMenu 弹出的坐标可以根据此关联控件计算。要求关联的控件是在界面布局

            var menu = new ContextMenu
{
Name = menuName,
Style = contextMenuStyle,
ItemsSource = menuItems,
};
canvas.ContextMenu = menu;

但是以上方法存在缺点,那就是对相同的业务逻辑,在 ContextMenu 关闭之前重新赋值,将存在重入问题,重入问题也许导致了某个过程的 ContextMenu 依然由于找不到关联的控件,弹出在左上角。例如以上代码被快速进入两次,第一次的 ContextMenu 对象还没完成弹出,第二次就进入,第二次的 ContextMenu 将会覆盖 canvas 的 ContextMenu 属性,从而让第一次的 ContextMenu 找不到关联的控件,让第一次的 ContextMenu 弹出到左上角,或者计算 DPI 不对

如果采用第一个方法,可以通过缓存 ContextMenu 的方式,代替每次都创建。或者判断当前正在准备弹出 ContextMenu 就不继续创建

第二个方法是设置 ContextMenu 的 PlacementTarget 属性,通过此属性可以让 ContextMenu 关联控件,如以下代码

            var menu = new ContextMenu
{
Name = menuName,
Style = contextMenuStyle,
ItemsSource = menuItems,
// Popup 内部不处理显示过程中的 DPI 改变,依赖于创建时要能找到正确的屏幕,
// 如果什么都不指定,那么创建会创建到主屏,如果实际显示在副屏了,那就会因为 DPI 缩放导致尺寸不对。
//
// 寻找创建时的屏幕时,会寻找 PlacementTarget 和 VisualTreeHelper.GetContainingVisual2D(VisualTreeHelper.GetParent(this)),
// 这里通过指定 PlacementTarget 确保创建的屏幕正确
PlacementTarget = canvas,
};

WPF 修复 ContextMenu 在开启 PerMonitorV2 后所用 DPI 错误的更多相关文章

  1. 修复直接删除linux系统后grub丢失错误

    如果删除了系统后,grub丢失,开机出现“grub>”的话,可以用如下代码进入目标linux系统:grub>ls (hd0,X)/boot             //x为目标系统所在分区 ...

  2. 网站开启https后加密协议始终是TLS1.0如何配置成TLS1.2?

    p { margin-bottom: 0.1in; line-height: 120% } 网站开启https后加密协议始终是TLS1.0如何配置成TLS1.2? 要在服务器上开启 TLSv1.,通常 ...

  3. OS X yosemite开启trim后,开机禁止符号,解决办法

    最近电脑卡得比较严重,像我这种要求电脑反应快的人为了找一个合适的输入法都宁愿花好几天去研究,所以在网上也找了一些关于如何优化mac的东西,结果悲催了,开启trim后,头都吓得出了一把冷汗. 原因:tr ...

  4. IIS开启伪静态后html静态页面无法访问的解决方法

    IIS开启伪静态后,发现原本存在的html静态页面无法访问了,显示的404错误.网上查了下,是因为实现伪静态就是使用 URLRewriter 来映射后缀,会把asp等动态页面映射成html,但是原来存 ...

  5. 我的Android进阶之旅------>解决Jackson等第三方转换Json的开发包在开启混淆后转换的实体类数据都是null的bug

    1.错误描述 今天测试人员提了一个bug,说使用我们的app出现了闪退的bug,后来通过debug断点调试,发现我们的app转换服务器发送过来的json数据后,都是为null.而之前已经提测快一个月的 ...

  6. WPF中ContextMenu(右键菜单)使用Command在部分控件上默认为灰色的处理方法

    原文:WPF中ContextMenu(右键菜单)使用Command在部分控件上默认为灰色的处理方法 问题描述 今天发现如果我想在一个TextBlock弄一个右键菜单,并且使用Command绑定,结果发 ...

  7. [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口

    原文:[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 周银辉 现象: 大家可以试试下面这个很有趣但会带来Defect的现象:当我 ...

  8. Android出现错误后改正后仍显示错误

    今天编Android的时候,layout.xml出现了错误,改正后仍显示错误.试了很多方法. 后来,将原来的复制并删掉,然后再粘贴上去就可以了.

  9. 使用struts框架后的404错误

    访问jsp界面后出现404错误,我开始以为是因为struts没有配置好,在网上找了很多解决方法, 试了一遍,无效, 最后在参考书上看到“struts2推荐把所有的视图界面存放在WEB-INF目录下,这 ...

  10. SharePoint 2013 附加内容数据库后出现404错误

    本文讲述怎样解决SharePoint 2013 加内容数据库(Content DataBase)后出现404错误. 笔者依照http://technet.microsoft.com/en-us/lib ...

随机推荐

  1. Csharp学习Linq

    Linq的学习 这里继续使用之前文章创建的学生类,首先简单介绍一下linq的使用. Student.cs public class Student { public int Id { get; set ...

  2. uni-app 地图全解析+事件监听

    最近找到了一篇uni-app的地图解决方案精品文章,这里分享给大家,希望对大家有所帮助 转载地址:https://blog.csdn.net/cplvfx/article/details/111447 ...

  3. 《Go程序设计语言》学习笔记之slice

    <Go程序设计语言>学习笔记之slice 一. 环境 Centos8.5, go1.17.5 linux/amd64 二. 概念 1) slice 表示一个拥有相同类型元素的可变长度的序列 ...

  4. 【论文阅读】NIDS对抗性机器学习综述

    基本信息 题目:Adversarial Machine Learning for Network Intrusion Detection Systems: A Comprehensive Survey ...

  5. OpenCvSharp+Yolov5Net+Onnx 完整Demo

    效果 工程 代码 using Microsoft.ML.OnnxRuntime; using OpenCvSharp; using System; using System.Collections.G ...

  6. Scala 中断循环

    一.采用 Scala 自带的函数,退出循环 1 package com.atguigu.break 2 3 object TestBreak { 4 import scala.util.control ...

  7. 12 CSS 的float属性

    12 CSS 的float属性 流动布局 流动模型(Flow),即文档流,浏览器打开HTML网页时,从上往下,从左往右,逐一加载. 在正常情况下,HTML元素都会根据文档流来分布网页内容的. 文档流有 ...

  8. OpenHarmony:4.0 Release版本的开发数据

    OpenAtom OpenHarmony 4.0 Release版本于 10 月 27 日发布,经过了32周的开发周期.在此期间,有 65499 个 Committs 进入了 版本.在这个周期内完成了 ...

  9. Qt 实现涂鸦板一:简易涂鸦板

    新建一个Qt项目,在 .h 文件中写入 #pragma once #include <QtWidgets/QWidget> #include "ui_xuexi.h" ...

  10. 「译文」深入了解Kubernetes和Nomad

    ️原文链接: https://www.cncf.io/blog/2023/10/23/introduction-a-closer-look-at-kubernetes-and-nomad/ ✍️作者: ...