我现在要实现的功能就是类似dreamweaver
当双击dreamweaver关联的文件时,比如asp文件时,如果dreamweaver已启动,那么不再启动dreamweaver,只是在这个已启动的dreamweaver添加一个窗口,如何做到?
现在我通过检查Process,可在双击关联的文件的时候检查是否已启动,如果没启动,就直接启动主程序。但如果已启动了,如何不再新加进程,而在原来的程序中添加一个窗口?

解决方案 »

  1.   

    经检查发现,如果已经启动了,调用SendMessage(Windows API)通知正在运行的主程序,然后退出。
    正在运行的主程序在接收到消息后,添加一个新窗口并打开被双击的文件,然后使自身窗口处于激活状态。
      

  2.   

    如果我用c++,我会用mutex来处理,在c#中,我使用了netlover大哥的方法(见他的个人网站)步骤如下:
    1、在ide中建立一winform程序,名称为SingleLink
    2、用笔记本程序建立一后缀任意的文件(我使用.pg做后缀),使用文件夹选项中的文件关联,建  立.pg文件的open操作使用SingleLink程序。
    3、在SingleLink中代码如下(目前该实验程序不能独自启动,只能又双击.pg文件才能启动:):namespace SingleLink
    {
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.InteropServices;

    /// <summary>
    /// Form1 的摘要说明。
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
    /// <summary>
    /// 必需的设计器变量。
    /// </summary>
    private System.ComponentModel.Container components = null;
            
     
    [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 SW_MAXIMIZE = 3;  public Form1()
    {
    //
    // Windows 窗体设计器支持所必需的
    //
    InitializeComponent(); //
    // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
    //
    } /// <summary>
    /// 清理所有正在使用的资源。
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null) 
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    } #region Windows 窗体设计器生成的代码
    /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
    /// 此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
    // 
    // Form1
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
    this.ClientSize = new System.Drawing.Size(292, 266);
    this.Name = "Form1";
    this.Text = "Form1";
    this.Load += new System.EventHandler(this.Form1_Load); }
    #endregion /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main(string[] args) 
    {
    if(args.Length!=1)
    return;
    Process instance = RunningInstance();
    if (instance == null)
    {
    Application.Run(new Form1());
    }
    else
    HandleRunningInstance(instance);
    }
    public static Process RunningInstance()
    {
    Process current = Process.GetCurrentProcess();
    Process[] processes = Process.GetProcessesByName (current.ProcessName); //遍历正在有相同名字运行的例程
    foreach (Process process in processes)
    {
    //忽略现有的例程
    if (process.Id != current.Id)
    {
    //确保例程从EXE文件运行
    if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
    current.MainModule.FileName)
    {
    //返回另一个例程实例
    return process;
    }
    }
    }
    return null;
    }
    public static void HandleRunningInstance(Process instance)
    {
    //确保窗口没有被最小化或最大化
    ShowWindowAsync (instance.MainWindowHandle , SW_MAXIMIZE); //设置真实例程为foreground window
    SetForegroundWindow (instance.MainWindowHandle);
    } private void Form1_Load(object sender, System.EventArgs e)
    {

    }
    }
    }
      

  3.   

    看到了吧,程序中实际对.pg文件没有进行任何处理,这是楼主要做的部分。整个程序只是演示如何保证在系统中存在且只存在它的一个运行实例,而我只不过照搬了netlover的方法。当然也可以通过其他方法实现。文件关联只不过是一个障眼法而已,个人认为与这部分功能的程序实现无关:)只是注意双击.pg文件,系统会将该文件路径作为启动参数传递给SingleLink程序(在args[0]中)。至于mdi的问题,我想如果楼主在args[]数组中获得了.pg文件的路径,那么处理它添加窗口等问题就迎刃而解了!
      

  4.   

    想使用SendMessage API,但是却没有API手册,不知道怎么调用,网上查也没查到。哎
      

  5.   

    楼主,一下程序你满意否?双击.pg文件运行,如果singelink已存在,该程序将获得.pg文件完整路径,并显示出来。使用的是WM_COPYDATA消息,加上Marshal类方法,通过sendmessage实现(注意,在这里由于存在内存复制,因此只能使用sendmessage,而不能用postmessage)程序源码如下:
    namespace SingleLink
    {
    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    /// <summary>
    /// Form1 的摘要说明。
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
    /// <summary>
    /// 必需的设计器变量。
    /// </summary>
    private System.ComponentModel.Container components = null;
            
     
    [DllImport("User32.dll")]
    private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
    [DllImport("User32.dll")] 
    private static extern bool  SetForegroundWindow(IntPtr hWnd); [DllImport("User32.dll")] 
    private static extern int SendMessage(IntPtr hWnd,uint Msg,int wParam,int lParam); private const int SW_MAXIMIZE = 3; 
           
    private const int WM_COPYDATA=0x004A;

    public Form1()
    {
    //
    // Windows 窗体设计器支持所必需的
    //
    InitializeComponent(); //
    // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
    //
    } /// <summary>
    /// 清理所有正在使用的资源。
    /// </summary>
    protected override void Dispose( bool disposing )
    {
    if( disposing )
    {
    if (components != null) 
    {
    components.Dispose();
    }
    }
    base.Dispose( disposing );
    } #region Windows 窗体设计器生成的代码
    /// <summary>
    /// 设计器支持所需的方法 - 不要使用代码编辑器修改
    /// 此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
    // 
    // Form1
    // 
    this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
    this.ClientSize = new System.Drawing.Size(292, 266);
    this.Name = "Form1";
    this.Text = "Form1";
    }
    #endregion /// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main(string[] args) 
    {
    if(args.Length!=1)
    return;
    Process instance = RunningInstance();
    if (instance == null)
    {
    Application.Run(new Form1());
    }
    else
    {

    IntPtr strPtr=Marshal.StringToHGlobalAnsi(args[0]);
    COPYDATASTRUCT copyData;
    copyData.dwData=0;
    copyData.cbData=(uint)Encoding.Default.GetByteCount(args[0].ToCharArray(),0,args[0].Length);
    copyData.lpData=strPtr;
    IntPtr ptr=Marshal.AllocHGlobal((IntPtr)(Marshal.SizeOf(copyData)));
    Marshal.StructureToPtr(copyData,ptr,true);
    Form1.SendMessage(instance.MainWindowHandle,WM_COPYDATA,-1,(int)ptr);
    HandleRunningInstance(instance);
    }
    }
    public static Process RunningInstance()
    {
    Process current = Process.GetCurrentProcess();
    Process[] processes = Process.GetProcessesByName (current.ProcessName); //遍历正在有相同名字运行的例程
    foreach (Process process in processes)
    {
    //忽略现有的例程
    if (process.Id != current.Id)
    {
    //确保例程从EXE文件运行
    if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
    current.MainModule.FileName)
    {
    //返回另一个例程实例
    return process;
    }
    }
    }
    return null;
    }
    public static void HandleRunningInstance(Process instance)
    {
    //确保窗口没有被最小化或最大化
    ShowWindowAsync (instance.MainWindowHandle , SW_MAXIMIZE); //设置真实例程为foreground window
    SetForegroundWindow (instance.MainWindowHandle);
    }

    protected override void WndProc(ref Message m)
    {
    // TODO:  添加 Form1.WndProc 实现
    switch(m.Msg)
    {
    case WM_COPYDATA:
    string path="abc";
    //if(m.WParam!=IntPtr.Zero)
    COPYDATASTRUCT copyData=(COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)m.LParam,typeof(COPYDATASTRUCT));
    if(copyData.lpData!=IntPtr.Zero)
       path=Marshal.PtrToStringAnsi(copyData.lpData,(int)copyData.cbData);
    MessageBox.Show(path);
    break;
    }
    base.WndProc (ref m);
    }
    }
    //[StructLayout(LayoutKind.Sequential)]
    struct COPYDATASTRUCT
    {
    public uint dwData;
    public uint cbData;
    public IntPtr lpData;
    }
    }