Читаем Программирование на Visual C++. Архив рассылки полностью

AДля начала два замечания. Во-первых, CDialog таки наследует функцию PreCreateWindow от своего предка – класса CWnd. Другой вопрос, что эта функция не вызывается в процессе создания диалогового окна. Во-вторых, MFC не регистрирует класс диалогового окна, оставляя имя, предопределённое в Windows. Вместо этого MFC передаёт адрес своей собственной диалоговой функции (AfxDlgProc) при вызове CreateDialogIndirect.

Итак, мы установили, что диалоговое окно создаётся в функции CreateDialogIndirect. Мы не можем повлиять на процесс создания окна, а значит не можем и изменить имя класса. Придётся искать обходные пути. Самый простой из них, на мой взгляд – дать диалогу "во владение" невидимое окно, для которого заголовок и имя класса известны. Затем можно найти это окно с помощью FindWindow, переместиться к самому диалогу через GetWindow и сделать на него SetForegroundWindow.

Вот фрагмент функции InitInstance, который делает всё необходимое (использование статических переменных выглядит несколько коряво – я использовал их, чтобы весь код был в одном месте, но в реальной программе лучше сделать их членами класса).

BOOL CMyApp::InitInstance {

 …

 HWND hWnd = FindWindow("{4C1D4220-C3E5-11d4-93A8-B5D00D46136A}", NULL);

 if (hWnd != NULL) {

  hWnd = GetWindow(hWnd, GW_OWNER);

  SetForegroundWindow(hWnd);

  return FALSE;

 }

 WNDCLASS wc;

 ZeroMemory(&wc, sizeof(wc));

 wc.hInstance = AfxGetInstanceHandle;

 wc.lpfnWndProc = DefWindowProc;

 wc.lpszClassName = "{4C1D4220-C3E5-11d4-93A8-B5D00D46136A}";

 RegisterClass(&wc);

 static CMyDlg dlg;

 m_pMainWnd = &dlg

 dlg.Create(IDD_MY_DIALOG, NULL);

 static CWnd wndDummy;

 wndDummy.CreateEx(0, "{4C1D4220-C3E5-11d4-93A8-B5D00D46136A}", "", 0, CRect(0,0,0,0), &dlg, 0);

 …

 return TRUE;

}

Обратите внимание на использование GUIDа в качестве имени класса. Он получен с помощью утилиты Guidgen (меню Tools). Вероятность того, что в системе найдутся окна с таким классом, не имеющие отношения к нашей программе, представляется ничтожно малой.

Александр Шаргин

А вот если к этому ответу добавить механизм mutex'ов, то получится действительно корректный способ.

Хочу обратить ваше внимание на один факт, присутствующий в обоих предыдущих ответах. Функция активизации уже запущенной копии целиком возлагается именно на вторую копию. Многие предлагали посылать первой копии сообщение, чтобы она воостановилась сама. Это в общем случае не работает (т.е. работает не во всех системах), из-за того, что приложение не может активизировать свое главное окно, если само не активно, и при этом не помогают ни BringWindowToTop, ни SetForegroundWindow.

Интересующимся этой темой я настоятельно рекомендую ознакомиться со статьей by Joseph M. Newcomer, где подробно разбираются достоинства и, главное, недостатки, каждого метода. А методов, помимо рассмотренных выше, очень много, напр. file mapping, shared variable и др. (я не стал публиковать эти ответы т.к. все эти объекты используются с одной целью, которая отлично решается с помощью mutex'ов).

Некоторые ссылались на статью в MSDN Q109175 – так вот: там используется некорректное решение!

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT