Я пишу приложение C#, которое должно прервать сообщения Окна, что другой приложения отсылает. Компания, которая записала приложение, которое я контролирую, отправила мне некоторый пример кода, однако это находится в C++, который я действительно не знаю.
В примере кода C++, который я сделал, они используют следующий код:
UINT uMsg = RegisterWindowMessage(SHOCK_MESSAGE_BROADCAST);
ON_REGISTERED_MESSAGE(WM_SHOCK_BROADCAST_MESSAGE, OnShockStatusMessage)
LRESULT OnShockStatusMessage(WPARAM wParam, LPARAM lParam);
Насколько я понимаю это получает идентификатор из Windows для определенного сообщения, к которому мы хотим прислушаться. Затем мы просим, чтобы C++ назвал OnShockStatusMessage каждый раз, когда сообщение, соответствующее идентификатору, прерывается.
После небольшого количества исследования я соединил следующее в C#
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
private IntPtr _hWnd; // APS-50 class reference
private List<IntPtr> _windowsMessages = new List<IntPtr>(); // APS-50 messages
private const string _className = "www.AuPix.com/SHOCK/MessageWindowClass";
// Windows Messages events
private const string _messageBroadcast = "www.AuPix.com/SHOCK/BROADCAST";
private const string _messageCallEvents = "www.AuPix.com/SHOCK/CallEvents";
private const string _messageRegistrationEvents = "www.AuPix.com/SHOCK/RegistrationEvents";
private const string _messageActions = "www.AuPix.com/SHOCK/Actions";
private void DemoProblem()
{
// Find hidden window handle
_hWnd = FindWindow(_className, null);
// Register for events
_windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageActions ) ) );
_windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageBroadcast ) ) );
_windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageCallEvents ) ) );
_windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageRegistrationEvents ) ) );
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
// Are they registered Windows Messages for the APS-50 application?
foreach (IntPtr message in _windowsMessages)
{
if ((IntPtr)m.Msg == message)
{
Debug.WriteLine("Message from specified application found!");
}
}
// Are they coming from the APS-50 application?
if ( m.HWnd == shock.WindowsHandle)
{
Debug.WriteLine("Message from specified application found!");
}
}
Поскольку я понимаю, что это должно сделать ту же основную вещь в этом это:
Однако в моем переопределении WndProc () метод ни одна из моих проверок не прерывает ни одного из определенных сообщений или любого сообщения из приложения, которое я контролирую.
Если я Отладка. WriteLine для всех сообщений, которые проникают через него, я вижу, что это контролирует их. Однако это никогда не отфильтровывает сообщения, что я хочу.
Путем выполнения приложения мониторинга в качестве примера, записанного в C++ I, видят, что сообщения Окна отправляются и забираются - это - просто мой C# implemention, не делает того же.
Оказалось, что мне также нужно послать другому приложению PostMessage с просьбой отправить моему приложению Window Messages.
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ACTIVE_CALLINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ALL_REGISTRATIONINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_CALL_EVENTS, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_REGISTRATION_EVENTS, (int)_thisHandle);
Не очень красивый код, но достаточно хороший, чтобы доказать, что он работает, а это все, что мне нужно на данный момент :)
Я думаю, проблема в вашем определении P/Invoke для RegisterWindowMessage()
. pinvoke.net предлагает использовать следующее:
[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);
Использование uint
в качестве возвращаемого значения вместо IntPtr
должно изменить ситуацию. Обычно вы хотите использовать IntPtr
, когда возвращаемое значение является дескриптором (например, HWND
или HANDLE
), но когда возвращаемое значение может быть непосредственно преобразовано в тип C#, лучше использовать этот тип.