2016-10-24 4 views
0

Я использую RegisterRawInputDevices of user32.dll для регистрации клавиатуры, но возвращает false. Я разрабатываю надстройку Office с использованием VSTO и C#.RegisterRawInputDevices return false

[StructLayout(LayoutKind.Sequential)] 
public struct RAWINPUTDEVICE 
{ 
    [MarshalAs(UnmanagedType.U2)] 
    public UInt16 usUsagePage; 
    [MarshalAs(UnmanagedType.U2)] 
    public UInt16 usUsage; 
    [MarshalAs(UnmanagedType.U4)] 
    public int dwFlags; 
    public IntPtr hwndTarget; 
} 

[DllImport("User32.dll", SetLastError = true)] 
public static extern bool RegisterRawInputDevices(RAWINPUTDEVICE[] pRawInputDevice, 
    UInt32 uiNumDevices, UInt32 cbSize); 

[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

public void Register() 
{ 
    IntPtr hwnd = FindWindow("PPTFrameClass", "Presentation1 - PowerPoint"); 
    RegisterKeyboardDevice(hwnd); 
} 

public void RegisterKeyboardDevice(IntPtr hwnd) 
{ 
    const int RIDEV_INPUTSINK = 0x00000100; 
    RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[1]; 
    rid[0].usUsagePage = Convert.ToUInt16(1); 
    rid[0].usUsage = Convert.ToUInt16(6); 
    rid[0].dwFlags = RIDEV_INPUTSINK; 
    rid[0].hwndTarget = hwnd; 
    if (!RegisterRawInputDevices(rid, Convert.ToUInt32(rid.Length), 
     Convert.ToUInt32(Marshal.SizeOf(rid[0])))) 
    { 
     throw new ApplicationException("Failed to register raw input device(s). " + 
      "Error code: " + Marshal.GetLastWin32Error()); 
    } 
} 

Но та же логика отлично работает для VB.NET и COM-addins. Пожалуйста, поправьте меня, если я ошибусь.

+0

Попробуйте использовать '[DllImport (" User32.dll ", SetLastError = true)]'. Теперь 'Marshal.GetLastWin32Error()' должно быть заполнено чем-то более полезным, чтобы точно определить ошибку. – haindl

+0

В сообщении об исключении я получил только «87». Я не получаю никаких подробностей об этом исключении. Если бы вы могли помочь, это было бы лучше. –

+0

Ошибка Win32 87 - это «0x00000057» в шестнадцатеричном виде и означает «ERROR_INVALID_PARAMETER». (Ссылка на [здесь] (https://msdn.microsoft.com/en-us/library/cc231199.aspx).) Таким образом, вы должны проверить все свои параметры. Следующий шаг, который я хотел бы попробовать, - добавить это к первому параметру или вашей внешней сигнатуре метода в соответствии с [здесь] (http://www.pinvoke.net/default.aspx/user32.registerrawinputdevices): '[MarshalAs (UnmanagedType .LPArray, SizeParamIndex = 0)] RAWINPUTDEVICE [] pRawInputDevice' – haindl

ответ

0

Вы можете позвонить RegisterRawInputDevices только в тех окнах, которые относятся к тому же процессу, что и ваш код.

Я проверил ваш код в Excel C# VSTO addin, а также в Excel C# COM addin, и в обоих случаях я мог успешно позвонить RegisterRawInputDevices в самом окне Excel и в тестовом окне WPF, которое было создано изнутри addin, без какой-либо ошибки. (Моей версией для этого теста был 64-разрядный формат Excel 2016.)

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

Таким образом, ваш код работает отлично, но вы должны использовать окно, принадлежащее к тому же процессу. И я думаю, что разница в вашем добавлении VB.NET заключается в том, что он работает, потому что он играет по этому правилу.