窗体在托盘隐藏后,再次双击exe如何激活并显示?

_真真 2014-03-09 09:07:54
大神们好 !

我想做一个类似迅雷,有道词典,电脑管家之类的托盘程序,点击关闭和最小化都显示在托盘,

点击托盘图标或者桌面图标激活主窗体让其显示。


关闭和最小化显示托盘我已实现,在最小化和关闭事件前,使用hide方法让其隐藏。

并且我已经实现了点击托盘让其显示出来,

但是我现在如果点击桌面图标或点击exe,如何激活被我隐藏的窗体?

我在网上已经搜了一大堆文章,大部分都是说
[DllImport("user32.dll")]
public static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
引用user32.dll来显示,但我试过,只有窗体最小化以后(不是隐藏),并且任务栏有图标的情况下,才可以显示出来,如果隐藏hide的话或者虽然使用最小化,但把任务栏图标隐藏,用此方法是显示不出来。

请问大神们如何实现呢?
...全文
558 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
於黾 2015-02-12
  • 打赏
  • 举报
回复
引用 15 楼 SmileSkyNet 的回复:
你这个其实涉及到软件只运行一个实例的问题,这个可以在网上找,我告诉你思路:当你运行软件时也就是在programe.cs的main方法中加上判断软件是否运行的代码,如果已经运行就显示窗体,那么怎么能显示已经隐藏的窗体呢?在这里我觉得可以这样来实现: 软件搞一个启动界面,然后通过这个界面进入主界面,这是关键的一步,我暂时设主界面为MainForm 那么在Programe.CS中加入 Public static MainForm mainfrm; 在启动界面中这样进行主界面 Programe.mainfrm=new MainForm(); Programe.mainfrm.Show(); 那么在Programe.cs的Main方法中这样判断 //if软件已经运行 //mainfrm.Show(); 这个是我的一个解决方法没有用代码去验证,你可以试下!
这是一个很不靠谱,很不负责任的解决方案 一个进程里的静态变量,并不会出现在另一个进程里,没有任何联系 根本不存在内存全局静态变量,每一个进程的内存区域都是独立的,不受其他程序分配的内存影响的 你在一个进程里定义的对象,要在另一个进程里直接调用???
於黾 2015-02-12
  • 打赏
  • 举报
回复
学习一下进程间通信 程序运行时先判断是否已经有同名进程在运行,如果没有,正常运行 如果有,那么给进程发个消息,然后就自己退出 另一方面,进程收到消息,就从隐藏状态还原 虽然使用最小化,但把任务栏图标隐藏,用此方法是显示不出来 不要老用小偷程序的思路去做正规的程序 好比你把钥匙忘在家里了,那么要么打电话给女朋友,让她送钥匙过来,要么打电话给开锁公司.总之这些都是基于"通信" 而不是你自己去爬窗户
SmileSkyNet 2015-02-11
  • 打赏
  • 举报
回复
你这个其实涉及到软件只运行一个实例的问题,这个可以在网上找,我告诉你思路:当你运行软件时也就是在programe.cs的main方法中加上判断软件是否运行的代码,如果已经运行就显示窗体,那么怎么能显示已经隐藏的窗体呢?在这里我觉得可以这样来实现: 软件搞一个启动界面,然后通过这个界面进入主界面,这是关键的一步,我暂时设主界面为MainForm 那么在Programe.CS中加入 Public static MainForm mainfrm; 在启动界面中这样进行主界面 Programe.mainfrm=new MainForm(); Programe.mainfrm.Show(); 那么在Programe.cs的Main方法中这样判断 //if软件已经运行 //mainfrm.Show(); 这个是我的一个解决方法没有用代码去验证,你可以试下!
  • 打赏
  • 举报
回复
引用 7 楼 nanfei01055 的回复:
c#.net没做过,以前vb我用的DDE,很简单
c#一样很简单,有封装好的“托盘图标控制对象”winform控件,而且可以捕获各种事件,可以自定义各种事件(例如通知程序的主窗口执行show()方法)。 问题是,你有没有注意到他们想“即使在任务栏托盘图标隐藏时也要点击出来”这种描述?你可以看到,在你的回复的上面的那几位,都是考虑如何“偷别人”的进程,从外部去控制进程去“模拟用户点击”。而不是正规地让一个进程“内建”响应用户的点击托盘图标的操作。 所以用一个做正规软件的思路去理解某些的说明,如果不小心,会看错意思的。
qq_25972309 2015-02-11
  • 打赏
  • 举报
回复
引用 8 楼 sj178220709 的回复:
进程监测防多开 加单例模式
我也遇到了同样的问题,好像开单例模式没有用呢
qq_25972309 2015-02-11
  • 打赏
  • 举报
回复
引用 7 楼 nanfei01055 的回复:
c#.net没做过,以前vb我用的DDE,很简单
我也遇到了同样的问题,好像开单例模式没有用呢
qq_25972309 2015-02-11
  • 打赏
  • 举报
回复
引用 7 楼 nanfei01055 的回复:
c#.net没做过,以前vb我用的DDE,很简单
我也遇到了同样的问题,好像开单例模式没有用呢
nanfei01055 2014-03-10
  • 打赏
  • 举报
回复
c#.net没做过,以前vb我用的DDE,很简单
_真真 2014-03-10
  • 打赏
  • 举报
回复
回复1楼,2楼. 这个方法我试过了,我用的就是和你们一样的代码。 可以判断出进程是否已开启,但是使用user32.dll 这样只能调出最小化后的窗体,窗体hide隐藏后,调用不出来。 hide后如何调出来呢?
assky124 2014-03-10
  • 打赏
  • 举报
回复
在Main函数中检测进程是否已存在


