SendMessage?

{Eve}

Mitglied
Hi,

ich habe über die Möglichkeiten von SendMessage gelesen. Gut. Jetzt wollte ich das mal kurz ausprobieren und hab kleine Testapp gemacht.

Mit SendKeys funktioniert es, aber bei SendMessage funktioniert es nicht und ich verstehe einfach nicht wo mein Fehler liegt.
Ich habe schon viele verschiedene Dinge ausprobiert, aber ich finde die Lösung des Problems einfach nicht.

Hat vielleicht jemand von euch eine Idee wo mein Fehler ist. Bin für jeden Hinweis dankbar :)

Ich benutze Win7 64Bit, ist es möglich das es da ein Problem gibt?

Code:
static class Program
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        static private String m_strNameOfAppToSendInput = "notepad++";
        public const Int32 WM_KEYDOWN = 0x100;
        public const Int32 WM_KEYUP = 0x101;
        
        [STAThread]
        static void Main()
        {          
            Process[] rgProcesses = Process.GetProcesses();

            foreach (Process cProcess in rgProcesses)
            {
                if (cProcess.ProcessName == m_strNameOfAppToSendInput)
                {
                    IntPtr ProcessMainHandle = cProcess.MainWindowHandle;
                                        
                    //das geht
                    //SetForegroundWindow(ProcessMainHandle);
                    //SendKeys.SendWait("test"); 

                    //warum das nicht
                    IntPtr swdRet = new IntPtr(0);
                    swdRet = SendMessage(ProcessMainHandle, WM_KEYUP, (IntPtr)Convert.ToInt64(Keys.I), IntPtr.Zero);
                }
            }      
        }
    }
 
Hi.

Das Haupt-Fenster einer Applikation ist nicht unbedingt das Fenster, welches die WM_KEYUP, WM_KEYDOWN bzw. WM_CHAR Nachrichten verarbeitet.

Du müßtest das Kind-Fenster der Applikation finden (siehe http://www.pinvoke.net/default.aspx/user32.findwindowex) wo der Text eingegeben werden soll. In der Regel ein Edit bzw. Textfeld. Wie das Zielfenster heißt, bzw. welche Klasse es hat, kannst du z.B. mit Spy++ ermitteln.

Dann solltest du eine WM_KEYDOWN, WM_CHAR und WM_KEYUP Sequenz senden.

Gruß
 
Hi,

vielen Dank für die Hilfe.
Ich habe die Window- Handles überprüft und so sind sie jetzt richtig.
Laut return- Wert der SendMessage- Methode sollte der Aufruf erfolgreich durchgeführt worden sein, allerdings wird der Buchstabe im Notepad nicht angezeigt.

Hat jemand noch einen Ratschlag was falsch sein könnte?

So sieht der Code jetzt aus:

Code:
namespace WindowsFormsApplication1
{
    static class Program
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

        public const UInt32 WM_KEYDOWN = 0x100;
        public const UInt32 WM_KEYUP = 0x101;

        [STAThread]
        static void Main()
        {
            IntPtr hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Notepad", null);
            IntPtr hwndedit = FindWindowEx(hwnd, IntPtr.Zero, "Edit", null);

            IntPtr sdwRet = new IntPtr(0);
            IntPtr sdwKey = new IntPtr(Convert.ToInt64(Keys.A));
            sdwRet = SendMessage(hwndedit, WM_KEYDOWN, sdwKey, IntPtr.Zero);
            //Returns TRUE if the message succeeds

            Console.WriteLine("ERROR: swdRet = " + sdwRet);
        }
    }
}

Gruss
 
Ahhhh (*licht aufgehe*)

Wie schon gesagt, mußt du eine komplette WM_KEYDOWN, WM_CHAR und WM_KEYUP Sequenz senden.
Das war mir die ganze Zeit gar nicht klar.

Vielen Dank für deine Hilfe jetzt funktioniert es. :)

So sieht es jetzt aus:

Code:
namespace WindowsFormsApplication1
{
    static class Program
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);

        public const UInt32 WM_KEYDOWN = 0x100;
        public const UInt32 WM_KEYUP = 0x101;
        public const UInt32 WM_CHAR = 0x0102;
        
        [STAThread]
        static void Main()
        {
            IntPtr hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Notepad", null);
            IntPtr hwndedit = FindWindowEx(hwnd, IntPtr.Zero, "Edit", null);

            IntPtr sdwRet = new IntPtr(0);
            IntPtr sdwKey = new IntPtr(Convert.ToInt64(Keys.A));
            sdwRet = SendMessage(hwndedit, WM_KEYDOWN, sdwKey, IntPtr.Zero);
            sdwRet = SendMessage(hwndedit, WM_CHAR, sdwKey, IntPtr.Zero);
            sdwRet = SendMessage(hwndedit, WM_KEYUP, sdwKey, IntPtr.Zero);
        }
    }
}


Hätte noch eine Frage.
Muss ich diese
Code:
 public const UInt32 WM_KEYDOWN = 0x100;
immer in den Code schreiben oder sind diese Events irgendwo in einer Klasse vordefiniert und kann die von dort abrufen?

Gruss
 
Muss ich diese
Code:
 public const UInt32 WM_KEYDOWN = 0x100;
immer in den Code schreiben oder sind diese Events irgendwo in einer Klasse vordefiniert und kann die von dort abrufen?
Soweit mir bekannt ist müssen diese Konstanten selbst definiert werden - die externen Funktionen mußt du ja auch über PInvoke erst nutzbar machen.

Gruß
 
Zurück