#c_sharp
Нахожу окно с заголовком test, переключаю на него фокус: IntPtr Handle = FindWindow(null, "test"); SetForegroundWindow(Handle); И теперь мне нужно отправить в окно текст "/test 12345", первым символом обязательно слеш. Язык системы в момент отправки неизвестен, но и фиг с ним, мне ж нужен английский: InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("en-US")); после чего отправляю нажатия кнопок: SendKeys.SendWait("/test 12345"); А окно получает ".еуые 12345". При этом язык системы в трее отображается как русский. Если вручную, перед отправкой клавиш из моей программы, переключить язык в конечном окне на англ, то все приходит как нужно, а значит "InputLanguage.CurrentInputLanguage" не срабатывает, либо я использую его неправильно и он меняет только раскладку, не меняя язык. Теста ради сделал перед отправкой InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("ru-RU")); и О ЧУДО отправился текст "/test 12345". Опять же, теста ради, переключаю в конечном окне язык на англ, и теперь уже отправляется "|test 12345". И это все с учетом того, что выше в коде я сделал переключение на русскую раскладку. Нагуглил, что отправлять слеш в русской раскладке нужно через ".", отправляю ".test 12345" и теперь независимо от того, какой язык отображается в трее, конечное окно получает "/test 12345". Вроде бы то что нужно, НО! программой пользуются и иностранцы, у которых нет русского языка в системе, и они получают ".test 12345". Абсурд... Я в замешательстве. Передать текст в данное окно другим способом, кроме как имитируя нажатия клавиш, нельзя.
Ответы
Ответ 1
Проблема с SendKeys: для многоязычных сценариев эта команда не подходит. Из MSDN: If your application is intended for international use with a variety of keyboards, the use of Send could yield unpredictable results and should be avoided. Вместо этого (если вы, конечно, под Windows) нужно пользоваться напрямую WinAPI-командой SendInput. P/Invoke-сигнатуру можно подсмотреть на pinvoke.net: [DllImport("user32.dll")] internal static extern uint SendInput( uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize); SendInput может делать много разных хитрых штук, но для нашего случая мы должны симулировать лишь юникодный ввод, т. к. он не зависит от выбранной раскладки. Поэтому код заметно упрощается: INPUT CreateUnicodeInput(char c) { return new INPUT() { type = INPUT_TYPE.INPUT_KEYBOARD, U = { ki = new KEYBDINPUT() { wScan = (ScanCodeShort)(short)c, wVk = 0, dwFlags = KEYEVENTF.UNICODE } } }; } var inputs = "/test 12345 ляляфафа".Select(CreateUnicodeInput).ToArray(); SendInput((uint)inputs.Length, inputs, INPUT.Size); Недостающие структуры данных (также с pinvoke.net): [StructLayout(LayoutKind.Sequential)] public struct INPUT { internal INPUT_TYPE type; internal InputUnion U; internal static int Size { get { return Marshal.SizeOf(typeof(INPUT)); } } } internal enum INPUT_TYPE : uint { INPUT_MOUSE = 0, INPUT_KEYBOARD = 1, INPUT_HARDWARE = 2 } [StructLayout(LayoutKind.Explicit)] internal struct InputUnion { [FieldOffset(0)] internal MOUSEINPUT mi; [FieldOffset(0)] internal KEYBDINPUT ki; [FieldOffset(0)] internal HARDWAREINPUT hi; } [StructLayout(LayoutKind.Sequential)] internal struct MOUSEINPUT { internal int dx; internal int dy; internal int mouseData; internal MOUSEEVENTF dwFlags; // uint internal uint time; internal UIntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] internal struct KEYBDINPUT { internal VirtualKeyShort wVk; // short internal ScanCodeShort wScan; // short internal KEYEVENTF dwFlags; internal int time; internal UIntPtr dwExtraInfo; } [Flags] internal enum KEYEVENTF : uint { EXTENDEDKEY = 0x0001, KEYUP = 0x0002, SCANCODE = 0x0008, UNICODE = 0x0004 } [StructLayout(LayoutKind.Sequential)] internal struct HARDWAREINPUT { internal int uMsg; internal short wParamL; internal short wParamH; } Для ваших целей в принципе достаточно и этого (отсутствующие типы можно без потери корректности заменить на то, что в комментарии после их объявления). Но для полноты ответа приведу и типы, не нужные для конкретно вашего решения; возможно, они пригодятся кому-то ещё: [Flags] internal enum MOUSEEVENTF : uint { ABSOLUTE = 0x8000, HWHEEL = 0x01000, MOVE = 0x0001, MOVE_NOCOALESCE = 0x2000, LEFTDOWN = 0x0002, LEFTUP = 0x0004, RIGHTDOWN = 0x0008, RIGHTUP = 0x0010, MIDDLEDOWN = 0x0020, MIDDLEUP = 0x0040, VIRTUALDESK = 0x4000, WHEEL = 0x0800, XDOWN = 0x0080, XUP = 0x0100 } internal enum VirtualKeyShort : short { //////Left mouse button /// LBUTTON = 0x01, //////Right mouse button /// RBUTTON = 0x02, //////Control-break processing /// CANCEL = 0x03, //////Middle mouse button (three-button mouse) /// MBUTTON = 0x04, //////Windows 2000/XP: X1 mouse button /// XBUTTON1 = 0x05, //////Windows 2000/XP: X2 mouse button /// XBUTTON2 = 0x06, //////BACKSPACE key /// BACK = 0x08, //////TAB key /// TAB = 0x09, //////CLEAR key /// CLEAR = 0x0C, //////ENTER key /// RETURN = 0x0D, //////SHIFT key /// SHIFT = 0x10, //////CTRL key /// CONTROL = 0x11, //////ALT key /// MENU = 0x12, //////PAUSE key /// PAUSE = 0x13, //////CAPS LOCK key /// CAPITAL = 0x14, //////Input Method Editor (IME) Kana mode /// KANA = 0x15, //////IME Hangul mode /// HANGUL = 0x15, //////IME Junja mode /// JUNJA = 0x17, //////IME final mode /// FINAL = 0x18, //////IME Hanja mode /// HANJA = 0x19, //////IME Kanji mode /// KANJI = 0x19, //////ESC key /// ESCAPE = 0x1B, //////IME convert /// CONVERT = 0x1C, //////IME nonconvert /// NONCONVERT = 0x1D, //////IME accept /// ACCEPT = 0x1E, //////IME mode change request /// MODECHANGE = 0x1F, //////SPACEBAR /// SPACE = 0x20, //////PAGE UP key /// PRIOR = 0x21, //////PAGE DOWN key /// NEXT = 0x22, //////END key /// END = 0x23, //////HOME key /// HOME = 0x24, //////LEFT ARROW key /// LEFT = 0x25, //////UP ARROW key /// UP = 0x26, //////RIGHT ARROW key /// RIGHT = 0x27, //////DOWN ARROW key /// DOWN = 0x28, //////SELECT key /// SELECT = 0x29, //////PRINT key /// PRINT = 0x2A, //////EXECUTE key /// EXECUTE = 0x2B, //////PRINT SCREEN key /// SNAPSHOT = 0x2C, //////INS key /// INSERT = 0x2D, //////DEL key /// DELETE = 0x2E, //////HELP key /// HELP = 0x2F, //////0 key /// KEY_0 = 0x30, //////1 key /// KEY_1 = 0x31, //////2 key /// KEY_2 = 0x32, //////3 key /// KEY_3 = 0x33, //////4 key /// KEY_4 = 0x34, //////5 key /// KEY_5 = 0x35, //////6 key /// KEY_6 = 0x36, //////7 key /// KEY_7 = 0x37, //////8 key /// KEY_8 = 0x38, //////9 key /// KEY_9 = 0x39, //////A key /// KEY_A = 0x41, //////B key /// KEY_B = 0x42, //////C key /// KEY_C = 0x43, //////D key /// KEY_D = 0x44, //////E key /// KEY_E = 0x45, //////F key /// KEY_F = 0x46, //////G key /// KEY_G = 0x47, //////H key /// KEY_H = 0x48, //////I key /// KEY_I = 0x49, //////J key /// KEY_J = 0x4A, //////K key /// KEY_K = 0x4B, //////L key /// KEY_L = 0x4C, //////M key /// KEY_M = 0x4D, //////N key /// KEY_N = 0x4E, //////O key /// KEY_O = 0x4F, //////P key /// KEY_P = 0x50, //////Q key /// KEY_Q = 0x51, //////R key /// KEY_R = 0x52, //////S key /// KEY_S = 0x53, //////T key /// KEY_T = 0x54, //////U key /// KEY_U = 0x55, //////V key /// KEY_V = 0x56, //////W key /// KEY_W = 0x57, //////X key /// KEY_X = 0x58, //////Y key /// KEY_Y = 0x59, //////Z key /// KEY_Z = 0x5A, //////Left Windows key (Microsoft Natural keyboard) /// LWIN = 0x5B, //////Right Windows key (Natural keyboard) /// RWIN = 0x5C, //////Applications key (Natural keyboard) /// APPS = 0x5D, //////Computer Sleep key /// SLEEP = 0x5F, //////Numeric keypad 0 key /// NUMPAD0 = 0x60, //////Numeric keypad 1 key /// NUMPAD1 = 0x61, //////Numeric keypad 2 key /// NUMPAD2 = 0x62, //////Numeric keypad 3 key /// NUMPAD3 = 0x63, //////Numeric keypad 4 key /// NUMPAD4 = 0x64, //////Numeric keypad 5 key /// NUMPAD5 = 0x65, //////Numeric keypad 6 key /// NUMPAD6 = 0x66, //////Numeric keypad 7 key /// NUMPAD7 = 0x67, //////Numeric keypad 8 key /// NUMPAD8 = 0x68, //////Numeric keypad 9 key /// NUMPAD9 = 0x69, //////Multiply key /// MULTIPLY = 0x6A, //////Add key /// ADD = 0x6B, //////Separator key /// SEPARATOR = 0x6C, //////Subtract key /// SUBTRACT = 0x6D, //////Decimal key /// DECIMAL = 0x6E, //////Divide key /// DIVIDE = 0x6F, //////F1 key /// F1 = 0x70, //////F2 key /// F2 = 0x71, //////F3 key /// F3 = 0x72, //////F4 key /// F4 = 0x73, //////F5 key /// F5 = 0x74, //////F6 key /// F6 = 0x75, //////F7 key /// F7 = 0x76, //////F8 key /// F8 = 0x77, //////F9 key /// F9 = 0x78, //////F10 key /// F10 = 0x79, //////F11 key /// F11 = 0x7A, //////F12 key /// F12 = 0x7B, //////F13 key /// F13 = 0x7C, //////F14 key /// F14 = 0x7D, //////F15 key /// F15 = 0x7E, //////F16 key /// F16 = 0x7F, //////F17 key /// F17 = 0x80, //////F18 key /// F18 = 0x81, //////F19 key /// F19 = 0x82, //////F20 key /// F20 = 0x83, //////F21 key /// F21 = 0x84, //////F22 key, (PPC only) Key used to lock device. /// F22 = 0x85, //////F23 key /// F23 = 0x86, //////F24 key /// F24 = 0x87, //////NUM LOCK key /// NUMLOCK = 0x90, //////SCROLL LOCK key /// SCROLL = 0x91, //////Left SHIFT key /// LSHIFT = 0xA0, //////Right SHIFT key /// RSHIFT = 0xA1, //////Left CONTROL key /// LCONTROL = 0xA2, //////Right CONTROL key /// RCONTROL = 0xA3, //////Left MENU key /// LMENU = 0xA4, //////Right MENU key /// RMENU = 0xA5, //////Windows 2000/XP: Browser Back key /// BROWSER_BACK = 0xA6, //////Windows 2000/XP: Browser Forward key /// BROWSER_FORWARD = 0xA7, //////Windows 2000/XP: Browser Refresh key /// BROWSER_REFRESH = 0xA8, //////Windows 2000/XP: Browser Stop key /// BROWSER_STOP = 0xA9, //////Windows 2000/XP: Browser Search key /// BROWSER_SEARCH = 0xAA, //////Windows 2000/XP: Browser Favorites key /// BROWSER_FAVORITES = 0xAB, //////Windows 2000/XP: Browser Start and Home key /// BROWSER_HOME = 0xAC, //////Windows 2000/XP: Volume Mute key /// VOLUME_MUTE = 0xAD, //////Windows 2000/XP: Volume Down key /// VOLUME_DOWN = 0xAE, //////Windows 2000/XP: Volume Up key /// VOLUME_UP = 0xAF, //////Windows 2000/XP: Next Track key /// MEDIA_NEXT_TRACK = 0xB0, //////Windows 2000/XP: Previous Track key /// MEDIA_PREV_TRACK = 0xB1, //////Windows 2000/XP: Stop Media key /// MEDIA_STOP = 0xB2, //////Windows 2000/XP: Play/Pause Media key /// MEDIA_PLAY_PAUSE = 0xB3, //////Windows 2000/XP: Start Mail key /// LAUNCH_MAIL = 0xB4, //////Windows 2000/XP: Select Media key /// LAUNCH_MEDIA_SELECT = 0xB5, //////Windows 2000/XP: Start Application 1 key /// LAUNCH_APP1 = 0xB6, //////Windows 2000/XP: Start Application 2 key /// LAUNCH_APP2 = 0xB7, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_1 = 0xBA, //////Windows 2000/XP: For any country/region, the '+' key /// OEM_PLUS = 0xBB, //////Windows 2000/XP: For any country/region, the ',' key /// OEM_COMMA = 0xBC, //////Windows 2000/XP: For any country/region, the '-' key /// OEM_MINUS = 0xBD, //////Windows 2000/XP: For any country/region, the '.' key /// OEM_PERIOD = 0xBE, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_2 = 0xBF, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_3 = 0xC0, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_4 = 0xDB, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_5 = 0xDC, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_6 = 0xDD, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_7 = 0xDE, //////Used for miscellaneous characters; it can vary by keyboard. /// OEM_8 = 0xDF, //////Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard /// OEM_102 = 0xE2, //////Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key /// PROCESSKEY = 0xE5, //////Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. ///The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, ///see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP /// PACKET = 0xE7, //////Attn key /// ATTN = 0xF6, //////CrSel key /// CRSEL = 0xF7, //////ExSel key /// EXSEL = 0xF8, //////Erase EOF key /// EREOF = 0xF9, //////Play key /// PLAY = 0xFA, //////Zoom key /// ZOOM = 0xFB, //////Reserved /// NONAME = 0xFC, //////PA1 key /// PA1 = 0xFD, //////Clear key /// OEM_CLEAR = 0xFE } internal enum ScanCodeShort : short { LBUTTON = 0, RBUTTON = 0, CANCEL = 70, MBUTTON = 0, XBUTTON1 = 0, XBUTTON2 = 0, BACK = 14, TAB = 15, CLEAR = 76, RETURN = 28, SHIFT = 42, CONTROL = 29, MENU = 56, PAUSE = 0, CAPITAL = 58, KANA = 0, HANGUL = 0, JUNJA = 0, FINAL = 0, HANJA = 0, KANJI = 0, ESCAPE = 1, CONVERT = 0, NONCONVERT = 0, ACCEPT = 0, MODECHANGE = 0, SPACE = 57, PRIOR = 73, NEXT = 81, END = 79, HOME = 71, LEFT = 75, UP = 72, RIGHT = 77, DOWN = 80, SELECT = 0, PRINT = 0, EXECUTE = 0, SNAPSHOT = 84, INSERT = 82, DELETE = 83, HELP = 99, KEY_0 = 11, KEY_1 = 2, KEY_2 = 3, KEY_3 = 4, KEY_4 = 5, KEY_5 = 6, KEY_6 = 7, KEY_7 = 8, KEY_8 = 9, KEY_9 = 10, KEY_A = 30, KEY_B = 48, KEY_C = 46, KEY_D = 32, KEY_E = 18, KEY_F = 33, KEY_G = 34, KEY_H = 35, KEY_I = 23, KEY_J = 36, KEY_K = 37, KEY_L = 38, KEY_M = 50, KEY_N = 49, KEY_O = 24, KEY_P = 25, KEY_Q = 16, KEY_R = 19, KEY_S = 31, KEY_T = 20, KEY_U = 22, KEY_V = 47, KEY_W = 17, KEY_X = 45, KEY_Y = 21, KEY_Z = 44, LWIN = 91, RWIN = 92, APPS = 93, SLEEP = 95, NUMPAD0 = 82, NUMPAD1 = 79, NUMPAD2 = 80, NUMPAD3 = 81, NUMPAD4 = 75, NUMPAD5 = 76, NUMPAD6 = 77, NUMPAD7 = 71, NUMPAD8 = 72, NUMPAD9 = 73, MULTIPLY = 55, ADD = 78, SEPARATOR = 0, SUBTRACT = 74, DECIMAL = 83, DIVIDE = 53, F1 = 59, F2 = 60, F3 = 61, F4 = 62, F5 = 63, F6 = 64, F7 = 65, F8 = 66, F9 = 67, F10 = 68, F11 = 87, F12 = 88, F13 = 100, F14 = 101, F15 = 102, F16 = 103, F17 = 104, F18 = 105, F19 = 106, F20 = 107, F21 = 108, F22 = 109, F23 = 110, F24 = 118, NUMLOCK = 69, SCROLL = 70, LSHIFT = 42, RSHIFT = 54, LCONTROL = 29, RCONTROL = 29, LMENU = 56, RMENU = 56, BROWSER_BACK = 106, BROWSER_FORWARD = 105, BROWSER_REFRESH = 103, BROWSER_STOP = 104, BROWSER_SEARCH = 101, BROWSER_FAVORITES = 102, BROWSER_HOME = 50, VOLUME_MUTE = 32, VOLUME_DOWN = 46, VOLUME_UP = 48, MEDIA_NEXT_TRACK = 25, MEDIA_PREV_TRACK = 16, MEDIA_STOP = 36, MEDIA_PLAY_PAUSE = 34, LAUNCH_MAIL = 108, LAUNCH_MEDIA_SELECT = 109, LAUNCH_APP1 = 107, LAUNCH_APP2 = 33, OEM_1 = 39, OEM_PLUS = 13, OEM_COMMA = 51, OEM_MINUS = 12, OEM_PERIOD = 52, OEM_2 = 53, OEM_3 = 41, OEM_4 = 26, OEM_5 = 43, OEM_6 = 27, OEM_7 = 40, OEM_8 = 0, OEM_102 = 86, PROCESSKEY = 0, PACKET = 0, ATTN = 0, CRSEL = 0, EXSEL = 0, EREOF = 93, PLAY = 0, ZOOM = 98, NONAME = 0, PA1 = 0, OEM_CLEAR = 0, }Ответ 2
Я бы попробовал подогнать текст под CultureInfo.InvariantCulture, она всегда и везде одинаковая должна быть.
Комментариев нет:
Отправить комментарий