Вопрос, с которым вы столкнулись, заключается в том, что в Delphi XE3 при работе с компонентами FMX не удаётся настроить обработку сообщений для иконки в системном трее под Windows. Сообщения, отправляемые иконке, не обрабатываются, несмотря на то, что сама иконка отображается корректно.
Описание проблемы
Вы используете код для работы с системным треем, который должен обрабатывать сообщения от иконки, но процедура TrayMessage не вызывается. В коде используется константа WM_ICONTRAY для определения сообщения, которое должно вызывать эту процедуру. Вы создали тестовое приложение, которое настраивает данные иконки в FormCreate и добавляет её в трей при нажатии кнопки, но процедура TrayMessage не выполняется.
Анализ проблемы
Проблема заключается в том, что в FMX нет прямого доступа к сообщениям окна, как это реализовано в VCL. В FMX используется единая функция WndProc, которая обрабатывает определённые сообщения для различных элементов управления, и она не предназначена для предоставления доступа к пользовательским сообщениям.
Подтверждённый ответ
Для решения проблемы вам необходимо создать отдельное окно, которое будет обрабатывать сообщения от иконки трея. В FMX для этого можно использовать функцию AllocateHWnd, которая создаст окно с пользовательской процедурой WndProc. Вот пример кода, который демонстрирует, как это можно сделать:
type
TForm2 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{$IFDEF MSWINDOWS}
TrayWnd: HWND;
TrayIconData: TNotifyIconData;
TrayIconAdded: Boolean;
procedure TrayWndProc(var Message: TMessage);
{$ENDIF}
public
{ Public declarations }
end;
{$IFDEF MSWINDOWS}
const
WM_ICONTRAY = WM_USER + 1;
{$ENDIF}
procedure TForm2.FormCreate(Sender: TObject);
begin
{$IFDEF MSWINDOWS}
TrayWnd := AllocateHWnd(TrayWndProc);
with TrayIconData do
begin
cbSize := SizeOf(TrayIconData);
Wnd := TrayWnd;
uID := 1;
uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
uCallbackMessage := WM_ICONTRAY;
hIcon := ... // Загрузка иконки
StrPCopy(szTip, 'testapp');
end;
{$ENDIF}
end;
procedure TForm2.FormDestroy(Sender: TObject);
begin
{$IFDEF MSWINDOWS}
if TrayIconAdded then
Shell_NotifyIcon(NIM_DELETE, @TrayIconData);
DeallocateHWnd(TrayWnd);
{$ENDIF}
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
{$IFDEF MSWINDOWS}
if not TrayIconAdded then
TrayIconAdded := Shell_NotifyIcon(NIM_ADD, @TrayIconData);
{$ENDIF}
end;
{$IFDEF MSWINDOWS}
procedure TForm2.TrayWndProc(var Message: TMessage);
begin
if Message.MSG = WM_ICONTRAY then
begin
// Обработка сообщений от иконки трея
end
else
Message.Result := DefWindowProc(TrayWnd, Message.Msg, Message.WParam, Message.LParam);
end;
{$ENDIF}
Заключение
Использование AllocateHWnd позволяет создать отдельное окно для обработки сообщений трея, что решает проблему, с которой вы столкнулись. Это решение специфично для Windows, так как трей является функциональностью, отсутствующей в других операционных системах, поддерживаемых FMX.
Проблемой является отсутствие обработки сообщений для иконки в системном трее в Delphi XE3, что связано с особенностями работы с сообщениями в компонентах FMX.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.