Пользователь передает имя исполняемого приложения, которое он хочет выполнить. Для этого программа ищет вероятные процессы с именами исполняемых файлов, которые точно соответствуют вводу пользователя. Пользователь подтверждает выбранное приложение, когда его спрашивают, и программа объединяет эти окна (не уделяя им фокуса).
Проблема
Проблема этой программы в том, что она отображает и объединяет ВСЕ окна приложения, включая те, с которыми пользователь не должен взаимодействовать (иногда они скрыты при запуске приложения). Это вызывает проблемы с рабочим столом, и я не знаю, как отличить окна, обращенные к пользователю, от других окон. Существует ли набор флагов свойств, которые обычно используют обычные окна, и которые мне нужно проверить?
См. изображение ниже. Эти окна не являются интерактивными, как обычные окна, и обладают странными свойствами.
Прошу прощения за длину кода, но он скомпилируется в среде Windows.

// C++ standard library
#include
#include
#include
#include
#include
#include
#include
#include
// Windows API
#include
// Windows API helpers
#include
/**
* @brief Takes a snapshot of all processes in the system and returns a vector containing each process entry.
*
*/
static std::vector getAllProcesses( ) {
// Take the snapshot.
HANDLE snapshotHandle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); // @Todo Handle errors.
assert( snapshotHandle != INVALID_HANDLE_VALUE );
// Get all the processes in the snapshot.
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof( PROCESSENTRY32 ); // Must initialize this member before iterating.
bool noErrors = Process32First( snapshotHandle, &processEntry ); // @Todo Handle errors.
assert( noErrors ); // For now, assume this always succeeds the first time.
std::vector result;
result.push_back( processEntry ); // Append the first process entry.
// Query for the next process entry.
DWORD errorCode = ERROR_SUCCESS;
if ( !Process32Next( snapshotHandle, &processEntry ) ) {
errorCode = GetLastError( );
}
while ( errorCode != ERROR_NO_MORE_FILES ) {
result.push_back( processEntry );
errorCode = ERROR_SUCCESS;
if ( !Process32Next( snapshotHandle, &processEntry ) ) {
errorCode = GetLastError( );
}
}
CloseHandle( snapshotHandle );
return result;
}
/**
* @brief Returns the name of the executable file for a process.
*
*/
static std::wstring getProcessName( PROCESSENTRY32 const& p ) {
std::wstring result;
size_t const nameLength = wcslen( p.szExeFile );
for ( size_t i = 0; i < nameLength; ++i ) {
result.push_back( p.szExeFile );
}
return result;
}
/**
* @brief Returns the ID of the process that opened a given window.
*
*/
static DWORD getWindowProcessID( HWND windowHandle ) {
DWORD processID = 0;
DWORD threadID = GetWindowThreadProcessId( windowHandle, &processID );
if ( threadID == 0 ) {
std::abort( );
}
return processID;
}
/**
* @brief Determines whether a given window was opened by a given process.
*
* @return true if the process opened the window.
* @return false if the process did not open the window.
*/
static bool windowOpenedByProcess( HWND windowHandle, DWORD processID ) {
return getWindowProcessID( windowHandle ) == processID;
}
/**
* @brief Returns a vector containing the IDs of the given processes.
*
*/
static std::vector getProcessIDs( std::vector const& processes ) {
std::vector ids;
for ( const PROCESSENTRY32& i : processes ) {
ids.push_back( i.th32ProcessID );
}
return ids;
}
/**
* @brief Determines whether a given window was opened by any of the given processes.
*
* @return true if the window was opened by one of the processes.
* @return false if the window was not opened by any of the processes.
*/
static bool windowOpenedByProcessAnyOf( HWND windowHandle, std::vector const& processes ) {
std::vector processIDs = getProcessIDs( processes );
for ( const DWORD& i : processIDs ) {
if ( windowOpenedByProcess( windowHandle, i ) ) {
return true;
}
}
return false;
}
/**
* @brief Returns a string where all alphabetic characters in the given string have been demoted to lowercase.
*
*/
template Container toLower( Container const& c ) {
Container result;
for ( Element const& e : c ) {
if ( isalpha( e ) ) {
int const lowerAsInt = tolower( e );
// assert((lowerAsInt >= CHAR_MIN) && (lowerAsInt 0; --count ) {
std::wstring processName = toLower( getProcessName( processes.at( i ) ) );
size_t foundAt = processName.find( searching );
if ( foundAt != std::wstring::npos ) {
++i; // Found a loose match. Move on to the next one.
} else {
processes.erase( processes.begin( ) + i ); // No match. Remove this one.
}
}
}
/**
* @brief Takes a vector of processes and removes the ones whose executable name does not exactly match the filtering
* key.
*
*/
static void filterProcessesNotMatchingName( std::vector& processes, std::wstring const& searchFor ) {
size_t count = processes.size( );
for ( size_t i = 0; count > 0; --count ) {
if ( getProcessName( processes.at( i ) ) == searchFor ) {
++i;
} else {
processes.erase( processes.begin( ) + i );
}
}
}
/**
* @brief Returns a vector containing the executable names of all given processes.
*
*/
static std::vector getProcessNames( std::vector const& allProcesses ) {
std::vector result;
for ( PROCESSENTRY32 const& i : allProcesses ) {
result.push_back( getProcessName( i ) );
}
return result;
}
/**
* @brief Converts a narrow string to a wide string.
*
*/
static inline std::wstring narrowToWideString( std::string const& as ) {
// deal with trivial case of empty string
if ( as.empty( ) )
return std::wstring( );
// determine required length of new string
size_t reqLength = ::MultiByteToWideChar( CP_UTF8, 0, as.c_str( ), ( int )as.length( ), 0, 0 );
// construct new string of required length
std::wstring ret( reqLength, L'\0' );
// convert old string to new string
::MultiByteToWideChar( CP_UTF8, 0, as.c_str( ), ( int )as.length( ), &ret[0], ( int )ret.length( ) );
// return new string ( compiler should optimize this away )
return ret;
}
/**
* @brief Prints a container type as a numbered list to standard output.
*
*/
static void printNumberedList( std::set const& container ) {
int n = 1;
for ( auto const& i : container ) {
std::wcout
Подробнее здесь: https://stackoverflow.com/questions/791 ... nteractive
Мобильная версия