程序最小化到托盘后,当再次点击运行程序时,弹出已运行程序的主窗口

zhufengming 2010-07-09 02:35:49
有一个程序名叫WindowsFormsApplication2.exe,它只有一个主窗口名为Form1.当我第一次运行它时,主窗口显示出来后,当我点最小化按钮后,程序最小化到任务栏;当我点关闭按钮后,程序最小化到系统托盘
当我再次双击WindowsFormsApplication2.exe,把前面已经隐藏的程序的主窗口显示出来。但问题是最小化到任务栏时,主窗口可以弹出;最小化到系统托盘就弹不出主窗口.
代码如下:
新建立一个项目WindowsFormsApplication2,在默认生成的Form1窗体上拖一个notifyIcon,命名为notifyIcon1。并随便指定一个图标
在Form1的FormClosing事件里写如下代码
        
//点击窗体的关闭按钮时,不关闭程序,而是最小化到系统托盘
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.notifyIcon1.Visible = true;
this.Hide();
e.Cancel = true;
}

在Program.cs类里写如下代码:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication2
{
static class Program
{
private static string strAppConstName = "WindowsFormsApplication2";
private static string strProcessName = "WindowsFormsApplication2";
//防止程序多次运行
private static Mutex mutexObject;
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
//取得当前系统的版本
OperatingSystem os = Environment.OSVersion;
if ((os.Platform == PlatformID.Win32NT) && (os.Version.Major >= 5))
{
strAppConstName = @"Global\" + strAppConstName;
}
try
{
mutexObject = new Mutex(false, strAppConstName);
}
catch (ApplicationException e)
{
return;
}


//第一次运行
if (mutexObject.WaitOne(0, false))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run( new Form1());
mutexObject.ReleaseMutex();
}
else //当再次运行后 弹出已运行程序的主窗口
{
Process prevProcess = GetPreviousProcess();
//当程序最小化到系统托盘后,这个条件就为假了。不执
//行WakeupWindow(prevProcess.MainWindowHandle);
//如果在else里也执行WakeupWindow(prevProcess.MainWindowHandle);主窗口也弹不出来。好像是
//prevProcess.MainWindowHandle 为零了

if ((prevProcess != null) &&(prevProcess.MainWindowHandle != IntPtr.Zero))
{
WakeupWindow(prevProcess.MainWindowHandle);
}
else
{
//
MessageBox.Show("已经运行,并驻留在任务托盘。", "");
// WakeupWindow(prevProcess.MainWindowHandle);
}
}
mutexObject.Close();
}





public static Process GetPreviousProcess()
{
Process curProcess = Process.GetCurrentProcess();
Process[] allProcesses = Process.GetProcessesByName(strProcessName);
System.Windows.Forms.MessageBox.Show(allProcesses.Length.ToString());
foreach (Process checkProcess in allProcesses)
{
if (checkProcess.Id != curProcess.Id)
{
if (String.Compare(checkProcess.MainModule.ModuleName,curProcess.MainModule.ModuleName, true) == 0)
{
return checkProcess;
}
}
}
return null;
}




public static void WakeupWindow(IntPtr hWnd)
{
if (IsIconic(hWnd))
{
ShowWindowAsync(hWnd, SW_RESTORE);
}
SetForegroundWindow(hWnd);
}



[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd);
private const int SW_RESTORE = 1;

}
}


现在我想当我最小化到系统托盘时,再双击WindowsFormsApplication2.exe时也能弹出已运行的窗口??????????
谢谢各位了!!!!!!!!!!!!!!!
...全文
1027 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhufengming 2010-07-13
  • 打赏
  • 举报
回复
把我的解决方法也贴出来供大家研究。
1:建立一个新的项目名为:MoreView
2:默认生成的窗体Form1的代码为:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MoreView
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.notifyIcon1.Visible = true;
this.Hide();
e.Cancel = true;
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
IntPtr mainWindowHandle = this.Handle;
try
{
lock (this)
{
API.WriteHandle(mainWindowHandle);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

Program类的文件的代码为:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace MoreView
{
static class Program
{
private static string ProcessName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
private static string mutexName = "Local\\" + ProcessName;
private static Mutex mutex = null;
private static API api;
private static IntPtr mainWindowHandle = System.IntPtr.Zero;
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
try
{
mutex = new Mutex(false, mutexName);
}
catch
{
Application.Exit();
}

if (mutex.WaitOne(0, false))
{
lock (typeof(Form1))
{
API.CreateMMF("Local" + "file://" + ProcessName, API.FileAccess.ReadWrite, 8);
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
try
{
lock (typeof(Form1))
{
mainWindowHandle = API.ReadHandle("Local" + "file://" + ProcessName);
}
if (mainWindowHandle != IntPtr.Zero)
{
API.ShowWindow(mainWindowHandle, 1);
}
return;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace +
"\n\n" + "Application Exiting...", "Exception thrown");
}

GC.KeepAlive(mutex);
try
{
mutex.ReleaseMutex();
}
catch (ApplicationException ex)
{
MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace,
"Exception thrown");
GC.Collect();
}
}
}
}
}

新添加一个类名为:API.cs,代码为:
using System;
using System.Runtime.InteropServices;

namespace MoreView
{
public class API
{
private const int INVALID_HANDLE_VALUE = -1;
private const int FILE_MAP_WRITE = 0x2;
private const int FILE_MAP_READ = 0x0004;
private static IntPtr memoryFileHandle;
[DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

[DllImport("kernel32.dll", EntryPoint = "OpenFileMapping", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping(int wDesiredAccess, bool bInheritHandle, String lpName);

[DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);


//hFile——要进行内存映射的文件句柄。当在系统页文件中创建MMF时,这个值必须是0xFFFFFFFF(-1)。
//lpAttributes——指向一个SECURITY_ATTRIBUTES结构体的指针
//flProtect——为内存映射文件指定的保护类型。
//PAGE_READONLY——只读访问。
//PAGE_READWRITE——读/写访问。
//PAGE_WRITECOPY——Copy-on-write访问。
//PAGE_EXECUTE_READ——读取和执行访问。
//PAGE_EXECUTE_READWRITE——读取、写入和执行访问。
//dwMaximumSizeHigh——文件映射对象的最大大小的DWORD值的高位。
//dwMaximumSizeLow——文件映射对象的最大大小的DWORD值的低位。
//lpName——文件映射对象的名字。

[DllImport("Kernel32.dll")]
public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);

[DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CloseHandle(uint hHandle);

public enum FileAccess : int
{
ReadOnly = 2,
ReadWrite = 4
}
/// <summary>
/// 创建共享内存
/// </summary>
/// <param name="fileName"></param>
/// <param name="access"></param>
/// <param name="size"></param>
/// <returns></returns>
public static void CreateMMF(string fileName, FileAccess access, int size)
{
if (size < 0)
throw new ArgumentException("The size parameter" +
" should be a number greater than Zero.");

memoryFileHandle = CreateFileMapping(-1,
IntPtr.Zero, (uint)access, 0, (uint)size, fileName);

if (memoryFileHandle == IntPtr.Zero)
throw new Exception("Creating Shared Memory failed.");
}


/// <summary>
/// 写共享内存
/// </summary>
/// <param name="windowHandle"></param>
public static void WriteHandle(IntPtr windowHandle)
{
IntPtr mappedViewHandle = MapViewOfFile(memoryFileHandle, (uint)FILE_MAP_WRITE, 0, 0, 8);
if (mappedViewHandle == IntPtr.Zero)
throw new Exception("Creating" +
" a view of Shared Memory failed.");

Marshal.WriteIntPtr(mappedViewHandle, windowHandle);

UnmapViewOfFile(mappedViewHandle);
CloseHandle((uint)mappedViewHandle);
}


/// <summary>
/// 读共享内存
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static IntPtr ReadHandle(string fileName)
{
IntPtr mappedFileHandle =
OpenFileMapping((int)FileAccess.ReadWrite, false, fileName);

if (mappedFileHandle == IntPtr.Zero)
throw new Exception("Opening the" +
" Shared Memory for Read failed.");

IntPtr mappedViewHandle = MapViewOfFile(mappedFileHandle,
(uint)FILE_MAP_READ, 0, 0, 8);
if (mappedViewHandle == IntPtr.Zero)
throw new Exception("Creating" +
" a view of Shared Memory failed.");

IntPtr windowHandle = Marshal.ReadIntPtr(mappedViewHandle);
if (windowHandle == IntPtr.Zero)
throw new ArgumentException("Reading from the specified" +
" address in Shared Memory failed.");

UnmapViewOfFile(mappedViewHandle);
CloseHandle((uint)mappedFileHandle);
return windowHandle;
}



}
}



代码没有加注释,用到了很多API,大家自己查吧
zhufengming 2010-07-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wanggangchun 的回复:]
这个能满足你的要求。

C# code
static class Program
{
private static string strProcessName = "Form1" ;
private static string strAppName = "WindowsFormsApplication1";
stati……
[/Quote]

这个方法比我的解决方法简单
xjzhangbowei 2010-07-10
  • 打赏
  • 举报
回复
收藏了 学习学习
xyadmin 2010-07-09
  • 打赏
  • 举报
回复
学习+收藏
shikun520 2010-07-09
  • 打赏
  • 举报
回复
收藏了~嘿嘿,,,,
sd_cx 2010-07-09
  • 打赏
  • 举报
回复
学习了~~
cejay 2010-07-09
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wanggangchun 的回复:]

C# code
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
this.WindowState =……
[/Quote]
wgc 2010-07-09
  • 打赏
  • 举报
回复
这个能满足你的要求。
    static class Program
{
private static string strProcessName = "Form1" ;
private static string strAppName = "WindowsFormsApplication1";
static int hWnd = 0;
const int SW_SHOW = 5;

[DllImport("user32.dll", EntryPoint = "ShowWindow")]
public static extern int ShowWindow(int hwnd, int nCmdShow);

[DllImport("user32")]
public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount);

[DllImport("user32")]
public static extern int EnumWindows(CallBack x, int y);

public delegate bool CallBack(int hWnd, int lParam);

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Process[] ps = Process.GetProcessesByName(strAppName);

CallBack myCallBack = new CallBack(FineAppWindow);
EnumWindows(myCallBack, 0);

if (ps.Length > 1)
{
ShowWindow(hWnd, SW_SHOW);
return;
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public static bool FineAppWindow(int hwnd, int lParam)
{
StringBuilder sb = new StringBuilder(200);
int n = GetWindowText(hwnd, sb, 200);

if (sb.ToString() == strProcessName)
{
hWnd = hwnd;
}
return true;
}
}

wgc 2010-07-09
  • 打赏
  • 举报
回复
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal;
if(this.Visible == false)
this.Show();
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
this.notifyIcon1.Visible = true;
this.Hide();
e.Cancel = true;
}

以上代码经测试,正常。
liherun 2010-07-09
  • 打赏
  • 举报
回复
和现实社会一样
zhufengming 2010-07-09
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 blogtjf 的回复:]
你已打开的窗体是showdialog出来的还是show出来的的啊,我也在问showdialog出来,然后再次还原时怎么不显示的问题
[/Quote]

我要显示的是程序主窗口。应该是show()。
zhufengming 2010-07-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 messi_yang 的回复:]
自己做的一個小的託盤
添加一NotifyIcon1 控件 然后

VB.NET code

Private Sub NotifyIcon1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.Click
If WindowState = FormWindowSta……
[/Quote]
我的意思不是点击系统托盘图标把主窗口弹出来,而是重新双击这个程序的.exe文件,把系统中已经正在运行的这个程序的主界面显示出来
宇峰科技 2010-07-09
  • 打赏
  • 举报
回复
你已打开的窗体是showdialog出来的还是show出来的的啊,我也在问showdialog出来,然后再次还原时怎么不显示的问题
messi_yang 2010-07-09
  • 打赏
  • 举报
回复
自己做的一個小的託盤
添加一NotifyIcon1 控件 然后

Private Sub NotifyIcon1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles NotifyIcon1.Click
If WindowState = FormWindowState.Minimized Then
WindowState = FormWindowState.Maximized
Activate()
NotifyIcon1.Visible = False
'ShowInTaskbar = True
自己需要的主頁面= True
End If
Sub
qqzhangmin520 2010-07-09
  • 打赏
  • 举报
回复
收藏 看高手
louti 2010-07-09
  • 打赏
  • 举报
回复
关注 学习 帮顶 沙发
PhoneticHelper Ver1.0 帮助说明

