none
API MoveWindow funktioniert nicht RRS feed

  • Frage

  • Guten Abend,

    wenn es nach drei Tagen immer noch keine Lösung für mich gibt, komme ich wieder mal nicht umhin, in eurem Forum um Hilfe zu bitten.

    Wegen Umstellung auf WIN 10 muss ich unseren DiktatePlayer neu programmieren. Ich habe eine Exe kompiliert. Verwende das Control WindowsMediaPlayer. Hab es auf ein Form gepappt. Zeige es sehr klein unten rechts auf dem Desktop an. Das Soundfile übergebe ich der Anwendung beim Starten als Parameter. Habe bewusst keine Einzelinstanzanwendung erstellt, damit ich mehrere Player gleichzeitig darstellen kann.

    Damit sich die einzelnen Player nicht überlappen, sollen sie sich immer oberhalb des zuletzt geöffneten Fensters anordnen. War beim alten Programm ein unschlagbarer Vorteil, weill die Mitarbeiterin problemlos zwischen den Diktaten wechseln konnte. Will jetzt gegenüber früher auf die API zugreifen. Die einzelnen Prozesse heissen ja alle gleich, so dass ich sie leicht aus GetProcesses herausfiltern kann. Aus der Anzahl sollte ich die Lokalisation ableiten können. Aber das MoveWindow stellt sich stur. Im Netz gibt es viele ganz unterschiedliche Beispiele dafür, hab aber keins zum Laufen gebracht. Eine Exception wird nicht geworfen, nur das Fenster bleibt immer in der oberen linken Ecke (Pos 0,0). Hab befürchtet, dass ein inaktives oder überdecktes Fenster nicht bewegt werden kann. Deshalb hab ich SetForegroundWindow und ShowWindow eingebaut. Aber das hat mir nichts gebracht. Weiss jemand Rat?

    Viele Grüße Norbert

        <DllImport("user32.dll")>
        Public Shared Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean
        End Function
    
        <DllImport("user32.dll")>
        Public Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Int32
        End Function
    
        <DllImport("user32.dll")>
        Public Shared Function MoveWindow(ByVal hWnd As IntPtr, 
                                          ByVal x As Integer, 
                                          ByVal y As Integer, 
                                          ByVal nWidth As Integer, 
                                          ByVal nHeight As Integer, 
                                          ByVal bRepaint As Boolean) As Boolean
    
    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
            soundFile = My.Application.CommandLineArgs(0)        	
            Player.URL = soundFile
    
            'Fenster Koordinaten setzen
          	Dim hWnd As IntPtr
          	Dim z As Integer = 10
            For Each p As Process In Process.GetProcesses
                	z += 1
                	If SetForegroundWindow(p.MainWindowHandle) Then
                   		ShowWindow(p.MainWindowHandle, 9)
               	End If
    	        hWnd = p.Handle
                    MoveWindow(hWnd, 200, z * 100, 50, 50, True)
    

    Donnerstag, 28. November 2019 17:40

