RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 937449
Accepted
Павел Ериков
Павел Ериков
Asked:2020-01-28 03:32:41 +0000 UTC2020-01-28 03:32:41 +0000 UTC 2020-01-28 03:32:41 +0000 UTC

通过 C# 程序在资源管理器中显示多个选定文件的路径

  • 772

我希望当您在资源管理器中选择几张照片并单击“打开”时,会打开一个程序,您可以在其中处理有关这些文件的信息。

我已经尝试过实现这一点,但是选择几个文件会打开几个程序窗口。

做了一点小调整

应用程序.xaml.cs

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    public IntPtr lpData;
}
public const uint WM_COPYDATA = 0x004A;

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    Process this_process = Process.GetCurrentProcess();

    Process[] other_processes =
    Process.GetProcessesByName(this_process.ProcessName).Where(pr => pr.Id != this_process.Id).ToArray();

    foreach (var pr in other_processes)
    {
         pr.WaitForInputIdle(1000);
         IntPtr hWnd = pr.MainWindowHandle;
         if (hWnd == IntPtr.Zero) continue;
         string command = e.Args[0] + " " + e.Args.Length;
         var cds = new COPYDATASTRUCT();
         cds.dwData = (IntPtr)1;
         cds.cbData = (command.Length + 1) * 2;
         cds.lpData = Marshal.StringToHGlobalUni(command);
         SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds);
         Marshal.FreeHGlobal(cds.lpData);
         Environment.Exit(0);
    }
}    

和 MainWindow.xaml.cs

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
     if (msg == WM_COPYDATA)
     {
         COPYDATASTRUCT data = new COPYDATASTRUCT();
         data = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, data.GetType());
         MessageBox.Show("Received command: " + Marshal.PtrToStringUni(data.lpData));
     }

     return IntPtr.Zero;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
     WindowInteropHelper h = new WindowInteropHelper(this);
     HwndSource source = HwndSource.FromHwnd(h.Handle);
     source.AddHook(new HwndSourceHook(WndProc));//регистрируем обработчик сообщений      
}

原则上一切都很好,因为。当我单击图片时(程序窗口打开时),它显示在 MessageBox.Show 它的路径中。但是现在的问题是,如果我选择几张图片并单击打开,那么与图片一样多的实例会更早打开。现在 MessageBox.Show 将只显示首先选择的图片的路径。

c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    MSDN.WhiteKnight
    2020-01-29T13:33:28Z2020-01-29T13:33:28Z

    当用户在 Explorer 中打开多个文件时,Explorer 大约会同时创建多个进程。但是,从进程开始到窗口准备好接收消息的那一刻要经过一段时间。因此需要稍微修改WM_COPYDATA 方法来处理这种情况:在主进程中添加等待窗口创建的等待,避免使用 MessageBox 因为它会阻塞执行等。

    应用类:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Windows;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    namespace WpfApp1
    {
    
        public partial class App : Application
        {
    
            [DllImport("user32.dll")]
            public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
    
            [StructLayout(LayoutKind.Sequential)]
            public struct COPYDATASTRUCT
            {
                public IntPtr dwData;
                public int cbData;
                public IntPtr lpData;
            }
    
            public const uint WM_COPYDATA = 0x004A;
    
            private void Application_Startup(object sender, StartupEventArgs e)
            {
                string command = "";
                string[] argv = Environment.GetCommandLineArgs();
                if (argv.Length > 1)
                    command = argv[1];
    
                Process this_process = Process.GetCurrentProcess();
                Process main_process;
    
                //найти все процессы с таким же именем, запущенные ранее данного процесса
                Process[] other_processes =
                    Process.GetProcessesByName(this_process.ProcessName)
                    .Where(pr => { return pr.Id != this_process.Id && pr.StartTime <= this_process.StartTime;})
                    .OrderBy((pr) => { return pr.StartTime; })
                    .ToArray();
    
                //найти основной процесс
                if (other_processes.Length > 0) main_process = other_processes[0];
                else return;
    
                //ждем создания окна в основном процессе
                IntPtr hWnd;
                int c = 0;
                while (true)
                {
                    hWnd = main_process.MainWindowHandle;
                    if (hWnd != IntPtr.Zero) break;
                    System.Threading.Thread.Sleep(100);
                    c++;
                    if (c > 10) { return; }
                }
    
                //отправляем команду
                var cds = new COPYDATASTRUCT();
                cds.dwData = (IntPtr)1;
                cds.cbData = (command.Length + 1) * 2;
                cds.lpData = Marshal.StringToHGlobalUni(command);
                SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds);
                Marshal.FreeHGlobal(cds.lpData);
    
                //завершаем работу
                Environment.Exit(0);    
            }        
        }
    }
    

    MainWindow.xaml:

    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        
            mc:Ignorable="d"
            Title="MainWindow" Height="400" Width="600" Loaded="Window_Loaded">
    
        <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
            <TextBox HorizontalAlignment="Left" Height="210" Margin="10,46,0,0"
                     x:Name="tbFilename"
                     TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="427"/>
        </Grid>
    </Window>
    

    主窗口.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Runtime.InteropServices;
    using System.Windows.Interop;
    
    namespace WpfApp1
    {
        public partial class MainWindow : Window
        {                     
    
            //обработчик сообщений для окна
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                if (msg == App.WM_COPYDATA)
                {
                    App.COPYDATASTRUCT data = new App.COPYDATASTRUCT();
                    data = (App.COPYDATASTRUCT)Marshal.PtrToStructure(lParam, data.GetType());
                    tbFilename.Text += Marshal.PtrToStringUni(data.lpData)+";";                
                }
    
                return IntPtr.Zero;
            }
    
            public MainWindow()
            {
                InitializeComponent();
    
                string[] argv = Environment.GetCommandLineArgs();
                if (argv.Length > 1)
                    tbFilename.Text += argv[1] + ";";            
            }        
    
    
            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                WindowInteropHelper h = new WindowInteropHelper(this);
                HwndSource source = HwndSource.FromHwnd(h.Handle);
                source.AddHook(new HwndSourceHook(WndProc));//регистрируем обработчик сообщений            
            }
        }
    }
    
    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5