NWNotifyIcon.pas
上传用户:hbtcygglw
上传日期:2007-01-07
资源大小:281k
文件大小:11k
源码类别:

其他

开发平台:

Delphi

  1. unit NWNotifyIcon;
  2. interface
  3. uses
  4.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  5.   ShellAPI, Menus;
  6. const
  7.   WM_IconMessage = WM_USER + 888;
  8.   WM_CtrlMsssage = WM_USER + 666;
  9. type
  10.   TNWNotifyIcon = class(TComponent)
  11.   private
  12.     { Private declarations }
  13.     FButtonDown: Boolean;
  14.     FButtonRect: TRect;
  15.     FCanvas: TCanvas;
  16.     FDown: Boolean;
  17.     FGlyph: TBitmap;
  18.     FIcon: TIcon;
  19.     FIconData : TNotifyIconData;
  20.     FIconPopupMenu: TPopupMenu;
  21.     FParentForm: TForm;
  22.     FPrevParentWndProc: Pointer;
  23.     FRightMargin: Integer;
  24.     FSeekAndDestroy: Boolean;
  25.     FVisible: Boolean;
  26.     procedure NewParentWndProc(var Msg: TMessage);
  27.     procedure PaintCaption(Down: Boolean);
  28.     procedure SetGlyph(Value: TBitmap);
  29.     procedure SetIcon(const Value: TIcon);
  30.     procedure SetIconPopupMenu(const Value: TPopupMenu);
  31.     procedure SetRightMargin(Value: Integer);
  32.     procedure SetVisible(Value: Boolean);
  33.   protected
  34.     { Protected declarations }
  35.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  36.   public
  37.     { Public declarations }
  38.     constructor Create(AOwner: TComponent); override;
  39.     destructor Destroy; override;
  40.   published
  41.     { Published declarations }
  42.     property Glyph: TBitmap read FGlyph write SetGlyph;
  43.     property Icon: TIcon read FIcon write SetIcon;
  44.     property IconPopupMenu: TPopupMenu read FIconPopupMenu write SetIconPopupMenu;
  45.     property RightMargin: Integer read FRightMargin write SetRightMargin default 68;
  46.     property Visible: Boolean read FVisible write SetVisible default True;
  47.   end;
  48. procedure Register;
  49. implementation
  50. {$R *.DCR}
  51. procedure Register;
  52. begin
  53.   RegisterComponents('NoctWolf', [TNWNotifyIcon]);
  54. end;
  55. constructor TNWNotifyIcon.Create(AOwner: TComponent);
  56. var
  57.   P: Pointer;
  58. begin
  59.   inherited Create(AOwner);
  60.   FCanvas := TCanvas.Create;
  61.   FGlyph := TBitmap.Create;
  62.   FIcon := TIcon.Create;
  63.   FGlyph.LoadFromResourceName(HInstance,'CAPTIONBMP');
  64.   FIcon.Handle:=LoadIcon(HInstance,PChar('NOTIFYICON'));
  65.   FParentForm := TForm(AOwner);
  66.   FRightMargin:=68;
  67.   FVisible := True;
  68.   with FIconData do
  69.   begin
  70.     cbSize := SizeOf(FIconData);
  71.     Wnd := FParentForm.Handle;
  72.     uID := 0;
  73.     uFlags := nif_Icon Or nif_Message Or nif_Tip;
  74.     uCallBackMessage := WM_IconMessage;
  75.     hIcon := FIcon.Handle;
  76.     StrLCopy(szTip,PChar(Application.Title),64);
  77.   end;
  78.   FPrevParentWndProc := Pointer(GetWindowLong(FParentForm.Handle, GWL_WNDPROC));
  79.   P := MakeObjectInstance(NewParentWndProc);
  80.   SetWindowLong(FParentForm.Handle, GWL_WNDPROC, LongInt(p));
  81. end;
  82. destructor TNWNotifyIcon.Destroy;
  83. begin
  84.   Shell_NotifyIcon(NIM_DELETE,@FIconData);
  85.   if not FSeekAndDestroy then{ParentForm.HandleAllocated}
  86.   begin
  87.     Visible := False;
  88.     SetWindowLong(FParentForm.Handle, GWL_WNDPROC, LongInt(FPrevParentWndProc));
  89.   end;
  90.   FIcon := TIcon.Create;
  91.   FGlyph.Free;
  92.   FCanvas.Free;
  93.   inherited Destroy;
  94. end;
  95. procedure TNWNotifyIcon.NewParentWndProc(var Msg: TMessage);
  96. var
  97.   Point: TPoint;
  98.   I: Integer;
  99. begin
  100.   with Msg do
  101.   begin
  102.     Result := CallWindowProc(FPrevParentWndProc, FParentForm.Handle, Msg, WParam, LParam);
  103.     if FVisible then
  104.     begin
  105.       if (Msg = wm_NCPaint) or (Msg = wm_NCActivate) then
  106.       begin
  107.         PaintCaption(False);
  108.       end
  109.       else if Msg = wm_NCHitTest then
  110.       begin
  111.         if Result = htCaption then
  112.         begin
  113.           Point.x := LoWord(lParam);
  114.           ScreenToClient(FParentForm.Handle, Point);
  115.           if (Point.x > FButtonRect.Left) and (Point.x < FButtonRect.Right) then
  116.           begin
  117.             if not FDown and FButtonDown then PaintCaption(True);
  118.             Result := WM_CtrlMsssage;
  119.           end
  120.           else if FDown then
  121.           begin
  122.             PaintCaption(False);
  123.           end;
  124.         end
  125.         else
  126.           if FDown then PaintCaption(False);
  127.       end
  128.       else if (Msg = wm_NCLButtonDown) or (Msg = wm_NCLButtonDblClk) then
  129.       begin
  130.         if wParam = WM_CtrlMsssage then
  131.         begin
  132.           if not FDown then PaintCaption(True);
  133.           if not FButtonDown then
  134.           begin
  135.             FButtonDown := True;
  136.             SetCapture(FParentForm.Handle);
  137.           end;
  138.         end
  139.         else
  140.         begin
  141.           if FDown then PaintCaption(False);
  142.           if FButtonDown then
  143.           begin
  144.             FButtonDown := False;
  145.             ReleaseCapture;
  146.           end;
  147.         end;
  148.       end
  149.       else if (Msg = wm_NCLButtonUp) or (Msg = wm_LButtonUp) then
  150.       begin
  151.         if FButtonDown then
  152.         begin
  153.           FButtonDown := False;
  154.           ReleaseCapture;
  155.           if FDown then
  156.           begin
  157.             FIconData.hIcon := FIcon.Handle;
  158.             Shell_NotifyIcon(NIM_ADD,@FIconData);
  159.             FParentForm.Hide;
  160.           end;
  161.         end;
  162.         if FDown then PaintCaption(False);
  163.       end
  164.       else if (Msg = wm_Close) or (Msg = wm_Destroy) then
  165.       begin
  166.         FSeekAndDestroy := True;
  167.       end
  168.       else if (Msg=WM_IconMessage)and(LParam=WM_RButtonDown)then
  169.       begin
  170.         if IconPopupMenu<>nil then
  171.         begin
  172.           SetForegroundWindow(FParentForm.Handle);
  173.           GetCursorPos(Point);
  174.           IconPopupMenu.Popup(Point.x,Point.y);
  175.         end;
  176.       end
  177.       else if(Msg=WM_IconMessage)and(LParam=WM_LButtonDblClk)then
  178.       begin
  179.         if not FParentForm.Showing then
  180.         begin
  181.           I := -1;
  182.           if FIconPopupMenu <> nil then
  183.             I := GetMenuDefaultItem(FIconPopupMenu.Handle,1,0);
  184.           if I > -1 then
  185.           begin
  186.             FIconPopupMenu.Items[I].Click;
  187.           end
  188.           else
  189.           begin
  190.             FParentForm.Show;
  191.             Shell_NotifyIcon(NIM_DELETE,@FIconData);
  192.           end;
  193.         end;
  194.       end;
  195.     end;
  196.   end;
  197. end;
  198. procedure TNWNotifyIcon.Notification(AComponent: TComponent;
  199.   Operation: TOperation);
  200. begin
  201.   inherited Notification(AComponent, Operation);
  202.   if (Operation = opRemove) and (AComponent = FIconPopupMenu) then
  203.     FIconPopupMenu := nil;
  204. end;
  205. procedure TNWNotifyIcon.PaintCaption(Down: Boolean);
  206. var
  207.   DC: hDC;
  208.   R: TRect;
  209.   Image, CaptionImage: TBitmap;
  210.   LeftX, x, y, FrameY: Integer;
  211.   Shift: Byte;
  212.   procedure DrawUpFrame;
  213.   begin
  214.     with FCanvas do
  215.     begin
  216.       Pen.Color := clBtnHighlight;
  217.       MoveTo(LeftX, FrameY + y + 1);
  218.       LineTo(LeftX, FrameY);
  219.       LineTo(LeftX + x + 3, FrameY);
  220.       Pen.Color := clBlack;
  221.       MoveTo(LeftX, FrameY + y + 2);
  222.       LineTo(LeftX + x + 2, FrameY + y + 2);
  223.       LineTo(LeftX + x + 2, FrameY - 1);
  224.       Pen.Color := clBtnShadow;
  225.       MoveTo(LeftX + x + 1, FrameY + 1);
  226.       LineTo(LeftX + x + 1, FrameY + y + 1);
  227.       LineTo(LeftX, FrameY + y + 1);
  228.       Shift := 1;
  229.     end;
  230.   end;
  231.   procedure DrawDownFrame;
  232.   begin
  233.     with FCanvas do
  234.     begin
  235.       Pen.Color := clBlack;
  236.       MoveTo(LeftX, FrameY + y + 1);
  237.       LineTo(LeftX, FrameY);
  238.       LineTo(LeftX + x + 3, FrameY);
  239.       Pen.Color := clBtnHighlight;
  240.       MoveTo(LeftX, FrameY + y + 2);
  241.       LineTo(LeftX + x + 2, FrameY + y + 2);
  242.       LineTo(LeftX + x + 2, FrameY - 1);
  243.       Pen.Color := clBtnShadow;
  244.       MoveTo(LeftX + x, FrameY + 1);
  245.       LineTo(LeftX + 1, FrameY + 1);
  246.       LineTo(LeftX + 1, FrameY + y + 1);
  247.       Pen.Color := clSilver;
  248.       MoveTo(LeftX + x + 1, FrameY + 1);
  249.       LineTo(LeftX + x + 1, FrameY + y + 1);
  250.       LineTo(LeftX, FrameY + y + 1);
  251.       Shift := 2;
  252.     end;
  253.   end;
  254. begin
  255.   DC:=0;
  256.   FDown := Down;
  257.   if FVisible then
  258.   begin
  259.     try
  260.       DC := GetWindowDC(FParentForm.Handle);
  261.       FCanvas.Handle := DC;
  262.       Image := TBitmap.Create;
  263.       CaptionImage := TBitmap.Create;
  264.       GetWindowRect(FParentForm.Handle, R);
  265.       R.Right := R.Right - R.Left;
  266.       if FParentForm.BorderStyle = bsSingle then
  267.         FrameY := GetSystemMetrics(sm_cyFrame) + 1
  268.       else if FParentForm.BorderStyle = bsDialog then
  269.         FrameY := GetSystemMetrics(sm_cyBorder) + 4
  270.       else if FParentForm.BorderStyle = bsSizeToolWin then
  271.         FrameY := GetSystemMetrics(sm_cySizeFrame) + 2
  272.       else if FParentForm.BorderStyle = bsToolWindow then
  273.         FrameY := GetSystemMetrics(sm_cyBorder) + 4
  274.       else
  275.         FrameY := GetSystemMetrics(sm_cyFrame) + 2;
  276.       LeftX := R.Right - RightMargin - FrameY;
  277.       if (FParentForm.BorderStyle = bsSizeToolWin) or
  278.          (FParentForm.BorderStyle = bsToolWindow) then
  279.       begin
  280.         y := GetSystemMetrics(sm_cySMCaption) - 8;
  281.         x := GetSystemMetrics(sm_cxSMSize) - 5;
  282.       end
  283.       else
  284.       begin
  285.         y := GetSystemMetrics(sm_cyCaption) - 8;
  286.         x := GetSystemMetrics(sm_cxSize) - 5;
  287.       end;
  288.       with FButtonRect do
  289.       begin
  290.         Left := LeftX - FrameY;
  291.         Top := FrameY;
  292.         Right := Left + x + 3;
  293.         Bottom := y + 2;
  294.       end;
  295.       if Down then
  296.         DrawDownFrame
  297.       else
  298.         DrawUpFrame;
  299.       Image.Assign(FGlyph);
  300.       Image.Canvas.Brush.Color:=clBtnFace;
  301.       Image.Canvas.BrushCopy(Image.Canvas.ClipRect,FGlyph,FGlyph.Canvas.ClipRect,FGlyph.Canvas.Pixels[0,FGlyph.Height-1]);
  302.       CaptionImage.Assign(Image);
  303.       CaptionImage.Canvas.Brush.Color:=clBtnText;
  304.       CaptionImage.Canvas.BrushCopy(CaptionImage.Canvas.ClipRect,Image,Image.Canvas.ClipRect,clBlack);
  305.       StretchBlt(DC, LeftX + Shift, FrameY + Shift, x, y, CaptionImage.Canvas.Handle, 0, 0, CaptionImage.Width, CaptionImage.Height, srcCopy);
  306.       CaptionImage.Free;
  307.       Image.Free;
  308.     finally
  309.       ReleaseDC(FParentForm.Handle, DC);
  310.     end;
  311.   end;
  312. end;
  313. procedure TNWNotifyIcon.SetGlyph(Value: TBitmap);
  314. begin
  315.   if FGlyph <> Value then
  316.   begin
  317.     FGlyph.Assign(Value);
  318.     SendMessage(FParentForm.Handle, wm_NCActivate, 0, 0);
  319.   end;
  320. end;
  321. procedure TNWNotifyIcon.SetIcon(const Value: TIcon);
  322. begin
  323.   if FIcon <> Value then
  324.   begin
  325.     FIcon.Assign(Value);
  326.     FIconData.hIcon := FIcon.Handle;
  327.     Shell_NotifyIcon(NIM_MODIFY,@FIconData);
  328.   end;
  329. end;
  330. procedure TNWNotifyIcon.SetIconPopupMenu(const Value: TPopupMenu);
  331. begin
  332.   if FIconPopupMenu <> Value then
  333.   begin
  334.     FIconPopupMenu := Value;
  335.     if Value <> nil then Value.FreeNotification(Self);
  336.   end;
  337. end;
  338. procedure TNWNotifyIcon.SetRightMargin(Value: Integer);
  339. begin
  340.   if FRightMargin <> Value then
  341.   begin
  342.     FRightMargin := Value;
  343.     SendMessage(FParentForm.Handle, wm_NCActivate, 0, 0);
  344.   end;
  345. end;
  346. procedure TNWNotifyIcon.SetVisible(Value: Boolean);
  347. begin
  348.   if FVisible <> Value then
  349.   begin
  350.     FVisible := Value;
  351.     SendMessage(FParentForm.Handle, wm_NCActivate, 0, 0);
  352.   end;
  353. end;
  354. end.