Main()
{
   if(CheckAppIsRun())
   {
      SendMessageToActive(); //发送Window消息,重写主窗体的WndProc函数,处理自定义的Window消息
   }
   else
   {
      RunApp();   //启动新程序
   }
}

BenBenBears 2014-03-10
  • 打赏
  • 举报
回复
互斥

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Directory_File
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Boolean createdNew; //返回是否赋予了使用线程的互斥体初始所属权
            System.Threading.Mutex instance = new System.Threading.Mutex(true, "MutexName",out createdNew); //同步基元变量
            if (createdNew) //赋予了线程初始所属权,也就是首次使用互斥体
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1()); 
                instance.ReleaseMutex();
            }
            else
            {
                MessageBox.Show("已经启动了一个程序!","系统提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
                Application.Exit();
            }
        }
    }
}
ycg_893 2014-03-10
  • 打赏
  • 举报
回复
窗口隐藏是无法接收消息的,你可用WCF的管道命名来接收消息.
是_这样吗 2014-03-10
  • 打赏
  • 举报
回复

[System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);
        private void Form1_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Process oProcess = System.Diagnostics.Process.GetCurrentProcess();
            System.Diagnostics.Process[] aoProcesses = System.Diagnostics.Process.GetProcessesByName(oProcess.ProcessName);
            if (aoProcesses.Length > 1)
            {
                MessageBox.Show(
                      "程序 \""
                    + oProcess.ProcessName
                    + "\" 已经运行.", "Ultrasimple");
                SetForegroundWindow(aoProcesses[aoProcesses[0].Id ==
                        oProcess.Id ? 1 : 0].MainWindowHandle);
                return;
            }
  • 打赏
  • 举报
回复
进程监测防多开 加单例模式
  • 打赏
  • 举报
回复
要实现这个就必须禁止程序躲开,在禁止程序多开关闭新启动的程序的时候使程序在前段显示。 给你个winform的禁止程序多开,替换整个Program文件的代码以及 Application.Run方法的参数 这个方法也是百度搜到的。

 static class Program
    {
        /// <summary>  
        /// /// The main entry point for the application.     
        /// /// </summary>       
         [STAThread]
         static void Main()      
         {           

             bool createdNew;    
             //系统能够识别有名称的互斥,因此可以使用它禁止应用程序启动两次  
             //第二个参数可以设置为产品的名称:Application.ProductName 
             //每次启动应用程序,都会验证名称为SingletonWinAppMutex的互斥是否存在 
             Mutex mutex = new Mutex(false, "SingletonWinAppMutex", out createdNew); 
             //如果已运行,则在前端显示            //createdNew == false,说明程序已运行 
             if (!createdNew)           
             {                
                 Process instance = GetExistProcess();  
                 if (instance != null)           
                 {                   
                     //让程序前段显示并且关闭新启动的程序
                     SetForegroud(instance);   
                     Application.Exit();        
                     return;           
                 }       
             }          
             Application.EnableVisualStyles();    
             Application.SetCompatibleTextRenderingDefault(false);
             //把Application.Run中的参数改为你的主窗体名
             Application.Run(new UpdateVersion());     
         }        /// <summary>      
                  /// /// 查看程序是否已经运行     
                  /// /// </summary>       
                  /// /// <returns></returns>     
                   private static Process GetExistProcess()   
                   {          
                       Process currentProcess = Process.GetCurrentProcess();  
                       foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName)) 
                       {               
                           if ((process.Id != currentProcess.Id) && 
                               (Assembly.GetExecutingAssembly().Location == currentProcess.MainModule.FileName)) 
                           {                  
                               return process;   
                           }   
                       }         
                       return null;   
                   }       
        /// <summary>      
        /// /// 使程序前端显示   
        /// /// </summary>     
        /// /// <param name="instance"></param> 
         private static void SetForegroud(Process instance)  
         {            
             IntPtr mainFormHandle = instance.MainWindowHandle;  
             if (mainFormHandle != IntPtr.Zero)      
             { 
                 ShowWindowAsync(mainFormHandle, 1);   
               SetForegroundWindow(mainFormHandle);
             }       
         }

        [DllImport("User32.dll")]  
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("User32.dll")]  
        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
    }
ryyxyz11y 2014-03-09
  • 打赏
  • 举报
回复
你可以在.exe运行时,判断是否已有该程序已运行,如果运行的话,把改程序显示出来就好,没写过相应代码,网上找了一段,你可以尝试一下。 using System.Runtime.InteropServices; using System.Diagnostics; using System.Reflection; 其他代码省略。仅仅从一个form启动讲。每个form都有个main入口。 static void Main() { Process instance = RunningInstance(); //获取运行中的实例 if (instance==null) Application.Run(new Form1()); else { HandleRunningInstance(instance);//处理得到的进程。 } } private static Process RunningInstance() {Process current = Process.GetCurrentProcess(); //得到当前form1的进程 Process[] processes = Process.GetProcessesByName(current.ProcessName);// 得到所有同名进程。 foreach(Process MyProcess in processes) { if(MyProcess.Id!= current.Id) //不同的进程id,也就是肯定不是同一进程 { if(Assembly.GetExecutingAssembly().Location.Replace( "/ ", "\\ ")==current.MainModule.FileName) //进程名不同而id不同 的时候,比较程序启动的路径 return MyProcess; } } return null; } private static void HandleRunningInstance(Process instance) { MessageBox.Show( "程序已经运行! "); ShowWindowAsync(instance.MainWindowHandle,1); //调用api函数,正常显示窗口 SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端。 } [DllImport( "User32.dll ")] private static externbool ShowWindowAsync(System.IntPtr hWnd, int cmdShow); [DllImport( "User32.dll ")] private static extern bool SetForegroundWindow(System.IntPtr hWnd);

110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