2012-01-16 1 views
2

Я пытался это сделать, но не получил хороших результатов. Я использовал функции GetForegroundWindow(), AttachThreadInput (uint, uint, bool) и GetFocus() для отправки строк в другое окно. Он работает с Notepad, Wordpad и другими приложениями, но не с Microsoft Word.Как отправить строку в другое приложение, включая Microsoft Word

int foregroundWindowHandle = GetForegroundWindow(); 
uint remoteThreadId = GetWindowThreadProcessId(foregroundWindowHandle, 0); 
uint currentThreadId = GetCurrentThreadId(); 
bool b = AttachThreadInput(remoteThreadId, currentThreadId, true); 
int focused = GetFocus(); 
int d = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); 
b = AttachThreadInput(remoteThreadId, currentThreadId, false); 
SendMessage(focused , WM_GETTEXT, builder.Capacity, builder); 
clip = builder.ToString(); 

//Text operations... 

SendMessage(focused, WM_SETTEXT, 0, builder); 

Это код, который у меня есть, но он не работает с Word. Я знаю, что Word использует пользовательские элементы управления, но я думаю, что должен быть другой способ справиться с этим.

Например: Windows Speech Recognition отправляет текст всем приложениям, имеющим фокус, даже если это Word. Я не думаю, что они вносили данные вручную.

Я думал использовать функцию SendInputs, но я не знаю, как это сделать.

+0

Для чего вы можете использовать GetGUIThreadInfo для получения сфокусированного HWND без AttachThreadInput. Но в любом случае SendInput - это самый простой способ отправки нажатий клавиш в окно, сфокусированное в данный момент. – BrendanMcK

ответ

6

Проверьте, не работает ли следующее: вам просто нужно позвонить SendString. Это должно работать для любого приложения, которое может получать текст, окно которого в данный момент активно.

Весь код, за исключением первого способа, относится к pinvoke.net.

/// <summary> 
/// Synthesizes keystrokes corresponding to the specified Unicode string, 
/// sending them to the currently active window. 
/// </summary> 
/// <param name="s">The string to send.</param> 
public static void SendString(string s) 
{ 
    // Construct list of inputs in order to send them through a single SendInput call at the end. 
    List<INPUT> inputs = new List<INPUT>(); 

    // Loop through each Unicode character in the string. 
    foreach (char c in s) 
    { 
     // First send a key down, then a key up. 
     foreach (bool keyUp in new bool[] { false, true }) 
     { 
      // INPUT is a multi-purpose structure which can be used 
      // for synthesizing keystrokes, mouse motions, and button clicks. 
      INPUT input = new INPUT 
      { 
       // Need a keyboard event. 
       type = INPUT_KEYBOARD, 
       u = new InputUnion 
       { 
        // KEYBDINPUT will contain all the information for a single keyboard event 
        // (more precisely, for a single key-down or key-up). 
        ki = new KEYBDINPUT 
        { 
         // Virtual-key code must be 0 since we are sending Unicode characters. 
         wVk = 0, 

         // The Unicode character to be sent. 
         wScan = c, 

         // Indicate that we are sending a Unicode character. 
         // Also indicate key-up on the second iteration. 
         dwFlags = KEYEVENTF_UNICODE | (keyUp ? KEYEVENTF_KEYUP : 0), 

         dwExtraInfo = GetMessageExtraInfo(), 
        } 
       } 
      }; 

      // Add to the list (to be sent later). 
      inputs.Add(input); 
     } 
    } 

    // Send all inputs together using a Windows API call. 
    SendInput((uint)inputs.Count, inputs.ToArray(), Marshal.SizeOf(typeof(INPUT))); 
} 

