Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013

Отображение скрытого в трее окна программы при попытке запуска ее копий

11.10.2013, 22:51. Показов 3715. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Имеется код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, "MyApp");
 if(!hMutex)
   hMutex = CreateMutex(0, 0, "MyApp");
 else
   {
     HWND hWnd = FindWindow(0, "MyApp");
 
     if (IsWindowVisible(hWnd))
       SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
     else
       MessageBox(hWnd, "Приложение уже запущено (находится в трее).", "MyApp", MB_ICONASTERISK+MB_TOPMOST);
     SetForegroundWindow(hWnd);
     return 0;
   }
 
 Application->Initialize();
 SetApplicationMainFormOnTaskBar(Application, true);
 Application->Title = "MyApp";
 Application->CreateForm(__classid(TForm1), &Form1);
 Application->CreateForm(__classid(TForm2), &Form2);
 Application->Run();
 
 ReleaseMutex(hMutex);
 // CloseHandle(hMutex);
Cуть такова - запрещено открывать копии приложения, при попытке сделать это работающая программа должна переноситься на передний план. В случае, когда приложение не скрыто в трее (то есть свойство Visible = 1 плюс находится в панели задач, причем не важно, в "свернутом" - минимизированном - состоянии или "обычном", не свернутом), требуемое выполняется.
Иначе возникают проблемы.
Если заменить строку (используемую как "заглушку")
C++
1
MessageBox(hWnd, "Приложение уже запущено (находится в трее).", "MyApp", MB_ICONASTERISK+MB_TOPMOST);
на, к примеру,
C++
1
SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
то окно программы становится видимым и "выносится" на передний план, но при этом кнопка "свернуть программу (в панель задач)" перестает реагировать (чего в идеале не должно происходить).
Подскажите, как устранить досадное недоразумение (и заодно заполнить несколько пробелов в моих "знаниях").
Миниатюры
Отображение скрытого в трее окна программы при попытке запуска ее копий  
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.10.2013, 22:51
Ответы с готовыми решениями:

Ошибка при попытке компиляции и последующего запуска программы
Доброго времени суток! Недавно появился один глюк, который очень сильно напрягает и который я уже длительное время не могу решить. При...

Как отключить отображение программы в трее, чтобы при этом она продолжала работать в фоне?
Всем привет. Есть программа, которая умеет сворачиваться в трей. Нужно отключить отображение этой программы в трее, но чтобы при этом...

Вылет программы при попытке создания главного и дочернего окна
Подскажите пожалуйста, что я сделала не так? Запускается и вылетает. А должно создаваться два окна:основное и дочернее. #include...

8
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
12.10.2013, 00:53
gunslier, это смотря как ты сливал форму в трей... Попробовал вот так:

C++
1
2
3
4
5
6
7
8
9
10
void __fastcall TForm1::MyMinimize(TObject *Sender)
{
    Application->Restore(); // Magic !!!
    Hide();
    TrayIcon1->Visible = true;
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Application->OnMinimize = MyMinimize;
}
Тогда кнопка прекрасно работает после восстановления из трея...
1
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013
12.10.2013, 04:11  [ТС]
Твой код работает отлично, за это отдельное спасибо, но у меня немного другая ситуация.
Опишу как можно подробнее.
1. Иконка в трее видна всегда, то есть с самого начала
C++
1
TrayIcon1->Visible = 1;
2. Нажатие на кнопку "свернуть в панель задач (ПЗ)" опять же всегда сворачивает форму в ПЗ и ничего более не делает.
3. Нажатие на кнопку "закрыть" ("крестик") скрывает форму:
C++
1
2
3
4
5
6
7
8
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  if (Tag == 0)
  {
    CanClose = 0;
    Hide();
  }
}
За собственно закрытие приложения отвечает отдельная TButton кнопка (но это не так важно, так как на сабж не влияет):
C++
1
2
3
4
5
void __fastcall TForm1::exitClick(TObject *Sender)
{
  Form1->Tag = 1;
  Close();
}
Далее самое "интересное", на мой взгляд.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void __fastcall TForm1::TrayIcon1Click(TObject *Sender)
{
  if (Form1->Visible == 0)  // если форма скрыта
  {
    Form1->Show();  // отображаем ее
    Form1->WindowState = wsNormal;  // обычный размер
    Form1->FormStyle = fsStayOnTop;  // переносим на передний план
    Form1->FormStyle = fsNormal;  // делаем "обычным"
  }
  else
  {
    if (Form1->WindowState != wsMinimized)  // форма не минимизирована?
      Form1->Hide();  // скрываем
    else  // если свернута в панель задач
    {
      SendMessage(Form1->Handle, WM_SYSCOMMAND, SC_RESTORE, 0);  // восстанавливаем
      SetForegroundWindow(Form1->Handle);  // переносим на передний план
    }
  }
}
И в исходном коде (Project -> View Source) обрабатываем запуск копий приложения.
Как уже говорил, проблема возникает в случае, когда форма скрыта (видна только иконка в трее, напомню - ее Visible всегда "true"):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
          ............................. 
          HWND hWnd = FindWindow(0, "MyApp");
 
          if (IsWindowVisible(hWnd))
            SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);  // программа была свернута в панель задач или развернута - всё ОК
          else
          {
            SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);  // была скрыта - проблемы, не реагируют на нажатия кнопки "свернуть" и "закрыть" (форма "вынеслась" на передний план); вкладки TabSheet PageControl'a формы становятся визуально пустыми; думаю, дело в этой строке (и в моей голове)
