Как спрятать консольное приложение в трей?

Я хочу, чтобы мое консольное приложение было скрыто на панели задач после его запуска. При работе с графическим приложением я использовал TTrayIcon, и оно работало без проблем. Для консольного приложения я использовал функцию ShowWindow с SW_HIDE и TNotifyIconData, чтобы создать значок на панели задач, но столкнулся с проблемой, когда значок консоли все еще появлялся на панели задач Windows.

procedure HideShowConsoleWindow(isShowForm: Boolean);
var
  Style: LongInt;
  app: THandle;
begin
  app := GetConsoleWindow;
  Style := GetWindowLong(GetConsoleWindow, GWL_EXSTYLE);
  if isShowForm then
  begin
    SetWindowLong(app, GWL_EXSTYLE, Style or WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
    ShowWindow(app, SW_HIDE);
  end
  else
  begin
    SetWindowLong(app, GWL_EXSTYLE, Style and not WS_EX_TOOLWINDOW or WS_EX_APPWINDOW);
    ShowWindow(app, SW_SHOW);
  end;
end;

procedure AddTrayIcon;
var
  NotifyIconData: TNotifyIconData;
begin
  FillChar(NotifyIconData, SizeOf(TNotifyIconData), 0);
  NotifyIconData.cbSize := SizeOf(TNotifyIconData);
  NotifyIconData.Wnd := GetConsoleWindow;
  NotifyIconData.uID := 1;
  NotifyIconData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
  NotifyIconData.uCallbackMessage := $0400 + 1;
  NotifyIconData.hIcon := LoadIcon(0, IDI_APPLICATION);
  StrPCopy(NotifyIconData.szTip, 'My Console App');
  Shell_NotifyIcon(NIM_ADD, @NotifyIconData);
end;

Есть ли способ скрыть консольное приложение с панели задач и добавить его в системный трей?

Вы не являетесь владельцем окна консоли, оно даже не принадлежит вашему процессу. Вы показываете, что не пытаетесь манипулировать этим. Консольное приложение — неправильный выбор для этой задачи.

Remy Lebeau 19.07.2024 10:12

Вы никогда не проверяете результат функции — ни для Shell_NotifyIcon(), ни для SetWindowLong(). Функции могут не работать, как указано в их документации. Почему нужна консольная программа, а не программа с графическим интерфейсом без единого окна?

AmigoJack 19.07.2024 10:54

Shell_NotifyIcon() возвращает true, и я вижу значок на панели задач. SetWindowLong() не возвращает 0, и если я правильно понимаю, это означает, что функция выполнена успешно.

Sashko1121 19.07.2024 13:24

Трей еще можно назвать «областью уведомлений».

Andreas Rejbrand 19.07.2024 13:27
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
172
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Невозможно воспроизвести с помощью Delphi 7 в Windows 7x64: моей программе удается скрыть как окно консоли, так и кнопку задачи:

program HideConsoleWindow;

{$APPTYPE CONSOLE}

const
  SW_HIDE= 0;
  user32= 'user32.dll';
  kernel32= 'kernel32.dll';

type
  HWND= type LongWord;
  BOOL= LongBool;

  function GetConsoleWindow(): HWND; stdcall; external kernel32 name 'GetConsoleWindow';
  function GetForegroundWindow(): HWND; stdcall; external user32 name 'GetForegroundWindow';
  function SetForegroundWindow( h: HWND ): BOOL; stdcall; external user32 name 'SetForegroundWindow';
  function ShowWindow( h: HWND; nCmdShow: Integer ): BOOL; stdcall; external user32 name 'ShowWindow';

var
  hConsole, hFore: HWND;

begin
  hConsole:= GetConsoleWindow();
  if hConsole<> 0 then begin
    if SetForegroundWindow( hConsole ) then begin
      hFore:= GetForegroundWindow();
      if hFore<> 0 then begin
        ShowWindow( hFore, SW_HIDE );
        // Task button should be gone also in recent Windows versions.
      end else begin
        // No foreground window available - still try to set window.
        ShowWindow( hConsole, SW_HIDE );
      end;
    end else begin
      // Console wasn't brought to foreground - still try to set window.
      ShowWindow( hConsole, SW_HIDE );
    end;
  end else begin
    // Couldn't get console window.
  end;
end.

С GWL_EXSTYLE возиться вообще не следует. И вы должны знать, что если вы запустите эту программу в существующей консоли, вы также скроете это окно консоли - возможно, вы не хотите этого делать, поскольку она все еще живет, и тогда вам остается только убить его процесс.

Когда я использую ShowWindow(GetConsoleWindow(), SW_HIDE); консоль сворачивается до панели задач Windows.

Sashko1121 19.07.2024 13:11

Вот почему я упомянул свою версию для Windows и Delphi. Мой код был опубликован до того, как и более поздние ответы испытывают то же (неправильное) поведение, что и вы, и предлагают сначала ввести SetForegroundWindow( hConsole ), а затем использовать дескриптор GetForegroundWindow(), чтобы скрыться.

AmigoJack 19.07.2024 13:23

Другие вопросы по теме