zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    2020年封装APP之详解
    Linux 强制卸载硬盘 (Device is busy)
    pacman 非交互状态使用
    Snakemake 修改默认工作目录
    LaTeX 表格排版中遇到 Misplaced oalign
    重启崩溃的 KDE
    python robot.libraries.BuiltIn import BuiltIn库
    logging 常用配置
    paramiko 获取远程服务器文件
    物理时间使用Python脚本转格林卫时间
  • 原文地址:https://www.cnblogs.com/shsgl/p/4317162.html
Copyright © 2011-2022 走看看