Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# have an equivalent of Delphi's message keyword?

In delphi, I can create my own message like this,

const MY_MESSAGE = WM_USER+100;
procedure MyMessage(var Msg: TMessage); message MY_MESSAGE;

procedure TForm1.MyMessage(var Msg: TMessage);
begin
....
end;

bu in c# I can do that like this

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);
}

but I don't want to override WndProc(), I want to create my own MyMessage() function, and when I post message it will run.

How can I do that? Thanks.

like image 729
Okan Kocyigit Avatar asked Apr 18 '11 19:04

Okan Kocyigit


People also ask

What is the main cause of hep C?

Hepatitis C is a liver infection caused by the hepatitis C virus (HCV). Hepatitis C is spread through contact with blood from an infected person. Today, most people become infected with the hepatitis C virus by sharing needles or other equipment used to prepare and inject drugs.

Does hep C go away?

Hepatitis C virus (HCV) causes both acute and chronic infection. Acute HCV infections are usually asymptomatic and most do not lead to a life-threatening disease. Around 30% (15–45%) of infected persons spontaneously clear the virus within 6 months of infection without any treatment.

What does hep C pain feel like?

Many people with chronic HCV suffer from aches and pains in their joints. A variety of different joints can be involved but the most common are in the hands and wrists. These pains are often minor but occasionally the pain can be quite severe. In such cases painkillers can be used to relieve the symptoms.

Does hep C treatment make you sick?

Like the other antivirals, the side effects are mild. You might have a slight headache or bellyache, or you might feel tired. Glecaprevir and pibrentasvir (Mavyret): Three pills daily can treat all types of hep C. Side effects are mild and can include headache, fatigue, diarrhea, and nausea.


2 Answers

That's a special feature of Delphi of which there is no analogue in C#. In C# you need to override WndProc().

like image 190
David Heffernan Avatar answered Nov 02 '22 18:11

David Heffernan


Something that looks very similar can be done using .NET reflection and custom attributes. I think performance would be OK for production use, but not worth it since this still requires overriding WndProc to call the custom dispatcher, and once the WndProc is put into place, it takes one line of code to call the custom dispatcher OR 3 lines of code to write a proper switch statement. If the code is called from a "base" class you then inherit from it might be worth it.

Just in case you were wondering, I'm doing this because I'm lerarning C# + .NET and was curious what could be done.

Here's how the code would look like, once the "plumbing" is done:

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);
    }
}

And here's the "plumbing". A lot more code that implements the code to identify all windows message handler routines (based on custom attribute), and cache all those results using a couple of dictionaries (so the heavy-lifting only needs to be done once).

// 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);
        }
    }
    
}
like image 42
Cosmin Prund Avatar answered Nov 02 '22 18:11

Cosmin Prund