AxAcroPDF は、フォーカスを取得するとすぐに、ショートカット、キーの押下など、すべてのキー関連のイベントを飲み込みます。メッセージ フィルターを追加しましたが、キー関連のメッセージも取得しません。これは COM コンポーネントです。関連性はありますか?
コントロールがそれらを飲み込み始める前にこれらをキャッチする方法はありますか?
Hans の言うとおりです。Acrobat Reader は、マネージ コード内から直接アクセスできない 2 つの子 AcroRd32 プロセスを生成します。
私はこれを実験しましたが、3 つの実行可能なオプションがあります。
グローバル システム フックを作成し、子 AcroRd32 ウィンドウに送信された WM_SETFOCUS メッセージを探してフィルター処理し、応答することができます。次のようなラッパー ライブラリを使用して、C# 内からこれを実現できます: http://www.codeproject.com/KB/system/WilsonSystemGlobalHooks.aspx
アプリケーションのインスタンスが複数ある場合や、AcroRd32 の他のインスタンスが存在する場合があるため、正しいプロセスを特定する必要もあります。これは最も決定論的な解決策ですが、アプリケーションは存在するすべてのウィンドウに送信されるメッセージをフィルタリングするようになるため、通常、このアプローチはお勧めしません。プログラムがシステムの安定性に悪影響を与える可能性があるからです。
別の PDF 表示コントロールを見つけます。いくつかの商用コンポーネントについては、この回答を参照してください: .net PDF ビューアー コントロール、または独自のロール: http://www.codeproject.com/KB/applications/PDFViewerControl.aspx
受け入れられるハックを見つけます。アプリケーションがどの程度堅牢である必要があるかによって、次のようなコードが適している場合があります (私の場合には適していました)。
DateTime _lastRenav = DateTime.MinValue;
public Form1()
{
InitializeComponent();
listBox1.LostFocus += new EventHandler(listBox1_LostFocus);
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
axAcroPDF1.src = "sample.pdf"; //this will cause adobe to take away the focus
_lastRenav = DateTime.Now;
}
void listBox1_LostFocus(object sender, EventArgs e)
{
//restores focus if it were the result of a listbox navigation
if ((DateTime.Now - _lastRenav).TotalSeconds < 1)
listBox1.Focus();
}
これはプロセス外の COM コンポーネントであり、それが問題です。SetParent() で規定されている Windows SDK 要件に完全に違反しています。ウィンドウがフォーカスされると、acroread.exe プロセスのメッセージ ループがすべてのメッセージを取得し、メッセージ フィルターはメッセージを表示できなくなります。
技術的には、SetWindowsHookEx() を使用してプロセスに DLL を挿入し、WH_GETMESSAGE でメッセージを監視することで修正できます。しかし、そのような DLL を C# 言語で作成することはできません。
少佐、私は知っています。そのプログラムでは、それが欠けているようには見えません。
何らかの理由で、AxAcroPDF コントロールを直接無効にするという Tim の回答は、私の場合はうまくいきませんでした。以前に選択した Textbox の Leave イベントも発生しません。
機能しているのは、無効になっている GroupBox 内に AxAcroPDF コントロールをネストすることです。私のアプリケーションのユーザーは、PDF を表示するだけで操作する必要がないため、デザイナーで GroupBox の Enabled プロパティを False に設定します。