Oberflächen-Bedienung eines anderen Programmes unterbinden



  • Ich entwickle ein Programm, das eine andere Windows-Applikation überwacht. Dabei wird diese Applikation von meinem Programm aus gestartet. Mein Programm bleibt im Hintergrund unsichtbar und meldet sich nur, wenn die überwachte Applikation bestimmte Dateien oder Registry-Einträge erstellt.

    Nun möchte ich erreichen, dass wenn mein Programm z.B. eine Meldung anzeigt, die überwachte Applikation nicht mehr per Oberfläche bedient werden kann, also z.B. keine Dialoge mehr weggeklickt werden können, bis ich von meinem Programm aus das wieder freigebe. Ich möchte also auf eine Art dasselbe erreichen, wie man mit ShowModal im eigenen Projekt erreicht - nur auf eine andere Applikation bezogen. Hoffentlich versteht Ihr was ich meine, sonst erklär ich noch nes bissel mehr...

    Kann mir jemand sagen, wie ich das erreichen könnte?
    - Adrian



  • Hab es nicht probiert aber es gibt zwei Möglichkeiten:
    1. Du zeigst einen Dialog an und übergibst als Parent das Window-Handle des anderen Programmes (wird aber vermutlich nicht gehen)
    2. Du injizierst einen RemoteThread und zeigst dann den Dialog mit dem passenden Parent-Handle an



  • Vielen Dank für die Idee! Bei meinen weiteren Recherchen bin ich jetzt aber gerade auf die ultimative API gestossen: EnableWindow(HWND hwnd, bool enabled);
    Mit dieser kann man genau das machen, was ich will.

    Jetzt muss ich einfach noch die API finden, um von einem Process-Handle das Window-Handle zu erhalten.
    - Adrian



  • Hier übrigens noch eine fertige Lösung:

    EnableAllWindowsOfProcess(AnsiString procExeName, DWORD procID, bool state)
    

    Wenn man die Process ID weiss, kann man direkt die Process ID übergeben. Andernfalls den Namen des Prozesses (z.B. Project1.exe / explorer.exe)

    Dazu der Source:

    int EnableAllWindowsOfProcess(AnsiString procExeName, DWORD procID, bool state)
    {
        vector<HWND>    hwnds;
        char            buf[255];
    
        if (procID == 0) procID = GetProcessIdByName (procExeName);
        hwnds = GetHwndOfProcessID (procID);
    
        for (unsigned int i = 0; i < hwnds.size(); ++i)
        {
            EnableWindow (hwnds[i], state);
        }
    
        return hwnds.size();
    }
    
    DWORD GetProcessIdByName (AnsiString ExeFileName)
    {
        bool            ContinueLoop;
        HANDLE          FSnapshotHandle;
        PROCESSENTRY32  FProcessEntry32;
        DWORD           ret                 = 0;
    
        FSnapshotHandle = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
        FProcessEntry32.dwSize = sizeof(FProcessEntry32);
        ContinueLoop = Process32First(FSnapshotHandle, &FProcessEntry32);
    
        do
        {
            if ( (ExtractFileName(FProcessEntry32.szExeFile).UpperCase() == ExeFileName.UpperCase() )  ||
                 (UpperCase (FProcessEntry32.szExeFile) == ExeFileName.UpperCase()) )
            {
                     ret = FProcessEntry32.th32ProcessID;
            }
    
            ContinueLoop = Process32Next(FSnapshotHandle, &FProcessEntry32);
        } while (ContinueLoop);
    
      CloseHandle(FSnapshotHandle);
    
      return ret;
    }
    
    BOOL CALLBACK enumWindowsProc(HWND hwnd, LPARAM lParam)
    {
        ((vector<HWND> *)lParam)->push_back (hwnd);
    }
    
    vector<HWND> GetHwndOfProcessID (int processID)
    {
        HWND            hwnd    = 0;
        DWORD           procID;
        vector<HWND>    hwnds;
        vector<HWND>    appHwnds;
    
        EnumWindows ((WNDENUMPROC)enumWindowsProc, (long)&hwnds);
    
        for (unsigned int i = 0; i < hwnds.size(); ++i)
        {
            GetWindowThreadProcessId (hwnds[i], &procID);
            if (procID == processID)
                appHwnds.push_back(hwnds[i]);
        }
    
        return appHwnds;
    }
    

    Das ganze ist mit BCB kompilierbar und funktioniert 🕶
    - Adrian


Anmelden zum Antworten