最近在写一款软件

软件是用来接收其他程序传递过来的命令行,并形成列表

大概的最终效果就像下图一样

原本为了程序美观是打算用listbox自绘列表,字和图片都绘制好了发现自己不会绘制按钮

所以最终采用了datagridview控件,这个直接就可以插入按钮,就省去了那些问题,不过界面美观就一直是遗憾了(希望有界面方面的大牛可以指导我!)

因为程序启动的方式是被其他程序启动并发送的有命令行

所以,如果有多条消息默认情况下会被打开多个程序,因此开始了如下的各种解决方法

1.命令行的读取

这个相对就比较简单了,修改Program的Main方法

        [STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args));
}

这样就实现了获取命令行,命令行中间用空格隔开,最终程序得到args文本数组

窗口新增获取数组的初始化方法

 public Form1(string[] args)
{
InitializeComponent();
try
{
//这里是将args插入列表的操作 }
catch (Exception)
{
}
}

当然这些都是十分简单的,网上随手查阅就能找到

接下来是程序禁止重复运行,因为我们想把列表显示在一个窗口中,而不是每个窗口都显示一条数据

所以程序是不可以被重复运行的.Program.cs新增代码如下

        #region 防止重复运行
public static Process RunningInstance()
{ Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
{
return process;
}
}
}
return null;
}
public static void HandleRunningInstance(Process instance)
{
ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
SetForegroundWindow(instance.MainWindowHandle);
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private const int WS_SHOWNORMAL = ;
#endregion

新增之后再Main方法做判断,并且如果已经存在打开的窗口的话,就激活打开的窗口

static void Main(string[] args)
{
Process instance = RunningInstance();
if (instance == null)
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.Run(new Form1(args)); }
else
{
HandleRunningInstance(instance);
}
}

做完这些,程序已经不能被重复运行了,再测试,新的问题又来了...程序没有被多次打开,但是同样的,列表永远只会有一条数据,不会被更新

新运行的程序收到的命令行没能告知到旧的窗口,因此需要传递值到旧的窗口,这个方法也有很多,最终我采用的是SendMessage

新增代码如下

        #region 发送消息
const int WM_COPYDATA = 0x004A; [DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int msg, uint wParam, ref COPYDATASTRUCT lParam); [DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern int FindWindow(string lpClassName, string lpWindowName); public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
#endregion

然后再封装一个方法

        static void Send(string[] args)
{
int WINDOW_HANDLER = FindWindow(null, @"这里要改成你的窗口标题,Form1的Text");
if (WINDOW_HANDLER != )
{
StringBuilder sb = new StringBuilder();
foreach (string item in args)
{
sb.Append(item + " ");
}
byte[] sarr = System.Text.Encoding.Default.GetBytes(sb.ToString());
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr);
cds.lpData = sb.ToString();
cds.cbData = len + ;
int sendRet = SendMessage((IntPtr)WINDOW_HANDLER, WM_COPYDATA, , ref cds);
if (sendRet != )
{
MessageBox.Show("传递参数失败!");
}
}
else{
MessageBox.Show("没有发现旧窗口!");
}
}

接下来重新改动一下Main方法

 static void Main(string[] args)
{
Process instance = RunningInstance();
//如果不存在旧窗口
if (instance == null)
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.DoEvents();
System.Windows.Forms.Application.Run(new Form1(args)); }
else
{
//如果存在先激活
HandleRunningInstance(instance);
//如果收到的有参数就传递,没有就忽略
if (args.Length>)
{
Send(args);
} }
}

这样,发送参数的部分就完成了.还剩下最后一步,Form中接收传递过来的参数

在Form中新增如下代码

        #region 接收消息
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
const int WM_COPYDATA = 0x004A;
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT mystr = new COPYDATASTRUCT();
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
string[] s = mystr.lpData.Split(new string[]{" "},StringSplitOptions.RemoveEmptyEntries);
if (s.Length>)
{
//这里写收到参数的情况操作
//mystr.lpData为实际收到的文本,可以直接操作,我这里分割为数组来区分标题,网址等了
}
break; default:
base.DefWndProc(ref m);
break;
}
}
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
#endregion

做完这些我们想要的效果就完全实现了,每次我们的程序被运行都只会有一个窗口,并且所有的数据会汇总在这里

以上文章都乃小生的个人见解,可能会有小的错误或者更好的方法来实现.也希望大家能评论出来让我学习

另外,希望有会自绘列表中带有按钮的大大们,可以指导一下小生

