2009-05-01 17 views
4

フォームが非アクティブ化されたときにどのウィンドウがフォーカスを受け取るかを知る方法を知っていますか?フォームが非アクティブ化されたときにアクティブ化が行われる場所を決定する

+0

あなたは何をしようとしていますか? – BlackTigerX

+1

フォーカスが私のフォームの1つに転送されているのか、私のアプリケーションからではない別のウィンドウに転送されているのかを調べようとしています。 (私のアプリケーションは、2つのフォームで構成されています。アプリケーションからフォーカスを移動しているときに非表示にする必要があります。 –

答えて

6

答えが見つかりました。アクティブ化イベントと非アクティブ化イベントを購読する代わりに、WndProcでWM_ACTIVATEメッセージ(アクティブ化と非アクティブ化の両方に使用)を処理します。それはアクティブにされているウィンドウのハンドルを報告するので、私はそのハンドルを自分のフォームのハンドルと比較し、フォーカスがそれらのいずれかに変化しているかどうかを判断できます。

const int WM_ACTIVATE = 0x0006; 
const int WA_INACTIVE = 0; 
const int WA_ACTIVE = 1; 
const int WA_CLICKACTIVE = 2; 

protected override void WndProc(ref Message m) 
{ 
    if (m.Msg == WM_ACTIVATE) 
    { 
     // When m.WParam is WA_INACTIVE, the window is being deactivated and 
     // m.LParam is the handle of the window that will be activated. 

     // When m.WParam is WA_ACTIVE or WA_CLICKACTIVE, the window is being 
     // activated and m.LParam is the handle of the window that has been 
     // deactivated. 
    } 

    base.WndProc(ref m); 
} 

編集:この方法は、(例えば、外部ポップアップウィンドウ)に適用されるウィンドウの外側に使用することができます。

NativeWindowを使用して、ハンドルに基づいて任意のウィンドウにアタッチし、メッセージループを表示できます。 (VSでインテリセンスウィンドウと同様)オートコンプリートのポップアップウィンドウを実装するとき、私は同じ問題を抱えている

public class Popup : Form 
{ 
    const int WM_ACTIVATE = 0x0006; 
    const int WA_INACTIVE = 0; 
    private ParentWindowIntercept parentWindowIntercept; 

    public Popup(IntPtr hWndParent) 
    { 
     this.parentWindowIntercept = new ParentWindowIntercept(hWndParent); 
    } 

    private class ParentWindowIntercept : NativeWindow 
    { 
     public ParentWindowIntercept(IntPtr hWnd) 
     { 
      this.AssignHandle(hWnd); 
     } 

     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_ACTIVATE) 
      { 
       if ((int)m.WParam == WA_INACTIVE) 
       { 
        IntPtr windowFocusGoingTo = m.LParam; 
        // Compare handles here 
       } 
      } 

      base.WndProc(ref m); 
     } 
    } 
} 
+0

インターセプトトリックは本当にクールです。 – dbkk

0

Form.ActiveForm静的プロパティを使用してアクティブフォームを決定できるはずです。

+1

残念ながら、Form.ActiveForm –

0

:次のコード例を参照してください。

WndProcの問題点は、ポップアップをホストする任意のフォームにコードを追加する必要があることです。

代わりの方法は、タイマーを使用し、短い間隔の後にForm.ActiveControlをチェックすることです。このようにして、コードはエディタコントロール内の、またはポップアップフォームの中にカプセル化されます。

Form _txPopup; 

// Subscribe whenever convenient 
public void IntializeControlWithPopup(Form _hostForm) 
{ 
    _hostForm.Deactivate + OnHostFormDeactivate; 
} 

Timer _deactivateTimer; 
Form _hostForm; 
void OnHostFormDeactivate(object sender, EventArgs e) 
{ 
    if (_deactivateTimer == null) 
    { 
     _mainForm = sender as Form; 
     _deactivateTimer = new Timer(); 
     _deactivateTimer.Interval = 10; 
     _deactivateTimer.Tick += DeactivateTimerTick; 
    } 
    _deactivateTimer.Start(); 
} 

void DeactivateTimerTick(object sender, EventArgs e) 
{ 
    _deactivateTimer.Stop(); 
    Form activeForm = Form.ActiveForm; 
    if (_txPopup != null && 
     activeForm != _txPopup && 
     activeForm != _mainForm) 
    { 
     _txPopup.Hide(); 
    } 
} 
+0

はい、それは確かにこれを行うことは可能ですが、フォームが無効になっている間、フォームはアクティブ化されます。 WndProcメソッドのコードをポップアップでカプセル化する方法を示すために私の答えを編集しました –

+0

@ Zach。私はタイマーが壊れやすいかもしれないことに同意します。あなたの傍受のトリックは素晴らしいです、それが可能であることを知らなかった。 – dbkk

+1

私はまたこの質問をしたときに私のランチャープロジェクトPromptu(http://www.PromptuLauncher.com/)用のIntellisenseに似たオートコンプリートポップアップウィンドウを実装しようとしました。具体的な実装上の課題を解決するためのお手伝いをさせていただきました他の2つの関連する質問があります: http://stackoverflow.com/questions/992352/overcome-os-imposed-windows-form-minimum-size-limit http://stackoverflow.com/questions/813745/keep-window-inactive-in-appearance-even-when-activated –

関連する問題