- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 FMX(XE3、Windows)设置托盘图标时遇到问题。我使用的代码可以在无数线程中找到,但我没有获得图标工作的消息处理。
为了说明这一点,我创建了一个测试应用程序,它在 FormCreate 中设置 TrayIcon 数据并使用按钮创建它。它将显示正确的图标和正确的工具提示,但 TrayMessage 过程永远不会被调用。
unit Unit2;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, Messages,
Windows, ShellAPI, FMX.Platform.Win;
const
WM_ICONTRAY = WM_USER + 1;
type
TForm2 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
TrayIconData: TNotifyIconData;
procedure TrayMessage(var Msg: TMessage); message WM_ICONTRAY;
end;
var
Form2: TForm2;
implementation
{$R *.fmx}
procedure TForm2.Button1Click(Sender: TObject);
begin
Shell_NotifyIcon(NIM_ADD, @TrayIconData);
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
with TrayIconData do
begin
cbSize := SizeOf;
Wnd := FmxHandleToHWND(self.Handle);
uID := 0;
uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
uCallbackMessage := WM_ICONTRAY;
hIcon := GetClassLong(FmxHandleToHWND(self.Handle), GCL_HICONSM);
StrPCopy(szTip, 'testapp');
end;
end;
procedure TForm2.TrayMessage(var Msg: TMessage);
begin
case Msg.lParam of
WM_LBUTTONDOWN: ShowMessage('LBUTTON');
WM_RBUTTONDOWN: ShowMessage('RBUTTON');
end;
end;
end.
我用 VCL 创建了相同的场景,它按预期工作。唯一的区别是直接使用 Form2.Handle 而不是 FMX 转换(并使用 Application.Handle 加载图标数据,但这不是 FMX 中问题的一部分)。谁能指出我正确的方向吗?
最佳答案
与 VCL 不同,FireMonkey 不会将原始窗口消息分派(dispatch)给 FMX 控件进行自定义处理(这会违背跨平台框架的目的)。 FireMonkey 在 FMX.Platform.Win
单元中实现了一个 WndProc()
函数,该函数用于 FireMonkey 创建的所有 HWND
窗口。该实现处理它需要处理的某些窗口消息,相应地触发各种控制方法(WMPaint()
、KeyUp/Down()
、MouseUp/Down()
等),然后将未处理的消息直接传递给 DefWindowProc()
进行操作系统处理,根本不让控件看到消息。
因此,您要访问原始消息的唯一方法是:
创建您自己的窗口,例如直接使用 AllocateHWnd()
或 CreateWindow/Ex()
。
通过 Get/SetWindowLong/Ptr()
直接 Hook FireMonkey 的 HWND
窗口。由于 FireMonkey 是一个跨平台框架,而 HWND
窗口是特定于平台的实现细节,因此我建议避免使用这种方法。
通过SetWindowsHookEx()
使用线程特定的消息 Hook 。通过使它们特定于线程,您可以避免编写 DLL 来实现 Hook 。
在这种特殊情况下,#1 是您的最佳选择。托盘图标是 Windows 特定的功能,因此您确实应该使用不与 FireMonkey 绑定(bind)的 Windows 特定代码来处理它们。您可以使用 AllocateHWnd()
来使用 Form 类(或任何类)的方法作为 WndProc()
来接收托盘消息,同时仍然允许Form 类来处理它们。例如:
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
...
else
Message.Result := DefWindowProc(TrayWnd, Message.Msg, Message.WParam, Message.LParam);
end;
{$ENDIF}
关于delphi - FMX - Trayicon 消息处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20109686/
我正在尝试使用 TrayIcon 使基本系统托盘消息显示在 Windows 8.1 中。但是,当我运行该程序时,没有任何显示。这是代码: package alert1; import java.net
我仍然有不知道在哪里存储我的 TrayIcon 的问题。基本上,如果 Windows 要从“自动启动”启动我的程序……它就会崩溃。我发现问题出在我给定的 TrayIcon 路径上。我在 C# WPF
这里真正的问题可能是在 Java 中是否有更好的显示桌面消息的方法。然而…… 我正在使用 Java trayicon 向桌面用户显示消息。因为他们想保留某些消息直到用户点击它们,为了使用“displa
我在 visual studio 2005 Express Edition 中编译了我的 trayicon 实用程序 c++ 代码,托盘图标气球成功显示,但后来我删除了我的防火墙,切换到 Window
我在使用 FMX(XE3、Windows)设置托盘图标时遇到问题。我使用的代码可以在无数线程中找到,但我没有获得图标工作的消息处理。 为了说明这一点,我创建了一个测试应用程序,它在 FormCreat
是否可以通过编程方式关闭 TTrayIcon 气球提示? 问题: 我有一个计时器,每分钟检查一次消息。当它发现一条消息(例如 ABC 服务已停止)时,它会显示带有消息的气球: procedure TF
我正在尝试在已出现的托盘中添加 TrayIcon。我是 Java 新手,所以我可能会调用错误的方法。有人可以帮我吗?我使用的代码是: if (!SystemTray.isSupported()) {
我正在编写一个带有 SystemTray 图标的 Java 应用程序,我想将换行符放入 TrayIcon 的“显示消息”中,但是普通的 html 技巧似乎不起作用(就像它在 JLabels 中一样).
我有一个使用 JFrame 以及 TrayIcon 的 java 应用程序,并且我向 TrayIcon { private BoundedRangeModel boundedRangeModel;
目前在我的(JRuby 代码)中,我想以不同于“双击托盘图标”(awt.TrayIcon 实例)的方式处理“气球关闭”消息: import java.awt.TrayIcon import java.
在有关 TrayIcon 的 setImage 方法的 Java 文档中( http://docs.oracle.com/javase/7/docs/api/java/awt/TrayIcon.htm
如何捕获文本/文件/任何其他 DataFlavor 到 java.awt.TrayIcon 上的拖放事件(放置在 java.awt.SystemTray 中) ? 最佳答案 显然这还不被支持(Java
我有以下问题:我的鼠标输入方法不起作用,我不知道为什么。按下鼠标效果很好,只有 mouseEntered 不行。 这是鼠标监听器: MouseListener mouseListener = new
虽然我在 unity3D 中编写 C# 脚本已经有几年了,但我对 C# 编程还很陌生。我目前正在尝试制作一个 WPF 托盘图标,我在网上找到的所有资源都告诉我使用 System.Windows.For
我只需要一个简单的示例,了解如何轻松地将带有 python 的图标放在我的系统托盘上。这意味着:我运行程序,没有显示任何窗口,只有一个托盘图标(我有一个 png 文件)出现在系统托盘中,当我右键单击它
我想在附加图片中绘制自定义云(系统气球)。可能吗? 最佳答案 QSystemTrayIcon类有一个简单的气球消息选项可用 ( QSystemTrayIcon::showMessage ) 但它只提供
在运行mp3播放器时,它在某些歌曲上崩溃了。 考虑到这一点,当我用str.length()== 128调用setToolTip(str)时,它不是播放器本身,而是java TrayIcon类。 我写了
我有一个框架、两个按钮和一个 JEDI TrayIcon(TJvTrayIcon,版本 3.40)。德尔福XE。 第一个按钮: Frame11.Visible := true; 第二: Frame11
Java 自 1.6 起允许创建 TrayIcon http://docs.oracle.com/javase/8/docs/api/java/awt/SystemTray.html 我想做的是创建一
我正在为 Windows 编写一个系统托盘应用程序(从 this thread 收集了很多信息)。我有 ContextMenu 工作 - 您可以右键单击并以这种方式执行功能。 我想在左键单击时弹出一个
我是一名优秀的程序员,十分优秀!