c# 防止重复运行 弹出已运行窗口并传递消息的更多相关文章

  1. 自定义HttpModule,用于未登录用户,不弹出Windows认证窗口,而是跳转回SSO站点

    2012年的一篇随笔记录,可以学习到如何自定义HttpModule,而具体里面针对需求开发的代码,可能未必能让大伙了解到什么,可快速扫描而过. using System; using System.W ...

  2. c# 定时关闭 MessageBox 或弹出的模态窗口

    我们都知道,MessageBox弹出的窗口是模式窗口,模式窗口会自动阻塞父线程的.所以如果有以下代码: MessageBox.Show("内容',"标题"); 则只有关闭 ...

  3. QT QDialog如何弹出一个子窗口

    1. 假设已有一个QDialog的父窗口, 想弹出的子窗口为自己实现的myDialog : QDialog. myDialog 设计和平常的QDialog一样, childDialog : publi ...

  4. AOPR弹出Order Now窗口怎么办

    当我们忘记了我们自己设置的office密码的时候,需要一款office密码破解软件来帮我们破解,Advanced Office Password Recovery就是这样的一款软件,其简称AOPR.试 ...

  5. php弹出式登录窗口并获得登录后返回值

    一款bootstrap样式结合php制作的弹出式登录窗口,输入用户名和密码后,ajax传参给后台,并获得登录后返回值. hwLayer+ajax弹出登录框 $(function() { $('#for ...

  6. [Selenium]通过Selenium实现在当前浏览器窗口点击一个图标之后,弹出另外一个窗口,关闭这个窗口,再回到原来的窗口进行操作

    public void clickReportIcon(){ String initialWindowHandle = driver.getWindowHandle(); //保存原始的浏览器窗口 p ...

  7. PyQt(Python+Qt)学习随笔:在一个窗口点击按钮弹出另一个窗口的实现方法及注意事项

    在Qt Designer中定义了两个窗口,一个主窗口一个弹出窗口,需要实现在主窗口点击一个按钮时弹出弹出窗口. 经老猿验证: 1.弹窗的窗口类型无特殊要求,只要是QWidget等窗口部件就可以,也可以 ...

  8. ifix 在切换菜单按钮弹出”已打开该画面“bug修复

    在ifix项目中,实际上会用到点击按钮弹出按钮菜单,点击另一按钮弹出另一按钮菜单的情况.一般在使用过程中切换菜单可有如下两种普遍做法: 1.使用ClosePicture "Middle&qu ...

  9. Android 定时重复启动弹出窗口。

    本来想着用handlerpostdelay就可以实现,没想到演示后关闭应用居然报错. 后来想到是没有了activity. ((Activity)context).isFinishing() 可以传入c ...

随机推荐

  1. Hibernate---数据操作示例BY实体映射文件

    创建一个Student.java类:该类需要一个无参的构造函数,以及属性的get/set方法 public class Student implements Serializable { privat ...

  2. Eclipse Java 构建路径 ---Eclipse教程第13课

    Eclipse Java 构建路径 设置 Java 构建路径 Java构建路径用于在编译Java项目时找到依赖的类,包括以下几项: 源码包 项目相关的 jar 包及类文件 项目引用的的类库 我们可以通 ...

  3. 《Cracking the Coding Interview》——第6章:智力题——题目1

    2014-03-19 06:40 题目:有20瓶药,其中19瓶装的都是1.0克的药片,只有1瓶装了1.1克的药.给你一个能称出具体克数的电子秤,只允许你称一次,怎么找出那瓶不一样的? 解法:如果药片管 ...

  4. 《Cracking the Coding Interview》——第1章:数组和字符串——题目6

    2014-03-18 01:45 题目:给定一个NxN的矩阵,就地旋转90度.(没有样例又不说方向的话,随便往哪儿转.) 解法:如果N为奇数,除了中心点以外四等分.如果N为偶数,四等分.按照A-> ...

  5. 【Dual Support Vector Machine】林轩田机器学习技法

    这节课内容介绍了SVM的核心. 首先,既然SVM都可以转化为二次规划问题了,为啥还有有Dual啥的呢?原因如下: 如果x进行non-linear transform后,二次规划算法需要面对的是d`+1 ...

  6. 4.实现简单的shell sed替换功能

    # -*- coding:utf-8 -*- # Author: JACK ZHAO # 程序1: 实现简单的shell sed替换功能 import sys #判断参数个数 if len(sys.a ...

  7. Mac 电脑鼠标和触摸板滚动方向不一致的问题【已解决】

    当我们使用鼠标连接到 MacBook 时,会发现无论怎么设置,鼠标和触摸板的滚动方向都是相反的,导致不能同时使用鼠标和触摸板 解决方法: 我安装了下面的程序,它只允许您反转鼠标的滚动行为: Scrol ...

  8. 【bzoj1565】[NOI2009]植物大战僵尸 拓扑排序+最大权闭合图

    原文地址:http://www.cnblogs.com/GXZlegend/p/6808268.html 题目描述 输入 输出 仅包含一个整数,表示可以获得的最大能源收入.注意,你也可以选择不进行任何 ...

  9. 【BZOJ1179】[Apio2009]Atm (tarjan+SPFA)

    显而易见的tarjan+spfa...不解释了 ; type edgetype=record toward,next:longint; end; var edge1,edge2:..maxn] of ...

  10. POJ 2195 Going Home | 带权二分图匹配

    给个地图有人和房子 保证人==房子,每个人移动到房子处需要花费曼哈顿距离的代价 问让人都住在房子里最小代价 显然是个带权二分图最大匹配 转化成以一个网络,规定w是容量,c是代价 1.S向人连边,w=1 ...