C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

C#で他アプリにALT+"Fキー"などの押した状態を送信

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■83033 / inTopicNo.1)  C#で他アプリにALT+"Fキー"などの押した状態を送信
  
□投稿者/ ぼっさっさ (1回)-(2017/02/27(Mon) 22:08:26)

分類:[C#] 

VisualStudio2015 C#でフォームアプリケーションを作成していますが、他の起動中のアプリを操作したいのですが、
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

PostMessage(hwnd, 0x0100, 0x41, 0);で、aボタンを押した状態などは送信できますが、
「ALT + F」の同時押し状態はどのように送信できるのでしょうか。教えてください。

引用返信 編集キー/
■83034 / inTopicNo.2)  Re[1]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ 魔界の仮面弁士 (1150回)-(2017/02/27(Mon) 23:36:51)
2017/02/28(Tue) 09:47:25 編集(投稿者)

No83033 (ぼっさっさ さん) に返信
> PostMessage(hwnd, 0x0100, 0x41, 0);で、aボタンを押した状態などは送信できますが、

0x0100(WM_KEYDOWN) を送りつけているようですが、
WM_CHAR で受け取るウィンドウもあれば、GetAsyncKeyState で判定するウィンドウもあるので、
SendInput API とか SendKeys とかでキーストロークを投げつけたほうが汎用的かも知れません。
非アクティブなウィンドウが相手だと使えないですが。


> 「ALT + F」の同時押し状態はどのように送信できるのでしょうか。教えてください。

PostMessage にしても PostThreadMessage にしても、

WM_KEYDOWN で ALT 送信
WM_KEYDOWN で F 送信
WM_KEYUP で F 送信
WM_KEYUP で ALT 送信

じゃないですかね。

…違った。Alt なので WM_SYSKEYDOWN の方ですね。


ひとまず手元のアプリには、こんな感じで送れました。
手抜きなので、LParam に渡す lKeyData は数値を直接記載しています。


PostMessage(hWnd, WM_SYSKEYDOWN, Keys.Menu, 0x20380001);
PostMessage(hWnd, WM_SYSKEYDOWN, Keys.F, 0x20210001);
PostMessage(hWnd, WM_SYSCHAR, 'f', 0x20210001);
PostMessage(hWnd, WM_SYSKEYUP, Keys.F, 0xE0210001);
PostMessage(hWnd, WM_KEYUP, Keys.Menu, 0xC0380001);
引用返信 編集キー/
■83037 / inTopicNo.3)  Re[2]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ ぼっさっさ (2回)-(2017/02/28(Tue) 21:54:38)
ご回答ありがとうございます。

メモ帳を操作するために
以下のように
IntPtr hwnd = GetDesktopWindow();
// メモ帳のウインドウハンドル取得
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "notepad", null);
// メモ帳ウインドウ内の「edit」ウインドウのハンドル取得
hwnd = FindWindowEx(hwnd, IntPtr.Zero, "edit", null);

PostMessage(hWnd, WM_SYSKEYDOWN, Keys.Menu, 0x20380001);
PostMessage(hWnd, WM_SYSKEYDOWN, Keys.F, 0x20210001);

ALT+Fの操作ができました。

ちなみにLPARAMの値は、何を表していますでしょうか。
どこで調べるとよいでしょうか。


引用返信 編集キー/
■83044 / inTopicNo.4)  Re[3]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ 魔界の仮面弁士 (1151回)-(2017/03/01(Wed) 01:18:52)
No83037 (ぼっさっさ さん) に返信
> IntPtr hwnd = GetDesktopWindow();
> hwnd = FindWindowEx(hwnd, IntPtr.Zero, "notepad", null);
> hwnd = FindWindowEx(hwnd, IntPtr.Zero, "edit", null);

Alt + F の送出なら、edit まで辿らなくても
notepad に直接送り付ければ十分かも。


> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.Menu, 0x20380001);
> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.F, 0x20210001);

hWnd ではなく
hwnd だったのでは?


> ちなみにLPARAMの値は、何を表していますでしょうか。
> どこで調べるとよいでしょうか。
LPARAM の値はメッセージによって異なります。
WM_SYSKEYDOWN の場合はこちらをご覧ください。
https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms646286.aspx


今回の場合は 32bitの整数で、各ビットに以下の意味があります。

 16bit (0〜15bit目) キーリピート数(今回は 0x1)
 8bit (16〜23bit目) スキャンコード
 1bit (24bit目) 拡張キーが押されたかどうか(今回は 0)
 4bit (25〜28bit目) 未使用(0 固定)
 1bit (29bit目) コンテキストコード
 1bit (30bit目) 直前にキーが押されていたか(今回は 0)
 1bit (31bit目) 変換状態(0 固定)


キーリピートは、キーを押し続けたときにカウントアップされる値です。

