(BTW this is C# .NET 4.5)
I have some unmanaged DLL that talks to some hardware. I wrap a bunch of code and get something simple, as a class object, that I can create in a WinForm.
private AvaSpec AS = new AvaSpec();
public AvaSpec_Form()
{
InitializeComponent();
AS.SpectrumMeasuredEvent += (se, ev) => { SpectrumMeasured(ev); };
AS.Init(this.Handle);
AS.Activate();
// configure as desired
// AS.l_PrepareMeasData.m_IntegrationDelay = 0;
if (AS.DeviceList.Count > 0)
{
AS.Start();
}
}
However, the DLL relies on receiving messages through WndProc. The best way I could figure out to do this is to overload the WndProc method on the Form:
protected override void WndProc(ref Message m)
{
// catch WndProc messages that AvaSpec defines as its own
if (m.Msg == AvaSpec.WM_MEAS_READY ||
m.Msg == AvaSpec.WM_APP ||
m.Msg == AvaSpec.WM_DBG_INFOAs ||
m.Msg == AvaSpec.WM_DEVICE_RESET )
{
AS.WndProcMessageReceived(ref m);
}
// else pass message on to default message handler
base.WndProc(ref m);
}
How can I hide this overload somehow in the class definition so that the overload method does not need to be added to the Form itself? There is some talk of the IMessageFilter interface, but it still looks to require some code in the form to add the filter. Any ideas on how to make this more elegant?
Ok I figured it out based on Colin Smith's hints.
You derive your class from NativeWindow:
https://msdn.microsoft.com/en-us/library/system.windows.forms.nativewindow(v=vs.110).aspx
Then assign the parent (form) Handle (that you pass by some initialization) to the Handle that NativeWindow provides to the class object. Then, you can overload the WndProc method directly in the object.
// object definition
public class AvaSpec : NativeWindow
{
protected override void WndProc(ref Message m)
{
// catch WndProc messages that AvaSpec defines as its own
if (m.Msg == AvaSpec.WM_MEAS_READY ||
m.Msg == AvaSpec.WM_APP ||
m.Msg == AvaSpec.WM_DBG_INFOAs ||
m.Msg == AvaSpec.WM_DEVICE_RESET)
{
WndProcMessageReceived(ref m);
}
// Call base WndProc for default handling
base.WndProc(ref m);
}
...(snip)
public void Init(IntPtr parentHandle)
{
this.AssignHandle(parentHandle);
...(snip)
and use it (pass handle pointer via some init) like so:
// WinForm definition
public partial class AvaSpec_X : Form
{
private AvaSpec AS = new AvaSpec();
public AvaSpec_X()
{
InitializeComponent();
AS.SpectrumMeasuredEvent += (se, ev) => { SpectrumMeasured(ev); };
AS.Init(this.Handle);
AS.Activate();
// configure as desired
//AS.l_PrepareMeasData.m_IntegrationDelay = 0;
if (AS.DeviceList.Count > 0)
{
AS.Start();
}
}
...(snip)