zoukankan      html  css  js  c++  java
  • 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;
    }
    
    转载请注明出处,欢迎交流。
  • 相关阅读:
    Python---HTML常用标签
    Python---进阶---Tkinter---game
    工程师的URL大全
    docker安装小笔记
    SQL server查询语句
    非常好用的sersync同步工具
    运维自动化的标准
    使用ansible实现轻量级的批量主机管理
    emos邮件系统的web密码修改方法
    Linux 之 rsyslog+mysql+LogAnalyzer 日志收集系统
  • 原文地址:https://www.cnblogs.com/louzixl/p/14658921.html
Copyright © 2011-2022 走看看