WPF -- 使用當前進程打開自定義文件的一種方式


問題描述

當雙擊打開自定義格式的文件時,希望使用當前正在運行的進程,而不是另起一個進程。

本文介紹一種方式解決如上問題,方案參考user3582780的解答

設置自定義文件格式的默認打開方式

參考鏈接,具體步驟如下:

  1. 在HKEY_CLASSES_ROOT中新建項,命名為自定義文件格式(如.custom),設置其默認值(如mycustom);
  2. 在HKEY_CLASSES_ROOT中新建項,命名為步驟1中的默認值,即mycustom;
  3. 在mycustom中新建項,命名為DefaultIcon,設置默認值(Icon路徑);
  4. 在mycustom中新建項,命名為shell,在shell中繼續新建項open,在open中新建項command,設置其默認值(格式:程序路徑 "%1")

使用當前實例打開文件

首先,當雙擊自定義格式文件進行打開時,會將該文件的路徑作為參數傳遞給程序,因此打開程序應響應啟動參數。

在WPF應用程序中,Application的OnStartup方法會攜帶程序的啟動參數(通過Environment也可獲取啟動參數)。

當雙擊自定義格式文件時,若有一個實例正在運行,並不會直接使用該實例打開文件,而是會重新打開一個實例。此時需要將新實例的啟動參數傳遞給當前實例並關閉新實例。

本文使用發送窗口消息的方式處理該問題,即使用Win32的SendMessage接口發送參數給當前實例窗口,當前實例響應消息處理即可。具體實現方案如下:

// App
private static Mutex mutex;
protected override void OnStartup(StartupEventArgs e)
{
    mutex = new Mutex(true, "myapp", out bool ret);

    if(!ret)
        Reopen(e);

    // ...
}

private void Reopen(StartupEventArgs e)
{
    // IntPtr hwnd = FindWindow(null, "window title");
    if(e.Args.Length > 0)
        SendMessage();

    Environment.Exit(0);
}

private void SendMessage(IntPtr hwnd, string data)
{
    CopyDataStruct cds = new CopyDataStruct();
    try
    {
        cds.cbData = (data.Length + 1) * 2; // number of bytes
        cds.lpData = Win32.LocalAlloc(0x40, cds.cbData); // known local-pointer in RAM
        Marshal.Copy(data.ToCharArray(), 0, cds.lpData, data.Length); // Copy data to preserved local-pointer
        cds.dwData = (IntPtr)1;
        SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref cds);
    }
    finally
    {
        cds.Dispose();
    }
}

// Window
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if(msg == WM_COPYDATA)
    {
        CopyDataStruct st = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
        string strData = Marshal.PtrToStringUni(st.lpData);
        OpenFile(strData);
        Activate();
    }

    return IntPtr.Zero;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM