delphi程序最小化任务栏控件 托盘

unit MyTray;

interface

uses   Windows,Messages,SysUtils,Classes,Graphics,Controls, Forms,Dialogs,ShellApi,ExtCtrls,StdCtrls;

const //自定义托盘消息   WM_TrayMsg=WM_USER+10;

type //恢复窗口的方式,左双击,右双击,左单击,右双击   TRMode=(LDbClick,RDbClick,LCLick,RClick);   TMyTray=class(TComponent)

private
    { Private declarations }
    //私有成员
  FIcon:TIcon;//图标
FDfIcon:THandle;//应用程序的默认图标
  FSetDfIcon:Boolean;//是否用应用程序的图标,如果为True,则Ficon为nil
  FIconData:TNotifyIconData;//托盘数据结构
  isMin:Boolean;//标识是否窗口最小化了
  FHandle:HWnd;//不可视建窗体句柄,用于处理托盘事件
  FActive:Boolean;//是否启用托盘
  FHint:string;//托盘提示字符串
  FRMode:TRMode;//恢复窗口的方式
  isClickIn:Boolean;//标识鼠标是否点在图标上
  OldStyleEX:longInt;//保存老的窗口风格
//事件成员
  FOnIconClick:TNotifyEvent;
  FOnIconDblClick:TNotifyEvent;
  FOnIconMouseMove:TMouseMoveEvent;
  FOnIconMouseDown:TMouseEvent;
  FOnIconMouseUp:TMouseEvent;
//设置方法
  procedure SetIcon(value:TIcon);
  procedure SetDfIcon(value:boolean);
  procedure SetActive(value:boolean);
  procedure SetHint(value:string);
  procedure SetRMode(value:TRMode);
//私有方法
  procedure SetTray(Way:DWORD);//设置托盘样式,修改,删除,增加
  function GetActiveIcon:THandle;//取得有用的图标句柄

protected
  { Protected declarations }
  //应用程序的消息钩子,获得主窗口的最小化消息
  function AppMsgHook(var Msg:TMessage):Boolean;
  procedure WndProc(var Msg:TMessage);//不可视窗口的窗口过程
//以下为事件的调度函数
  procedure DblClick;dynamic;
  procedure Click;dynamic;
  procedure MouseDown(Button:TMouseButton;Shift:TShiftState;X,Y:Integer);dynamic;
  procedure MouseUp(Button:TMouseButton;Shift:TShiftState;X,Y:Integer);dynamic;
  procedure MouseMove(Shift:TShiftState;X,Y:Integer);dynamic;

public
    { Public declarations }
    constructor Create(AOwner:TComponent);override;
    destructor Destroy;override;
  published
    { Published declarations }
    property Active:Boolean read FActive write SetActive default False;
  property Icon:TIcon read FIcon write SetICon;
  property SetDfIconed:boolean read FSetDfIcon write SetDfIcon default true;
  property Hint:String read FHint write SetHint;
  property RMode:TRmode read FRmode write SetRMode default LDbClick;
//事件的方法指针
  property OnIconClick:TNotifyEvent read FOnIconClick write FOnIconClick;
  property OnIconDblClick:TNotifyEvent read FOnIconDblClick write FOnIconDblClick;
  property OnIconMouseMove:TMouseMoveEvent read FOnIconMouseMove write FOnIconMouseMove;
  property OnIconMouseDown:TMouseEvent read FOnIconMouseDown write FOnIconMouseDown;
  property OnIconMouseUp:TMouseEvent read FOnIconMouseUp write FOnIconMouseUp;
  end;

procedure Register;

implementation

procedure Register; begin   RegisterComponents(‘Samples’, [TMyTray]); end;

///////////TmyTray////////////////////////////
constructor TMyTray.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
//设置程序钩子,指定AppMsgHook为处理函数,
//则,应用程序的任何消息都将经过这个函数
  Application.HookMainWindow(AppMsgHook);
  FICon:=TICon.Create;
//得到默认图标的句柄,图标为应用程序的图标
  FDfIcon:=Application.Icon.Handle;
  FSetDfIcon:=True;
  FActive:=False;
  FRMode:=LDbClick;
  isMin:=False;
//创建一个不可视窗口,并指定窗口过程,以处理托盘事件
  FHandle:=AllocateHWnd(WndProc);