const int INPUT_MOUSE = 0; 
const int INPUT_KEYBOARD = 1; 
const int INPUT_HARDWARE = 2; 
const uint KEYEVENTF_EXTENDEDKEY = 0x0001; 
const uint KEYEVENTF_KEYUP = 0x0002; 
const uint KEYEVENTF_UNICODE = 0x0004; 
const uint KEYEVENTF_SCANCODE = 0x0008; 
const uint XBUTTON1 = 0x0001; 
const uint XBUTTON2 = 0x0002; 
const uint MOUSEEVENTF_MOVE = 0x0001; 
const uint MOUSEEVENTF_LEFTDOWN = 0x0002; 
const uint MOUSEEVENTF_LEFTUP = 0x0004; 
const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; 
const uint MOUSEEVENTF_RIGHTUP = 0x0010; 
const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020; 
const uint MOUSEEVENTF_MIDDLEUP = 0x0040; 
const uint MOUSEEVENTF_XDOWN = 0x0080; 
const uint MOUSEEVENTF_XUP = 0x0100; 
const uint MOUSEEVENTF_WHEEL = 0x0800; 
const uint MOUSEEVENTF_VIRTUALDESK = 0x4000; 
const uint MOUSEEVENTF_ABSOLUTE = 0x8000; 

struct INPUT 
{ 
    public int type; 
    public InputUnion u; 
} 

[StructLayout(LayoutKind.Explicit)] 
struct InputUnion 
{ 
    [FieldOffset(0)] 
    public MOUSEINPUT mi; 
    [FieldOffset(0)] 
    public KEYBDINPUT ki; 
    [FieldOffset(0)] 
    public HARDWAREINPUT hi; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct MOUSEINPUT 
{ 
    public int dx; 
    public int dy; 
    public uint mouseData; 
    public uint dwFlags; 
    public uint time; 
    public IntPtr dwExtraInfo; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct KEYBDINPUT 
{ 
    /*Virtual Key code. Must be from 1-254. If the dwFlags member specifies KEYEVENTF_UNICODE, wVk must be 0.*/ 
    public ushort wVk; 
    /*A hardware scan code for the key. If dwFlags specifies KEYEVENTF_UNICODE, wScan specifies a Unicode character which is to be sent to the foreground application.*/ 
    public ushort wScan; 
    /*Specifies various aspects of a keystroke. See the KEYEVENTF_ constants for more information.*/ 
    public uint dwFlags; 
    /*The time stamp for the event, in milliseconds. If this parameter is zero, the system will provide its own time stamp.*/ 
    public uint time; 
    /*An additional value associated with the keystroke. Use the GetMessageExtraInfo function to obtain this information.*/ 
    public IntPtr dwExtraInfo; 
} 

[StructLayout(LayoutKind.Sequential)] 
struct HARDWAREINPUT 
{ 
    public uint uMsg; 
    public ushort wParamL; 
    public ushort wParamH; 
} 

[DllImport("user32.dll")] 
static extern IntPtr GetMessageExtraInfo(); 

[DllImport("user32.dll", SetLastError = true)] 
static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); 
+0

Спасибо, он отлично работает. Я обнаружил, что pinvoke.net немного отличается, и я не нашел, как отправить especifical chars, ваш метод сделал снова ** Спасибо. ** – Francerz

+0

@ user1152446 Если это ответит на ваш вопрос, пожалуйста, отметьте его как принятый: http: //meta.stackexchange.com/questions/5234/ –

0

Word не использует стандартный элемент управления редактирования, который отвечает на WM_TEXT. Чтобы вытолкнуть текст в Word, вы можете использовать SendInput для поддельного ввода или автоматизации COM, или UI Automation.

Последний из этих вариантов, UI Automation, был бы моим выбором и является тем, как MS собирается вам сделать это в наши дни.

+0

UI Automation требует, чтобы вы имели предварительные знания о структуре управления вашего приложения; вам нужно будет закодировать другое решение для каждого нового целевого приложения. – Douglas

+0

... который идеально подходит для некоторых сценариев, например, когда вы хотите отправить текст непосредственно в определенные текстовые поля или элементы управления в пользовательском интерфейсе. Но я предполагаю, что вопрос был для чего-то более общего. – Douglas

+0

@Douglas С другой стороны, SendInput требует, чтобы другое приложение имело фокус ввода и чтобы фокус ввода находился на правильном управлении. Так что это действительно лошади. Код в Q предполагал предварительное знание приложения, но это может быть просто просто непреднамеренным. –

Смежные вопросы