2010-07-20 30 views
7

Tôi đang viết một ứng dụng C# cần chặn Thông báo cửa sổ rằng các ứng dụng khác đang gửi đi. Công ty đã viết ứng dụng mà tôi đang theo dõi đã gửi cho tôi một số mã ví dụ, tuy nhiên trong C++ mà tôi không thực sự biết.C# - Chụp tin nhắn Windows từ một ứng dụng cụ thể

Trong C++ mã ví dụ tôi đã có họ sử dụng đoạn mã sau:

UINT uMsg = RegisterWindowMessage(SHOCK_MESSAGE_BROADCAST); 
ON_REGISTERED_MESSAGE(WM_SHOCK_BROADCAST_MESSAGE, OnShockStatusMessage) 
LRESULT OnShockStatusMessage(WPARAM wParam, LPARAM lParam); 

Theo tôi được biết này lấy một Id từ Windows cho thông điệp cụ thể chúng tôi muốn lắng nghe. Sau đó, chúng tôi yêu cầu C + + gọi OnShockStatusMessage bất cứ khi nào một thông báo khớp với Id bị chặn.

Sau một chút nghiên cứu, tôi đã đặt lại với nhau sau trong 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!"); 
    } 

} 

Như tôi hiểu điều này nên làm điều cơ bản giống nhau, ở chỗ nó:

  1. Finds các ứng dụng tôi muốn theo dõi
  2. Đăng ký thông báo cửa sổ Tôi muốn chặn
  3. Đồng hồ cho tất cả Thông báo cửa sổ - sau đó loại bỏ những thông tin tôi cần

Tuy nhiên, tôi ghi đè lên phương thức WndProc() không kiểm tra bất kỳ thông điệp cụ thể nào hoặc thông báo nào từ ứng dụng tôi đang theo dõi.

Nếu tôi Gỡ lỗi.WriteLine cho tất cả thư đi qua nó, tôi có thể thấy rằng nó đang theo dõi chúng. Tuy nhiên nó không bao giờ lọc ra các thông điệp mà tôi muốn.

Bằng cách chạy ứng dụng giám sát mẫu được viết bằng C++, tôi có thể thấy rằng các tin nhắn cửa sổ đang được gửi và chọn - nó chỉ là triển khai C# của tôi không làm như vậy.

Trả lời

1

Hóa ra tôi cũng cần gửi đơn đăng ký khác PostMessage yêu cầu gửi đơn đăng ký của tôi thông báo cửa sổ.

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); 

Không mã đẹp, nhưng đủ tốt để chứng minh nó hoạt động đó là tất cả những gì cần cho bây giờ :)

0

Tôi nghĩ rằng vấn đề là với định nghĩa P/Gọi của bạn cho RegisterWindowMessage(). pinvoke.net gợi ý sử dụng những điều sau đây:

[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] 
static extern uint RegisterWindowMessage(string lpString); 

Sử dụng uint như giá trị trả về thay vì IntPtr nên sự khác biệt. Thông thường bạn muốn sử dụng IntPtr khi giá trị trả về là một điều khiển (chẳng hạn như HWND hoặc HANDLE), nhưng khi giá trị trả lại có thể được chuyển đổi trực tiếp thành loại C#, tốt hơn nên sử dụng loại đó.

+0

Đoạn mã ví dụ bạn đã đưa ra ở đây thực sự là những gì tôi đang sử dụng tại thời điểm này :) –

+0

@Peter Ah, đã bỏ lỡ điều đó. Tại sao bạn làm cho Danh sách một Danh sách IntPtr? Tại sao không chỉ làm cho nó Danh sách ? – Andy

+0

Tôi hy vọng nó chỉ là để sao chép các báo cáo [DllImport] từ trang web khác nhau, xem nếu nó thực hiện bất kỳ sự khác biệt, nhưng mỗi một có sự khác biệt nhỏ. –

Các vấn đề liên quan