WinAPI - ShowWindow, kleines Problemchen...

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Killerjo96.

    WinAPI - ShowWindow, kleines Problemchen...

    Hallöschen,

    bin mich momentan bisschen an die Windows API am rantasten. Momentan bin ich an der ShowWindow Funktion dran.
    Eigentlich funktioniert alles, bis auf eins xD.

    Also ich verwalte 7 Server Files eines Spiels mit meinem Programm.
    Da 7 Programme in der Taskbar manchmal ganz schön nerven können, lasse ich sie mit der WinAPI ShowWindow Funktion aus der TaskBar ausblenden.

    Zitat von Microsoft Dot Net:
    SW_HIDE
    0



    Hides the window and activates another window.

    So das klappt auch wunderbar, aber jetzt möchte ich dem Benutzer es auch ermöglichen das diese in der TaskBar wieder angezeigt werden, und wie sich jetz vllt. jeder denken kann ist genau dies mein Problem.
    Es klappt einfach nicht, es ist egal welchen Parameter ich nehme, die Programme bleiben in der Taskleiste unsichtbar. Weiß jemand wie ich die wieder, minimiert in der Taskleiste anzeigen lassen kann?

    Hoffe ihr wisst was ich meine

    Danke im Voraus. 8o
    .NET-Fenster haben die Property ShowInTaskBar.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das ist mir klar. :D
    Du hast doch bei ShowWindow(HWND, SW_HIDE); ein Fensterhandle.
    Genau dieses musst Du nehmen, wenn Du ShowWindow(HWND, SW_SHOW); aufrufst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hier ist die Enum aus dem Header
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Enum ShowWindowCommands
    2. SW_HIDE = 0
    3. SW_SHOWNORMAL = 1
    4. SW_NORMAL = 1
    5. SW_SHOWMINIMIZED = 2
    6. SW_SHOWMAXIMIZED = 3
    7. SW_MAXIMIZE = 3
    8. SW_SHOWNOACTIVATE = 4
    9. SW_SHOW = 5
    10. SW_MINIMIZE = 6
    11. SW_SHOWMINNOACTIVE = 7
    12. SW_SHOWNA = 8
    13. SW_RESTORE = 9
    14. SW_SHOWDEFAULT = 10
    15. SW_FORCEMINIMIZE = 11
    16. SW_MAX = 11
    17. End Enum


    Also nimm 0 für Hide und 5 für Show, aber am Besten kopier dir eben die Enum und gibst die als Parameter an

    VB.NET-Quellcode

    1. Declare Function ShowWindow Lib "User32" (ByVal hWnd As IntPtr, ByVal nCmdShow As ShowWindowCommands) As Boolean

    Das hilft ungemein ^^

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Gonger96“ ()

    Okey, passt auf.


    Ich habe mir ne methode geschrieben ManageWindow(ByVal PID As Integer, ByVal nCmdShow As ShowWindowCommands)

    in der Methode hab ich folgendes stehen:

    VB.NET-Quellcode

    1. Public Shared Sub ManageWindow(ByVal PID As Integer, Byval nCmdShow As ShowWindowCommands)
    2. For Each Proc As Process In Process.GetProcesses
    3. If Proc.ID = PID Then
    4. ShowWindow(Proc.MainWindowHandler, nCmdShow)
    5. End If
    6. Next
    7. End Sub


    So krieg ich das Handle, und mit dem das die Prozesse in der TaskBar unsichtbar werden funktioniert ja auch, nur das sie aus dem Unsichtbaren Status nicht mehr in den sichtbaren status zurückkehren. Das funktioniert nicht.
    Kann es sein, dass wenn du das Zeug wieder einblenden möchtest "MainWindowHandler" 0 ist?
    Wenn ja musst du halt die versteckten Fensterhandles zwischenspeichern.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Den ID kriege ich, weil ich den Prozess selber starte, ich habe mir eine Globale Variable angelegt: Public Shared WorldServer_PID As Integer

    und dieser Variable weise ich so ihre ID zu.

    VB.NET-Quellcode

    1. Private Shared Sub WorldServer()
    2. Dim ProcHandle As New Process
    3. ProcHandle.StartInfo.FileName = "C:\Users\Johannes\Documents\FlyFF\V15\Files\Resource\WorldServer.exe"
    4. ProcHandle.StartInfo.WorkingDirectory = "C:\Users\Johannes\Documents\FlyFF\V15\Files\Resource"
    5. ProcHandle.Start()
    6. WorldServer_PID = ProcHandle.Id
    7. Thread.Sleep(MSecs)
    8. Do Until ProcHandle.Responding
    9. Loop
    10. ManageWindow(WorldServer_PID, WINDOWSTATE.SW_HIDE)
    11. End Sub



    Somit starte ich den WOrldServer, und dieser wird, nachdem er alle Resourcen geladen hat Respondive und wird danach mit ManageWindow(WorldServer_PID, WINDOWSTATE.SW_HIDE) versteckt.
    Jetzt hab ich ja meine Variable WorldServer_PID und jetzt möchte ich aus einer anderen Klasse den WorldServer wieder sichtbar machen. Die Methode ManageWindow ist Shared also für andere Klassen benutzbar.

    Workspace ist die Klasse in der ManageWindow drin ist.

    VB.NET-Quellcode

    1. Workspace.ManageWindow(Workspace.WorldServer_PID, Workspace.WINDOWSTATE.SW_SHOWMINIMIZED) '


    aber das funktioniert nicht mehr, weder showminimized noch sonst irgendwelche von denen die´s gibt...
    So, hier nochmal ein einfaches Beispiel was bei mir nicht funktioniert:

    VB.NET-Quellcode

    1. Private Declare Auto Function ShowWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Int32
    2. Dim Handl As IntPtr
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Dim ProcHandle As New Process
    5. ProcHandle.StartInfo.FileName = "C:\Windows\System32\Notepad.exe"
    6. ProcHandle.Start()
    7. Handl = ProcHandle.MainWindowHandle
    8. End Sub
    9. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    10. For Each Proc As Process In Process.GetProcesses
    11. If Proc.MainWindowHandle = Handl Then
    12. ShowWindow(Proc.MainWindowHandle, WINDOWSTAT.SW_HIDE)
    13. End If
    14. Next
    15. End Sub
    16. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    17. For Each Proc As Process In Process.GetProcesses
    18. If Proc.MainWindowHandle = Handl Then
    19. ShowWindow(Proc.MainWindowHandle, WINDOWSTAT.SW_RESTORE)
    20. End If
    21. Next
    22. End Sub
    23. Public Enum WINDOWSTAT As Integer
    24. SW_HIDE = 0 ' Versteckt das Fenster
    25. SW_MAXIMIZE = 3 ' Maximiert das Fenster
    26. SW_MINIMIZE = 6 ' Minmiert das Fenster
    27. SW_NORMAL = 1 ' Aktiviert das Fenster
    28. SW_SHOW = 5 ' Zeigt das Fenster an, auch wenn es versteckt ist
    29. SW_RESTORE = 9 ' Stellt das Fenster wieder her
    30. SW_SHOWMAXIMIZED = 3 ' Zeigt das Fenster an und Maximiert es
    31. SW_SHOWMINIMIZED = 2 ' Zeigt das Fenster an und Minimiert es
    32. SW_SHOWMINNOACTIVE = 7 ' Minimiert das Fenster aber aktiviert es nicht
    33. SW_SHOWNA = 8 ' Zeigt das Fenster an aber aktiviert es nicht
    34. SW_SHOWNOACTIVATE = 4 ' Zeigt das Fenster an ohne es zu aktivieren
    35. SW_SHOWNORMAL = 1 ' Zeigt das Fenster und aktiviert dies
    36. End Enum


    Dabei soll Button 1 notepad starten,
    button 2, notepad verstecken und button 3 es wiederherstellen.

    die beiden letzteren funktionieren nicht, weder verstecken noch wiederherstellen, wo ist das problem?
    Button3-> Was machst du da für nen Blödsinn? Du hast das Handle doch schon, welchen Sinn hat es dann dieses noch in der Schleife zu suchen...
    einfach

    VB.NET-Quellcode

    1. ShowWindow(Handl, WINDOWSTAT.SW_SHOW)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:

    Du hast das Handle doch schon, welchen Sinn hat es dann dieses noch in der Schleife zu suchen...


    Funktionert trotzdem so nicht:

    VB.NET-Quellcode

    1. Private Declare Auto Function ShowWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal nCmdShow As Int32) As Int32
    2. Dim Handl As IntPtr
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Dim ProcHandle As New Process
    5. ProcHandle.StartInfo.FileName = "C:\Windows\System32\Notepad.exe"
    6. ProcHandle.Start()
    7. Handl = ProcHandle.MainWindowHandle
    8. End Sub
    9. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    10. ShowWindow(Handl, WINDOWSTAT.SW_HIDE)
    11. End Sub
    12. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    13. ShowWindow(Handl, WINDOWSTAT.SW_RESTORE)
    14. End Sub
    15. Public Enum WINDOWSTAT As Integer
    16. SW_HIDE = 0 ' Versteckt das Fenster
    17. SW_MAXIMIZE = 3 ' Maximiert das Fenster
    18. SW_MINIMIZE = 6 ' Minmiert das Fenster
    19. SW_NORMAL = 1 ' Aktiviert das Fenster
    20. SW_SHOW = 5 ' Zeigt das Fenster an, auch wenn es versteckt ist
    21. SW_RESTORE = 9 ' Stellt das Fenster wieder her
    22. SW_SHOWMAXIMIZED = 3 ' Zeigt das Fenster an und Maximiert es
    23. SW_SHOWMINIMIZED = 2 ' Zeigt das Fenster an und Minimiert es
    24. SW_SHOWMINNOACTIVE = 7 ' Minimiert das Fenster aber aktiviert es nicht
    25. SW_SHOWNA = 8 ' Zeigt das Fenster an aber aktiviert es nicht
    26. SW_SHOWNOACTIVATE = 4 ' Zeigt das Fenster an ohne es zu aktivieren
    27. SW_SHOWNORMAL = 1 ' Zeigt das Fenster und aktiviert dies
    28. End Enum


    Edit: Beim Button 2 wäre es ja dann genau so blöd deswegen hab ichs da auch rausgenommen aber dort funktionierts auch nciht...
    Edit²: Wenn ich nach dem Starten von notepad das handle in einer msgbox ausgeben lasse (MsgBox(Handle)), dann steht in der MsgBox 0 ist das richtig? Weil dann kanns ja nicht funktionieren wenn er ein falsches/kein handle übergibt -.-
    was hat denn das Handle für einen Wert? Die Frage ist, ob das Fenster zu dieser Zeit überhaupt schon existiert, vielleicht benötigst du ja nach dem Start des Processes ein WaitForInputIdle...

    Und Ob SW_RESTORE da das richtige ist weiß ich nicht, aber eins was ich weiß, ist dass SW_SHOW nach SW_HIDE funktioniert...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Killerjo96 schrieb:

    aber dort funktionierts auch nciht...
    Klar, denn Windows braucht seine Zeit, bis das Fenster stabil steht.

    VB.NET-Quellcode

    1. ProcHandle.Start()
    2. ProcHandle.WaitForInputIdle() ' dies hier
    3. Handl = ProcHandle.MainWindowHandle
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja ich hab schon probiert Thread.Sleep(5000) ich probier es nochmal mit nem WaitForInputIdle,

    aber das SW_HIDE funktionert ja schon nich, deswegen wirds wohl am Handle liegen.

    Edit: Das WaitForInputIdle hat jetzt funktioniert ich krieg jetzt das richtige Handle übergeben, vielen Dank ;)

    Edit²: Übrigends: Das SW_HIDE und SW_RESTORE Funktionert prima.