2

ファイル経由で外部アプリケーションを起動するコードをたくさん見てきましたが、それは問題ではありません。私が望む動作を正確に明確にするために:

  1. 特定のファイル名に対して、正しいプロセスを起動します。
  2. 関連付けられたプロセスがない場合は、適切なシェル ダイアログがユーザーに関連付けを求めるプロンプトを表示する必要があります。
  3. アプリケーションの起動中、このアプリケーションは Z オーダーの後ろ (または起動中のアプリのすぐ後ろ) に移動し、そこにとどまる必要があります。

ステップ3は私が正しくないものです。psd ファイルを使用して Photoshop を起動していますが、aplash 画面が表示されている間、アプリがフォーカスを求めて戦うため点滅します。ちゃんと起動すれば問題ないのですが、フラッシュ画面表示中のちらつきが気になりません。

これまでの私の最善の試みは次のとおりです。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Romy.Core
{
    internal static class Example
    {
        public const int SW_RESTORE = 9;

        private static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

        private const uint SWP_NOACTIVATE = 0x0010;

        private const uint SWP_NOMOVE = 0x0002;

        private const uint SWP_NOSIZE = 0x0001;

        public static void SendWindowBack(IntPtr handle)
        {
            NativeMethods.SetWindowPos(handle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
        }

        public static async void ShellExecuteFile(this IWin32Window window, string filename)
        {
            var p = Process.Start(new ProcessStartInfo()
            {
                FileName = filename,
                Verb = "open",
                UseShellExecute = true,
                ErrorDialog = true
            });

            SendWindowBack(window.Handle);

            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        p.WaitForInputIdle();
                        IntPtr handle = p.MainWindowHandle;

                        while (handle == IntPtr.Zero)
                        {
                            await Task.Delay(TimeSpan.FromMilliseconds(250D));
                            handle = p.MainWindowHandle;
                        }

                        if (handle != IntPtr.Zero)
                        {
                            if (NativeMethods.IsIconic(handle))
                                NativeMethods.ShowWindowAsync(handle, SW_RESTORE);

                            if (NativeMethods.SetForegroundWindow(handle))
                                NativeMethods.SetActiveWindow(handle);
                        }
                    }
                    catch (InvalidOperationException) { }
                    catch (PlatformNotSupportedException) { }
                    catch (NotSupportedException) { }
                    catch (Exception ex) { ex.Log(); }
                }).TimeoutAfter(TimeSpan.FromSeconds(3D));
            }
            catch (TimeoutException) { }
        }

        [SuppressUnmanagedCodeSecurity]
        internal static class NativeMethods
        {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool IsIconic(System.IntPtr hWnd);

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool SetForegroundWindow(System.IntPtr hWnd);

            [DllImport("user32.dll")]
            internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
                int X, int Y, int cx, int cy, uint uFlags);

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool ShowWindowAsync(System.IntPtr hWnd, int nCmdShow);

            [DllImport("user32.dll")]
            internal static extern System.IntPtr SetActiveWindow(System.IntPtr hWnd);
        }
    }
}
4

1 に答える 1

0

SendWindowBackへの呼び出しを削除し、 SetForegroundWindowSetWindowLongに置き換えてみてください。これは要件を満たす必要があります。

...(または起動中のアプリのすぐ後ろ)そしてそこにとどまります..

const int GWL_HWNDPARENT = (-8);

[DllImport("user32.dll", SetLastError = true)]
static extern int SetWindowLong(IntPtr childHandle, int nIndex, IntPtr parentHandle);

if (handle != IntPtr.Zero)
{
    if (NativeMethods.IsIconic(handle))
        NativeMethods.ShowWindowAsync(handle, SW_RESTORE);

    SetWindowLong(handle, GWL_HWNDPARENT, window.Handle)
    NativeMethods.SetActiveWindow(handle);
}     
于 2014-05-04T21:10:15.640 に答える