none
Externes Programm / Fenster Grösse und Position Ermittel und ändern RRS feed

  • Frage

  • Hallo ich habe ein kleines Problem :-(

    Ich habe ein VB geschrieben welches ein externes Programm startet und auch schliesse.

    Ich möchte aber beim Start die Position und die Grösse des Programms ändern.

    Ich bekomme das mit Notepad ..... öffnen und verschieben (FindWindows/GetWindows) hin aber bei meinem Externen Programm ändert sich immer die Titelleiste :-( 

    Ich kenne die PrcessID :-) aber wie setzte ich das nun zum Fenster und ändern in den Quellcode ein?

    Dim NotepadRect As RECT NotepadHandlePDI = FindWindow("Notepad", vbNullString) GetWindowRect(NotepadHandlePDI, NotepadRect) intX = 225 intY = 225 intCX = 225 intCY = 225 SetWindowPos(NotepadHandlePDI, HWND_NOTOPMOST, intX, intY, intCX, intCY, SWP_SHOWWINDOW)


    Vielen Dank für jede unterstützung

    Freitag, 3. Januar 2014 16:18

Antworten

  • Jetzt kann ich auch dein Problem nachvollziehen ;)

    Deine Anwendug heißt Kasse.exe. Ich nehme mal an, das es kein weiteres Programm mit diesem Namen gibt. Außerdem läuft das Programm nur einmal. Über den Namen des Prozesses kommen wir an alles was wir brauchen:

    Dim p As Process = Process.GetProcessesByName("Notepad")(0)
    Durch daas Process-Objekt kommen wir an das handle des Hauptfensters:
    p.MainWindowHandle 
    Dieses Handle kannst du nun an SetWindowPos übergeben:
    SetWindowPos(p.MainWindowHandle , ...


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert xpd1000 Freitag, 3. Januar 2014 21:29
    Freitag, 3. Januar 2014 20:28
    Moderator
  • Die GetProcessesByName liefert ein Array von Prozessen die mit dem Namen übereinstimmen. Wir wollen aber den ersten Prozess. Der Index istNullbasiert, 0 = 1. Element. (wir gehen davon aus das die Kasse läuft, sonst würde dein Programm garnicht funktionieren können)

    Der Fehler kommt, wenn kein Prozess gefunden wurde. Gucke mal in den Taskmanager wie der Prozess wirklich heißt. Du darfst das .exe aber nicht mitschreiben.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert xpd1000 Freitag, 3. Januar 2014 21:29
    Freitag, 3. Januar 2014 21:05
    Moderator

Alle Antworten

  • Hallo,
    wenn du das Programm selbst startest, dann hast du auch ein Process-Onjekt:

    Dim p As New Process()
    p.StartInfo.FileName = "notepad.exe"
    p.Start()

    Mit Hilfe diesen Objekts kannst du das Handle des Hauptfensters bekommen. Ich habe mir den Code von hier und hier für SetWindowPos kopiert. und soufgerufen:

    While p.MainWindowHandle = IntPtr.Zero
        Thread.Sleep(10) 'Warten bis Fenster da ist
    End While
    SetWindowPos(p.MainWindowHandle, HWND_TOP, 10, 10, 1500, 700, SetWindowPosFlags.ShowWindow)

    Die Schleife ist wichtig, da das Fenster eine kurze Zeit benötigt um Aufzutauchen. Unabhängig von dieser Zeit funktioniert der Code immer. Anschließend rufe ich SetWindowPos auf. Notepad erscheint an der oberen linken Ecke meines linken Monitors.

    Wenn du, warum auch immer, wirklich nur die procId hast, kannst du den Process trotzdem über GetProcessById bekommen:

    Dim p As Process = Process.GetProcessById(procId)
    Irgend eine Änderung an der Titelleiste kann ich nicht feststellen. Macht das andere Programm noch irgendetwas anderes beim start? Wie hast du die Funktion SetWindowPos deklariert? Sind die Werte für intX usw. gültig?



    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Freitag, 3. Januar 2014 17:53
    Moderator
  • Danke für die schnelle Antwort:-)

    hmmmm

    Ehrlich ich verstehe nur Bahnhof und geben mal ein paar mehr Infos.

    Also ich habe eine Kassensoftware welche im Tabakwaren und Zeitschriften eingesetzt werden soll.

    1. Erledigtes Problem: Zeitschriften (Barcode) / Es ist kein MVP Modul in der Kassensoftware enthalten daher werden die Zahlen-Tasten (Barcode-Scan) vom VB abgefangen und Ausgewertet und dann per Sendkey an die Kasse gegeben. Funktioniert gut ( aufgefallen ist das sendkey schneller ist wenn die Spracherkennung von Win7 eingeschaltet ist.

    2. Das Problem: Die Mitarbeiter klicken hier und dort und dann ist die Kasse nicht mehr an der Position wo sie sein soll ( Die Damen sind schon etwas Älter ) nun ist Holland in Not. Daher möchte ich erreichen das beim Start die Kassensoftware immer an der gleichen stelle erscheint.   

    Es gibt ein Form1 -> Bildschirm füllend und 6
    Button 1= startet oder beendet die Kasse, 2= startet oder beendet das abfangen der Zahlen-Tasten(Barcode-Scan), 3=Frei, 4=Frei, 5=Frei, 6= Beenden PC

    also ich habe folgendes was mit dem Problem zu tun hat:

    Public Class Form1 'Fenster auf neue Position setzen Private Declare Function SetWindowPos Lib "user32.dll" ( _ ByVal hwnd As Int32, _ ByVal hWndInsertAfter As Int32, _ ByVal x As Int32, _ ByVal y As Int32, _ ByVal cx As Int32, _ ByVal cy As Int32, _ ByVal wFlags As Int32) As Int32 Dim intX As Integer Dim intY As Integer Dim intCX As Integer Dim intCY As Integer Private Const HWND_NOTOPMOST As Int32 = -2 Private Const SWP_SHOWWINDOW As Int32 = &H40 'Fenster position ermitteln/auslesen Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer Private Declare Function GetWindowRect Lib "user32" Alias "GetWindowRect" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer Private Structure RECT Public Left As Int32 Public Top As Int32 Public Right As Int32 Public Bottom As Int32 End Structure Private NotepadHandlePDI As Integer

    Die Variablen der Programm ID kommen aus Modul1

     '### Abschnitt KASSE ###
        Public CaoKasseID_TXT As String 'Gibt die PID Sichtbar aus
        Public CAOKasseStartStop As Integer = 0 'Prüfung ob Kasse AN oder AUS | Startet Kassen oder Beendet Kasse
        Public CaoKasseID As Process
        Public CAOKasseArtikelSuche As Integer = 0 'Ist die Variable für die Suche Nach Artikel in der Kasse | Startet die Suche in der Kassen oder Beendet diese
    Dann wieder bei Form1 beim Klick.....

    Private Sub CAOKasseStartStopButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CAOKasseStartStopButton.Click If Module1.CAOKasseStartStop = 0 Then

    Module1.CaoKasseID = Process.GetProcessById(Shell("C:\Ordner1\cao_kasse.exe", AppWinStyle.NormalFocus)) Module1.CaoKasseID_TXT = Module1.CaoKasseID.Id System.Threading.Thread.Sleep(1000) For i As Integer = 0 To 3 System.Threading.Thread.Sleep(100) SendKeys.SendWait("{TAB}") Next System.Threading.Thread.Sleep(100) SendKeys.SendWait("wert1") System.Threading.Thread.Sleep(100) SendKeys.SendWait("{TAB}") System.Threading.Thread.Sleep(100) SendKeys.SendWait("wert2") SendKeys.SendWait("{TAB}") System.Threading.Thread.Sleep(100) SendKeys.SendWait("{Enter}") Module1.CAOKasseStartStop = 1 CAOKasseStartStopButton.BackColor = Color.Lime System.Threading.Thread.Sleep(500) ZeitschriftenModulStartStop = 1 ZeitschriftenModulStartStopButton.BackColor = Color.Lime DIT_SYS_Info_ALL.BackColor = Color.Gainsboro() DIT_SYS_Info_ALL.Font = New Font(InfoBox.Font.Name, 7, InfoBox.Font.Style, InfoBox.Font.Unit) DIT_SYS_Info_ALL.Text = "Programm ID: " & Module1.CaoKasseID_TXT ' Anfang Problem Dim NotepadRect As RECT NotepadHandlePDI = FindWindow("CAO-Kasse 1.4", vbNullString) MsgBox(NotepadHandlePDI) GetWindowRect(NotepadHandlePDI, NotepadRect) MsgBox("Top = " & NotepadRect.Top & _ vbCrLf & "Bottom = " & NotepadRect.Bottom & _ vbCrLf & "Left = " & NotepadRect.Left & _ vbCrLf & "Right = " & NotepadRect.Right) intX = 225 intY = 225 intCX = 225 intCY = 225 SetWindowPos(NotepadHandlePDI, HWND_NOTOPMOST, intX, intY, intCX, intCY, SWP_SHOWWINDOW) ' Ende Problem

    Alles funktioniert bis auf den Bereich Problem :-) NEIN ich habe das nicht gelernt, Ja das könnt ihr sehen da könnte sicher richtig viel Optimiert werden (kommt Später). Nun wieder zum Problem Block

    Folgenden funktioniert nicht:

    NotepadHandlePDI = FindWindow("CAO-Kasse 1.4", vbNullString)

    Die MSG´s werden NICHT mit ID und Angaben zur Größe gefüllt.

    Aber wenn ich aus der Obigen Zeile das mache:

    NotepadHandlePDI = FindWindow("Notepad", vbNullString) 

    funktionieren die MSG´s mit ID und Angaben zur Größe und auch danach ändert das Skript das Notepad auf 225x225.

    Mein Problem ist das ich nicht Notepad habe sondern das Programm Kasse.exe welches ich nicht mit "FindWindow" finden kann. :-(

    Wie kann ich nun in den Block mein Programm Packen? Bitte für Dummies erklären den ich bin einer. Danke


    • Bearbeitet xpd1000 Freitag, 3. Januar 2014 20:10
    Freitag, 3. Januar 2014 19:59
  • Jetzt kann ich auch dein Problem nachvollziehen ;)

    Deine Anwendug heißt Kasse.exe. Ich nehme mal an, das es kein weiteres Programm mit diesem Namen gibt. Außerdem läuft das Programm nur einmal. Über den Namen des Prozesses kommen wir an alles was wir brauchen:

    Dim p As Process = Process.GetProcessesByName("Notepad")(0)
    Durch daas Process-Objekt kommen wir an das handle des Hauptfensters:
    p.MainWindowHandle 
    Dieses Handle kannst du nun an SetWindowPos übergeben:
    SetWindowPos(p.MainWindowHandle , ...


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert xpd1000 Freitag, 3. Januar 2014 21:29
    Freitag, 3. Januar 2014 20:28
    Moderator
  • OK

    ich bekomme noch .......

    Ein Ausnahmefehler des Typs "System.IndexOutOfRangeException" ist in Lay.exe aufgetreten.

    Zusätzliche Informationen: Der Index war außerhalb des Arraybereichs.

    Ich nehme mal an das hat etwas mit der (0) zu tun oder?  was sagt die (0) aus?

    MOMENT ICH GLAUBE ICH HABS

    NEE doch nicht

    • Bearbeitet xpd1000 Freitag, 3. Januar 2014 21:04
    Freitag, 3. Januar 2014 20:57
  • Die GetProcessesByName liefert ein Array von Prozessen die mit dem Namen übereinstimmen. Wir wollen aber den ersten Prozess. Der Index istNullbasiert, 0 = 1. Element. (wir gehen davon aus das die Kasse läuft, sonst würde dein Programm garnicht funktionieren können)

    Der Fehler kommt, wenn kein Prozess gefunden wurde. Gucke mal in den Taskmanager wie der Prozess wirklich heißt. Du darfst das .exe aber nicht mitschreiben.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    • Als Antwort markiert xpd1000 Freitag, 3. Januar 2014 21:29
    Freitag, 3. Januar 2014 21:05
    Moderator
  • Ja das mit der .exe hatte ich jetzt auch raus und ein ganz anderes Problem.-)

    scheinbar ist hinter dem Kassenfenster welches ich sehe ein zweites Fenster dessen Grösse sich auch ändert also funktioniert der Quellcode super gut :-) 

    Vielen Dank bis hierher nun werde ich mal alleine weiter schauen wie ich das lösen kann zurnot muss ich Not werde ich das Programm dann doch einfach in ein Form einbetten was ich eigentlich nicht will. Oder per SendMouse (gibt es sicherlich) die Fenster Größe bestimmen. Naja Vielen lieben Dank


    Freitag, 3. Januar 2014 21:23