2011-02-22 18 views
10

Estoy creando una aplicación que utiliza un proyecto principal que está conectado a varias DLL diferentes. Desde una ventana DLL necesito poder abrir una ventana en otra, pero las DLL no se pueden referenciar entre sí.Enviar mensaje en C#

Me fue sugerido usar la función sendmessage en la primera DLL y tener un oyente en el programa principal que dirige ese mensaje a la DLL apropiada para abrir su ventana.

Sin embargo, no estoy familiarizado en absoluto con la función sendmessage y estoy teniendo mucha dificultad compilando cosas juntas a partir de la información que encuentro en línea.

Si alguien me puede mostrar la forma correcta (si la hay) de utilizar la función sendmessage y quizás la forma en que un oyente captura ese mensaje sería increíble. Aquí está el código que tengo hasta ahora. No estoy seguro de si voy en la dirección correcta.

[DllImport("user32.dll")] 
    public static extern int FindWindow(string lpClassName, String lpWindowName); 
    [DllImport("user32.dll")] 
    public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); 

    public void button1_Click(object sender, EventArgs e) 
    { 
     int WindowToFind = FindWindow(null, "Form1"); 
    } 
+0

Hola Nicole, SendMessage "podría" ayudar en este caso sí, pero me temo que no es la forma más fácil de alcanzar su objetivo. ¿Puedes describir un poco cuál es tu escenario completo? ¿Tiene 1 aplicación WindowsForms y algunas bibliotecas de clases que contienen formularios adicionales que le gustaría mostrar o, en caso negativo, qué está intentando hacer exactamente? Da más detalles y veremos qué camino tomar. –

+0

Si tiene control en ambas aplicaciones, use alguna otra estrategia de IPC (named pipe/socket) –

Respuesta

6

No es necesario que envíes mensajes.

Agregue event a un formulario y un controlador de eventos al otro. Luego puede usar un tercer proyecto que hace referencia a los otros dos para adjuntar el controlador de eventos al evento. Las dos DLL no necesitan referenciarse para que esto funcione.

0

No parece una buena idea utilizar el mensaje de envío. Creo que deberías tratar de evitar el problema de que las DLL no se pueden hacer referencia entre sí ...

0

Algunas otras opciones:

Asamblea Común

Cree otro ensamblado que tiene algunas interfaces comunes que pueden ser implementadas por las asambleas.

Reflexión

Esto tiene todo tipo de advertencias e inconvenientes, pero se puede utilizar para crear instancias de reflexión/comunicarse con las formas. Esto es tanto dinámico como dinámico en tiempo de ejecución (no hay comprobación estática de este código en tiempo de compilación).

0

Basándose en la respuesta de Mark Byers.

El tercer proyecto podría ser un proyecto WCF, alojado como un servicio de Windows. Si todos los programas escucharon ese servicio, una aplicación podría llamar al servicio. El servicio pasa el mensaje a todos los clientes que escuchan y pueden realizar una acción si corresponde.

buenos vídeos WCF aquí - http://msdn.microsoft.com/en-us/netframework/dd728059

8
public static extern int FindWindow(string lpClassName, String lpWindowName); 

Para encontrar la ventana, se necesita el nombre de clase de la ventana.He aquí algunos ejemplos:

C#:

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

Ejemplo de un programa que hice, escrito en VB:

hParent = FindWindow("TfrmMain", vbNullString) 

Con el fin de obtener el nombre de la clase de una ventana, que' Necesitará algo llamado Win Spy

Una vez que tenga el control de la ventana, puede enviar mensajes utilizando la función SendMessage (IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam).

hWnd, aquí, es el resultado de la función FindWindow. En los ejemplos anteriores, esto será hwnd y hParent. Le dice a la función SendMessage a qué ventana enviar el mensaje.

El segundo parámetro, wMsg, es una constante que indica el TIPO del mensaje que está enviando. El mensaje puede ser una pulsación de tecla (por ejemplo, enviar "la tecla enter" o "la barra espaciadora" a una ventana), pero también puede ser un comando para cerrar la ventana (WM_CLOSE), un comando para alterar la ventana (ocultarlo, muéstrelo, minimícelo, modifique su título, etc.), una solicitud de información dentro de la ventana (obtener el título, obtener texto dentro de un cuadro de texto, etc.), y así sucesivamente. Algunos ejemplos comunes incluyen los siguientes:

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 

Estos se pueden encontrar con un visor de API (o un simple editor de texto, como Bloc de notas) abriendo (Microsoft Studio Directorio de Visual)/Common/Herramientas/WINAPI/winapi32. TXT.

Los siguientes dos parámetros son ciertos detalles, si es necesario. En términos de presionar ciertas teclas, especificarán exactamente qué tecla específica se va a presionar.

C# ejemplo, configurar el texto de "WindowHandle" con WM_SETTEXT:

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

Más ejemplos de un programa que hice, escrito en VB, fijando el icono de un programa (ICONBIG es una constante que se puede encontrar en winapi32.txt):

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

Otro ejemplo de VB, al pulsar la tecla de espacio (VK_SPACE es una constante que se puede encontrar en winapi32.txt):

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

VB enviar un clic de botón (botón izquierdo hacia abajo y luego hacia arriba):

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

Ni idea de cómo configurar el oyente dentro de un DLL, pero estos ejemplos deben ayudar en la comprensión de cómo enviar el mensaje.

2

Usted está casi allí. (tenga en cuenta el cambio en el valor de retorno de la declaración FindWindow). Yo recomendaría usar RegisterWindowMessage en este caso para que no tenga que preocuparse por los pormenores de 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); 
} 

Y luego en su clase Form1:

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

Tenga en cuenta que no se han compilado cualquiera de los anteriores por lo que puede ser necesario ajustar algunos parámetros. También tenga en cuenta que otras respuestas que le advierten de SendMessage son perfectas. No es la forma preferida de comunicación entre módulos en la actualidad y, en términos generales, anula el WndProc y el uso de SendMessage/PostMessage implica una buena comprensión de cómo funciona el Win32 message infrastructure.

Pero si quieres/necesito ir por esta ruta, creo que lo anterior te ayudará a ir en la dirección correcta.

Cuestiones relacionadas