Announcement

Collapse
No announcement yet.

Fenster / Prozess in den Vordergrund holen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Fenster / Prozess in den Vordergrund holen

    Ich habe ein Java-Programm, was einen versteckten Word-Prozess startet (dieses ist nicht veränderbar). Ein darin von mir gestricktes VBA-Makro bringt nun eine Abfrageformular auf den Schirm. Das Fenster selbst und der Eintrag in der Taskleiste werden aber leider nicht angezeigt. Das Fenster kann aber per ALT-Tab bzw. Taskmanager erreicht werden und arbeitet dann auch normal weiter und hat den Focus.

    Ich habe schon probiert:
    • SetFocus
    • SetForegroundWindow
    • BringWindowToTop
    • ShowWindow
    • ShowWindowAsync
    • SwitchToThisWindow
    • SetWindowPlacement
    • AttachThreadInput (zum Wechseln des Focuses zum eigenen Thread, um dann das Fenster nach vorn zu bringen)


    Nichts klappt. Hat noch jemand eine Idee, wie man das Fenster sichtbar bekommt und den Focus verpasst. Ich mutmaße mal, dass man irgendwie das Fenster erst sichtbar schalten muss...

  • #2
    Was hat die Frage mit NET zu tun? -> verschoben.
    Zuletzt editiert von Christian Marquardt; 27.02.2014, 08:45.
    Christian

    Comment


    • #3
      Zeig doch mal ein wenig Code. Insbesondere denn wie du an das Handle des Fenster kommst das du ja eigentlich für alle von dir angesprochenen API Methoden brauchst.

      Comment


      • #4
        Das Fenster-Handle zu bekommen ist relativ simple. Normalerweise nehme ich die WindowFromAccessibleObject, da ich so sehr einfach ein eindeutiges Ergebnis bekommt. Die FindWindowEx ist hier nur zum Vergleichstest, da sie eben im Allgemeinen fensternamenabhängig und somit erst mal nicht eindeutig ist.
        Code:
        Private Declare Function WindowFromAccessibleObject Lib "oleacc.dll" ( _
            ByVal IAcessible As Object, _ 
            ByRef hWnd As Long) As Long
        
        Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
           (ByVal hWndParent As Long, _
            ByVal hWndChildAfter As Long, _
            ByVal lpszClass As String, _
            ByVal lpszWindow As String) As Long
        
        Private Sub UserForm_Initialize()
            'zum Testen
            Dim hWnd As Long, hWnd2 As Long
            
            WindowFromAccessibleObject Me, hWnd
            hWnd2 = FindWindowEx(0&, 0&, vbNullString, Caption)
            
            MsgBox hWnd & vbNewLine & hWnd2
        End Sub
        Die Handle sind identisch und ungleich 0 und funktioniert anderswo auch richtig (z. B. SetFocus bei nicht-modalen Fenstern).

        Dann habe ich es eben probiert:
        Code:
        SetForegroundWindow hWnd
        nach http://support.microsoft.com/kb/186431:
        Code:
        BringWindowToTop hWnd
        nach 'http://stackoverflow.com/questions/6228089/how-do-i-bring-an-unmanaged-application-window-to-front-and-make-it-the-active:
        Code:
        ShowWindowAsync hWnd, SW_RESTORE
        SetForegroundWindow hWnd
        wobei SetForegroundWindow hier eigentlich für das Hauptfenster des Prozesses (objProcesses[0].MainWindowHandle) aufgerufen wird, an das ich aber nicht so schnell mal ohne weiteres rankomme, und
        Code:
        ShowWindowAsync(hWnd, SW_SHOWDEFAULT);
        ShowWindowAsync(hWnd, SW_SHOW);
        SetForegroundWindow(hWnd);
        nach u.a. http://www.c-plusplus.de/forum/231249-full:
        Code:
        If hwnd <> GetForegroundWindow Then
            Dim idThreadForeground As Long
            Dim idThreadMe As Long
        
            idThreadForeground = GetWindowThreadProcessId(GetForegroundWindow, Null)
            idThreadMe = GetWindowThreadProcessId(hwnd, Null)
        
            If idThreadForeground <> idThreadMe Then
                AttachThreadInput idThreadForeground, idThreadMe, True
                SetForegroundWindow hwnd
                AttachThreadInput idThreadForeground, idThreadMe, False
            Else
                SetForegroundWindow hwnd
            End If
        End If
        nach https://groups.google.com/forum/#!to...vc/_qDZf3qdVaY
        Code:
        SwitchToThisWindow hWnd, TRUE
        Das Verhalten bleibt überall gleich. Ein Blinken in der Taskleiste gibt es natürlich auch nicht, da der Prozess / das Fenster dort gar nicht angezeigt wird.

        Ich habe die Aufrufe auch im UserForm_Activate() probiert, da dort das Fenster bereits angezeigt wird. Auch hier kommt gleichartig das Fenster nicht direkt, sondern nur über den Taskwechsel zum Vorschein.

        Comment


        • #5
          [gelöst] Fenster / Prozess in den Vordergrund holen

          Der Weg über AttachThreadInput war schon der richtige. Es hatte sich einerseits noch ein Fehler eingeschlichen (der zweite Parameter von GetWindowThreadProcessId darf nicht NULL sondern muss 0 sein), andererseits blieb das Fenster weiterhin hinter dem Fenster des aufrufenden Prozesses.

          SetForegroundWindow geht eben nur, wenn der Prozess auch im Vordergrund ist (ist mitlerweile konsequent so gewollt, so dass eigentlich kein Programm sich mehr in den Vordergrund drängeln kann). Ein SetForegroundProcess existiert aber nicht. Daher muss man den Input entsprechend holen und mit diesem Trick das Vordergrund-Fenster und damit den Vordergrund-Prozess übenehmen. Neben dem Setzen des Vordergrund-Fensters muss dieses dann zusätzlich auch noch wirklich in den Vordergrund gebracht werden, sonst bleibt es einfach hinten liegen.
          Code:
          Private Declare Function WindowFromAccessibleObject Lib "oleacc.dll" ( _
              ByVal IAcessible As Object, ByRef hWnd As Long) As Long
          
          Private Declare Function GetForegroundWindow Lib "user32.dll" ( _
              ) As Long
          
          Private Declare Function AttachThreadInput Lib "User32" ( _
              ByVal idAttach As Integer, _
              ByVal idAttachTo As Integer, _
              ByVal fAttach As Integer) As Integer
               
          Private Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
              ByVal hWnd As Long, _
              lpdwProcessId As Long) As Long
            
          Private Declare Function SetForegroundWindow Lib "user32.dll" ( _
              ByVal hWnd As Long) As Long
              
          Private Declare Function BringWindowToTop Lib "User32" ( _
              ByVal hWnd As Long) As Long
                   
          
          
          Private Sub UserForm_Initialize()
              Dim hWnd As Long
              
              WindowFromAccessibleObject Me, hWnd
             
              If hWnd <> GetForegroundWindow Then
                  Dim idThreadForeground As Long
                  Dim idThreadMe As Long
          
                  idThreadForeground = GetWindowThreadProcessId(GetForegroundWindow, 0)
                  idThreadMe = GetWindowThreadProcessId(hWnd, 0)
          
                  If idThreadForeground <> idThreadMe Then
                      AttachThreadInput idThreadForeground, idThreadMe, True
                      SetForegroundWindow hWnd
                      BringWindowToTop hWnd
                      AttachThreadInput idThreadForeground, idThreadMe, False
                  Else
                      SetForegroundWindow hWnd
                      BringWindowToTop hWnd
                  End If
              End If
          End Sub

          Comment

          Working...
          X