0

アプリのフォームのコンストラクターで、ネイティブの GetForegroundWindow WinAPI 関数を呼び出して、C#/Net 2.0/WinForms のフォアグラウンド ウィンドウへのハンドルを取得しようとしています。

Windows Explorer または Total Commander からプログラムを直接実行すると、Windows Explorer または Total Commander ウィンドウが正しく識別されます。

ただし、デスクトップに自分のプログラムへのショートカットを作成し、そのショートカットのショートカット キー (たとえば Ctrl+Alt+X とします) を設定すると、ショートカットを使用してプログラムを実行すると、フォアグラウンド ウィンドウが "Shell_TrayWnd window" (ハンドル 0x00010064) であり、実際のウィンドウではありません。(たとえば、Firefox を上で実行しているとします。Ctrl+Alt+X を押すと、プログラムが起動し、フォアグラウンド ウィンドウが Firefox ではなく、タスクバーであると表示されます - Shell_TrayWnd.)

    public MainForm()
    {
        this.InitializeComponent();

        IntPtr handle = WinAPI.GetForegroundWindow();
        this.Text = handle.ToString();
        StringBuilder title = new StringBuilder(255);
        if (WinAPI.GetWindowText(handle, title, 255) > 0)
        {
            this.Text += title.ToString();
        }
    }

実際の前景ウィンドウを取得するにはどうすればよいですか? GetWindow のような他の関数を (また) 使用する必要がありますか?

ありがとうございました

4

3 に答える 3

1

GetForegroundWindow を呼び出す時点で、タスク バー実際のフォアグラウンド ウィンドウである可能性があることに注意してください。これは、単にショートカット キーを処理しているのは Explorer であり、タスク バーは Explorer に属している (Shell_TrayWnd はタスク バーのウィンドウ クラス) ためです。

グローバル アクティブ ウィンドウで何かをしたい場合は、アプリケーションを起動してバックグラウンドで待機させる方がよい場合があります。次に、アプリケーションの実行中にキーの押下を処理できるため、エクスプローラーが干渉することはありません。

どういうわけか、これはRaymond Chenの記事を思い出させます。

于 2010-04-21T16:17:20.503 に答える
0

あなたは私と同じことをしようとしていると思います — 現在のパスでエクスプローラーからシェルを開きます。

私はまったく同じ問題に遭遇しました。これが私のために働いているプログラムです。タイトルが実際のパスであるウィンドウが見つかるまで、表示EnumWindowsされているすべてのウィンドウを検索するために使用します。

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class ShellHere
{
    // Thanks to pinvoke.net for the WinAPI stuff

    [DllImport("user32.dll")]
    private static extern int EnumWindows(CallBackPtr callPtr, int lPar); 

    [DllImport("user32.dll")]
    static extern int GetWindowText(int hWnd, StringBuilder text, int count);

    [DllImport("user32.dll", EntryPoint="GetWindowLong")]
    private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, GWL nIndex);

    [DllImport("user32.dll", EntryPoint="GetWindowLongPtr")]
    private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, GWL nIndex);

    public delegate bool CallBackPtr(int hwnd, int lParam);
    private static CallBackPtr _callBackPtr;

    // This static method is required because Win32 does not support
    // GetWindowLongPtr directly
    public static IntPtr GetWindowLongPtr(IntPtr hWnd, GWL nIndex)
    {
        if (IntPtr.Size == 8)
            return GetWindowLongPtr64(hWnd, nIndex);
        else
            return GetWindowLongPtr32(hWnd, nIndex);
    }

    public static bool FindPathInTitle( int hwnd, int lparams )
    {
        const int nChars = 256;
        StringBuilder buffer = new StringBuilder( nChars );

        IntPtr result = GetWindowLongPtr( new IntPtr(hwnd), GWL.GWL_STYLE );

        // ignore invisible windows
        if ( (result.ToInt64() & WS_VISIBLE) != 0 )
        {
            if ( GetWindowText( hwnd, buffer, nChars ) > 0 )
            {
                string title = buffer.ToString();

                // ignore the taskbar
                if ( title.ToLower() != "start" && Directory.Exists( title ) )
                {
                    _folder = title;
                    return false;
                }
            }
        }

        return true;
    }

    private static string _folder;

    public static void Main()
    {
        _callBackPtr = new CallBackPtr( FindPathInTitle );
        EnumWindows( _callBackPtr, 0 );

        Process shell = new Process();
        shell.StartInfo.FileName = "cmd.exe";
        if ( !string.IsNullOrEmpty( _folder ) )
            shell.StartInfo.WorkingDirectory = _folder;
        shell.Start();
    }

    public enum GWL
    {
        GWL_WNDPROC =    (-4),
        GWL_HINSTANCE =  (-6),
        GWL_HWNDPARENT = (-8),
        GWL_STYLE =      (-16),
        GWL_EXSTYLE =    (-20),
        GWL_USERDATA =   (-21),
        GWL_ID =     (-12)
    }

    // Window Styles 
    const UInt32 WS_VISIBLE = 0x10000000;
}

これまでのところうまくいっています(Win7-64)。エクスプローラー ウィンドウを直接開く必要はありません。タブ オーダーの次のウィンドウが使用されます。

于 2010-09-23T05:37:09.000 に答える
0

前景ウィンドウが何のために必要なのかわからないので、これが役立つ場合とそうでない場合があります。

おそらく、次の方法でショートカットから起動したことを検出できます。

その場合、Z オーダーで前のウィンドウ、またはデスクトップ ウィンドウの一番上にあるウィンドウを取得しようとすることがあります。

于 2010-09-23T08:47:55.187 に答える