C#是否有Delphi的等价物';s消息关键字?
在delphi中,我可以像这样创建我自己的消息C#是否有Delphi的等价物';s消息关键字?,c#,delphi,windows-messages,C#,Delphi,Windows Messages,在delphi中,我可以像这样创建我自己的消息 const MY_MESSAGE = WM_USER+100; procedure MyMessage(var Msg: TMessage); message MY_MESSAGE; procedure TForm1.MyMessage(var Msg: TMessage); begin .... end; 但在c#我可以这样做 public static uint ms; protected override void WndProc(ref
const MY_MESSAGE = WM_USER+100;
procedure MyMessage(var Msg: TMessage); message MY_MESSAGE;
procedure TForm1.MyMessage(var Msg: TMessage);
begin
....
end;
但在c#我可以这样做
public static uint ms;
protected override void WndProc(ref Message m)
{
if(m.Msg == ms)
MessageBox.Show("example");
else
base.WndProc(ref m);
}
void Button1Click(object sender, EventArgs e)
{
PostMessage(HWND_BROADCAST,ms,IntPtr.Zero,IntPtr.Zero);
}
但我不想重写WndProc(),我想创建自己的MyMessage()函数,当我发布消息时,它将运行
我该怎么做?
谢谢。这是Delphi的一个特殊功能,在C#中没有类似的功能。在C#中,您需要重写
WndProc()
可以使用.NET
反射和自定义属性来完成一些看起来非常相似的操作。我认为性能对于生产使用是可以的,但不值得,因为这仍然需要重写WndProc
来调用自定义调度程序,并且一旦WndProc
就位,就需要一行代码来调用自定义调度程序,或者需要三行代码来编写适当的switch
语句。如果代码是从“基类”调用的,那么从它继承的代码可能是值得的
万一你想知道,我这么做是因为我在学习C++.NET,并且很好奇能做些什么。
下面是“管道”完成后代码的样子:
这是“管道”。更多的代码实现了识别所有windows消息处理程序例程(基于自定义属性)的代码,并使用两个字典缓存所有这些结果(因此繁重的工作只需完成一次)
//设置消息ID的自定义属性
类WinMessageHandler:System.Attribute
{
公共信息;
公共WinMessageHandler(int Msg){this.Msg=Msg;}
}
类WinMessageDispatcher
{
//这是在应用程序的生命周期内缓存的,它保存每种类型所需的
//调度信息。
私有类WinMessageDispatcher\u PerType
{
私人词典;
//通用处理程序
public bool HandleMessage(object OnInstance,ref Message msg)
{
System.Reflection.MethodInfo方法;
if(dict.TryGetValue(msg.msg,out方法))
{
//打电话
object[]p=新对象[1];
p[0]=味精;
return(bool)方法调用(OnInstance,p);
msg=p[0];
}
其他的
{
返回false;
}
}
//构造函数,初始化“dict”
公共WinMessageDispatcher_PerType(类型t)
{
dict=新字典();
foreach(t.GetMethods()中的var方法)
{
var attribs=method.GetCustomAttributes(typeof(WinMessageHandler),true);
如果(attribs.Length>0)
{
//检查返回类型
如果(method.ReturnParameter.ParameterType!=typeof(bool))抛出新异常(string.Format(“{0}不返回bool”,method.Name));
//检查方法参数
var param=method.GetParameters();
如果(param.Length!=1)抛出新异常(string.Format(“{0}不接受1个参数”,method.Name));
//哎呀!我如何检查“ref”参数的类型?
如果(!param[0].ParameterType.IsByRef)引发新异常(string.Format(“{0}不接受System.Windows.Forms.Message类型的ref参数,但接受{1}”类型的参数),则为method.Name,param[0].ParameterType.ToString());
//将该方法添加到字典中
dict.Add(((WinMessageHandler)attribs[0]).Msg,方法);
}
}
}
}
//字典将“类型”链接到每种类型的缓存实现
专用静态字典dict;
//静态类型初始值设定项
静态WinMessageDispatcher()
{
dict=新字典();
}
//消息调度器
公共静态布尔调度(对象对象对象,参考消息消息消息)
{
if(ObjInstance==null)返回false;
其他的
{
WinMessageDispatcher_PerType PerType;
锁(dict)
{
if(!dict.TryGetValue(ObjInstance.GetType(),out PerType))
{
PerType=新的WinMessageDispatcher_PerType(ObjInstance.GetType());
dict.Add(ObjInstance.GetType(),PerType);
}
}
返回PerType.HandleMessage(对象,参考消息);
}
}
}
public partial class Form1 : Form
{
private const int WM_MOUSEMOVE = 0x0200;
// This is the Delphi-lookalike declaration for the WM_MOUSEMOVE handler.
// I'd say it looks very much "alike!"
[WinMessageHandler(WM_MOUSEMOVE)]
public bool UnHandler(ref Message X)
{
this.Text = "Movement";
return false;
}
// While simple, this is unfortunately a deal-breaker. If you need to go through the
// trouble of writing this stub WndProc, might as well write a proper switch statement
// and call the handler directly.
protected override void WndProc(ref Message m)
{
if (!WinMessageDispatcher.Dispatch(this, ref m)) base.WndProc(ref m);
}
}
// Custom attribute to set message ID
class WinMessageHandler : System.Attribute
{
public int Msg;
public WinMessageHandler(int Msg) { this.Msg = Msg; }
}
class WinMessageDispatcher
{
// This is cached for the life of the application, it holds the required per-type
// dispatching information.
private class WinMessageDispatcher_PerType
{
private Dictionary<int, System.Reflection.MethodInfo> dict;
// generic handler
public bool HandleMessage(object OnInstance, ref Message msg)
{
System.Reflection.MethodInfo method;
if (dict.TryGetValue(msg.Msg, out method))
{
// Set up the call
object[] p = new object[1];
p[0] = msg;
return (bool)method.Invoke(OnInstance, p);
msg = p[0];
}
else
{
return false;
}
}
// Constructor, initializes the "dict"
public WinMessageDispatcher_PerType(Type t)
{
dict = new Dictionary<int, System.Reflection.MethodInfo>();
foreach (var method in t.GetMethods())
{
var attribs = method.GetCustomAttributes(typeof(WinMessageHandler), true);
if (attribs.Length > 0)
{
// Check return type
if (method.ReturnParameter.ParameterType != typeof(bool)) throw new Exception(string.Format("{0} doesn't return bool", method.Name));
// Check method parameters
var param = method.GetParameters();
if (param.Length != 1) throw new Exception(string.Format("{0} doesn't take 1 parameter", method.Name));
// Ooops! How do I check the TYPE of the "ref" parameter?
if (!param[0].ParameterType.IsByRef) throw new Exception(string.Format("{0} doesn't take a ref parameter of type System.Windows.Forms.Message but a parameter of type {1}", method.Name, param[0].ParameterType.ToString()));
// Add the method to the dictionary
dict.Add(((WinMessageHandler)attribs[0]).Msg, method);
}
}
}
}
// Dictionary to link "Types" to per-type cached implementations
private static Dictionary<Type, WinMessageDispatcher_PerType> dict;
// Static type initializer
static WinMessageDispatcher()
{
dict = new Dictionary<Type, WinMessageDispatcher_PerType>();
}
// Message dispatcher
public static bool Dispatch(object ObjInstance, ref Message msg)
{
if (ObjInstance == null) return false;
else
{
WinMessageDispatcher_PerType PerType;
lock (dict)
{
if (!dict.TryGetValue(ObjInstance.GetType(), out PerType))
{
PerType = new WinMessageDispatcher_PerType(ObjInstance.GetType());
dict.Add(ObjInstance.GetType(), PerType);
}
}
return PerType.HandleMessage(ObjInstance, ref msg);
}
}
}