如何在C#中将类实例传递给WndProc

时间:2014-02-12 07:00:16

标签: c# windows wndproc

如何将我的主窗体中的对象实例传递给WndProc方法

对于前者: 我有一个ComboBox对象 - objCombo 。我必须在系统绘制下拉列表框之前捕获某个窗口消息。

一种方法,我可以有一个自定义的组合框,它来自ComboBox

public class CustomComboBox : ComboBox 
{
   //... some initialization code goes here

   protected override void WndProc(ref Message m)
   {
        if (m.Msg == WM_CTLCOLORLISTBOX)
        {
          // capture the message and do some work.
          //here i can get the reference to the CustomComboBox by using 
          //this keyword.
        }
   }

}

但是,我想知道有没有一种方法,我可以做到这一点,而无需完成创建自定义组合框的过程,并做同样的事情。即使用对我的组合框实例的引用捕获我的Form类中的Windows消息。 ?

即。

public class MyForm : Form
{
   //... some initialization code goes here including the InitializeComponent 
   // for form objects and other controls 

   private void CaptureComboWndProc(ref Message m)
   {
     // this method will capture only the windows message specific to objCombo ??
   }

}

我希望我清楚这个问题 谢谢和干杯 跋蹉

2 个答案:

答案 0 :(得分:3)

更好的方法是创建一个组合框的后代。这是非常明确的做法。

但是你可以从消息中找到控件,这是你的去向。

使用Control.FromHandle查找发布消息的控件。

   protected override void WndProc(ref Message m)
   {
        if (m.Msg == WM_CTLCOLORLISTBOX)
        {
            if(Control.FromHandle(m.HWnd) == this.objCombo)
            {
                CaptureComboWndProc(ref m);
            }
        }
   }

   private void CaptureComboWndProc(ref Message m)
   {

   }

和......最后我想说不要请这样做。

答案 1 :(得分:2)

有可能,通用技术在Windows GUI编程中被称为“对窗口进行子类化”。它的工作原理是替换窗口的窗口过程。这已经在您在工具箱(ListView,ComboBox等)中找到的每个本机窗口控件中完成,这就是它们如何引发事件。并且可以反复完成。无需pinvoke,NativeWindow类使用其AssignHandle()方法支持它。

您必须从NativeWindow派生自己的类并重写WndProc()方法以实现自定义消息处理。比如使用表单的Load事件来附加它。大致是:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }

    private class ComboHooker : NativeWindow {
        protected override void WndProc(ref Message m) {
            if (m.Msg == 0x134) {
                // etc...
            }
            else {
                // Stop sub-classing on WM_NCDESTROY
                if (m.Msg == 0x82) this.ReleaseHandle();
                base.WndProc(ref m);
            }
        }
    }

    private void hookComboBoxes(Control.ControlCollection ctls) {
        foreach (Control ctl in ctls) {
            if (ctl.GetType() == typeof(ComboBox)) {
                new ComboHooker().AssignHandle(ctl.Handle);
            }
            hookComboBoxes(ctl.Controls);
        }
    }

    protected override void OnLoad(EventArgs e) {
        hookComboBoxes(this.Controls);
        base.OnLoad(e);
    }
}