Я хочу, чтобы мое консольное приложение было скрыто на панели задач после его запуска. При работе с графическим приложением я использовал 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;
Есть ли способ скрыть консольное приложение с панели задач и добавить его в системный трей?
Вы никогда не проверяете результат функции — ни для Shell_NotifyIcon()
, ни для SetWindowLong()
. Функции могут не работать, как указано в их документации. Почему нужна консольная программа, а не программа с графическим интерфейсом без единого окна?
Shell_NotifyIcon() возвращает true, и я вижу значок на панели задач. SetWindowLong() не возвращает 0, и если я правильно понимаю, это означает, что функция выполнена успешно.
Трей еще можно назвать «областью уведомлений».
Невозможно воспроизвести с помощью 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.
Вот почему я упомянул свою версию для Windows и Delphi. Мой код был опубликован до того, как и более поздние ответы испытывают то же (неправильное) поведение, что и вы, и предлагают сначала ввести SetForegroundWindow( hConsole )
, а затем использовать дескриптор GetForegroundWindow()
, чтобы скрыться.
Вы не являетесь владельцем окна консоли, оно даже не принадлежит вашему процессу. Вы показываете, что не пытаетесь манипулировать этим. Консольное приложение — неправильный выбор для этой задачи.