//          после, если кликнуть на иконку в трее, видно, как окно формы разборачивается из панели задач
//          MessageBox(hWnd, "Приложение уже запущено (находится в трее).", "MyApp", MB_ICONASTERISK+MB_TOPMOST);  // "заглушка"
          }
          SetForegroundWindow(hWnd);
          return 0;
         ..............................
}
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
12.10.2013, 13:18
gunslier, я бы вообще попробовал сделать вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, L"MyApp");
        if (!hMutex)
            hMutex = CreateMutex(0, 0, L"MyApp");
        else
        {
            HWND hWnd = FindWindow(0, L"MyApp");
 
            if (IsWindowVisible(hWnd))
            {
                SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
                SetForegroundWindow(hWnd);
            }
            else
                SendMessage(hWnd, MY_MESSAGE(), 0, 0);
 
            return 0;
        }
, где

C++
1
2
3
4
UINT MY_MESSAGE()
{
    return RegisterWindowMessage(L"UI_CyberForumMessage");
}
, а, собственно, по получению формой зарегистрированного сообщения:

C++
1
2
3
4
5
6
7
8
9
10
void __fastcall TForm1::WndProc(Winapi::Messages::TMessage &Message)
{
    TForm::WndProc(Message);
    if(Message.Msg == MY_MESSAGE())
    {
        this->Show();
        this->WindowState = wsNormal;
        Application->BringToFront();
    }
}
, тогда кнопка Minimize должна прекрасно работать...
1
place status here
 Аватар для gunslinger
3186 / 2220 / 640
Регистрация: 20.07.2013
Сообщений: 6,013
12.10.2013, 21:42  [ТС]
Выше всяких похвал. Как всегда, полный и исчерпывающий ответ.
Не только кнопка сворачивания, но и закрытия ("крестик") реагируют на нажатия.
UI, есть в программировании то, что ты не знаешь? (хотя вопрос скорее риторический)
0
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
20.06.2014, 16:48
UI, а где этот кусок кода необходимо прописать?

Цитата Сообщение от UI Посмотреть сообщение
gunslier, я бы вообще попробовал сделать вот так: Код C++1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
* * * * HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, L"MyApp");
* * * * if (!hMutex)
* * * * * * hMutex = CreateMutex(0, 0, L"MyApp");
* * * * else
* * * * {
* * * * * * HWND hWnd = FindWindow(0, L"MyApp");
if (IsWindowVisible(hWnd))
* * * * * * {
* * * * * * * * SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
* * * * * * * * SetForegroundWindow(hWnd);
* * * * * * }
* * * * * * else
* * * * * * * * SendMessage(hWnd, MY_MESSAGE(), 0, 0);
return 0;
* * * * }
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33374 / 21499 / 8235
Регистрация: 22.10.2011
Сообщений: 36,894
Записей в блоге: 11
20.06.2014, 17:08
Лучший ответ Сообщение было отмечено volvo как решение

Решение

Вот полностью файл проекта:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// ---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
// ---------------------------------------------------------------------------
 
#include "Funcs.h"
// В Funcs.h описан прототип функции MY_MESSAGE, реализация - в Funcs.cpp
 
USEFORM("Unit1.cpp", Form1);
 
// ---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    try
    {
 
        HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, L"MyApp");
        if (!hMutex)
            hMutex = CreateMutex(0, 0, L"MyApp");
        else
        {
            HWND hWnd = FindWindow(0, L"MyApp");
 
            if (IsWindowVisible(hWnd))
            {
                SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
                SetForegroundWindow(hWnd);
            }
            else
                SendMessage(hWnd, MY_MESSAGE(), 0, 0);
 
            return 0;
        }
 
        Application->Initialize();
        Application->MainFormOnTaskBar = true;
        Application->Title = L"MyApp";
        Application->CreateForm(__classid(TForm1), &Form1);
        Application->Run();
 
        ReleaseMutex(hMutex);
    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
// ---------------------------------------------------------------------------
1
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
20.06.2014, 17:32
Передача имени файла другой копии приложения.
0
 Аватар для Sasha
4956 / 2420 / 531
Регистрация: 05.06.2008
Сообщений: 7,518
Записей в блоге: 3
25.02.2017, 02:12
volvo, подскажи пожалуйста, в седьмом посте который ты привёл. Как в этом коде сделать так чтобы при повторном запуске программы раскрывалось окно из трея, но при этом не открывалась новая копия приложения? Потому как сейчас у меня при повторном запуске вторая копия не запускается т.к и надо, но мне бы ещё хотелось дополнить открытием главного окна из трея при повторном запуске.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.02.2017, 02:12
Помогаю со студенческими работами здесь

Перезагрузка программы с учетом запрета запуска нескольких копий
Не могу понять, какой код написать, если программа запустилась с параметром RESTART. Код перезагрузки WinExcec в данном случае - обертка...

Ошибка "Permission denied" при попытке запуска программы
Не могу запустить свой &quot;Hello world&quot;. Написал программу в текстовом файле, как положено. Hello.cpp Далее в терминале, запущенном из папки...

Не получается убрать белую рамку и вид окна в дизайнере не соответсвует реальному виду окна после запуска программы
Делал свой простенький Splash Screen с прогресс баром. В 2012-ой студии под Windows 8 все было ок. А вот я запустил этот самый проект в...

Ощибка при попытке запуска проекта
Привет всем! При сборке любого консольного приложения выскакивает предупреждение: ...

При попытке запуска системы включается GRUB4DOS
не знаю абсолютно, что это такое :( красный фон, менюшка.. при попытке захода в любой пункт меню пишет произошло все это после...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru