怎样通过正在运行的Process获取窗体的实例?

时间:2021-01-16 05:01:48
今天在做程序的单实例运行时发现个问题(Winform),我将程序运行后最小化到托盘,再次双击程序时弹出已运行的程序。

[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 = 1;
/// <summary>
/// 程序入口
/// </summary>
[STAThread]
static void Main()
{
    //其他代码省略。。。
    Process instance = RunningInstance();
    if (instance == null)
    {//运行程序}
    else//程序已经运行,显示已运行的程序
    {
        System.IntPtr handler = instance.MainWindowHandle;
        frmDefault frm = (frmDefault)Form.FromHandle(handler);//frmDefault程序主窗体,就是这句的问题
        frm.FormOpen();//主窗体中点击托盘图标显示窗体的方法
    }
}

frmDefault frm = (frmDefault)Form.FromHandle(handler);这句获取的frm是Null.
我试了下Form frm = (Form)Form.FromHandle(handler);frm 还是Null

请问怎么能通过运行的Process得到窗体的实例?

33 个解决方案

#1



///   <summary> 
///   程序入口 
///   </summary> 
[STAThread] 
static   void   Main() 

        //其他代码省略。。。 
        Process   instance   =   RunningInstance(); 
        if   (instance   ==   null) 
        {//运行程序} 
        else//程序已经运行,显示已运行的程序 
        { 
                System.IntPtr   handler   =   instance.MainWindowHandle; 
                frmDefault   frm   =   (frmDefault)Form.FromHandle(handler);//frmDefault程序主窗体,就是这句的问题 
                frm.FormOpen();//主窗体中点击托盘图标显示窗体的方法 
        } 


#2


Control.FromHandle不在同一进程没有用.
Form.FromHandle应该也是一样的。

#3


用API:
ShowWindow(SW_SHOWNORMAL);

#4


ShowWindow(handler, SW_SHOWNORMAL);

#5


帮顶~~~~~~~~~

#6


搞不懂 是不是可以父子窗体来搞这个东西

#7


我以前也做过类似的功能,就是当一个.exe程序(winform应用程序)已经打开的时候,再双击图标打开的时候就提示:程序已经启动,具体实现代码如下:
[STAThread]
        static void Main()
        {
            bool canStart;
            System.Threading.Mutex mutex = new System.Threading.Mutex(false,"进程名字-不带.exe的(也就是窗体的名字),我这里是GIS_DMC",out canStart);
            if (canStart)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new GIS_DMCForm());
            }
            else
            {
                MessageBox.Show("程序已启动");
            }
        }

#8


引用 7 楼 zhangjiewoshiwo 的回复:
我以前也做过类似的功能,就是当一个.exe程序(winform应用程序)已经打开的时候,再双击图标打开的时候就提示:程序已经启动,具体实现代码如下:
[STAThread]
static void Main()
{
bool canStart;
System.Threading.Mutex mutex = new System.Threading.Mutex(false,"进程名字-不带……

但实例运行这个没有问题,问题是else里的东西,原来我也和你一样是弹出个提示框。现在我先改为弹出已经运行的程序,而程序又是最小化到了托盘图标。
我是希望能获得已经打开的程序的Form实例,好让我调用里面的方法,一是判断窗体是否显示还是最小化到托盘图标,二是如果是后者,则调用实例的方法让窗体显示出来并隐掉托盘图标。

#9


引用 4 楼 cnzdgs 的回复:
ShowWindow(handler, SW_SHOWNORMAL);

谢谢提醒。
但我觉得FindWindow这个方法适合我。
今天我查FindWindow和FindWindowEx这两个方法查了一天了,还是没能成功找出要的东西。对API函数真的不熟悉啊。我又发了个帖。有时间的话帮我看下。
传送门:
http://topic.csdn.net/u/20100316/13/7e51301c-7e4c-4088-bc15-6a39d87ec2f3.html

#10



[DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

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

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetF(IntPtr hWnd);

        [STAThread]
        static void Main()
        {

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Process current = RunningInstance();

            if (current != null)
            {

                IntPtr handle = FindWindow(null, "Form1");

                ShowWindow(handle, 1);

                SetF(handle);
            }
            else
            {

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }

        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;
        }


#11


有点乱 没有整理

#12


引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoi……


一般情况下这样可以把Form1显示出来。
但我这有两个问题。
1.我在将窗口最小化时,隐藏窗口,显示托盘图标。如果窗口再次显示出来那托盘图标是要隐藏掉的,因为正常操作是点击托盘图标后窗口显示,托盘图标隐藏。用ShowWindow的话窗口是可以显示出来了,但托盘图标无法控制隐藏掉。
2.我做的窗口一开始出来默认的名字是不变的,比如是“FORM”,点击里面的菜单后窗口还是这个窗口,但点击不同的菜单窗口名字是要变的,变成“FORM-1”,“FORM-2”,“FORM-3”。。。所以IntPtr handle = FindWindow(null, "Form1");这么写不行的,点了某个菜单的话窗口就弹不出来了。
能不能用前面那个参数条件,后面那个传NULL?
前面那个参数是控件也就是窗体的类名吧,是要用Spy++可以查出来吧?

#13


我做的是先有个登录窗口,输入帐号密码后进入Default窗口,登录窗口隐藏。我需要弹出的是Default窗口。但用Spy++查出来的登录窗口和Default窗口的类名都是“WindowsForms10.Window.8.app.0.2004eee”。。。。

IntPtr handle = FindWindow("WindowsForms10.Window.8.app.0.2004eee", null);
ShowWindow(handle, 1);
SetF(handle);

用这个弹出来的是隐藏掉的登录界面。。。。这样不行- -

#14


我是来学习的,路过帮顶

#15


引用 12 楼 ddsxd19 的回复:
引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll",……


private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                notifyIcon1.Visible = true;
            }
        }
private void Form1_Activated(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
        }


最小化显示notifyIcon,Activated事件隐藏即可

#16



[System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   IntPtr   FindWindow(string   strclassName,   string   strWindowName);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   bool   OpenIcon(IntPtr   hWnd);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   bool   IsIconic(IntPtr   hWnd);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   int   SetForegroundWindow(IntPtr   hWnd);   
    
  void   FindAndOpenWindow(string   Title)   
  {   
  IntPtr   hWnd   = (IntPtr )  FindWindow(null,   Title);   
  if   (hWnd   !=   IntPtr.Zero)   
  {   
  bool   isIcon   =   IsIconic(hWnd);   
  if   (   !isIcon   )   
  {   
  SetForegroundWindow(hWnd);   
  }   
  else   
  {   
  OpenIcon(hWnd);   
  }   
  }   
  }   





IsIconic  函数功能:该函数确定给定窗口是否是最小化(图标化)的窗口。
  函数原型:BOOL IsIconic(HWND hWnd);
  参数:
  hWnd:被测试窗口的句柄。
  返回值:如果窗口已图标化,返回值为非零;如果窗口未图标化,返回值为零。
  速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:不支持;头文件:winuser.h;
  库文件:user32.Iib。


OpenIcon  VB声明 Declare Function OpenIcon Lib "user32" Alias "OpenIcon" (ByVal hwnd As Long) As Long
  说明:恢复一个最小化的程序,并将其激活 返回值 Long,非零表示成功,零表示失败。会设置GetLastError 参数表
  参数
  类型及说明:hwnd Long,欲恢复的窗口句柄
  针对vb窗体,应使用vb的WindowState属性

#17


可以自定义一个消息,通过发送这个消息让程序自己恢复窗口。

#18


引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[……

好主意!好方法!这样第一个问题就没问题了。
但第二个问题。。。我获取已运行程序窗口的代码是defaultWnd = FindWindow(null, "主窗体");
现在看来有问题,我用的是Mdi子窗口的方法,点击菜单不同的窗口显示在我的主窗体中,而且顺带的我让主窗体的Text也变了,"主窗体"就变成了"主窗体-1","主窗体-2".。。这些。这样上面的获取方法就不行了。。。

17楼的前辈还真是言简意赅。。。怎么找到上一个程序然后发个消息给他让窗口恢复啊?

#19


关键我这边FindWindow的第二个参数是在变的。。。以前这么做是为了方便用户看,没想到还带来这么个麻烦。。。这个浏览窗口提示不放在主窗体的标题上还真没地方放。。。不放这放哪啊。

#20


引用 16 楼 xingyuebuyu 的回复:
C# code

[System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   IntPtr   FindWindow(string   strclassName,   string   strWindowName);   
    
  [System.Runtime.……

非常感谢,竟然还有检查是否最小化到托盘图标的方法。。。不过我的最小化到托盘图标是我自己模拟的,就是把窗口隐藏再把Icon显示出来,这样也能检查的出来?
OpenIcon  这个方法的说明里不是说是针对vb窗体吗- -那对C#也能用啊?

问题是我现在的关键问题变了,IntPtr   hWnd   = (IntPtr )  FindWindow(null,   Title);  我这里的Title是变化的,这怎么找 - - 

#21


IntPtr hWnd = (IntPtr ) FindWindow("classname",null);
不要根据title来找,根据"classname"来找,用spy++可以看到。

OpenIcon  这个方法的说明里不是说是针对vb窗体吗- -那对C#也能用啊?
能用的,那上面只是百度上的一个说明,这个是系统user32.dll的一个方法,都可以用的


#22


引用 18 楼 ddsxd19 的回复:
引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, s……

额.......
1,使用spy++ 查看一下主窗体的类名,使用FindWindow(类名, null)来查。
2,窗体不多的话把标题做个集合吧,IntPtr不为0的就是。

#23



IntPtr handle = IntPtr.Zero;

                string[] str = new string[2];
                str[0] = "Form1";
                str[1] = "aaaa";

                for (int i = 0; i < str.Length; i++)
                {
                    handle = FindWindow(null, str[i]);
                    if (handle != IntPtr.Zero)
                    {
                        break;
                    }
                }

                ShowWindow(handle, 1);

                SetForegroundWindow(handle);



#24


使用ViewWizard也可以查看类名。
http://www.121xia.com/soft/52071.htm
拖着那个放大镜拽到你的窗体上就显示出来了。
IntPtr handle = FindWindow("WindowsForms10.Window.8.app.0.378734a", null);

#25


引用 22 楼 journeydj 的回复:
引用 18 楼 ddsxd19 的回复:

引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindo……

本来用 instance.MainWindowTitle 就算我的标题变了也是能获取到的,如果没有thid.hide()的话- -关键我一最小化隐藏掉窗口后就取不到了,得到的是空。。我郁闷。。。。

第一个用类名我试过了,在13楼,我运行程序是先打开loginForm,帐号密码确认后进入我的defaultForm,我现在要弄出来的是defaultForm,但找到的类名loginForm和defaultForm是一样的。。。我用那类名出来的是登录窗口不是默认主窗口;。。。难倒我看错了?我在查查看。。
第二个。。。我哭了。。是个方法~

#26


Spy++和ViewWizard这个工具都用了。果然两个窗体的类名是一模一样的。。。。。。。。。

#27


再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

#28


引用 27 楼 ddsxd19 的回复:
再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

你再调查一下看看吧 ,我能想到的就这些了 ,呵呵 。

#29


看了这么多 API,再回过头来看看楼主的需求,最适合的应该是Singleton 模式了,
使用这个,就没有楼主说的那些 api 烦劳

#30


引用 28 楼 journeydj 的回复:
引用 27 楼 ddsxd19 的回复:

再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

你再调查一下看看吧 ,我能想到的就这些了 ,呵呵 。

真是Very感谢,啥都不说了兄弟!眼泪哗哗的~

#31


引用 29 楼 alonesword 的回复:
看了这么多 API,再回过头来看看楼主的需求,最适合的应该是Singleton 模式了,
使用这个,就没有楼主说的那些 api 烦劳

单件模式啊~貌似不错。。。问题我没弄过。。不会- -有时间了研究下吧。。

#32


谢谢大家的帮助,结帖给分!

#33


楼主!还在CSDN活跃不?我现在也遇到与你第一个问题同样类似的问题,第二个问题,我已经解决了,用程序集的GUID来获取Process,GUID是每个软件唯一标识符!问下第一个问题怎么解决的?

#1



///   <summary> 
///   程序入口 
///   </summary> 
[STAThread] 
static   void   Main() 

        //其他代码省略。。。 
        Process   instance   =   RunningInstance(); 
        if   (instance   ==   null) 
        {//运行程序} 
        else//程序已经运行,显示已运行的程序 
        { 
                System.IntPtr   handler   =   instance.MainWindowHandle; 
                frmDefault   frm   =   (frmDefault)Form.FromHandle(handler);//frmDefault程序主窗体,就是这句的问题 
                frm.FormOpen();//主窗体中点击托盘图标显示窗体的方法 
        } 


#2


Control.FromHandle不在同一进程没有用.
Form.FromHandle应该也是一样的。

#3


用API:
ShowWindow(SW_SHOWNORMAL);

#4


ShowWindow(handler, SW_SHOWNORMAL);

#5


帮顶~~~~~~~~~

#6


搞不懂 是不是可以父子窗体来搞这个东西

#7


我以前也做过类似的功能,就是当一个.exe程序(winform应用程序)已经打开的时候,再双击图标打开的时候就提示:程序已经启动,具体实现代码如下:
[STAThread]
        static void Main()
        {
            bool canStart;
            System.Threading.Mutex mutex = new System.Threading.Mutex(false,"进程名字-不带.exe的(也就是窗体的名字),我这里是GIS_DMC",out canStart);
            if (canStart)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new GIS_DMCForm());
            }
            else
            {
                MessageBox.Show("程序已启动");
            }
        }

#8


引用 7 楼 zhangjiewoshiwo 的回复:
我以前也做过类似的功能,就是当一个.exe程序(winform应用程序)已经打开的时候,再双击图标打开的时候就提示:程序已经启动,具体实现代码如下:
[STAThread]
static void Main()
{
bool canStart;
System.Threading.Mutex mutex = new System.Threading.Mutex(false,"进程名字-不带……

但实例运行这个没有问题,问题是else里的东西,原来我也和你一样是弹出个提示框。现在我先改为弹出已经运行的程序,而程序又是最小化到了托盘图标。
我是希望能获得已经打开的程序的Form实例,好让我调用里面的方法,一是判断窗体是否显示还是最小化到托盘图标,二是如果是后者,则调用实例的方法让窗体显示出来并隐掉托盘图标。

#9


引用 4 楼 cnzdgs 的回复:
ShowWindow(handler, SW_SHOWNORMAL);

谢谢提醒。
但我觉得FindWindow这个方法适合我。
今天我查FindWindow和FindWindowEx这两个方法查了一天了,还是没能成功找出要的东西。对API函数真的不熟悉啊。我又发了个帖。有时间的话帮我看下。
传送门:
http://topic.csdn.net/u/20100316/13/7e51301c-7e4c-4088-bc15-6a39d87ec2f3.html

#10



[DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

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

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetF(IntPtr hWnd);

        [STAThread]
        static void Main()
        {

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Process current = RunningInstance();

            if (current != null)
            {

                IntPtr handle = FindWindow(null, "Form1");

                ShowWindow(handle, 1);

                SetF(handle);
            }
            else
            {

                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
        }

        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;
        }


#11


有点乱 没有整理

#12


引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", EntryPoi……


一般情况下这样可以把Form1显示出来。
但我这有两个问题。
1.我在将窗口最小化时,隐藏窗口,显示托盘图标。如果窗口再次显示出来那托盘图标是要隐藏掉的,因为正常操作是点击托盘图标后窗口显示,托盘图标隐藏。用ShowWindow的话窗口是可以显示出来了,但托盘图标无法控制隐藏掉。
2.我做的窗口一开始出来默认的名字是不变的,比如是“FORM”,点击里面的菜单后窗口还是这个窗口,但点击不同的菜单窗口名字是要变的,变成“FORM-1”,“FORM-2”,“FORM-3”。。。所以IntPtr handle = FindWindow(null, "Form1");这么写不行的,点了某个菜单的话窗口就弹不出来了。
能不能用前面那个参数条件,后面那个传NULL?
前面那个参数是控件也就是窗体的类名吧,是要用Spy++可以查出来吧?

#13


我做的是先有个登录窗口,输入帐号密码后进入Default窗口,登录窗口隐藏。我需要弹出的是Default窗口。但用Spy++查出来的登录窗口和Default窗口的类名都是“WindowsForms10.Window.8.app.0.2004eee”。。。。

IntPtr handle = FindWindow("WindowsForms10.Window.8.app.0.2004eee", null);
ShowWindow(handle, 1);
SetF(handle);

用这个弹出来的是隐藏掉的登录界面。。。。这样不行- -

#14


我是来学习的,路过帮顶

#15


引用 12 楼 ddsxd19 的回复:
引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll",……


private void Form1_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                notifyIcon1.Visible = true;
            }
        }
private void Form1_Activated(object sender, EventArgs e)
        {
            notifyIcon1.Visible = false;
        }


最小化显示notifyIcon,Activated事件隐藏即可

#16



[System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   IntPtr   FindWindow(string   strclassName,   string   strWindowName);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   bool   OpenIcon(IntPtr   hWnd);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   bool   IsIconic(IntPtr   hWnd);   
    
  [System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   int   SetForegroundWindow(IntPtr   hWnd);   
    
  void   FindAndOpenWindow(string   Title)   
  {   
  IntPtr   hWnd   = (IntPtr )  FindWindow(null,   Title);   
  if   (hWnd   !=   IntPtr.Zero)   
  {   
  bool   isIcon   =   IsIconic(hWnd);   
  if   (   !isIcon   )   
  {   
  SetForegroundWindow(hWnd);   
  }   
  else   
  {   
  OpenIcon(hWnd);   
  }   
  }   
  }   





IsIconic  函数功能:该函数确定给定窗口是否是最小化(图标化)的窗口。
  函数原型:BOOL IsIconic(HWND hWnd);
  参数:
  hWnd:被测试窗口的句柄。
  返回值:如果窗口已图标化,返回值为非零;如果窗口未图标化,返回值为零。
  速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:不支持;头文件:winuser.h;
  库文件:user32.Iib。


OpenIcon  VB声明 Declare Function OpenIcon Lib "user32" Alias "OpenIcon" (ByVal hwnd As Long) As Long
  说明:恢复一个最小化的程序,并将其激活 返回值 Long,非零表示成功,零表示失败。会设置GetLastError 参数表
  参数
  类型及说明:hwnd Long,欲恢复的窗口句柄
  针对vb窗体,应使用vb的WindowState属性

#17


可以自定义一个消息,通过发送这个消息让程序自己恢复窗口。

#18


引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[……

好主意!好方法!这样第一个问题就没问题了。
但第二个问题。。。我获取已运行程序窗口的代码是defaultWnd = FindWindow(null, "主窗体");
现在看来有问题,我用的是Mdi子窗口的方法,点击菜单不同的窗口显示在我的主窗体中,而且顺带的我让主窗体的Text也变了,"主窗体"就变成了"主窗体-1","主窗体-2".。。这些。这样上面的获取方法就不行了。。。

17楼的前辈还真是言简意赅。。。怎么找到上一个程序然后发个消息给他让窗口恢复啊?

#19


关键我这边FindWindow的第二个参数是在变的。。。以前这么做是为了方便用户看,没想到还带来这么个麻烦。。。这个浏览窗口提示不放在主窗体的标题上还真没地方放。。。不放这放哪啊。

#20


引用 16 楼 xingyuebuyu 的回复:
C# code

[System.Runtime.InteropServices.DllImport("user32.dll")]   
  private   static   extern   IntPtr   FindWindow(string   strclassName,   string   strWindowName);   
    
  [System.Runtime.……

非常感谢,竟然还有检查是否最小化到托盘图标的方法。。。不过我的最小化到托盘图标是我自己模拟的,就是把窗口隐藏再把Icon显示出来,这样也能检查的出来?
OpenIcon  这个方法的说明里不是说是针对vb窗体吗- -那对C#也能用啊?

问题是我现在的关键问题变了,IntPtr   hWnd   = (IntPtr )  FindWindow(null,   Title);  我这里的Title是变化的,这怎么找 - - 

#21


IntPtr hWnd = (IntPtr ) FindWindow("classname",null);
不要根据title来找,根据"classname"来找,用spy++可以看到。

OpenIcon  这个方法的说明里不是说是针对vb窗体吗- -那对C#也能用啊?
能用的,那上面只是百度上的一个说明,这个是系统user32.dll的一个方法,都可以用的


#22


引用 18 楼 ddsxd19 的回复:
引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, s……

额.......
1,使用spy++ 查看一下主窗体的类名,使用FindWindow(类名, null)来查。
2,窗体不多的话把标题做个集合吧,IntPtr不为0的就是。

#23



IntPtr handle = IntPtr.Zero;

                string[] str = new string[2];
                str[0] = "Form1";
                str[1] = "aaaa";

                for (int i = 0; i < str.Length; i++)
                {
                    handle = FindWindow(null, str[i]);
                    if (handle != IntPtr.Zero)
                    {
                        break;
                    }
                }

                ShowWindow(handle, 1);

                SetForegroundWindow(handle);



#24


使用ViewWizard也可以查看类名。
http://www.121xia.com/soft/52071.htm
拖着那个放大镜拽到你的窗体上就显示出来了。
IntPtr handle = FindWindow("WindowsForms10.Window.8.app.0.378734a", null);

#25


引用 22 楼 journeydj 的回复:
引用 18 楼 ddsxd19 的回复:

引用 15 楼 journeydj 的回复:
引用 12 楼 ddsxd19 的回复:

引用 10 楼 journeydj 的回复:
C# code

[DllImport("User32.dll ", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindo……

本来用 instance.MainWindowTitle 就算我的标题变了也是能获取到的,如果没有thid.hide()的话- -关键我一最小化隐藏掉窗口后就取不到了,得到的是空。。我郁闷。。。。

第一个用类名我试过了,在13楼,我运行程序是先打开loginForm,帐号密码确认后进入我的defaultForm,我现在要弄出来的是defaultForm,但找到的类名loginForm和defaultForm是一样的。。。我用那类名出来的是登录窗口不是默认主窗口;。。。难倒我看错了?我在查查看。。
第二个。。。我哭了。。是个方法~

#26


Spy++和ViewWizard这个工具都用了。果然两个窗体的类名是一模一样的。。。。。。。。。

#27


再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

#28


引用 27 楼 ddsxd19 的回复:
再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

你再调查一下看看吧 ,我能想到的就这些了 ,呵呵 。

#29


看了这么多 API,再回过头来看看楼主的需求,最适合的应该是Singleton 模式了,
使用这个,就没有楼主说的那些 api 烦劳

#30


引用 28 楼 journeydj 的回复:
引用 27 楼 ddsxd19 的回复:

再想想没别的好的办法就只能用第二种方法了。菜单列表我写到XML里了,取出来遍历一下应该问题不大。。。

你再调查一下看看吧 ,我能想到的就这些了 ,呵呵 。

真是Very感谢,啥都不说了兄弟!眼泪哗哗的~

#31


引用 29 楼 alonesword 的回复:
看了这么多 API,再回过头来看看楼主的需求,最适合的应该是Singleton 模式了,
使用这个,就没有楼主说的那些 api 烦劳

单件模式啊~貌似不错。。。问题我没弄过。。不会- -有时间了研究下吧。。

#32


谢谢大家的帮助,结帖给分!

#33


楼主!还在CSDN活跃不?我现在也遇到与你第一个问题同样类似的问题,第二个问题,我已经解决了,用程序集的GUID来获取Process,GUID是每个软件唯一标识符!问下第一个问题怎么解决的?