Andere Anwendung in den Vordergrund bringen u. neu positionieren



  • Hallo zusammen.

    Man soll ja dem Anwender alle möglichen u. unmöglichen Unklarheiten ersparen!
    Somit habe ich nun eine neue Aufgabe bekommen.

    Meine Anwendung darf kein zweites Mal im Rechner laufen.
    Das ist ja OK.
    Nun soll aber die erneut gestartete Anwendung die alte wieder in den Vordergrund bringen.
    Am Besten soll dabei auch noch deren Fenster neu positioniert werden.

    Grund für den Vorschlag ist gelegentliches seltsames Verhalten:
    Es kam vor, dass die alte, noch laufende Anwendung sich nicht mehr zu ihrer
    gewohnten Gestalt auf den Desktop bringen lies.
    Stattdessen hat sie sich (als Foreground-Window) zu einem sehr langen, horizontalen Strich am unteren Bildschirmrand mutiert.
    Ich hab auch keine Ahnung, wie das passieren kann. Aber das gab es halt.
    Das soll eben vermieden werden.

    Ich habe das mit diversen Functions versucht:
    Hier mal der Code-Ausschnitt
    do {
    if(sProcess.th32ProcessID==dwId)
    continue; // ignore the own process
    if(wcsncmp(pName,sProcess.szExeFile,2048))
    continue; // on not equal compare next process

        // process names are equal now!
        iRet=1;
        // Die schon bestehende Applikation wieder in den Fordergrund bringen, am besten Fenster neu positionieren.
        EnumWindows(EnumWindowsProcMy,sProcess.th32ProcessID);          
        SendMessage(g_HWND, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window
        SetForegroundWindow(g_HWND); 
        SetActiveWindow(g_HWND); 
        SetWindowPos(g_HWND, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); 
        RedrawWindow(g_HWND,0,0,RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );  // redraw to prevent the window blank.
    
        break; 
    
    } while(Process32Next(hSnapshot,&sProcess)); 
    

    Aber warum klappt das nicht?
    Vielen Dank schon mal.

    Grüsse
    Helmut



  • Eine Auswertung der Rückgabewerte der einzelnen Funktionen wäre schon mal ganz gut.
    Und wo kommt g_HWND her?



  • Der Hande g_HWND sollte eigentlich korrekt ermittelt sein.
    Er wird in einer Callback Fktn. ermittelt.
    Aber hier dann der vollständige Code:

    // Globaler Window Handle u. Callback
    HWND g_HWND=NULL;
    BOOL CALLBACK EnumWindowsProcMy(HWND hwnd,LPARAM lParam)
    {
        DWORD lpdwProcessId;
        GetWindowThreadProcessId(hwnd,&lpdwProcessId);
        if(lpdwProcessId==lParam)
        {
            g_HWND=hwnd;
            return FALSE;
        }
        return TRUE;
    }
    
    int CTitanCeApp::ProcessRunningOwn() 
    { 
        DWORD           dwId; 
        HANDLE          hSnapshot; 
        PROCESSENTRY32  sProcess; 
        WCHAR           cwBuffer[2048] = { 0 };
        LPWSTR          pszBuffer      = cwBuffer;
        LPWSTR          pName; 
        int             iLen,iRet=0; 
      
      
        iLen = GetModuleFileName(NULL,pszBuffer,sizeof(cwBuffer)); 
        dwId = GetCurrentProcessId(); 
      
        for(;iLen>0;iLen--) { 
            if(cwBuffer[iLen-1]=='\\')break; 
            if(cwBuffer[iLen-1]=='/' )break; 
        } 
      
        pName           = pszBuffer+iLen; 
        hSnapshot       = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 
        sProcess.dwSize = sizeof(sProcess); 
      
      
        if(!hSnapshot) { 
            return 0; 
        } 
      
        if(!Process32First(hSnapshot,&sProcess)) { 
            CloseHandle(hSnapshot); 
            return 0; 
        } 
      
        do { 
            if(sProcess.th32ProcessID==dwId) 
                continue; // ignore the own process 
            if(wcsncmp(pName,sProcess.szExeFile,2048))  
                continue;  // on not equal compare next process
               
            // process names are equal now!
            iRet=1;
            // Die schon bestehende Applikation wieder in den Fordergrund bringen, am besten Fenster neu positionieren.
            EnumWindows(EnumWindowsProcMy,sProcess.th32ProcessID);  
            SendMessage(g_HWND, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window
            SetForegroundWindow(g_HWND); 
            SetActiveWindow(g_HWND); 
            SetWindowPos(g_HWND, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); 
            RedrawWindow(g_HWND,0,0,RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );  // redraw to prevent the window blank.
           
            break; 
    
        } while(Process32Next(hSnapshot,&sProcess)); 
      
        CloseHandle(hSnapshot); 
        return iRet; 
    }
    

    Leider klappt das in diesem Forum nicht mehr mit der Quelltext-Markierung!



  • @elmut19 sagte in Andere Anwendung in den Vordergrund bringen u. neu positionieren:

    Leider klappt das in diesem Forum nicht mehr mit der Quelltext-Markierung!

    Tut es sehr wohl. Markiere Deinen Code und klicke auf </> über dem Textfeld.
    Alternativ schreibe ``` über und ``` unter deinen Code.



  • @swordfish sagte in Andere Anwendung in den Vordergrund bringen u. neu positionieren:

    @elmut19 sagte in Andere Anwendung in den Vordergrund bringen u. neu positionieren:

    Leider klappt das in diesem Forum nicht mehr mit der Quelltext-Markierung!

    Tut es sehr wohl. Markiere Deinen Code und klicke auf </> über dem Textfeld.
    Alternativ schreibe ``` über und ``` unter deinen Code.

    Danke für den Hinweis swordfish.


  • |  Mod

    Und warum machst Du es Dir so schwer? Warum der Quatsch mit dem Loop über alle Prozesse?

    Erzeuge einen Mutex mit einem Namen und prüfe den.
    Wenn der schon belegt ist, läuft Deine Anwendung.
    Dann suchst Du das Fenster mit der entsprechenden Fensterklasse (den Namen kannst Du ja selbst bestimmen) und lädst das Last active popup und machst es aktiv.

    	hWnd = ::GetLastActivePopup(hWnd);
    	// Bring the main window to the top
    	if (::IsIconic(hWnd))                 
    		// If iconic, restore the main window
    		::ShowWindow(hWnd,SW_RESTORE);     
    	// bring it to top       		
    	::SetForegroundWindow(hWnd);
    

    Das funktioniert bei mir perfekt.

    Lass den Unfug mit SetWindowPos. Auch das RedrawWindow etc. ist alles unnötig. Warum denkst Du musst Du das machen? Deine Anwendung bekommt doch entsprechende WM_PAINT Nachrichten von Windows...



  • @martin-richter
    Hallo Martin,

    das mit der Schleife über die Prozesse mag Quatsch sein. Sehe ich ein. Danke für die Lösung!

    Aber ich kann doch gar nicht sagen, dass das zuletzt aktive Fenster auch das der schon laufenden Anwendung ist, die ich suche.

    Und ich habe Deinen Quellcode dann auch eingesetzt.
    Aber leider poppt das gewünschte Fenster nicht hoch.
    Auch denke ich, dass es zuvor dann auch schon hätte hoch poppen müssen?

    Ich dachte eigentlich, dass dieses "SetForegroundWindow(..)" vielleicht nur den eigenen Prozessraum behandeln kann, oder?

    Grüsse
    Helmut



  • @elmut19
    Hast du denn auch befolgt, was über dem Code steht? Also mit CreateMutex einen Mutex erstellt und GetLastError auf ERROR_ALREADY_EXISTS überprüft? Mit WM_COPYDATA können dann auch die Argumente an die alte Anwendung übergeben werden.
    Und am Rande (da ich in Erinnerung habe, dass du schon mal mit Pufferüberläufen Probleme hattest): WinAPI-Stringfunktionen nehmen als „Größe” normalerweise die Länge in TCHARs (also deren Anzahl) und nicht die Größe des Arrays entgegen - auch GetModuleFileName.



  • @yahendrik sagte in Andere Anwendung in den Vordergrund bringen u. neu positionieren:

    CreateMutex

    Leider habe ich noch nie was mit einem MUTEX Objekt gemacht.
    Und nach erstem Lesen wird das auch recht kompliziert.
    Da ist nix mit "WM_COPYDATA" zu finden, oder wie man andere, als die Standard Parameter anwendet.

    Und trotz umständlicher Programmierung hätte ja auch alles funktioniert.
    Nur gab es ein paar Mal die Situation, dass die andere Anwendung sich hinter einem undefinierbaren Fenster (Grösse u Position) versteckte,
    in dem man sie nicht mehr finden konnte.

    Sonst hätte es ja auch gereicht, einfach nur zu melden "Läuft schon".

    Aber nun soll die schon laufende Anwendung auch noch automatisch hochgepoppt werden
    und am Besten zusätzlich deren Fensterposition und die Fenstergrösse neu gesetzt werden.


  • |  Mod

    Hier gibt es eine komplete Diskussion um das Thema. Inkl. fertiger Lösung:

    http://www.flounder.com/nomultiples.htm



  • @martin-richter
    Danke Martin, für den Hinweis auf diesen Artikel.

    Inzwischen habe ich etwas damit experimentiert.
    Leider produziert die Variante daraus Folgefehler, schon beim Comiplieren:
    Wenn ich die Window-Message wie folgt definiere:

    #define UWM_ARE_YOU_ME (WM_APP + 3)

    dann bekomme ich für den MESAGE_MAP Eintrag:

    ON_REGISTERED_MESSAGE(UWM_ARE_YOU_ME, OnAreYouMe)
    

    die Fehlermeldung

    1>..\WinKlassen\MainFrm.cpp(78) : error C2101: '&' on constant

    Und der gewünschte Effekt (ohne den MESASAGE_MAP Eintrag), dass das bestehende Fenster hochgepoppt wird, bleibt natürlich aus.





  • Der Beitrag von "flounder" und "Using Registered Messages" scheinen sich zu widersprechen.

    Das von flounder habe ich auch so in codeproject gefunden.
    Das widerspricht sich für mich auch.
    Leider werden da verschiedene Message-Arten durcheinander gewürfelt, sodass man kein konsistentes Beispiel hat.

    Mal wird eine Message einfach definiert, als WIN_APP+n, ein anderes Mal muss sie registriert werden. dan nist sie ein String, ...
    Und dann verstehe ich einfach nix mehr.

    Es sind da min. 5 Methoden durcheinander und kein funktionierendes Beispiel.

    Ich fürchte, so brauche ich noch ein paar Wochen, um das zu verstehen.


  • |  Mod

    Wenn Du ON_REGISTERED_MESSAGE benutzt dann musst Du auch eine Nachricht regsitrieren und den UINT als Referenz übergeben.
    Wenn Du WM_APP+x verwendest musst die ON_MESSAGE benutzen.

    Vergiss dieses ganze Heckmeck um registrierte Nachrichten und WM_APP Nachrichten.
    Solange Du weißt was Du tust! 😇



  • @martin-richter sagte in Andere Anwendung in den Vordergrund bringen u. neu positionieren:

    Wenn Du ON_REGISTERED_MESSAGE benutzt dann musst Du auch eine Nachricht regsitrieren und den UINT als Referenz übergeben.
    Wenn Du WM_APP+x verwendest musst die ON_MESSAGE benutzen.

    Vergiss dieses ganze Heckmeck um registrierte Nachrichten und WM_APP Nachrichten.
    Solange Du weißt was Du tust! 😇

    Tja, das weiss ich eben nicht!
    Aber hoffentlich bald



  • Vielen Dank Martin,

    jetzt hats geklappt!
    Und zwar mit der nicht registrierten Message.
    Die bestehende Anwendung wird nun auch, wie gewünscht in den Vordergrund gebracht.

    Da weiss ich nun etwas mehr, als vorher.

    Grüsse
    Helmut