1

デスクトップ上の現在/以前にアクティブだったウィンドウへのハンドルを取得する必要があります。基本的に私はスクリーン ショットを撮ることができる ac# Windows Forms アプリケーションに取り組んでいます。GetForegroundWindow PInvoke を使用してこのハンドルを取得していますが、メニュー クリックからコードを呼び出すと、アクティブ ウィンドウがメニュー自体のウィンドウに設定されているように見えるため、生成される画像は小さな黒い四角形になります。

アプリケーションは、コンテキスト メニューを使用してシステム トレイで実行されます。グローバル ホット キーも実装しましたが、これらは正常に機能しますが、マウスでコンテキスト メニューを使用すると、上記のシナリオが発生します。

以前にアクティブだったウィンドウ ハンドルを追跡するにはどうすればよいですか? 私のアプリケーションはトレイ アイコンとして実行されるため、wndproc をオーバーライドしても起動しないことに注意してください。NativeForm と MessageOnly フォームも試しましたが、アプリケーションにフォーカスがない限り、これらは起動しません。

グローバル フックと外部 dll に依存していますか? 確かに、この問題を解決する簡単な方法が必要ですか? (はい、特定のユーザビリティ シナリオのために、メニュー項目とキーボード ショートカットを実装する必要があります。

では、ウィンドウ自体がなく、フォーカスがない ac# アプリから、デスクトップ上の現在/以前のアクティブなウィンドウを追跡するにはどうすればよいですか?

助けてくれてありがとう

4

2 に答える 2

0

ContextMenuStripトレイメニューに次を使用するとします。

IntPtr lastHandle;
public IntPtr GetForegroundWin(){
   IntPtr hwnd = GetForegroundWindow();
   if(hwnd != contextMenuStrip1.Handle) lastHandle = hwnd; 
   return lastHandle;      
}
//Add a timer
Timer t = new Timer();
t.Interval = 1;
t.Tick += (s,e) => {
    GetForegroundWin();
};//Then you can get the foreground Handle by lastHandle
t.Start();//this timer will run as long as your application runs.

OK、タイマーを使用しなくても、 を使用する別の選択肢がありSetWinEventHookます。この関数は、コールバックをフックして、イベントを含むいくつかのイベントをキャッチするのに役立ちますactive window change。詳細については、次のリンクを参照してください:ポーリングせずに C# を使用して変更されたアクティブ ウィンドウを検出する

タイマー(ポーリング)を使用しないソリューションのコードは次のとおりです。

//Must add using System.Runtime.InteropServices;
public partial class Form1 : Form
{
    [DllImport("user32")]
    private static extern IntPtr SetWinEventHook(int minEvent, int maxEvent, IntPtr hModule, WinEventProcDelegate proc, int procId, int threadId, int flags);
    private delegate void WinEventProcDelegate(IntPtr hHook, int ev, IntPtr hwnd, int objectId, int childId, int eventThread, int eventTime);
    private void WinEventProc(IntPtr hHook, int ev, IntPtr hwnd, int objectId, int childId, int eventThread, int eventTime)
    {
        if(hwnd != contextMenuStrip1.Handle) lastHandle = hwnd;
    }
    public Form1()
    {
        InitializeComponent();            
        //EVENT_SYSTEM_FOREGROUND = 3
        //WINEVENT_OUTOFCONTEXT = 0
        SetWinEventHook(3, 3, IntPtr.Zero, WinEventProc, 0, 0, 0);                                                                      
    }
    IntPtr lastHandle;
}
//You can access the lastHandle to get the current active/foreground window. This doesn't require GetForegroundWindow()
于 2013-08-16T19:52:03.837 に答える