Send Message in C#

后端 未结 6 1280
野趣味
野趣味 2020-11-28 10:53

I\'m creating an application that uses a main project that is connected to several different DLLs. From one DLL window I need to be able to open a window in another but the

相关标签:
6条回答
  • 2020-11-28 11:14

    You are almost there. (note change in the return value of FindWindow declaration). I'd recommend using RegisterWindowMessage in this case so you don't have to worry about the ins and outs of WM_USER.

    [DllImport("user32.dll")]    
    public static extern IntPtr FindWindow(string lpClassName, String lpWindowName);    
    [DllImport("user32.dll")]    
    public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);    
    [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    static extern uint RegisterWindowMessage(string lpString);
    
    public void button1_Click(object sender, EventArgs e)   
    {        
         // this would likely go in a constructor because you only need to call it 
         // once per process to get the id - multiple calls in the same instance 
         // of a windows session return the same value for a given string
         uint id = RegisterWindowMessage("MyUniqueMessageIdentifier");
         IntPtr WindowToFind = FindWindow(null, "Form1");    
         Debug.Assert(WindowToFind != IntPtr.Zero);
         SendMessage(WindowToFind, id, IntPtr.Zero, IntPtr.Zero);
    }
    

    And then in your Form1 class:

    class Form1 : Form
    {
        [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
        static extern uint RegisterWindowMessage(string lpString);
    
        private uint _messageId = RegisterWindowMessage("MyUniqueMessageIdentifier");
    
        protected override void WndProc(ref Message m)
        {
           if (m.Msg == _messageId)
           {
               // do stuff
    
           }
           base.WndProc(ref m);
        }
    }
    

    Bear in mind I haven't compiled any of the above so some tweaking may be necessary. Also bear in mind that other answers warning you away from SendMessage are spot on. It's not the preferred way of inter module communication nowadays and genrally speaking overriding the WndProc and using SendMessage/PostMessage implies a good understanding of how the Win32 message infrastructure works.

    But if you want/need to go this route I think the above will get you going in the right direction.

    0 讨论(0)
  • It doesn't sound like a good idea to use send message. I think you should try to work around the problem that the DLLs can't reference each other...

    0 讨论(0)
  • 2020-11-28 11:21

    Building on Mark Byers's answer.

    The 3rd project could be a WCF project, hosted as a Windows Service. If all programs listened to that service, one application could call the service. The service passes the message on to all listening clients and they can perform an action if suitable.

    Good WCF videos here - http://msdn.microsoft.com/en-us/netframework/dd728059

    0 讨论(0)
  • 2020-11-28 11:22

    Some other options:

    Common Assembly

    Create another assembly that has some common interfaces that can be implemented by the assemblies.

    Reflection

    This has all sorts of warnings and drawbacks, but you could use reflection to instantiate / communicate with the forms. This is both slow and runtime dynamic (no static checking of this code at compile time).

    0 讨论(0)
  • 2020-11-28 11:24
    public static extern int FindWindow(string lpClassName, String lpWindowName);
    

    In order to find the window, you need the class name of the window. Here are some examples:

    C#:

    const string lpClassName = "Winamp v1.x";
    IntPtr hwnd = FindWindow(lpClassName, null);
    

    Example from a program that I made, written in VB:

    hParent = FindWindow("TfrmMain", vbNullString)
    

    In order to get the class name of a window, you'll need something called Win Spy

    Once you have the handle of the window, you can send messages to it using the SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam) function.

    hWnd, here, is the result of the FindWindow function. In the above examples, this will be hwnd and hParent. It tells the SendMessage function which window to send the message to.

    The second parameter, wMsg, is a constant that signifies the TYPE of message that you are sending. The message might be a keystroke (e.g. send "the enter key" or "the space bar" to a window), but it might also be a command to close the window (WM_CLOSE), a command to alter the window (hide it, show it, minimize it, alter its title, etc.), a request for information within the window (getting the title, getting text within a text box, etc.), and so on. Some common examples include the following:

    Public Const WM_CHAR = &H102
    Public Const WM_SETTEXT = &HC
    Public Const WM_KEYDOWN = &H100
    Public Const WM_KEYUP = &H101
    Public Const WM_LBUTTONDOWN = &H201
    Public Const WM_LBUTTONUP = &H202
    Public Const WM_CLOSE = &H10
    Public Const WM_COMMAND = &H111
    Public Const WM_CLEAR = &H303
    Public Const WM_DESTROY = &H2
    Public Const WM_GETTEXT = &HD
    Public Const WM_GETTEXTLENGTH = &HE
    Public Const WM_LBUTTONDBLCLK = &H203
    

    These can be found with an API viewer (or a simple text editor, such as notepad) by opening (Microsoft Visual Studio Directory)/Common/Tools/WINAPI/winapi32.txt.

    The next two parameters are certain details, if they are necessary. In terms of pressing certain keys, they will specify exactly which specific key is to be pressed.

    C# example, setting the text of windowHandle with WM_SETTEXT:

    x = SendMessage(windowHandle, WM_SETTEXT, new IntPtr(0), m_strURL);
    

    More examples from a program that I made, written in VB, setting a program's icon (ICON_BIG is a constant which can be found in winapi32.txt):

    Call SendMessage(hParent, WM_SETICON, ICON_BIG, ByVal hIcon)
    

    Another example from VB, pressing the space key (VK_SPACE is a constant which can be found in winapi32.txt):

    Call SendMessage(button%, WM_KEYDOWN, VK_SPACE, 0)
    Call SendMessage(button%, WM_KEYUP, VK_SPACE, 0)
    

    VB sending a button click (a left button down, and then up):

    Call SendMessage(button%, WM_LBUTTONDOWN, 0, 0&)
    Call SendMessage(button%, WM_LBUTTONUP, 0, 0&)
    

    No idea how to set up the listener within a .DLL, but these examples should help in understanding how to send the message.

    0 讨论(0)
  • 2020-11-28 11:35

    You don't need to send messages.

    Add an event to the one form and an event handler to the other. Then you can use a third project which references the other two to attach the event handler to the event. The two DLLs don't need to reference each other for this to work.

    0 讨论(0)
提交回复
热议问题