我希望当您在资源管理器中选择几张照片并单击“打开”时,会打开一个程序,您可以在其中处理有关这些文件的信息。
我已经尝试过实现这一点,但是选择几个文件会打开几个程序窗口。
做了一点小调整
应用程序.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 将只显示首先选择的图片的路径。
当用户在 Explorer 中打开多个文件时,Explorer 大约会同时创建多个进程。但是,从进程开始到窗口准备好接收消息的那一刻要经过一段时间。因此需要稍微修改WM_COPYDATA 方法来处理这种情况:在主进程中添加等待窗口创建的等待,避免使用 MessageBox 因为它会阻塞执行等。
应用类:
MainWindow.xaml:
主窗口.xaml.cs