1.开发背景
由于英语教师日常备课需要输入大量音标,而目前没有一种方便的音标输入方法,故开发出该小助手,以支持我国的教育事业。(呵呵,说得有点大:)
2.程序启动
本软件为绿色免安装,双击图标即可运行程序启动后,可最小化托盘,左键单击可还原窗口。右键在界面单击或单击托盘图标,会弹出快捷菜单,所有功能设置都在菜单中。
3.要功能
a.音标输入:点击界面中的音标按钮,即可在右下方黄色的输入框中输入音标,输入完成后,可点击复制按钮将音标复制到剪贴板中。可在菜单中设置“复制后自动清空输入框”。
b.发送音标:程序可将音标自动发送到指定的应用程序(目前支持Word、PowerPoint、WPS、记事本、写字板)。调出快捷菜单,选择“自动发送音标到指定程序”项,会弹出当前打开的程序文档列表,选择你要发送的程序即可。如果不需要发送,选择“(无)”。
c.自动添加分隔符:当点击复制按钮后,程序可自动添加音标的首尾分隔符。在菜单中设置即可。
d.音标朗读:当按下音标按键后,程序会朗读该音标。在菜单中设置即可。
e.前端显示:程序默认在最前端显示,要是为了在编辑文档方便输入。可在菜单中取消。
4.其他
软件还不完善,希望您多提意见,我会及更新。

E-mail:LBQ971101@163.com
(一).要功能 ·方便切换不同 IP 地址的网络连接,可保存多套方案 ·支持多网卡(包括隐藏网卡) ·支持 Mac 地址的修改,无需重启 ·支持切换 IP 后运行客户端程序(可选) ·可随系统启动并最小化到系统栏,支持右键菜单操作 ·有绿色和安装两个版本,供不同需要的用户选择下载   (二).使用方法 1.管理方案   为方便以后的切换、修改和备份,可以将想要设置的 IP 等信息保存为方案。界面里只提供预览功能,要添加或修改方案,在界面里点击“管理”按钮, 就会弹出方案管理的界面(如果第一次使用本软件,点击“当前方案”也可打开管理界面)。在此管理界面中可以执行“添加/删除/保存”等操作。注意,做过任何更改,只有保存后方案才会生效。 2.新建方案   在界面中点击“管理”,在弹出的方案管理的窗口中,点击“新建”按钮,就可以选择并输入配置方案,输入完后请点击“保存”。 3.删除方案   在界面中点击“管理”,在方案管理窗口中选中想要删除的方案,点击“删除”按钮,然后“保存”。 4.应用方案   在界面中,选择你想要的方案,在左边会同步列出当前方案的详细信息。点击“应用”按钮,选择“是”,就可以应用当前方案。 5.鼠标操作菜单   点击“关闭”按钮,窗口最小化到系统托盘,右键点击图标,也可以进行选择方案/显示窗口,或者打开并显示当前系统所有网络连接。 6.切换完后运行程序   个别网络环境,在切换完网络 IP信息后,需要用客户端登录才可上网。在程序的管理方案界面,选中“运行程序”,点击“浏览”,保存即可。 7.随系统启动   对于经常需要经常切换网络环境的用户,可以选择程序随系统启动。在管理界面中,选择“随系统启动”,点击保存。 8.快捷管理编辑 IP 信息   在管理界面,点击按钮“清空当前 IP 设置”,会将当前选择信息全部清空;点击按钮“从当前连接复制”,可将当前网络连接中的 IP 和 Mac 地址信息复制到当前方案(由于支持多网卡,复制信息以所选网络连接为准)。   (三).最后的说明   本来没想写这个东东的,只是老婆家里用的是方正宽带,BT 的 ISP,不支持路由,需绑定 MAC ,需安装客户端软件。。。在此种种条件的限制下,为了实现多机上网,只好使用双网卡共享上网。在这个过程中最麻烦的是网络切换, 切换完后还要运行客户端才能上网,经常的设置和输入 IP 信息,不胜其烦。 于是绿色小软件 IPWhiz 诞生了,欢迎大家帮忙测试并提宝贵意见,^o^

110,539

社区成员

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

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

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