//保存窗体的老的风格,在恢复窗口的同时也恢复原来的窗口风格
  OldStyleEX:=GetWindowLong(Application.Handle,GWL_EXSTYLE);
end;

destructor TMyTray.Destroy;

begin

Application.UnhookMainWindow(AppMsgHook); //对象释放之前先消除托盘

SetTray(NIM_DELETE); //释放不可能窗口的句柄

DeallocateHWnd(FHandle);

FICon.Free;

inherited Destroy;

end;

//应用程序钩子,可以截获应用程序的所有消息

function TMyTray.AppMsgHook(var Msg:TMessage):Boolean;
var
  placement:WINDOWPLACEMENT;
begin
  Result:=False;
  //保证程序不会在设计时处理最小化消息
  if  not (csDesigning in ComponentState)  then
  if  (Msg.Msg=WM_SYSCOMMAND) and (FActive)  then
  begin
    if msg.WParam=SC_MINIMIZE then
    begin
    //设置了这个属性后,窗口最小化就不会停在任务栏了,而是停在屏幕,
    //位置由SetWindowPlacement来决定
      ShowWindow(Application.Handle,SW_HIDE);
      SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW);
      GetWindowPlacement(Application.Handle,@placement);
      placement.flags:=WPF_SETMINPOSITION;
      placement.ptMinPosition.x:=1800;
      placement.ptMinPosition.y:=1200;
      SetWindowPlacement(Application.Handle,@placement);
      SetTray(NIM_ADD);
    end;
  end;
end;

procedure TMyTray.SetIcon(Value:TIcon);
begin
  FIcon.Assign(Value);
  FsetDfIcon:=False;//有了自定义的图标,则默认图标自动设为False
  if FIcon.Empty then
    FsetDfIcon:=True;
  if (isMin)and(Factive) then
    SetTray(NIM_MODifY);
end;

//设置是否为默认图标,与FIcon为互相的变量,只能有其中一个
procedure TMyTray.SetDfIcon(Value:Boolean);
begin
  if FSetDfIcon<>Value then
  begin
    FSetDfIcon:=Value;
    if not FSetDfIcon then
    begin
      if FIcon.Empty then
      begin
        FSetDfIcon:=True;
        exit;
      end;
    end
    else
    begin
      if (IsMin)and(FActive) then
        SetTray(NIM_MODifY);
    end;
  end;
end;

procedure TMyTray.SetActive(Value:Boolean);
begin
  if FActive<>Value then
  begin
    FActive:=Value;
  end;
end;

procedure TMyTray.SetHint(Value:String);
begin
  if FHint<>Value then
  begin
    FHInt:=Value;
    if (IsMin)and(FActive) then
    SetTray(NIM_MODifY);
  end;
end;

procedure TMyTray.SetRMode(Value:TRMode);
begin
  if FRmode<>Value then
  FRmode:=Value;
end;

//设置托盘方式,显示,修改,删掉,重要方法
procedure TMyTray.SetTray(Way:DWORD);
begin
FIconData.cbSize:=Sizeof(FIconData);
  FIconData.Wnd:=FHandle;
  FIConData.uID:=0;
  FIConData.uFlags:=Nif_ICON or Nif_MESSAGE or Nif_TIP;
  FIConData.uCallbackMessage:=WM_TrayMsg;
  FIConData.hIcon:=GetActiveIcon;
  StrLCopy(FIConData.szTip,Pchar(FHint),63);
  Shell_NotifyIcon(Way,@FIconData);
end;

//取得可用的图标
function TMyTray.GetActiveIcon:THandle;
begin
  if not FSetDfIcon then
    result:=FIcon.Handle
  else
    result:=FDfIcon;
end;

//托盘消息的截获,以调用相应的事件调度方法
procedure TMyTray.WndProc(var Msg:TMessage);
var
  p:TPoint;
begin
  if (Msg.Msg=WM_TrayMsg)and(FActive) then
  begin
    case Msg.LParam of
    WM_LBUTTONDBLCLK://左双击
    begin
      GetCursorPos(p);
      DblClick;
      MouseDown(mbLeft,KeysToShiftState(TWMMouse(Msg).Keys)+[ssDouble],P.X,P.Y);
      if FRmode=LDbclick then
      begin
        ShowWindow(Application.Handle,SW_SHOW);
