【无标题】wpf最小化至托盘和只允许一个实例(第二次运行激活上个实例)

news/2024/5/11 10:21:40/文章来源:https://blog.csdn.net/weixin_44003021/article/details/129166211

最小化至托盘使用ShowWindow实现。

ShowWindow nCmdShow参数参考https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-showwindow

如果使用Hide(),Show()来实现,它内部会改变Visibility的值,当我们第二次运行激活上个实例的时候无法直接通过ShowWindow直接激活窗口。

//在MainWindow中的代码 实现最小化至托盘
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "ShowWindow")]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);//设置右下角图标
private void SetIcon()
{string path = AppDomain.CurrentDomain.BaseDirectory + "Resources\\home.ico";if (File.Exists(path)){this.notifyIcon = new System.Windows.Forms.NotifyIcon();this.notifyIcon.Text = "XXX";//最小化到托盘时,鼠标点击时显示的文本System.Drawing.Icon icon = new System.Drawing.Icon(path);//程序图标this.notifyIcon.Icon = icon;this.notifyIcon.Visible = true;notifyIcon.MouseClick += new System.Windows.Forms.MouseEventHandler(notifyIcon_MouseClick);}
}
//窗体关闭事件,最小化至托盘
private void MetroWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{ShowWindow(Process.GetCurrentProcess().MainWindowHandle, 0);//隐藏窗口e.Cancel=true; return;
}
//图标上面的鼠标事件 激活窗体
private void notifyIcon_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)
{if (e.Button == form.MouseButtons.Left){if (WindowState == WindowState.Minimized)//防止窗体被最小化{WindowState = WindowState.Normal;}this.Activate();ShowWindow(new System.Windows.Interop.WindowInteropHelper(this).Handle, 5);//显示窗口}
}

只允许一个实例第二次运行激活上个实例使用Mutex锁和n个win32api

当最小化至托盘时使用EnumDesktopWindows函数枚举所有窗口来获取主窗口(参考https://stackoverflow.com/questions/21154693/activate-a-hidden-wpf-application-when-trying-to-run-a-second-instance)

public partial class App : Application
{[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]public static extern int SetForegroundWindow(IntPtr hwnd);[DllImport("user32.dll", EntryPoint = "ShowWindow")]public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);[DllImport("user32.dll")]private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProc ewp, int lParam);[DllImport("user32.dll")]static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);[DllImport("user32.dll")]private static extern uint GetWindowTextLength(IntPtr hWnd);[DllImport("user32.dll")]private static extern uint GetWindowText(IntPtr hWnd, StringBuilder lpString, uint nMaxCount);[DllImport("user32.dll", CharSet = CharSet.Auto)]static extern bool GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);[DllImport("user32.dll")]static extern int GetWindowLong(IntPtr hWnd, int nIndex);delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);const int GWL_EXSTYLE = (-20);const uint WS_EX_APPWINDOW = 0x40000;public const int WM_SYSCOMMAND = 0x112;public const int SC_RESTORE = 0xF120;System.Threading.Mutex mutex;protected override void OnStartup(StartupEventArgs e){try{//运行时根据XXX来获取这个锁,当第二个运行时就拿不到,就激活上个实例mutex = new System.Threading.Mutex(true, "XXX", out bool createNew);if (!createNew){var currProcess = Process.GetCurrentProcess();var sameNameProcess = Process.GetProcesses().FirstOrDefault(m => m.Id != currProcess.Id && m.ProcessName == currProcess.ProcessName && m.MainModule.FileName == currProcess.MainModule.FileName);if (sameNameProcess != null){var handle = sameNameProcess.MainWindowHandle;if (handle == IntPtr.Zero)//当最小化至托盘时MainWindowHandle句柄是0{handle = GetWindowHandle(sameNameProcess.Id);}if (handle == IntPtr.Zero){MessageBox.Show("未找到句柄,激活窗口失败,协同已启动请手动打开窗体"); return;}ShowWindow(handle,3);}Application.Current.Shutdown();}}catch (Exception ex){MessageBox.Show(ex);}base.OnStartup(e);}static bool IsApplicationWindow(IntPtr hWnd){return (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_APPWINDOW) != 0;}static IntPtr GetWindowHandle(int pid){var result = IntPtr.Zero;EnumWindowsProc enumerateHandle = delegate (IntPtr hWnd, int lParam){int id;GetWindowThreadProcessId(hWnd, out id);if (pid == id){var clsName = new StringBuilder(256);var hasClass = GetClassName(hWnd, clsName, 256);if (hasClass){var maxLength = (int)GetWindowTextLength(hWnd);var builder = new StringBuilder(maxLength + 1);GetWindowText(hWnd, builder, (uint)builder.Capacity);var text = builder.ToString();var className = clsName.ToString();if (className.StartsWith("HwndWrapper") && IsApplicationWindow(hWnd)){result = hWnd;return false;}}}return true;};EnumDesktopWindows(IntPtr.Zero, enumerateHandle, 0);return result;}
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_74293.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STC单片机启动看门狗定时器介绍和使用

STC单片机启动看门狗定时器介绍 ✨这里以STC8系列为例。 📑看门狗复位(WDT_CONTR) WDT_FLAG:看门狗溢出标志 看门狗发生溢出时,硬件自动将此位置 1,需要软件清零。EN_WDT:看门狗使能位 0:对单片机无影响 1:启动看门狗定时器。 注意:看门狗定时器可使用软件方式启动,…

CXL互联标准简介及相关资料

毕设是实现CXL的type3扩展内存设备,因为CXL技术非常新,2019年推出,本专栏也是记录CXL的相关知识与一些浅薄的理解 文章目录CXL出现的背景CXL是什么其他互联总线介绍CXL胜出的原因CXL内容简介包含三种协议 CXL.io/cache/memory支持三种设备类型…

Reids实战—黑马点评(三)秒杀篇

Reids实战—黑马点评(三)秒杀篇 来自黑马的redis课程的笔记 【黑马程序员Redis入门到实战教程,深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目】 目录Reids实战—黑马点评(三)秒杀篇一、全局唯一I…

DevOps实战50讲-(1)彻底理解DevOps

持续坚持原创输出,点击蓝字关注我吧软件质量保障:所寫即所思|一个阿里质量人对测试的所感所悟。浅谈软件开发流程软件开发流程是从需求分析、设计、编码、测试到上线等一系列环节的步骤和活动。通常来说,软件开发流程可以分为以下几个阶段&am…

Python 多进程多线程线程池进程池协程

目录 一、线程与进程很简单的介绍 1.1 线程与进程的区别 二、多进程Process 2.1 多进程与多线程的区别 2.2 多进程为啥要使用队列 2.3 控制进程运行顺序 2.3.1 join , 2.3.1 daemon 守护进程 2.4 进程id 2.5 进程 存活状态is_alive() 2.5 实现自定义多…

计算机图形学:liang算法和Cyrus-Beck算法

其中Cyrus-Beck算法呢,是计算一根直线一个多边形的交线段;liang算法是Cyrus的一个特例,即多边形刚好是矩形;先看看Cyrus算法的思路【从别的博客找的图片】:这很容易理解,点积>0时就可能中内部嘛&#xf…

Pyinstaller 打包EXE(七) 百篇文章学PyQT

本文章是百篇文章学PyQT6的第七篇,本文讲述如何使用Pyinstaller打包UI界面和代码,将程序打包成EXE来更为方便的进行部署,在写博客和学习的过程中会遇到很多问题,例如:PyQT6在网上很多博客都是PyQT5、或者PyQT4大部分都…

Amazon S3 服务15岁生日快乐!

2021年3月14日,作为第一个发布的服务,Amazon S3 服务15周岁啦!在中国文化里,15岁是个临界点,是从“舞勺之年”到“舞象之年”的过渡。相信对于 Amazon S3 和其他的云服务15周岁也将是其迎接更加美好未来的全新起点。亚…

java面试题-JVM内存结构

整体结构:1.说说JVM内存整体的结构?线程私有还是共享的?JVM(Java Virtual Machine)内存可以分为以下几个部分:程序计数器(Program Counter Register):是线程私有的&#…

深入浅出解析ChatGPT引领的科技浪潮【AI行研商业价值分析】

Rocky Ding写在前面 【AI行研&商业价值分析】栏目专注于分享AI行业中最新热点/风口的思考与判断。也欢迎大家提出宝贵的意见或优化ideas,一起交流学习💪 大家好,我是Rocky。 2022年底,ChatGPT横空出世,火爆全网&a…

Linux学习(8.6)文件与目录的默认权限与隐藏权限

目录 文件与目录的默认权限与隐藏权限 文件的默认权限:umask chattr (配置文件隐藏属性) lsattr (显示文件隐藏属性) 文件特殊权限: SUID, SGID, SBIT 观察文件类型:file 以下内容转载自鸟哥的Linux私房菜 文件与目录的默认权限与隐藏权…

【架构师】零基础到精通——架构发展

博客昵称:架构师Cool 最喜欢的座右铭:一以贯之的努力,不得懈怠的人生。 作者简介:一名Coder,软件设计师/鸿蒙高级工程师认证,在备战高级架构师/系统分析师,欢迎关注小弟! 博主小留言…

【20230225】【剑指1】分治算法(中等)

1.重建二叉树class Solution { public:TreeNode* traversal(vector<int>& preorder,vector<int>& inorder){if(preorder.size()0) return NULL;int rootValuepreorder.front();TreeNode* rootnew TreeNode(rootValue);//int rootValuepreorder[0];if(preo…

redis秒杀

redis优惠券秒杀 为什么订单表订单ID不采用自增长&#xff1f; id规律性太明显&#xff0c;容易被用户猜测到&#xff08;比如第一天下订单id10&#xff0c;第二天下订单id100&#xff0c;在昨天的1天内只卖出90商品&#xff09;受单表数据量限制&#xff08;订单数据量大&am…

从零开始学习iftop流量监控(找出服务器耗费流量最多的ip和端口)

一、iftop是什么iftop是类似于top的实时流量监控工具。作用&#xff1a;监控网卡的实时流量&#xff08;可以指定网段&#xff09;、反向解析IP、显示端口信息等官网&#xff1a;http://www.ex-parrot.com/~pdw/iftop/二、界面说明>代表发送数据&#xff0c;< 代表接收数…

chatGPT模型原理

文章目录简介BertGPT 初代GPT-2GPT-3chatGPT开源ChatGPT简介 openai 的 GPT 大模型的发展历程。 Bert 2018年&#xff0c;自然语言处理 NLP 领域也步入了 LLM 时代&#xff0c;谷歌出品的 Bert 模型横空出世&#xff0c;碾压了以往的所有模型&#xff0c;直接在各种NLP的建模…

EasyRecovery16MAC苹果版本Photo最新版数据恢复软件

无论是在工作学习中&#xff0c;还是在生活中&#xff0c;Word、Excle等办公软件都是大家很常用的。我们在使用电脑的过程中&#xff0c;有时会因自己的误删或电脑故障&#xff0c;从而导致我们所写的文档丢失了。出现这样的大家不要着急&#xff0c;今天小编就给大家推荐一款可…

FreeRTOS优先级翻转

优先级翻转优先级翻转&#xff1a;高优先级的任务反而慢执行&#xff0c;低优先级的任务反而优先执行优先级翻转在抢占式内核中是非常常见的&#xff0c;但是在实时操作系统中是不允许出现优先级翻转的&#xff0c;因为优先级翻转会破坏任务的预期顺序&#xff0c;可能会导致未…

YOLOv5模型学习记录

新年伊始&#xff0c;YOLOv8横空出世&#xff0c;这个还未开源时便引发界内广泛热议的目标检测算法&#xff0c;一经问世便再次引发热潮&#xff0c;而作为与其师出同源的YOLOv5&#xff0c;自然要拿来与其比较一番。接下来我们便来学习一下吧。 模型结构 首先便是模型结构了…

Rasa 3.x 学习系列-摆脱意图:一种新的对话模式

Rasa 3.x 学习系列-摆脱意图:一种新的对话模式 在2019年的一篇文章中,Alan Nichol写道 :是时候摆脱意图了。一年后,Rasa发布了Rasa中的第一个无意图(或“端到端”)对话模型。现在,我们宣布迈出了一个重要的步伐,将LLM的强大功能带入Rasa的对话管理中。 首先,意图非常…