また久々に
アクセスしてみたけど、なんと前回はちょうど1年前なのか!すごい偶然だなー。
だからと言って何と言うこともないんだけど。
ルーティング
coLinuxを導入中。coLinux -> windowsの仮想アダプタへのping(ping 192.168.0.1)は通るのに、インターネットにつないでいるアダプタにpingが通らない。
明らかにルーティングまわりだよなあ、と思いつつルーティングテーブルを見たりwindowsのroutingサービスが起動しているか見たりパーソナルファイヤーウォールを切ってみたりしたけどいっこうに解決しない。
うーん、なんだろうとおもったら、WindowsXP(2000も?)でルーティングを有効にするには、
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\IPEnableRouter
の値を1にする必要があるらしい。linuxでいう/proc/sys/net/ipv4/ip_forward、AIXでいう # no -o ipforwarding みたいなものか。レジストリとか聞くととたんにやる気が萎えてくるのはなんででしょうかね?
WM_KEYDOWN/WM_KEYUP
Syntax
WM_KEYDOWN WPARAM wParam LPARAM lParam;Parameters
wParam
Specifies the virtual-key code of the nonsystem key.
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.0-15 Specifies the repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative. 16-23 Specifies the scan code. The value depends on the OEM. 24 Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. T he value is 1 if it is an extended key; otherwise, it is 0. 25-28 Reserved; do not use. 29 Specifies the context code. The value is always 0 for a WM_KEYDOWN message. 30 Specifies the previous key state. The value is 1 if the key is down before the message is sent, or it is zero if the key is up. 31 Specifies the transition state. The value is always zero for a WM_KEYDOWN message.Return Value
An application should return zero if it processes this message.
Syntax
WM_KEYUP WPARAM wParam LPARAM lParam;Parameters
wParam
Specifies the virtual-key code of the nonsystem key.
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.0-15 Specifies the repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. The repeat count is always one for a WM_KEYUP message. 16-23 Specifies the scan code. The value depends on the OEM. 24 Specifies whether the key is an extended key, such as the right-hand AL and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0. 25-28 Reserved; do not use. 29 Specifies the context code. The value is always 0 for a WM_KEYUP message. 30 Specifies the previous key state. The value is always 1 for a WM_KEYUP message. 31 Specifies the transition state. The value is always 1 for a WM_KEYUP message. Return ValueAn application should return zero if it processes this message.
コントロールキーを送信
いわゆるモディファイヤキーを押すのは、アルファベットキーを押すのに比べるとちょっと面倒。たとえばCtrl+aを送る場合、今までの知識から想像すると
PostMessage(hWnd, WM_KEYDOWN, VK_CONTROL, 0); PostMessage(hWnd, WM_CHAR, 'a', 0); PostMessage(hWnd, WM_KEYUP, VK_CONTROL, 0);
これでいけそうなんだけど、うまくいかない。ただ"a"が出力されるだけでした。ただキーを押しただけだとうまくいかないらしい。ということは、グローバルなキーボードの状態を「Ctrl押下」に変更しないといけない。とすると、現在のキー入力を、アクティブになってるプロセスから、目的のアプリのプロセス*1にアタッチしないといけない。・・・ということで、下のようにすれば動くみたいです。
#includeint main(void){ HWND hWnd; BYTE kstats[256], ctrlstat; DWORD stid, dtid; hWnd = FindWindow("Notepad", NULL); hWnd = FindWindowEx(hWnd, NULL, "Edit", NULL); // キー入力をアタッチ stid = GetCurrentThreadId(); dtid = GetWindowThreadProcessId(hWnd, NULL); AttachThreadInput(stid, dtid, TRUE); // 現在のCtrlの状態を保存 GetKeyboardState(kstats); ctrlstat = kstats[VK_CONTROL]; // Ctrlを押した状態にする(「押してるかどうか」のフラグが0x80らしい) kstats[VK_CONTROL] |= 0x80; SetKeyboardState(kstats); // 'a'を送信 PostMessage(hWnd, WM_KEYDOWN, (WPARAM)VkKeyScan('a'), 0); // Ctrlの状態を戻す kstats[VK_CONTROL] = ctrlstat; SetKeyboardState(kstats); // キー入力をデタッチ AttachThreadInput(stid, dtid, FALSE); return 0; }
モディファイヤキーを送信するだけで、こんなに手間が増えるとは!恐るべし。
*1:正確にはスレッドのようですが