Menü lässt sich nicht über Metro (Windows 8 Kacheloberfläche) legen

  • Wie der Titel schon sagt, schaffe ich es nicht, ein (Kontext)-Menü in der Metro-Oberfläche anzeigen zu lassen.
    Mein Skript:

    Spoiler anzeigen
    [autoit]


    #include <Constants.au3>
    #include <GuiMenu.au3>
    #include <Misc.au3>
    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $hDLL = DllOpen("user32.dll")

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Contextmenu", 100, 100, 100, 100)
    $hMenu = GUICtrlCreateContextMenu()
    $hEntry1 = GUICtrlCreateMenuItem("Entry 1", $hMenu)
    GUICtrlCreateMenuItem("", $hMenu)
    $hAbout = GUICtrlCreateMenuItem("Über Win8 Contextmenu", $hMenu)
    $hExit = GUICtrlCreateMenuItem("Win8 Contextmenu beenden", $hMenu)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    WinSetOnTop($hGui, "", 1) ; Versuch, eigene GUI als Topmost zu markieren

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    If $msg == $hEntry1 Then
    MsgBox(0, "", "Entry 1")
    ElseIf $msg == $hAbout Then
    MsgBox(64, "Über Win8 Contextmenu", "Hier folgt der Text")
    ElseIf $msg == $hExit Then
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If _IsPressed(02, $hDLL) Then
    $activeWin = WinActive("") ; Handle des aktiven Fensters holen
    ConsoleWrite("Active win handle: " & $activeWin & @CRLF)
    $pos = MouseGetPos() ; Position für Kontextmenü herausfinden
    $winTitle = WinGetTitle($activeWin) ; liefert "Startmenü", wenn das aktive Fenster Metro war
    ConsoleWrite("Active win title: " & $winTitle & @CRLF)
    $winSize = WinGetPos($activeWin) ; Aus Spaß mal die Größe des Fensters abfragen
    ConsoleWrite("Active win geo: " & $winSize[0] & "," & $winSize[1] & "," & $winSize[2] & "," & $winSize[3] & @CRLF)
    $winState = WinGetState($activeWin) ; Fenster-Status - liefert 15 (1 + 2 + 4 + 8)
    ConsoleWrite("Active win state: " & $winState & @CRLF)
    ;~ $ret = WinMove($activeWin, "", 100, 100, 200, 200) ; funktioniert auch
    ;~ ConsoleWrite("Returned value (move): " & $ret & @CRLF)
    ;~ $ret = WinSetOnTop($activeWin, "", 0) ; liefert 1 (hat also angeblich funktioniert), trotzdem ist von meinem Fenster bzw. dem Kontextmenü nichts zu sehen
    ;~ ConsoleWrite("Returned value (setontop = 0): " & $ret & @CRLF)
    ;~ WinSetTrans($activeWin, "", 50) ; danach sind mein Fenster und das Menü (wird 3 Zeilen später erzeugt) im HINTERGRUND eindeutig erkennbar
    $ret = _WinAPI_SetWindowPos($activeWin, $HWND_BOTTOM, 0, 0, 1024, 768, $SWP_FRAMECHANGED) ; ändert weiterhin nichts an daran, dass mein Fenster im Hintergrund ist
    ConsoleWrite("Returned value (setwinpos): " & $ret & @CRLF)
    $ret = _GUICtrlMenu_TrackPopupMenu(GUICtrlGetHandle($hMenu), $hGui) ; hier wird das Kontextmenü erzeugt und ist nun auch im Hintergrund zu sehen
    ConsoleWrite("Returned value (cm): " & $ret & @CRLF)
    WinActivate($activeWin)
    ;~ $ret = WinMove($activeWin, "", 0, 0, 1024, 768) ; die WinMove-Spielerei rückgängig machen
    Sleep(5000)
    ;~ WinSetTrans($activeWin, "", 255) ; Transparenz wieder rückgängig machen
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    Sleep(10)
    WEnd

    [/autoit]


    Da das Kontextmenü dank Transparenz im Hintergrund zu sehen ist, liegt das Problem also darin, das Kontextmenü vor die Metro-Oberfläche zu bekommen!
    Hat irgendjemand eine Idee?

    • Offizieller Beitrag

    Hallo,

    Hundertprozentig auseinandergesetzt mit Metro und AutoIt habe ich mich noch nicht, ich weiß aber, dass das Metro (oder wie M$ das jetzt auch immer nennt ;) ) nicht kombinierbar ist mit normalen GUIs respektive der WinApi. Das wurde ja häufig kritisiert, dass M$ zwei Betriebssystem in eins gepackt hat. Die Metro ist nur für MUI Apps konzipiert.

    Schau mal hier rein: http://www.autoitscript.com/forum/topic/13…s-using-autoit/

    Gruß,
    Spider

  • Naja, so ganz stimmt das ja nicht.
    Meinen Tests nach handelt es sich bei Metro auch nur im Fenster. Dieses kann beispielsweise mit WinMove(), WinSetTrans(), etc. beliebig manipuliert werden.
    Das Problem ist lediglich, dass es auf irgendeine Art im Vodergrund gehalten wird.
    Bewegt und schrumpft man Metro mit

    [autoit]

    WinMove($handle, 100, 100, 100, 100)

    [/autoit]


    hat man halt ein 100x100 Pixel großes Quadrat Metro an der Stelle (100, 100). Auf dem Rest des Bildschirms ist dann der "normale" Desktop zu sehen.

    Es stellt sich jetzt halt nur die Frage, wie Microsoft bei Metro das "topmost" erzwingt und aufrechterhält und wie man das eventuell für sich nutzen kann. Ich müsste ja lediglich Metro ein paar Ebenen weiter nach unten schieben (bei der guten alten Z-Order) und schon wäre mein Problem gelöst. Aber scheinbar gilt die Z-Order für Metro nicht oder die machen da irgendwas anderes...

    Edit: Ich habe hier einen interessanten Artikel gefunden. In den Kommentaren darunter erklärt jemand die scheinbar notwendingen Schritte. Bei Gelegenheit werde ich mich mal daran versuchen (wobei ich auf die Schnelle nicht mal weiß, wie man Schritt 1 und 6/7 umsetzen soll/kann).

    Einmal editiert, zuletzt von _DICE_ (3. November 2012 um 16:34)

  • @ _DICE_
    Und wie bekommst Du das Handle der Metro UI raus?


    Edit:
    Es geht z.B. so:

    [autoit]

    Send("{LWIN}")
    Sleep(2000)
    $hMetro = WinGetHandle("")

    [/autoit]

    Einmal editiert, zuletzt von veronesi (2. Januar 2013 um 09:54)

  • Quasi wie Du selbst schon schriebst:

    Das erhalte ich über WinActive("").

    Das Programm, welches ich da testweise schrieb, startet und wartet ein paar Sekunden. In der Zeit wechsle ich manuell (bzw. über Send) zum Metro UI, sodass WinActive("") das Handle liefert.

    Ich habe auch schon probiert, Metro per Titel anzusprechen (den habe ich über WinGetTitle($handle) herausgefunden). Der Titel ist zwar immer der selbe, aber die ganzen kommenden Funktionen im Script haben dann nicht mehr funktioniert, sodass ich den Umweg über das Handle gehen muss!