https://blog.walterlv.com/walterlv吕毅的博客。.NET/C#/WinUI/MAUI/WPF Windows 应用开发者,微软最有价值专家,Microsoft MVP。 2023-08-03T11:51:42+08:00 吕毅 https://blog.walterlv.com/ Jekyll © 2014-2023 walterlv /assets/img/favicons/favicon.ico /assets/img/favicons/favicon-96x96.png 如何在控制台程序中监听 Windows 前台窗口的变化2023-08-03T11:50:23+08:00 https://blog.walterlv.com/post/monitor-foreground-window-on-windows 吕毅 前一段时间总会时不时发现当前正在打字的窗口突然失去了焦点,于是很希望有个工具能实时监听前台窗口的变化,并实时输出出来。 本文会介绍两类知识,一类是如何在 .NET/C# 程序中方便地调用 Win32 API,另一类是在控制台程序中开启 Windows 消息循环。 思路 获取当前前台窗口的本质 API 调用是 GetForegroundWindow。在拿到前台窗口的句柄后,进而获取到例如窗口标题、类名等信息。 var hWnd = GetForegroundWindow(); // 随后获取窗口标题、类名等…… 接下来,就是什么时机去调用这个 API 了。 虽然我第一时间想到了延时轮询的方式,并且好久以前也确实是这么写的。但其实有更好的方法来解决这个问题,而且 Lsj 的 Window Debugger 也正计划实现这个功能,对此也有更多的了解。 是的,我们... .NET/C# 程序如何在控制台/终端中以字符表格的形式输出数据2023-08-03T11:49:03+08:00 https://blog.walterlv.com/post/format-data-as-a-table-in-console 吕毅 在一篇在控制台窗口中监听前台窗口的博客中,我在控制台里以表格的形式输出了每一个前台窗口的信息。在控制台里编写一个字符表格其实并不难,毕竟 ASCII 中就已经提供了制表符。不过要在合适的位置输出合适的制表符,要写一些打杂式的代码了;另外,如果还要考虑表格列的宽度自适应,再考虑中英文在控制台中的对齐,还要考虑文字超出单元格时是裁剪/省略/换行。当把所有这些麻烦加到一起之后,写一个这样的辅助类来顶替那些麻烦事儿还是很有必要的。 效果预览 以下是我在前台窗口监视程序中的运行效果: 代码组织 我写了三个类来完成这样的事情: ConsoleTableBuilder<T> 用于构建表格 ConsoleTableColumnDefinition<T> 用于定义表格的列 ConsoleStringExtensions 由于在控制台中做中英文... 在 Windows 上如何在启动程序时单独为这个程序指定环境变量,而不需要编写任何代码或脚本2023-08-01T16:50:35+08:00 https://blog.walterlv.com/post/how-to-start-a-process-with-environment-variables-without-code 吕毅 有些程序没有内置提供代理的功能,但遵循环境变量中设置的代理。如果我们能有办法仅为这个特定的程序设置环境变量,那么我们就可以在不开启全局代理的情况下单独为这样的程序开启代理。 设置环境变量开启代理 比如,Unity Hub 就是这样的一个程序。为了让它开启代理,我们可以在命令行中用这样的三句命令启动它: > cd "C:\Program Files\Unity Hub" > set HTTP_PROXY=http://127.0.0.1:7778 > set HTTPS_PROXY=http://127.0.0.1:7778 > "Unity Hub.exe" 单独为程序设置环境变量的方法 如果,我们能用一句话就完成上面的三句命令,那么就可以直接在快捷方式中设置这个程序的代理了,不需要单独写一个脚本。 在这个问答中 Launch Windo... 如何正确调教 Visual Studio 自带的拼写检查功能2023-07-19T16:11:24+08:00 https://blog.walterlv.com/post/visual-studio-spell-checker-issue 吕毅 Visual Studio 2022 (17.6 Preview 2) 带来了拼写检查功能,此功能一出大家纷纷吐槽各种问题。不过团队中确实时不时会出现单词拼写错误的情况,所以有时又觉得非常需要它。 如果你打算在 Visual Studio 中好好使用这个自带的功能,那么可以阅读本文。对它有更多的了解之后,也许可以逐渐趋利避害。 开启拼写检查功能 目前,拼写检查器功能仍然是预览功能,所以需要在 Visual Studio 的“工具”->“选项”菜单中找到“环境”->“预览功能”选项卡,然后找到“拼写检查器”功能,把它打开。 拼写检查和忽略单词 开启了 Visual Studio 拼写检查器功能后,如果再在代码中写出了错误的单词,则会视时给出下划线提醒。不过注意,这个提醒只是 IDE 的提醒,不会出现在项目编译过程的警告或信息中。 下图是对 embed... WPF 像素着色器进阶:使用 HLSL 编写一个高性能的实时变化的 HSL/HSV/HSB 调色盘2023-05-25T16:33:06+08:00 https://blog.walterlv.com/post/wpf-draw-a-hsl-hsb-palette-using-hlsl 吕毅 要在代码里画一个 HSL/HSV/HSB 调色盘非常容易,不过如果这个调色盘需要实时变化,那么频繁绘制需要在 CPU 上大量创建或者修改位图,性能不太好。本文将使用 HLSL 来完成这一任务。 HLSL 入门 如果你对 WPF 使用像素着色器还不太了解,那么可以阅读入门文章: WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码 HSL/HSV/HSB 为了让后面的代码容易看懂,我们需要先简单了解一下 HSL/HSV/HSB。 HSL:hue 色相, saturation 饱和度, lightness 亮度 HSV/HSB:hue 色相, saturation 饱和度, value/brighness 明度 这是两个不同但类似的,符合人眼感知的颜色表示方法,其中后两者只是名称不同,实际上是完... WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码2023-05-22T22:06:04+08:00 https://blog.walterlv.com/post/create-wpf-pixel-shader-effects-using-shazzam-shader-editor.html 吕毅 HLSL,High Level Shader Language,高级着色器语言,是 Direct3D 着色器模型所必须的语言。WPF 支持 Direct3D 9,也支持使用 HLSL 来编写着色器。你可以使用任何一款编辑器来编写 HLSL,但 Shazzam Shader Editor 则是专门为 WPF 实现像素着色器而设计的一款编辑器,使用它来编写像素着色器,可以省去像素着色器接入到 WPF 所需的各种手工操作。 本文是 WPF 编写 HLSL 的入门文章,带大家使用 Shazzam Shader Editor 来编写最简单的像素着色器代码。 下载安装 实际上 Shazzam Shader Editor 有一段时间没有维护了,不过在 WPF 下依然是一个不错的编写 HLSL 的工具。 于是去我的镜像地址下载:https://github.com/walter... Windows 10 自带那么多图标,去哪里找呢?2023-05-19T19:48:24+08:00 https://blog.walterlv.com/post/where-is-the-windows-10-native-icons.html 吕毅 无意间发现我的 D 盘根目录中大部分的文件夹都是系统专用文件夹,有自己的独特图标,偶有一两个开发用的文件夹是默认图标。于是想把它们改成独特样式,而且是 Windows 10 那些新图标样式! 这是我的文件夹,我希望把最上面几个文件夹的图标改成下面那些风格。 大家都知道在文件夹上右键,选择 属性 → 自定义 → 更改图标,这里可以选择很多图标,但用了很多年看腻了,Windows 10 中还自带有那么多,它们又在哪里呢? Windows 10 自带的图标几乎都在 %systemroot%\system32\*.dll 中,主要是这些: Windows 10 风格 %systemroot%\system32\ddores.dll %systemroot%\system32\dmdskres.dll %systemroo... 如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀)2023-04-18T08:54:42+08:00 https://blog.walterlv.com/post/the-properties-that-affetcs-project-output-path.html 吕毅 我们都知道可以通过在 Visual Studio 中设置输出路径(OutputPath)来更改项目输出文件所在的位置。对于 .NET Core 所使用的 Sdk 风格的 csproj 格式来说,你可能会发现实际生成路径中带了 netcoreapp3.0 或者 net472 这样的子文件夹。 然而有时我们并不允许生成这样的子文件夹。本文将介绍可能影响实际输出路径的各种设置。 项目和输出路径 对于这样的一个简单的项目文件,这个项目的实际输出路径可能是像下图那样的。 <Project> <PropertyGroup> <TargetFramework>netcoreapp3.0</TargetFramework> <OutputPath>bin\$(Configuration)</Outp... 如何利用 Win32 API 设置两个窗口的所有者(Owner)关系2023-03-01T15:37:01+08:00 https://blog.walterlv.com/post/set-owner-window-using-win32-api 吕毅 设置两个窗口的父子关系非常简单,只需要调用 SetParent 函数即可。然而设置两个窗口的所有者(Owner)关系却没有一个简单直观的 API。那么本文介绍一下如何设置两个窗口的 Owner 关系。 设置所有者(Owner) 由于方法非常简单,所以我直接贴出 MainWindow 中的完整代码: public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); SourceInitialized += OnSourceInitialized; } private void OnSourceInitialized(object? sender, EventArgs e) { ... WPF 的 Dispatcher 为什么要创建一个隐藏窗口?2023-02-28T10:18:05+08:00 https://blog.walterlv.com/post/why-dispatcher-creates-a-hidden-message-only-window 吕毅 在深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsync 部分)中,我提到 Dispatcher 在构造函数中创建了一个隐藏窗口专门用来接收消息,以处理通过 Invoke 系列方法调用的那些操作。然而 C 不满足于只看到这个结论,他更期望知道为什么 WPF 一定要创建这个隐藏的窗口。其实对这个问题我也不知道答案,但在和他深入的探讨以及不断寻找资料的过程中,我们逐渐得知了缘由。 本文记录了这一次探讨,给希望了解 Windows、WPF 底层机制的人一些可供参考的思路和结论。当然,要特别感谢 C 提出了这个问题,并在讨论过程中给出了关键性的推理。 隐藏窗口的疑问 先来回顾一下 Dispatcher 构造函数中与创建窗口相关的部分: // Create the message-only window we use to receive me...