Сообщений 4 Оценка 297 Оценить |
Нечасто, но иногда все же бывает необходимо получить хэндл окна консольного приложения. Windows API не предусматривает никакой специальной функции для выполнения этой задачи, однако для её решения можно найти обходные пути.
Основная идея этого способа описана в статье Q124103 из Microsoft Knowledge Base. Она состоит в том, чтобы заменить название консоли на уникальную строку символов, посредством FindWindow() выполнить поиск хэндла окна, а затем вернуть окну прежнее название. Там же приведен код получения уникальной строки, основанный на комбинировании информации о текущем времени и идентификаторе процесса.
Приведенный ниже код использует несколько иной способ получения уникальной строки для названия консоли, который, на мой взгляд, нисколько не уступает способу от Microsoft, поскольку использует в качестве строки GUID - гарантированно уникальный идентификатор. Вы можете использовать любой из этих вариантов, равно как и разработать собственную методику.
///////////////////////////////////////////////////////////// // // Как спрятать и восстановить окно консоли? // #include <windows.h> #include <stdio.h> #include <objbase.h> #include <locale.h> #pragma comment(lib, "user32") #pragma comment(lib, "ole32") void main() { HRESULT hr; GUID guid; char title[256]; char newtitle[256]; wchar_t lpsz[256]; int size; HWND hwnd; // Инициализация окружения setlocale( LC_ALL, ".ACP" ); CoInitialize( NULL ); __try { // Создаем GUID hr = CoCreateGuid( &guid ); if( FAILED( hr ) ) __leave; // Конвертируем его в текстовое представление (UNICODE) size = StringFromGUID2( ( REFGUID ) guid, lpsz, 256 ); // Конвертируем UNICODE в ANSI wcstombs( newtitle, lpsz, size ); // Сохраняем текущий заголовок консоли GetConsoleTitle( title, sizeof( title ) ); // Устанавливаем уникальный заголовок SetConsoleTitle( newtitle ); // Microsoft рекомендует сделать паузу 40 мсек // для обновления заголовка консоли Sleep(40); // Поиск хэндла окна с известным нам заголовком hwnd = FindWindow( NULL, newtitle ); if(!hwnd) { printf( "Can't find window\n" ); __leave; } // Поиск успешно завершен, возвращаем старый заголовок SetConsoleTitle( title ); // Ждем 40мсек согласно рекомендациям MS Sleep(40); // Проверяем правильность найденного хэндла окна GetWindowText( hwnd, newtitle, sizeof( newtitle ) ); if( lstrcmp( title, newtitle ) ) { printf("Bad console title\n"); __leave; } // Хэндл получен правильно, используем его... if( IDNO == MessageBox( NULL, title, "Hide console?", MB_YESNO ) ) __leave; ShowWindow( hwnd, SW_HIDE ); MessageBox( NULL, "Press to bring it back", "Hidden!", MB_OK ); ShowWindow( hwnd, SW_SHOW ); } __finally { CoUninitialize(); } } |
Идея этого способа состоит в том, чтобы перечислить все открытые окна с помощью EnumWindows, а затем выбрать из них окно, созданное текущим потоком - это и будет окно консоли. Конечно, для перечисления гораздо лучше подошла бы функция EnumThreadWindows, но она почему-то отказывается перечислять консольные окна.
#include <windows.h> BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam) { if(GetWindowThreadProcessId(hwnd, NULL) == GetCurrentThreadId()) { *(HWND*)lParam = hwnd; return FALSE; } return TRUE; } int main() { HWND hWnd; EnumWindows(EnumWndProc, (LPARAM)&hWnd); // hWnd содержит дескриптор. ... } |
ПРИМЕЧАНИЕ Разумеется, такой способ будет работать при условии, что ваше консольное приложение не создаёт дополнительных графических окон верхнего уровня (редкий случай, но иногда бывает и такое). Если другие окна всё-таки создаются, можно ввести дополнительные условия проверки, которые отсекут все лишние окна, кроме консоли. Какие именно проверки могут потребоваться, зависит от конкретного приложения. Другой вариант - воспользоваться методом, описанном в предыдущем разделе. |
Сообщений 4 Оценка 297 Оценить |