WPF-禁止二次启动
App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
//禁止二次启动
this.Startup += new StartupEventHandler(App_Startup);
base.OnStartup(e);
}
#region 禁止二次启动
// 用于激活已打开的窗体
[DllImport("user32.dll")]
public static extern void SetForegroundWindow(IntPtr hwnd);
//操作当前窗体
//nCmdShow: 0关闭窗口/1正常大小显示窗口/2最小化窗口/3最大化窗口
[DllImport("user32.dll")]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow); System.Threading.Mutex mutex;
void App_Startup(object sender, StartupEventArgs e)
{
bool ret;
mutex = new System.Threading.Mutex(true, "WpfDemo", out ret);
if (!ret)
{
System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName("WpfDemo");
foreach (System.Diagnostics.Process p in proc)
{
SetForegroundWindow(p.MainWindowHandle);
ShowWindow(p.MainWindowHandle, );
NoSecond.SendMessage(p.MainWindowHandle);
}
Environment.Exit();
}
}
#endregion
NoSecond.cs
/// <summary>
/// 禁止程序二次启动
/// </summary>
public class WPFNoSecond
{
public const int NoSecond_DATA = 0x004A;
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage
(
IntPtr hWnd, //目标窗体句柄
int Msg, //WM_COPYDATA
int wParam, //自定义数值
ref CopyDataStruct lParam //结构体
);
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;//字符串长度
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;//字符串
} public static void SendMessage(IntPtr thisIntPtr)
{
IntPtr xmlIntPt = new IntPtr(GetIntPtr());
if (xmlIntPt != IntPtr.Zero || thisIntPtr != IntPtr.Zero)
{
CopyDataStruct cds;
cds.dwData = IntPtr.Zero;
cds.lpData = "";
cds.cbData = ;//注意:长度为字节数
int fromWindowHandler = ;// 消息来源窗体
SendMessage(thisIntPtr.ToInt32() == ? xmlIntPt : thisIntPtr, NoSecond_DATA, fromWindowHandler, ref cds);
}
} #region 窗体句柄指针
static string _IntPtrDataDic = AppDomain.CurrentDomain.BaseDirectory + "/XML/";
static string _IntPtrDataName = "Data.xml";
static void intPtrDataExists()
{
try
{
if (!System.IO.File.Exists(_IntPtrDataDic))
{
if (!Directory.Exists(_IntPtrDataDic)) { Directory.CreateDirectory(_IntPtrDataDic); }
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", ""));
XmlElement root = doc.CreateElement("Root");
root.InnerText = "";
doc.AppendChild(root);
doc.Save(_IntPtrDataDic);
}
}
catch (Exception) { }
}
static int GetIntPtr()
{
intPtrDataExists();
XDocument xml = XDocument.Load(_IntPtrDataDic + _IntPtrDataName);
XElement xmlRoot = xml.Root;
return Convert.ToInt32(xmlRoot.Value);
}
public static void SetIntPtr(string intPtr)
{
intPtrDataExists();
XDocument xml = XDocument.Load(_IntPtrDataDic + _IntPtrDataName);
XElement xmlRoot = xml.Root;
xmlRoot.Value = intPtr;
xml.Save(_IntPtrDataDic + _IntPtrDataName);
}
#endregion
}
Window.cs
#region 禁止二次启动
private void Window_SourceInitialized(object sender, EventArgs e)
{
HwndSource source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
if (source == null) { throw new Exception("Cannot get HwndSource instance."); }
source.AddHook(new HwndSourceHook(this.WndProc));
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
try
{
switch (msg)
{
case WPFNoSecond.NoSecond_DATA:
this.Show();
break;
}
}
catch (Exception) { }
return IntPtr.Zero;
}
#endregion
//最小化到托盘
private void Window_Min(object sender, RoutedEventArgs e)
{
//存储当前窗体句柄
WPFNoSecond.SetIntPtr(new WindowInteropHelper(this).Handle.ToString());
}
WPF-禁止二次启动的更多相关文章
- 问题-[delphi2007、2010]无法二次启动,报EditorLineEnds.ttr被占用,进程一直有bds.exe?
问题现象:delphi2007.2010无法二次启动,报EditorLineEnds.ttr被占用,而且进程中一直有bds.exe的进程? 问题原因:问题处理:方法一:可能是系统更新的东东造在的.KB ...
- WPF 开发自动开机启动程序
原文:WPF 开发自动开机启动程序 本文告诉大家如何在 WPF 开发一个可以自动启动的程序 本文使用的自动开机启动方法是通过快捷方式放在启动文件夹的方式. 创建快捷方式 /// <summary ...
- WPF应用程序的启动画面[Splash Screen本质分析]
原文:WPF应用程序的启动画面[Splash Screen本质分析] 不经意间发现了wpf的这个小玩意,感觉蛮有意思的.我在项目中添加了一张图片 如图: wpf-1.JPG(10.73 K) 2010 ...
- WPF属性(二)附加属性
原文:WPF属性(二)附加属性 附加属性是说一个属性本来不属于某个对象,但由于某种需求而被后来附加上,也就是把对象放入一个特定环境后对象才具有的属性就称为附加属性,附加属性的作用就是将属性与数据类型解 ...
- Caddy源码阅读(二)启动流程与 Event 事件通知
Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy C ...
- [WPF]WPF设置单实例启动
WPF设置单实例启动 使用Mutex设置单实例启动 using System; using System.Threading; using System.Windows; namespace Test ...
- [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat
概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...
- WPF的二维绘图(二)——几何图形Geometry
在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常应用中,更多的是使用DrawG ...
- 禁止Visual Studio启动时自动连接TFS服务器
在默认设置情况下,Visual Studio启动时,会自动连接上次打开过的TFS服务器.这种设计能够提高开发人员的工作效率,避免每次手动连接TFS服务器. 但是在某些情景中,也会给人造成不必要的麻烦, ...
随机推荐
- centos 6.7 搭建tornado + nginx + supervisor的方法(已经实践)
首先,本来不想写这篇博客了,但是我测试了很多网上的例子包括简书的,全不行,我总结原因是自己太笨,搞了俩个晚上,后来决定,自己还是写一篇记录下来,保证自己以后使用 环境: centos6.7 64 py ...
- Android二维码的生成,解析以及扫描功能
<1> 布局只有2个按钮,实现生成二维码和解析二维码 <Button android:layout_width="wrap_content" android:la ...
- Docker - Install docker on CentOS
1. 准备 由于 Dokcer 需要 64bit OS, 版本号 3.10 或者更新的版本.所以,需要我们先确认我们的 CentOS 系统 $ uname -r output :: 3.10.0-22 ...
- selenium 下载百度音乐并验证
package baidu; import java.io.File; import java.io.IOException; import java.util.List; import org.ap ...
- MySQL存储过程动态SQL语句的生成
用Mysql存储过程来完成动态SQL语句,使用存储过程有很好的执行效率: 现在有要求如下:根据输入的年份.国家.节假日类型查询一个节假日,我们可以使用一般的SQL语句嵌入到Java代码中,但是执行效率 ...
- iOS开发者联系 联系方式
苹果开发者客服电话地址:https://developer.apple.com/contact/phone.php 中国大陆地区客服电话: 中国香港地区客服电话:() 中国台湾地区客服电话: 链接地址 ...
- UML大战需求分析——阅读笔记06
状态机图和活动图在样子比较相似,但状态机图是用来为对象的状态及造成状态改变的事件建模.我们大二学习UML统一建模语言状态机图模块时了解到,UML的状态机图主要用于建立对象类或对象的动态行为模型,描述系 ...
- Mysql 迁移最完整可用的教程
此教程来源stackoverflow,仅供我自己需要时查看,其他人不可以瞎看! ## Stop MySQL using the following command: `sudo /etc/init.d ...
- [Spring] Spring配置文件中特殊字符的规定
今天查找一个错误,发现在xml里面不能包含特殊字符:&,特来总结一下: XML中共有5个特殊的字符,分别是:&<>“’.如果配置文件中的注入值包括这些特殊字符,就需要进行特 ...
- Beginning Scala study note(2) Basics of Scala
1. Variables (1) Three ways to define variables: 1) val refers to define an immutable variable; scal ...