C#调用base.WndProc报错“object不包含WndProc定义”问题求助
报错原因
WndProc是System.Windows.Forms.Form类提供的受保护虚方法,你当前的Program类默认继承自object基类,object没有定义WndProc方法,因此调用base.WndProc(ref m)时会直接触发该报错。- 额外的逻辑缺陷:
WM_DEVICECHANGE是Windows系统发送给窗口对象的系统消息,控制台应用默认没有窗口句柄和消息循环,即使解决了语法报错,当前代码也无法接收到USB插拔的通知消息。
修复方案
方案1:WinForm项目实现(推荐)
如果你是做WinForm桌面应用,直接将消息处理逻辑迁移到主窗体类即可:
- 新建Windows窗体应用项目,将
WndProc重写方法、DEV_BROADCAST_VOLUME结构体、DriveMaskToLetter方法全部复制到主窗体类(默认类名Form1,已默认继承Form)。 - 无需修改
base.WndProc调用,此时base指向Form基类,存在合法的WndProc实现。 - 程序启动后保持主窗体运行,即可正常接收USB设备插拔通知。
方案2:控制台项目兼容实现
如果需要保留控制台项目形态,可以自定义隐藏窗口类承载消息逻辑,示例代码如下:
using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace ConsoleApp5 { // 自定义隐藏窗口类,继承Form获得WndProc能力 public class UsbMonitorForm : Form { const int WM_DEVICECHANGE = 0x0219; const int DBT_DEVICEARRIVAL = 0x8000; const int DBT_DEVICEREMOVALCOMPLETE = 0x8004; const int DBT_DEVTYPVOLUME = 0x00000002; protected override void WndProc(ref Message m) { if (m.Msg == WM_DEVICECHANGE) { DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME)); if ((m.WParam.ToInt32() == DBT_DEVICEARRIVAL) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME)) { MessageBox.Show(DriveMaskToLetter(vol.dbcv_unitmask).ToString()); } if ((m.WParam.ToInt32() == DBT_DEVICEREMOVALCOMPLETE) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME)) { MessageBox.Show("usb out"); } } base.WndProc(ref m); } [StructLayout(LayoutKind.Sequential)] public struct DEV_BROADCAST_VOLUME { public int dbcv_size; public int dbcv_devicetype; public int dbcv_reserved; public int dbcv_unitmask; } private static char DriveMaskToLetter(int mask) { char letter; string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int cnt = 0; int pom = mask / 2; while (pom != 0) { pom = pom / 2; cnt++; } letter = cnt < drives.Length ? drives[cnt] : '?'; return letter; } } public class Program { [STAThread] static void Main(string[] args) { // 启动消息循环,运行隐藏窗口 Application.Run(new UsbMonitorForm() { ShowInTaskbar = false, WindowState = FormWindowState.Minimized }); } } }
使用该方案需要额外注意:控制台项目需要先添加System.Windows.Forms程序集引用,同时给Main方法加上[STAThread]特性才能正常启动窗体消息循环。
内容的提问来源于stack exchange,提问作者Aishwarya Munuswamy
相关产品推荐
相关产品推荐