//这里很重要的一个就是恢复窗口风格,不然下次把Active设为True
//最小化后,窗口依然会往左下角飞去,而托盘图标却看不见了.
        SetWindowLong(Application.Handle,GWL_EXSTYLE,OldStyleEX);
        SendMessage(Application.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
        SetTray(NIM_DELETE);
      end;
    end;
    WM_RBUTTONDBLCLK://右双击
    begin
      GetCursorPos(P);
      DblClick;
MouseDown(mbRight,KeysToShiftState(TWMMouse(Msg).Keys)+[ssDouble],P.X,P.Y);
      if FRmode=RDbclick then
      begin
        ShowWindow(Application.Handle,SW_SHOW);
        SetWindowLong(Application.Handle,GWL_EXSTYLE,OldStyleEX);
        SendMessage(Application.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
        SetTray(NIM_DELETE);
      end;
    end;
    WM_MOUSEMOVE://鼠标移动
    begin
      GetCursorPos(P);
      MouseMove(KeysToShiftState(TWMMouse(Msg).Keys),P.X,P.Y);
    end;
    WM_LBUTTONDOWN://左单击下
    begin
      GetCursorPos(P);
      IsClickIn:=True;
      MouseDown(mbLeft,KeysToShiftState(TWMMouse(Msg).Keys)+[ssLeft],P.X,P.Y);
    end;
    WM_LBUTTONUP://左单击弹起
    begin
      GetCursorPos(P);
      if IsClickIn then
      begin
        IsClickIn:=False;
        Click;
        if FRmode=LClick then
        begin
          ShowWindow(Application.Handle,SW_SHOW);
          SetWindowLong(Application.Handle,GWL_EXSTYLE,OldStyleEX);
          SendMessage(Application.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
          SetTray(NIM_DELETE);
        end;
      end;
      MouseUp(mbLeft,KeysToShiftState(TWMMouse(Msg).Keys)+[ssLeft],P.X,P.Y);
    end;
    WM_RBUTTONDOWN://右单击下
    begin
      GetCursorPos(P);
      IsClickIn:=True;
      MouseDown(mbRight,KeysToShiftState(TWMMouse(Msg).Keys)+[ssRight],P.X,P.Y);
    end;
    WM_RBUTTONUP://右单击弹起
    begin
      GetCursorPos(P);
      if IsClickIn then
      begin
        IsClickIn:=False;
        Click;
        if FRmode=RClick then
        begin
          ShowWindow(Application.Handle,SW_SHOW);
          SetWindowLong(Application.Handle,GWL_EXSTYLE,OldStyleEX);
          SendMessage(Application.Handle,WM_SYSCOMMAND,SC_RESTORE,0);
          SetTray(NIM_DELETE);
        end;
      end;
      MouseUp(mbRight,KeysToShiftState(TWMMouse(Msg).Keys)+[ssRight],P.X,P.Y);
    end;
  end;
end
else
  Msg.Result:=DefWindowProc(FHandle,Msg.Msg,Msg.wParam,Msg.lParam);
end;

//以下为几个事件的调度函数,比较简单.

procedure TMyTray.DblClick;
begin
  if Assigned(FOnIconDblClick) then
  FOnIconDblClick(Self);
end;

procedure TMyTray.Click;
begin
  if Assigned(FOnIconClick) then
  FOnIconClick(Self);
end;

procedure TMyTray.MouseDown(Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
begin
  if Assigned(FOnIconMouseDown) then
  FOnIconMouseDown(Self,Button,Shift,X,Y);
end;

procedure TMyTray.MouseUp(Button:TMouseButton;Shift:TShiftState;X,Y:Integer);
begin
  if Assigned(FOnIconMouseUp) then
  FOnIconMouseUp(Self,Button,Shift,X,Y);
end;

procedure TMyTray.MouseMove(Shift:TShiftState;X,Y:Integer);
begin
  if Assigned(FOnIconMouseMove) then
  FOnIconMouseMove(Self,Shift,X,Y);
end;

end.

时间: 2024-12-28 00:24:23

delphi程序最小化任务栏控件 托盘的相关文章

win10程序最小化后任务栏没有显示的解决方法

通常情况下我们会在电脑打开很多应用程序,当我们暂时不需要使用的时候我们会将它最小化,最小化后会以缩略图的形式出现在任务栏中,等我们有需要的时候再打开就行.但是今天用电脑时发现将程序最小化之后任务栏中却看不到程序的最小化窗口(注意为win10操作系统),这样使用带来非常的不方便,那么为什么会出现这种情况呢?经研究发现出现这种问题主要是由于资源管理器出现问题所引起的,下面为大家介绍解决方法.1.打开任务管理器,右击任务栏选择任务管理器或者同时按下[ctrl+shift+esc]组合键打开:2.找到[

delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)

1.所有程序最小化 uses ComObj; var shell : OleVariant; begin shell := CreateOleObject('Shell.Application'); shell.minimizeAll; end; 2.最小化其他程序 spy++ 查找要最小化的程序classname var Indicador :Integer; begin // Find the window by Classname Indicador := FindWindow(PChar

WPF程序最小化到任务通知栏

我们通常使用的桌面软件,都可以最小化到任务通知栏,并且可以从任务通知栏再打开当前软件,或者通过软件的快捷方式从任务通知栏呼出. 我们可以通过下面的方式把WPF程序最小化到任务栏.由于WPF并没有实现Notification的功能,我们需要借助于WinForm中NotifyIcon来实现,请看代码: using WinForms = System.Windows.Forms; private WinForms.NotifyIcon _notifyIcon; private WinForms.Con

如何控制其他程序窗体上的窗口控件

用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是回调函数.我的理解是这样的:回调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等等之类的.但是什么时候被调用却不知道了.回调函数一般是按照调用者的要求定义好参数和返回值的类型,你向调用者提供你的回调函数的入口地址,然后调用者有什么事件发生的时候就可以随时按照你提供的地址调用这个函数通知你,并按照预先规定好的形式传递参数.所以很多人打比方,说回调函数还真有点像您随身带的BP机:告诉别人

应用程序的可视化图形引擎库控件Vectordraw Developer Framework

VectorDraw Developer Framework (VDF)控件为您的应用程序增加动态的2D/3D图形.是一个可轻松创建爱你和管理及打印2D和3D图形的构件. 其对象可显示与大多数公共矢量格式和其他CAD对象兼容的方法和属性. 支持10多种矢量格式和多种离散格式.VectorDraw Developer Framework (VDF) 是完全基于对象的和支持 .NET 2的. 此组件是用.NET 2005 C# 代码写成的. 同时还提供了一个ActiveX构件. 此ActiveX构件

delphi Components[i]清除所有edit控件中的内容

(* 一般的清空combobox方法 combobox1.clear; ... combobox9.clear; *) procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin for i:=0 to self.ComponentCount-1 do begin if self.Components[i] is TCombobox then TCombobox(self.Components[i]).clear;

可以创建专业的客户端/服务器视频会议应用程序的音频和视频控件LEADTOOLS Video Conferencing SDK

LEADTOOLS Video Streaming Module控件为您创建一个自定义的视频会议应用程序和工具提供所有需要的功能.软件开发人员可以使用Video Streaming Module SDK,通过一些不同的配置来创建一些客户端/服务器应用程序.例如,如果有一个服务器需要向多个客户端发送音频/视频数据,那么就可以在服务器上创建这样的应用程序,比如多点传送或Web广播中的web多点传播.此外,当有多个捕捉点向一个源发送视频数据时,您可以创建安全/监控应用程序. 产品特征: 视频会议二进制

delphi xe6 for android 自带控件LocationSensor优先使用GPS定位的方法

delphi xe6 for android LocationSensor控件默认是优先使用网络定位,对定位精度要求高的应用我们可以修改原码直接指定GPS定位. 修改方法: 将C:\Program Files\Embarcadero\Studio\14.0\source\rtl\common\System.Android.Sensors.pas拷贝到自己的工程目录里 打开System.Android.Sensors.pas找到function TUIAndroidLocationSensor.D

Telerik 控件的汉化-检索当前控件的键值对

(第一次随手写了个东东发现被各种转载,傻笑下,那就顺便把下午试验出来的方式给大家分析下吧,妹纸说难得被转载一次,鼓励我多写点) telerik每个版本内置的英文是有差异的,然后很多资料的内置键值对都是不全的,下面的方法是用来查询当前控件的所有键值对. 这个是借鉴资料山寨来的思路. 核心思路其实就是新增一个继承LocalizationManager,CustomLocalizationManager类,然后重写这个类的语言的时候获取出所有键值对. 1.新建一个CustomLocalizationM