我正試圖編寫一個類庫,可以捕獲Windows消息,以便在設備已連接或刪除時通知我。通常,在Windows窗體應用程序中,我只是重寫WndProc方法,但在這種情況下沒有WndProc方法。有另外一種方法可以得到消息嗎?如何在沒有窗體的情況下接收即插即用設備通知
回答
你需要一個窗口,這是沒有辦法的。這是一個示例實現。爲DeviceChangeNotifier.DeviceNotify事件實現事件處理程序以獲取通知。在程序開始時調用DeviceChangeNotifier.Start()方法。在程序結束時調用DeviceChangeNotifier.Stop()。請注意,DeviceNotify事件在後臺線程中引發,請務必根據需要進行鎖定,以確保您的代碼線程安全。
using System;
using System.Windows.Forms;
using System.Threading;
class DeviceChangeNotifier : Form {
public delegate void DeviceNotifyDelegate(Message msg);
public static event DeviceNotifyDelegate DeviceNotify;
private static DeviceChangeNotifier mInstance;
public static void Start() {
Thread t = new Thread(runForm);
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
}
public static void Stop() {
if (mInstance == null) throw new InvalidOperationException("Notifier not started");
DeviceNotify = null;
mInstance.Invoke(new MethodInvoker(mInstance.endForm));
}
private static void runForm() {
Application.Run(new DeviceChangeNotifier());
}
private void endForm() {
this.Close();
}
protected override void SetVisibleCore(bool value) {
// Prevent window getting visible
if (mInstance == null) CreateHandle();
mInstance = this;
value = false;
base.SetVisibleCore(value);
}
protected override void WndProc(ref Message m) {
// Trap WM_DEVICECHANGE
if (m.Msg == 0x219) {
DeviceNotifyDelegate handler = DeviceNotify;
if (handler != null) handler(m);
}
base.WndProc(ref m);
}
}
我有一個工作的USB通信類,實現設備更改通知以稍微不同的方式,如果任何人有興趣。它非常緊湊(沒有評論),不依賴於Threading
或OnSourceInitialized
和HwndHandler
東西在客戶端。另外,您不需要上述的Form
或Window。可以使用任何可以覆蓋的類型WndProc()
。我使用Control
。
該示例僅包含通知所需的代碼,而沒有其他內容。示例代碼是C++/CLI,儘管我沒有訂閱將可執行代碼放在頭文件中的做法,爲了簡潔起見,我在這裏做了這個。
#pragma once
#include <Windows.h> // Declares required datatypes.
#include <Dbt.h> // Required for WM_DEVICECHANGE messages.
#include <initguid.h> // Required for DEFINE_GUID definition (see below).
namespace USBComms
{
using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Windows;
using namespace System::Windows::Forms;
// This function is required for receieving WM_DEVICECHANGE messages.
// Note: name is remapped "RegisterDeviceNotificationUM"
[DllImport("user32.dll" , CharSet = CharSet::Unicode, EntryPoint="RegisterDeviceNotification")]
extern "C" HDEVNOTIFY WINAPI RegisterDeviceNotificationUM(
HANDLE hRecipient,
LPVOID NotificationFilter,
DWORD Flags);
// Generic guid for usb devices (see e.g. http://msdn.microsoft.com/en-us/library/windows/hardware/ff545972%28v=vs.85%29.aspx).
// Note: GUIDs are device and OS specific and may require modification. Using the wrong guid will cause notification to fail.
// You may have to tinker with your device to find the appropriate GUID. "hid.dll" has a function `HidD_GetHidGuid' that returns
// "the device interfaceGUID for HIDClass devices" (see http://msdn.microsoft.com/en-us/library/windows/hardware/ff538924%28v=vs.85%29.aspx).
// However, testing revealed it does not always return a useful value. The GUID_DEVINTERFACE_USB_DEVICE value, defined as
// {A5DCBF10-6530-11D2-901F-00C04FB951ED}, has worked with cell phones, thumb drives, etc. For more info, see e.g.
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff553426%28v=vs.85%29.aspx.
DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
/// <summary>
/// Declare a delegate for the notification event handler.
/// </summary>
/// <param name="sender">The object where the event handler is attached.</param>
/// <param name="e">The event data.</param>
public delegate void NotificationEventHandler(Object^ sender, EventArgs^ e);
/// <summary>
/// Class that generetaes USB Device Change notification events.
/// </summary>
/// <remarks>
/// A Form is not necessary. Any type wherein you can override WndProc() can be used.
/// </remarks>
public ref class EventNotifier : public Control
{
private:
/// <summary>
/// Raises the NotificationEvent.
/// </summary>
/// <param name="e">The event data.</param>
void RaiseNotificationEvent(EventArgs^ e) {
NotificationEvent(this, e);
}
protected:
/// <summary>
/// Overrides the base class WndProc method.
/// </summary>
/// <param name="message">The Windows Message to process. </param>
/// <remarks>
/// This method receives Windows Messages (WM_xxxxxxxxxx) and
/// raises our NotificationEvent as appropriate. Here you should
/// add any message filtering (e.g. for the WM_DEVICECHANGE) and
/// preprocessing before raising the event (or not).
/// </remarks>
virtual void WndProc(Message% message) override {
if(message.Msg == WM_DEVICECHANGE)
{
RaiseNotificationEvent(EventArgs::Empty);
}
__super::WndProc(message);
}
public:
/// <summary>
/// Creates a new instance of the EventNotifier class.
/// </summary>
EventNotifier(void) {
RequestNotifications(this->Handle); // Register ourselves as the Windows Message processor.
}
/// <summary>
/// Registers an object, identified by the handle, for
/// Windows WM_DEVICECHANGE messages.
/// </summary>
/// <param name="handle">The object's handle.</param>
bool RequestNotifications(IntPtr handle) {
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_reserved = 0;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
return RegisterDeviceNotificationUM((HANDLE)handle, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE) != NULL;
}
/// <summary>
/// Defines the notification event.
/// </summary>
virtual event NotificationEventHandler^ NotificationEvent;
};
}
然後,在 '接收器'(即訂閱消耗我們的NotificationEvent
的對象),所有你需要做的是:
void Receiver::SomeFunction(void)
{
USBComms::EventNotifier usb = gcnew USBComms::EventNotifier();
usb->NotificationEvent += gcnew USBComms::NotificationEventHandler(this, &Receiver::USBEvent);
}
void Receiver::USBEvent(Object^ sender, EventArgs^ e)
{
// Handle the event notification as appropriate.
}
窗體是從控制和控制的後代無論如何都包裝一個win32窗口實例。我發現的唯一基於非窗口的方法是使用ManagementEventWatcher。但是這似乎有它自己的問題。 – Felix 2017-01-18 05:08:17
在Windows CE/Windows移動/ SmartDevice項目,標準Form
不提供覆蓋WndProc
方法,但可以通過根據Microsoft.WindowsCE.Forms.MessageWindow
創建一個類來創建一個構造函數,該構造函數接受一個表單,將該表單保存在局部變量中,以便該表單上的方法可以是在檢測到消息時調用。這裏有一個縮小的例子來說明。希望這對CE/Windows Mobile世界中的某個人有所幫助。
public class MsgWindow : Microsoft.WindowsCE.Forms.MessageWindow {
public const int WM_SER = 0x500;
public const int WM_SER_SCANDONE = WM_SER + 0;
frmMain msgform { get; set; }
public MsgWindow(frmMain msgform) {
this.msgform = msgform;
}
protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message m) {
switch (m.Msg) {
case WM_SER_SCANDONE:
this.msgform.RespondToMessage(WM_SER_SCANDONE);
break;
default:
break;
}
base.WndProc(ref m);
}
}
public partial class frmMain : Form {
public frmMain() {
InitializeComponent();
}
public void RespondToMessage(int nMsg) {
try {
switch (nMsg) {
case MsgWindow.WM_SER_SCANDONE:
// do something here based on the message
break;
default:
break;
}
} catch (Exception ex) {
MessageBox.Show(string.Format("{0} - {1}", ex.Message, ex.ToString()), "RespondToMessage() Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
// throw;
}
}
}
- 1. 如何在不知道類型的情況下設置屬性(即通過BeanUtils)
- 2. c#接收即插即用事件
- 3. 如何在沒有背景的情況下打印窗體
- 4. 如何在沒有窗體的情況下捕捉屏幕?
- 5. 如何在沒有證書的情況下編譯設備?
- 6. 如何在沒有AJAX的情況下接收xml代碼
- 7. 如何在沒有聲音的情況下顯示通知java
- 8. 在沒有eval的情況下即時創建一個Ruby類
- 9. 信標如何在沒有任何應用的情況下在設備上發送通知?
- 10. Subprocess.Popen即使在超時的情況下
- 11. 在不加載視圖的情況下接收通知
- 12. 如何在沒有任何點擊的情況下立即顯示對話框?
- 13. 即使在沒有行返回的情況下如何拉取摘要數據?
- 14. 在後臺接收推送通知並在用戶不知情的情況下創建本地通知
- 15. 如何在不知道具體類型的情況下獲得通用接口?
- 16. 即使應用程序關閉,whatsapp如何設法接收推送通知?
- 17. 如何在模態對話框打開的情況下接收通知
- 18. 即使應用未運行(即使在後臺中),我的設備上是否收到推送通知?
- 19. 如何在沒有窗口句柄的情況下使用RegisterDeviceNotification?
- 20. 如何在沒有窗口的情況下使用tkinter filedialog
- 21. 如何在沒有USB連接的情況下與Android設備進行通信。可能通過串行端口
- 22. 如何在沒有接收器的情況下使用Ruby的send方法?
- 23. 如何僅在不連接設備的情況下創建IPA?
- 24. 如何在不重複的情況下包含即插即用小部件靜態[CSS/JS]?
- 25. 如何在沒有插件的情況下使用fancybox和wordpress?
- 26. 如何在沒有太多延遲的情況下向80K設備發佈通知?
- 27. Dropzone js不能在沒有窗體的情況下工作
- 28. 使ActiveX控件在沒有窗體的情況下工作?
- 29. 如何在沒有Android設備的情況下開發Android應用程序?
- 30. 如何在沒有選擇項目的情況下通過QItemSelectionModel通知?
+1很好的例子,nobugz是正確的,你需要一個窗口。 – SwDevMan81 2010-01-14 02:40:23
+1。很好的例子。 – 2010-01-14 03:54:52
我看到你使用.Invoke。如果代理不在用戶界面中,這是否工作? – 2010-01-25 21:01:08