我想从一个系统图标事件中显示一个表单,它只显示任务栏旁边的一些信息,并在一段时间后消失。我遇到的主要问题是将表单定位在正确的位置和可见的位置上。我找到了几种方法来确定图标的位置,但在测试中,我发现它们基于OS不一致(我尝试在另一个应用程序中这样做,最后放弃并使用了居中模式形式)。例如:
procedure GetWorkAreaRect(var outrect: TRect);
// returns the dimensions of the work area.
begin
Systemparametersinfo(SPI_GETWORKAREA, 0, @outrect, 0);
end;当它起作用时,问题是从那里决定把表单放在哪里(上面,下面,左,右)。有什么建议吗?
编辑:问题在于定位表单与系统托盘图标的关系,而不一定确定系统托盘图标在哪里。我又做了一次尝试,只要满足了一些条件,我就能让它发挥作用。最值得注意的是,如果任务栏被设置为自动隐藏,它就无法工作,因为假设单击是在工作区域之外进行的。当窗体被设置为自动隐藏时,这是不正确的。
function PositionForm(X, Y, Width, Height: Integer): TPoint;
// receives mouse-click position in X and Y, form width and height in width and height
// returns Left and Top in TPoint.X and TPoint.Y.
var
workrect: TRect;
resrect: TPoint;
begin
GetWorkAreaRect(workrect);
if Y > WorkRect.Bottom then // taskbar is on bottom
begin
resRect.X := WorkRect.Right - Width;
resrect.Y := WorkRect.Bottom - Height;
end
else
if X > WorkRect.Right then // taskbar is on right
begin
resrect.X := WorkRect.Right - Width;
resrect.Y := WorkRect.Bottom - Height;
end
else
if X < WorkRect.Left then // taskbar is on left
begin
resrect.X := WorkRect.Left;
resrect.Y := WorkRect.Bottom - Height;
end
else
if Y < WorkRect.Top then // taskbar is on top
begin
resrect.X := WorkRect.Right - Width;
resrect.Y := WorkRect.Top;
end;
Result := ResRect;
end;所以从表面上看,问题似乎是找到一种独立的方法来确定任务栏resides...or在哪里可以扩展上面的逻辑来处理这个问题?
发布于 2013-04-30 07:05:30
当您的通知图标接收到与操作相对应的消息时,您可以在该点进行查询,以查找屏幕上的关联点。
例如,如果您正在处理图标的消息过程中的WM_RBUTTONUP、WM_CONTEXTMENU等,您可以调用GetMessagePos来查找与消息关联的图标上的位置。
我用以下函数将其封装起来,以便将消息解码为TPoint
function MessagePoint: TPoint;
begin
Result := TSmallPoint(GetMessagePos());
end;所以你可以做的是,在你的图标的消息过程中,记下这一点。当您需要显示表单时,请使用此点确定图标所在的位置。因为重点可以在任务栏中,所以您需要将其插入工作区。
在您的问题更新之后,您似乎想知道如何找到任务栏的位置。通过调用SHAppBarMessage传递ABM_GETTASKBARPOS来做到这一点。
发布于 2013-04-30 04:13:41
Windows不公开一种本机方式来查询系统托盘图标的位置,或者即使它们是可见的。但是,您可以使用一些较低级别的API技巧手动完成此操作,如下文所示:
CTrayIconPosition -我的托盘图标在哪里?
这至少适用于XP,甚至可能是Vista。Windows 7彻底重新设计了系统托盘的工作方式,所以我不知道这些技术是否还能继续工作。
发布于 2013-04-30 12:40:50
如果有TJvDesktopAlert和JVCL,则可以使用JVCL显示简单通知。
procedure TForm1.ShowDesktopAlert(const AHeader, AMessage: string);
begin
with TJvDesktopAlert.Create(nil) do
begin
StyleOptions.DisplayDuration := 5000;
HeaderText := AHeader;
MessageText := AMessage;
AutoFree := True;
Execute;
end;
end;https://stackoverflow.com/questions/16291698
复制相似问题