スキャンコードはキーに割り当てられた番号です。たとえばこんな値。
  Esc キーなら 0x01
  A キーなら 0x1E
  S キーなら 0x1F
  D キーなら 0x20
  F キーなら 0x21
  G キーなら 0x22
  Alt キーなら 0x38

拡張キーは、たとえば日本語109キーボードの場合、
左 Alt の時は 0、右 Alt の時は 1 です。

コンテキストコードは、Alt キーが押下されているかを示します。


> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.Menu, 0x20380001);
> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.F, 0x20210001);
この場合、両者の LParam はスキャンコード(16〜23bit目)のみが異なっており、
前者は 0x38、後者は 0x21 が指定されているというわけです。



> メモ帳を操作するために

あえて API を使わず、マネージコードのみで操作してみました。

private void button1_Click(object sender, EventArgs e)
{
  foreach (var p in Process.GetProcessesByName("notepad"))
  {
    var title = p.MainWindowTitle;
    var desktop = this.CreateAccessibilityInstance().Parent.Parent;
    var window = desktop.Navigate(AccessibleNavigation.FirstChild);
    while (window != null)
    {
      if (window.Role == AccessibleRole.Window && window.Name == title)
      {
        window.Select(AccessibleSelection.TakeFocus);

        var notepadItem = window.Navigate(AccessibleNavigation.FirstChild);
        while ((notepadItem = notepadItem.Navigate(AccessibleNavigation.Next)) != null)
        {
          if (notepadItem.Role == AccessibleRole.MenuBar)
          {
            var menu = notepadItem.Navigate(AccessibleNavigation.FirstChild);
            while (menu != null)
            {
              if (menu.Name == "ファイル(F)")
              {
                menu.DoDefaultAction();
                return;
              }
              menu = menu.Navigate(AccessibleNavigation.Next);
            }
          }
        }
      }
      window = window.Navigate(AccessibleNavigation.Next);
    }
  }
}

引用返信 編集キー/
■83054 / inTopicNo.5)  Re[4]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ ぼっさっさ (3回)-(2017/03/01(Wed) 20:45:37)
ご回答ありがとうございます。

>>Alt + F の送出なら、edit まで辿らなくても
>>notepad に直接送り付ければ十分かも。


> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.Menu, 0x20380001);
> PostMessage(hWnd, WM_SYSKEYDOWN, Keys.F, 0x20210001);

Alt + F以外の場合は、PostMessageで実行する方法は、
Alt + Eや Alt + Vなどは、
hwnd = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);
がなしではできないでしょうか。





引用返信 編集キー/
■83055 / inTopicNo.6)  Re[5]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ 魔界の仮面弁士 (1154回)-(2017/03/01(Wed) 21:09:59)
No83054 (ぼっさっさ さん) に返信
> Alt + F以外の場合は、PostMessageで実行する方法は、
> Alt + Eや Alt + Vなどは、
> hwnd = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);
> がなしではできないでしょうか。

あれ? 同様にトップレベルウィンドウに対して
 PostMessage(hWnd, WM_SYSKEYDOWN, Keys.E, 0x20120001);
とか
 PostMessage(hWnd, WM_SYSKEYDOWN, Keys.V, 0x202F0001);
を投げたら反応しませんか?
引用返信 編集キー/
■83057 / inTopicNo.7)  Re[6]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ ぼっさっさ (4回)-(2017/03/01(Wed) 21:55:12)
ご回答ありがとうございます。

以下のように"edit"に入れないとアクセスできません。

なにか、コードに問題はありますでしょうか。

[DllImport("user32.dll")]
private static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

private void button1_Click(object sender, EventArgs e)
{
IntPtr hWnd = GetDesktopWindow();
hWnd = FindWindowEx(hWnd, IntPtr.Zero, "notepad", null);

hWnd = FindWindowEx(hWnd, IntPtr.Zero, "edit", null);

PostMessage(hWnd, WM_SYSKEYDOWN, (int)Keys.Menu, 0x20380001);
PostMessage(hWnd, WM_SYSKEYDOWN, (int)Keys.E, 0x20120001);
}
引用返信 編集キー/
■83059 / inTopicNo.8)  Re[7]: C#で他アプリにALT+"Fキー"などの押した状態を送信
□投稿者/ 魔界の仮面弁士 (1155回)-(2017/03/02(Thu) 10:35:11)
No83057 (ぼっさっさ さん) に返信
> 以下のように"edit"に入れないとアクセスできません。
トップウィンドウに送る場合は、そのウィンドウが
フォアグラウンドなアクティブウィンドウである必要があります。

No83044 で言うと .Select(AccessibleSelection.TakeFocus); の部分。

"edit" であれば、非アクティブな場合にも受け付けてもらえるので確度が高そうですが、
いずれにせよメニュー操作であるなら、相手をアクティブにしておいた方が良いと思います。
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