Antworten

  • Hallo Norbert,

    versuch es mal so:

        Declare Function SetWindowPos Lib "user32.dll" (ByVal hwnd As IntPtr, 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
    
        Const SWP_NOSIZE As Int32 = &H1
        Const HWND_TOPMOST As Int32 = -1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim p() As Process = Process.GetProcessesByName("Notepad")
            If p.Length > 0 Then
                SetWindowPos(p(0).MainWindowHandle, HWND_TOPMOST, 10, -10, 0, 0, SWP_NOSIZE)
            End If
    
        End Sub

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Sonntag, 1. Dezember 2019 10:18
  • Danke! Habe gerade eben den Fehler gefunden. MainWindowHandle war immer Zero. Als ich danach gegoogelt habe kam die Erlösung:

    A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden, that is, processes that are not visible in the taskbar. This can be the case for processes that appear as icons in the notification area, at the far right of the taskbar.

    Also ShownInTaskbar der Fenster auf True gesetzt und Voila - alle API Funktionen (MoveWindow, SetWindowPos) funktionieren problemlos.

    Schönen Sonntag noch

    Norbert

    Sonntag, 1. Dezember 2019 12:23

Alle Antworten

  • Hab noch etwas gefunden - funktioniert aber auch nicht. Das Fenster wird nicht an die Pos 200,100 gesetzt

        Const SWP_NOSIZE As UInteger = &H1
        Const SWP_NOZORDER As UInteger = &H4
    
        Declare Function SetWindowPos Lib "user32.dll" (ByVal hwnd As IntPtr, 
    ByVal hWndInsertAfter As IntPtr,  ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As UInteger) 
    As Boolean
    
        SetWindowPos(handl, IntPtr.Zero, 200, 100, 0, 0, SWP_NOSIZE Or SWP_NOZORDER)
    

    Donnerstag, 28. November 2019 18:59
  • So gehts auch nicht

    <DllImport("user32.dll", SetLastError:=True)> Public Shared Function SetWindowPos(ByVal hwnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal wFlags As UInteger) As Boolean

    End Function


    Donnerstag, 28. November 2019 19:08
  • Hallo Norbert,

    wenn ich dich richtig verstehe, geht es lediglich darum, das Fenster beim Start an die richtige Stelle zu platzieren?

    Wenn du die Anzahl deiner Fenster (Prozesse) ermitteln kannst und somit die absolute Position errechnen kannst, kannst du doch einfach mit:

    Location = New Point(700, 80)
    im Form-Load Ereignis das Fenster positionieren.

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Donnerstag, 28. November 2019 23:12
  • Danke Stefan! Tja, wenn man um drei Ecken denkt, übersieht man das Naheliegendste. Klar hab ich ja in der kompilierten Exe noch mich selbst (Me, This) und kann mich über Me.Location selbst positionieren. Hab ich völlig übersehen. Hab nur an API gedacht. Aber warum SetWindowPos und MoveWindow nicht funktionieren hätte ich gern gewusst. Bestimmt brauche ich das später doch einmal ...

    Viele Grüße Norbert

    Freitag, 29. November 2019 09:02
  • Das Fenster beim Start zu positionieren war leider nur die halbe Miete. Beim Fertigstellen des Projekts ist mir wieder eingefallen, warum ich die API brauche. Zum Beispiel liegen am rechten Bildschirmrand nun 5 Diktate (5 Fenster) mit einem Versatz vertikal von 65 Pixel. Wenn ein Diktat abgearbeitet ist, kann man das Fenster schliessen. Angenommen man schliesst das 3. Fenster. Dann müssen die darüberliegenden 2 Fenster nach unten nachrutschen. Den Handler dazu wollte ich ins Closed schreiben. Also hier die Handles der Fenster holen und diese neu positionieren. Dazu müsste ich es aber erst einmal hinbekommen, das MoveWindow über die API zu realisieren. Daran verzweifele ich fast. Hat jemand einen funktionierenden Code dafür?

    Freitag, 29. November 2019 15:20
  • Nun habe ich folgendes getestet:

        Public Declare Auto Function MoveWindow Lib "user32.dll" (
                                                                 ByVal hWnd As IntPtr,
                                                                 ByVal X As Int32,
                                                                 ByVal Y As Int32,
                                                                 ByVal nWidth As Int32,
                                                                 ByVal nHeight As Int32,
                                                                 ByVal bRepaint As Boolean) As Boolean
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim p() As Process = Process.GetProcessesByName("DiktatePlayer")
            Dim hWnd As IntPtr = p(0).Handle
            MoveWindow(hWnd, 500, 200, 500, 100, True)
        End Sub
    
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            MoveWindow(Me.Handle, 500, 200, 500, 100, True)
        End Sub

    Das eigene Fenster lässt sich mit Button2 problemlos überallhin verschieben. Das Diktat-Fenster bleibt jedoch mit Button1 stur auf seiner alten Position. Wo ist das Problem???

    Samstag, 30. November 2019 09:49
  • Hallo Norbert,

    versuch es mal so:

        Declare Function SetWindowPos Lib "user32.dll" (ByVal hwnd As IntPtr, 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
    
        Const SWP_NOSIZE As Int32 = &H1
        Const HWND_TOPMOST As Int32 = -1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim p() As Process = Process.GetProcessesByName("Notepad")
            If p.Length > 0 Then
                SetWindowPos(p(0).MainWindowHandle, HWND_TOPMOST, 10, -10, 0, 0, SWP_NOSIZE)
            End If
    
        End Sub

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Sonntag, 1. Dezember 2019 10:18
  • Danke! Habe gerade eben den Fehler gefunden. MainWindowHandle war immer Zero. Als ich danach gegoogelt habe kam die Erlösung:

    A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window, the MainWindowHandle value is zero. The value is also zero for processes that have been hidden, that is, processes that are not visible in the taskbar. This can be the case for processes that appear as icons in the notification area, at the far right of the taskbar.

    Also ShownInTaskbar der Fenster auf True gesetzt und Voila - alle API Funktionen (MoveWindow, SetWindowPos) funktionieren problemlos.

    Schönen Sonntag noch

    Norbert

    Sonntag, 1. Dezember 2019 12:23