首页  编辑  

类似MSN的提示窗口

Tags: /超级猛料/VCL/Form,窗体/窗体特效/   Date Created:

类似MSN的提示窗口

unit TaskbarNotifier;

// By John O'Byrne - 05 July 2002

{ Translated from cpp to Delphi by Ian Boyd

 Source .cpp code taken from eMule}

{ Sample Usage:

FTaskbarNotifier := TTaskbarNotifier.CreateParented(Application.Handle);

FTaskbarNotifier.Skin.LoadFromResourceName(hInstance, 'taskbarNotifier');

FTaskbarNotifier.FontNormal.Color := clWhite;

FTaskbarNotifier.FontSelected.Color := clWhite;

FTaskbarNotifier.TextRect := Rect(3, 43, 213, 83);

FTaskbarNotifier.Show('', 0);

FTaskbarNotifier.Free;

}

interface

//{$INCLUDE compilers.inc}

uses

Messages, Windows, Graphics, Controls, Classes

{$IFDEF DELPHI7_UP}, Types{$ENDIF};

{$IFNDEF DELPHI7_UP}

type

TByteDynArray = array of Byte;

{$ENDIF}

const

WFTASKBARNOTIFIERCLICKED =  WM_USER+123;

TN_TEXT_NORMAL =      $0000;

TN_TEXT_BOLD =      $0001;

TN_TEXT_ITALIC =      $0002;

TN_TEXT_UNDERLINE =     $0004;

TBN_NULL =      0;

TBN_CHAT =      1;

TBN_DLOAD =     2;

TBN_LOG =      3;

TBN_IMPORTANTEVENT =  4;

WM_MOUSEHOVER =  $2A1;

WM_MOUSELEAVE =  $2A3;

type

TAnimationStatus = Integer;

const

IDT_HIDDEN =    0;

IDT_APPEARING =   1;

IDT_WAITING =    2;

IDT_DISAPPEARING =  3;

type

TTaskbarNotifier = class(TCustomControl)

private

 FTransparent: Boolean;

 FTransparentColor: TColor;

 procedure SetTransparent(const Value: Boolean);

 procedure SetTransparentColor(const Value: TColor);

 procedure BackgroundChanged;

//  function CreateRgnFromBitmap(hBmp: HBITMAP; color: TColor): HRGN;

protected

 FNormalFont: TFont;

 FSelectedFont: TFont;

 FNormalTextColor: TColor;

 FSelectedTextColor: TColor;

 FHandCursor: HCURSOR;

 FSkinBackground: TBitmap;

 FSkinRegion: HRGN;

 FBitmapHeight: Integer;

 FBitmapWidth: Integer;

 FTextRect: TRect;

 FTextFormat: Longint;

 FMouseIsOver: Boolean;

 FAnimStatus: TAnimationStatus;

 FTaskbarPlacement: Integer;

 FTimerPrecision: Integer;

 FTimeToStay: Integer;

 FShowEvents: Integer;

 FHideEvents: Integer;

 FCurrentPosX: Integer;

 FCurrentPosY: Integer;

 FCurrentWidth: Integer;

 FCurrentHeight: Integer;

 FIncrementShow: Integer;

 FIncrementHide: Integer;

 {Taskbar Notifier}

 FActiveMessageType: Integer;

 FMessageTypeClicked: Integer;

(*

 FTimeToShow: Integer;

 FTimeToHide: Integer;

 FDelayBetweenShowEvents: Integer;

 FDelayBetweenHideEvents: Integer;

 FStartPosX: Integer;

 FStartPosY: Integer;

 FIncrement: Integer;

*)

 function Get24BitPixels(pBitmap: HBITMAP;

   var wWidth: WORD; var wHeight: WORD): TByteDynArray;

 function GenerateRegion(Bitmap: HBITMAP; red, green, Blue: Byte): HRGN;

 procedure CreateParams(var Params: TCreateParams); override;

 procedure WMTimer(var Msg: TWMTimer); message WM_TIMER;

 procedure OnSkinBackgroundChange(Sender: TObject);

 procedure Paint; override;

  {TCustomControl's new handler for WM_PAINT messages}

 { Message Handlers }

 procedure WMMouseMove(var Message: TWMMouseMove); message WM_MOUSEMOVE;

 procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;

 procedure WMMouseHover(var Message: TMessage); message WM_MOUSEHOVER;

 procedure WMMouseLeave(var Message: TMessage); message WM_MOUSELEAVE;

 procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;

 procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

 procedure WMSetCursor(var Message: TWMSetCursor); message WM_SETCURSOR;

public

 constructor Create(AOwner: TComponent); override;

 destructor Destroy; override;

 procedure Show(const szCaption: string; MessageType: Integer;

   dwTimeToShow: Integer=500; dwTimeToStay: Integer=5000;

   dwTimeToHide: Integer=500; nIncrement: Integer=1); overload;

 procedure Hide;

 function SetSkin(nBitmapID: UINT;          red: SmallInt=-1; green:

SmallInt=-1; blue: SmallInt=-1): Boolean; overload;

 function SetSkin(const szFileName: string; red: SmallInt=-1; green:

SmallInt=-1; blue: SmallInt=-1): Boolean; overload;

 property FontNormal: TFont read FNormalFont;

 property FontSelected: TFont read FSelectedFont;

 property TextRect: TRect read FTextRect write FTextRect;

 property TransparentColor: TColor read FTransparentColor write

SetTransparentColor;

 property Transparent: Boolean read FTransparent write SetTransparent;

 property Skin: TBitmap read FSkinBackground;

 property AnimationStatus: TAnimationStatus read FAnimStatus;

{

 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

 afx_msg void OnDestroy();

 afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

 afx_msg void OnMouseMove(UINT nFlags, CPoint point);

 afx_msg void OnLButtonUp(UINT nFlags, CPoint point);

 afx_msg LRESULT OnMouseHover(WPARAM w, LPARAM l);

 afx_msg LRESULT OnMouseLeave(WPARAM w, LPARAM l);

 afx_msg BOOL OnEraseBkgnd(CDC* pDC);

 afx_msg void OnPaint();

 afx_msg void OnTimer(UINT nIDEvent);

}

end;

implementation

uses

SysUtils, ShellAPI, Math, Dialogs;

const

TASKBAR_ON_TOP =   1;

TASKBAR_ON_LEFT =  2;

TASKBAR_ON_RIGHT =  3;

TASKBAR_ON_BOTTOM =  4;

TASKBAR_X_TOLERANCE =  40;

TASKBAR_Y_TOLERANCE =  40;

function NearlyEqual(a, b, epsilon: Integer): Boolean;

begin

Result := Abs(a-b) < (epsilon / 2);

end;

constructor TTaskbarNotifier.Create(AOwner: TComponent);

var

osvi: OSVERSIONINFO;

begin

inherited Create(AOwner);

if ParentWindow = 0 then

 raise Exception.Create('Must create TTaskbarNotifier with.CreateParented(ParentHandle)');

FTaskbarPlacement := ABE_BOTTOM;

FAnimStatus := IDT_HIDDEN;

FTextFormat := DT_MODIFYSTRING or DT_WORDBREAK or DT_PATH_ELLIPSIS or

DT_END_ELLIPSIS; // Default Text format (see DrawText in the win32 API for the different values)

FHandCursor := LoadCursor(0, MAKEINTRESOURCE(32649)); // System Hand Cursor

FSkinBackground := TBitmap.Create;

FSkinBackground.OnChange := OnSkinBackgroundChange;

FTransparentColor := clFuchsia;

FTransparent := True;

{Normal text}

FNormalFont := TFont.Create;

FNormalFont.Color := rgb(133, 146, 181);

{Selected Text}

FSelectedFont := TFont.Create;

FSelectedFont.Style := FSelectedFont.Style + [fsUnderline];

FSelectedFont.Color := rgb(10, 36, 106);

// If running on NT, timer precision is 10 ms, if not timer precision is 50ms

osvi.dwOSVersionInfoSize := SizeOf(OSVERSIONINFO);

GetVersionEx(osvi);

if (osvi.dwPlatformId = VER_PLATFORM_WIN32_NT) then

 FTimerPrecision := 10

else

 FTimerPrecision := 50;

end;

destructor TTaskbarNotifier.Destroy;

begin

// No need to delete the HRGN,  SetWindowRgn() owns it after being called

FSkinBackground.Free;

FNormalFont.Free;

FSelectedFont.Free;

inherited Destroy;

end;

function TTaskbarNotifier.SetSkin(nBitmapID: UINT; red: SmallInt; green:

SmallInt; blue: SmallInt): Boolean;

begin

FSkinBackground.Handle := nBitmapID;

Result := True;

end;

function TTaskbarNotifier.SetSkin(const szFileName: string;

 red: SmallInt; green: SmallInt; blue: SmallInt): Boolean;

begin

FSkinBackground.LoadFromFile(szFilename);

Result := True;

end;

procedure TTaskbarNotifier.Show(const szCaption: string; MessageType:

Integer;

 dwTimeToShow: Integer; dwTimeToStay: Integer; dwTimeToHide: Integer;

 nIncrement: Integer);

var

nScreenWidth: Cardinal;

// nScreenHeight: Cardinal;

nEvents: Integer;

nBitmapSize: Integer;

rcTaskbar: TRect;

hWndTaskbar: HWND;

begin

if (FBitmapWidth = 0) or (FBitmapHeight = 0) then

 Exit;

Caption := szCaption;

FTimeToStay := dwTimeToStay;

nScreenWidth := GetSystemMetrics(SM_CXSCREEN);

// nScreenHeight := GetSystemMetrics(SM_CYSCREEN);

hWndTaskbar := FindWindow('Shell_TrayWnd', nil);

GetWindowRect(hWndTaskbar, rcTaskbar);

{Daniel Lohmann: Calculate taskbar position from its window rect. However,

 on XP it may be that the taskbar is slightly larger or smaller than the

 screen size. Therefore we allow some tolerance here.

}

if NearlyEqual(rcTaskbar.Left, 0, TASKBAR_X_TOLERANCE) and

  NearlyEqual(rcTaskbar.Right, nScreenWidth, TASKBAR_X_TOLERANCE) then

begin

 // Taskbar is on top or on bottom

 if NearlyEqual(rcTaskbar.Top, 0, TASKBAR_Y_TOLERANCE) then

  FTaskbarPlacement := ABE_TOP

 else

  FTaskbarPlacement := ABE_BOTTOM;

 nBitmapSize := FBitmapHeight;

end

else

begin

 // Taskbar is on left or on right

 if NearlyEqual(rcTaskbar.Left, 0, TASKBAR_X_TOLERANCE) then

  FTaskbarPlacement := ABE_LEFT

 else

  FTaskbarPlacement := ABE_RIGHT;

 nBitmapSize := FBitmapWidth;

end;

// We calculate the pixel increment and the timer value for the showing animation

if (dwTimeToShow > FTimerPrecision) then

begin

 nEvents := min((dwTimeToShow div FTimerPrecision div 2), nBitmapSize);

//<<-- enkeyDEV(Ottavio84) -Reduced frames of a half-

 FShowEvents := dwTimeToShow div nEvents;

 FIncrementShow := nBitmapSize div nEvents;

end

else

begin

 FShowEvents := FTimerPrecision;

 FIncrementShow := nBitmapSize;

end;

// We calculate the pixel increment and the timer value for the hiding animation

if dwTimeToHide > FTimerPrecision then

begin

 nEvents := min((dwTimeToHide div FTimerPrecision div 2), nBitmapSize);

//<<-- enkeyDEV(Ottavio84) -Reduced frames of a half-

 FHideEvents := dwTimeToHide div nEvents;

 FIncrementHide := nBitmapSize div nEvents;

end

else

begin

 FShowEvents := FTimerPrecision;

 FIncrementHide := nBitmapSize;

end;

case FAnimStatus of

IDT_HIDDEN:

 begin

  case FTaskbarPlacement of

  ABE_RIGHT:

   begin

    FCurrentPosX := rcTaskbar.Left;

    FCurrentPosY := rcTaskbar.Bottom - FBitmapHeight;

    FCurrentWidth := 0;

    FCurrentHeight := FBitmapHeight;

   end;

  ABE_LEFT:

   begin

    FCurrentPosX := rcTaskbar.Right;

    FCurrentPosY := rcTaskbar.Bottom - FBitmapHeight;

    FCurrentWidth := 0;

    FCurrentHeight := FBitmapHeight;

   end;

  ABE_TOP:

   begin

    FCurrentPosX := rcTaskbar.Right - FBitmapWidth;

    FCurrentPosY := rcTaskbar.Bottom;

    FCurrentWidth := FBitmapWidth;

    FCurrentHeight := 0;

   end;

  else //ABE_BOTTOM

   // Taskbar is on the bottom or Invisible

   FCurrentPosX := rcTaskbar.Right - FBitmapWidth;

   FCurrentPosY := rcTaskbar.Top;

   FCurrentWidth := FBitmapWidth;

   FCurrentHeight := 0;

  end;

  ShowWindow(Handle, SW_SHOWNOACTIVATE);

  FActiveMessageType := MessageType;

//<<--enkeyDEV(kei-kun) -TaskbarNotifier-

  SetTimer(Handle, IDT_APPEARING, FShowEvents, nil);

 end;

IDT_APPEARING:

  Repaint; //RedrawWindow;

IDT_WAITING:

 begin

  Repaint;{RedrawWindow;}

  KillTimer(Handle, IDT_WAITING);

  SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

 end;

IDT_DISAPPEARING:

 begin

  KillTimer(Handle, IDT_DISAPPEARING);

  SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

  case FTaskbarPlacement of

  ABE_RIGHT:

   begin

    FCurrentPosX := rcTaskbar.Left - FBitmapWidth;

    FCurrentWidth := FBitmapWidth;

   end;

  ABE_LEFT:

   begin

    FCurrentPosX := rcTaskbar.Right;

    FCurrentWidth := FBitmapWidth;

   end;

  ABE_TOP:

   begin

    FCurrentPosY := rcTaskbar.Bottom;

    FCurrentHeight := FBitmapHeight;

   end;

  else //ABE_BOTTOM

   FCurrentPosY := rcTaskbar.Top - FBitmapHeight;

   FCurrentHeight := FBitmapHeight;

  end;

  SetWindowPos(Handle, HWND_TOPMOST, FCurrentPosX, FCurrentPosY,

    FCurrentWidth, FCurrentHeight, SWP_NOACTIVATE);

  Repaint; //RedrawWindow;

 end;

end

end;

procedure TTaskbarNotifier.Hide;

begin

case FAnimStatus of

IDT_APPEARING: KillTimer(Handle, IDT_APPEARING);

IDT_WAITING: KillTimer(Handle, IDT_WAITING);

IDT_DISAPPEARING: KillTimer(Handle, IDT_DISAPPEARING);

end;

MoveWindow(Handle, 0, 0, 0, 0, True); { TODO : Last parameter, Repaint.

What is the implied value in MFC? }

ShowWindow(Handle, SW_HIDE);

FAnimStatus := IDT_HIDDEN;

FActiveMessageType := TBN_NULL; //<<--enkeyDEV(kei-kun) -TaskbarNotifier-

end;

function TTaskbarNotifier.GenerateRegion(Bitmap: HBITMAP; red, green, Blue:

Byte): HRGN;

var

wBmpWidth,wBmpHeight: WORD;

Rgn, TmpRgn: HRGN;

p, x, y: Integer;

jRed, jGreen, jBlue: Byte;

Pixels: TByteDynArray;

begin

// 24bit pixels from the bitmap

Pixels := Get24BitPixels(Bitmap, wBmpWidth, wBmpHeight);

// if (!pPixels) return NULL;

// create our working region

Rgn := CreateRectRgn(0, 0, wBmpWidth, wBmpHeight);

if Rgn=0 then

begin

 {delete pPixels;}

 Result := 0;

 Exit;

end;

p := 0;

for y := 0 to wBmpHeight-1 do

begin

 for x := 0 to wBmpWidth-1 do

 begin

  jRed   := Pixels[p+2];

  jGreen := Pixels[p+1];

  jBlue  := Pixels[p+0];

  if (jRed=red) and (jGreen=green) and (jBlue=blue) then

  begin

   // remove transparent color from region

   TmpRgn := CreateRectRgn(x, y, x+1, y+1);

   CombineRgn(Rgn, Rgn, TmpRgn, RGN_XOR);

   DeleteObject(TmpRgn);

  end;

  // next pixel

  Inc(p, 3);

 end;

end;

// release pixels

// delete pPixels;

// return the region

Result := Rgn;

end;

function TTaskbarNotifier.Get24BitPixels(pBitmap: HBITMAP;

 var wWidth: WORD; var wHeight: WORD): TByteDynArray;

var

bmpBmp: BITMAP;

pbmiInfo: PBITMAPINFO;

bmiInfo: BITMAPINFO;

wBmpWidth, wBmpHeight: WORD;

dc: HDC;

iRes: Integer;

begin

GetObject(pBitmap, SizeOf(bmpBmp), @bmpBmp);

pbmiInfo := @bmpBmp;

wBmpWidth  := pbmiInfo.bmiHeader.biWidth;

Dec(wBmpWidth, wBmpWidth mod 4);

wBmpHeight := pbmiInfo.bmiHeader.biHeight;

wWidth  := wBmpWidth;

wHeight := wBmpHeight;

try

 SetLength(Result, wBmpWidth*wBmpHeight*3);

except

 Result := nil;

 Exit;

end;

dc := GetWindowDC(Handle);

try

 bmiInfo.bmiHeader.biSize := SizeOf(BITMAPINFOHEADER);

 bmiInfo.bmiHeader.biWidth := wBmpWidth;

 bmiInfo.bmiHeader.biHeight := -wBmpHeight;

 bmiInfo.bmiHeader.biPlanes := 1;

 bmiInfo.bmiHeader.biBitCount := 24;

 bmiInfo.bmiHeader.biCompression := BI_RGB;

 bmiInfo.bmiHeader.biSizeImage := wBmpWidth*wBmpHeight*3;

 bmiInfo.bmiHeader.biXPelsPerMeter := 0;

 bmiInfo.bmiHeader.biYPelsPerMeter := 0;

 bmiInfo.bmiHeader.biClrUsed := 0;

 bmiInfo.bmiHeader.biClrImportant := 0;

 // get pixels from the original bitmap converted to 24bits

 iRes := GetDIBits(dc, pBitmap, 0, wBmpHeight, @Result[0], bmiInfo,

DIB_RGB_COLORS);

finally

 // release the device context

 ReleaseDC(0, dc);

end;

// if failed, cancel the operation.

if iRes = 0 then

begin

 SetLength(Result, 0);

 Result := nil;

 Exit;

end;

// return the pixel array

end;

(*

function TTaskbarNotifier.CreateRgnFromBitmap(hBmp: HBITMAP; color: TColor):

HRGN;

type

TRectArray = array of TRect;

PRectArray = ^TRectArray;

var

bm: BITMAP;

dcBmp: HDC;

hOldBitmap: HGDIOBJ;

RDHDR: Integer;

MAXBUF: Integer;

i, j: Integer; // current position in mask image

first: Integer; // left position of current scan line

wasfirst: Boolean; // set when if mask was found in current scan line

isMask: Boolean; // set when current color is mask color

pRgnData: PRgnDataHeader;

Rects: PRectArray;

begin

// this code is written by Davide Pizzolato

if hBmp = 0 then

begin

 Result := 0;

 Exit;

end;

GetObject(hBmp, SizeOf(BITMAP), @bm ); // get bitmap attributes

dcBmp := CreateCompatibleDC(GetDC(Handle)); //Creates a memory device

context for the bitmap

hOldBitmap := SelectObject(dcBmp, hBmp); //selects the bitmap in the device

context

RDHDR := SizeOf(RGNDATAHEADER);

MAXBUF := 40;  // size of one block in RECTs

// (i.e. MAXBUF*sizeof(RECT) in bytes)

// LPRECT pRects;

// DWORD cBlocks = 0;   // number of allocated blocks

first := 0; // left position of current scan line

// where mask was found

wasfirst := False;  // set when if mask was found in current scan line

// allocate memory for region data

// pRgnData := new BYTE[ RDHDR + ++cBlocks * MAXBUF * sizeof(RECT) ];

memset( pRgnData, 0, RDHDR + cBlocks * MAXBUF * sizeof(RECT) );

// fill it by default

pRgnData.dwSize := RDHDR;

pRgnData.iType := RDH_RECTANGLES;

pRgnData.nCount := 0;

for i := 0 to bm.bmHeight-1 do

begin

 for j := 0 to bm.bmWidth-1 do

 begin

  // get color

  ismask := (dcBmp.GetPixel(j,bm.bmHeight-i-1) != color);

  // place part of scan line as RECT region if transparent color found

  //after mask color or mask color found at the end of mask image

  if wasfirst and  (

   (ismask and (j = (bm.bmWidth-1))) or

   (ismask xor (j < bm.bmWidth))) then

  begin

   // get offset to RECT array in RGNDATA buffer

   pRects := Inc(pRgnData, RDHDR);

   // save current RECT

   pRects[ pRgnData->nCount++ ] = CRect( first, bm.bmHeight - i - 1,

j+(j==(bm.bmWidth-1)), bm.bmHeight - i );

   // if buffer full reallocate it

   if ( pRgnData->nCount >= cBlocks * MAXBUF ) then

   begin

    LPBYTE pRgnDataNew = new BYTE[ RDHDR + ++cBlocks * MAXBUF *

sizeof(RECT) ];

    memcpy( pRgnDataNew, pRgnData, RDHDR + (cBlocks - 1) * MAXBUF *

sizeof(RECT) );

    delete pRgnData;

    pRgnData = (RGNDATAHEADER* )pRgnDataNew;

   end;

   wasfirst = false;

  end

  else if ( !wasfirst && ismask ) then

  begin  // set wasfirst when mask is found

   first = j;

   wasfirst = true;

  end;

 end;

 dcBmp.SelectObject(hOldBitmap); //restore default object

 dcBmp.DeleteDC(); //release the bitmap

 // create region

 { Under WinNT the ExtCreateRegion returns NULL (by Fable@aramszu.net) }

 // HRGN hRgn = ExtCreateRegion( NULL, RDHDR + pRgnData->nCount *

sizeof(RECT), (LPRGNDATA)pRgnData );

 { ExtCreateRegion replacement { }

 HRGN hRgn=CreateRectRgn(0, 0, 0, 0);

 ASSERT( hRgn!=NULL );

 pRects = (LPRECT)((LPBYTE)pRgnData + RDHDR);

 for (i=0; i<(int)pRgnData->nCount; i++) do

 begin

  HRGN hr=CreateRectRgn(pRects[i].left, pRects[i].top, pRects[i].right,

pRects[i].bottom);

  VERIFY(CombineRgn(hRgn, hRgn, hr, RGN_OR)!=ERROR);

  if (hr) then

   DeleteObject(hr);

 end;

 ASSERT( hRgn!=NULL );

 { } ExtCreateRegion replacement }

 delete pRgnData;

 return hRgn;

end;

end;

*)

procedure TTaskbarNotifier.CreateParams(var Params: TCreateParams);

begin

inherited CreateParams(Params);

Params.Style := WS_POPUP;

Params.ExStyle := WS_EX_TOPMOST;

Params.X := 0;

Params.Y := 0;

Params.Width := 0;

Params.Height := 0;

{Window Class}

Params.WindowClass.style := CS_DBLCLKS or CS_SAVEBITS;

Params.WindowClass.hIcon := 0;

Params.WindowClass.hCursor := LoadCursor(0, IDC_ARROW);

Params.WindowClass.hbrBackground := COLOR_WINDOW+1;

end;

procedure TTaskbarNotifier.OnSkinBackgroundChange(Sender: TObject);

begin

BackgroundChanged;

end;

procedure TTaskbarNotifier.SetTransparent(const Value: Boolean);

begin

if FTransparent <> Value then

begin

 FTransparent := Value;

 BackgroundChanged;

end;

end;

procedure TTaskbarNotifier.SetTransparentColor(const Value: TColor);

begin

if FTransparentColor <> Value then

begin

 FTransparentColor := Value;

 BackgroundChanged;

end;

end;

procedure TTaskbarNotifier.BackgroundChanged;

var

bm: BITMAP;

red, green, blue: Byte;

dwResult: Integer;

begin

ZeroMemory(@bm, SizeOf(bm));

if FSkinBackground.Handle = 0 then

 Exit;

dwResult := GetObject(FSkinBackground.Handle, SizeOf(bm), @bm);

if dwResult = 0 then

begin

//  MessageDlg('Could not get new Skin object: '+#13#10+

//   SysErrorMessage(GetLastError), mtError, [mbOk], 0);

 Beep;

 Exit;

end;

FBitmapWidth := bm.bmWidth;

FBitmapHeight := bm.bmHeight;

FTextRect := rect(0, 0, bm.bmWidth, bm.bmHeight);

if FTransparent then

begin

 red :=   (FTransparentColor shr 16) and $FF;

 green := (FTransparentColor shr  8) and $FF;

 blue :=  (FTransparentColor)        and $FF;

 // No need to delete the HRGN,  SetWindowRgn() owns it after being called

 FSkinRegion := GenerateRegion(FSkinBackground.Handle,

  red, green, blue);

 SetWindowRgn(Handle, FSkinRegion, True);

end;

end;

{

BEGIN_MESSAGE_MAP(TTaskbarNotifier, CWnd)

ON_WFCREATE()

ON_WFMOUSEMOVE()

ON_WFDESTROY()

ON_WFERASEBKGND()

ON_WFPAINT()

ON_MESSAGE(WFMOUSELEAVE, OnMouseLeave)

ON_MESSAGE(WFMOUSEHOVER, OnMouseHover)

ON_WFSETCURSOR()

ON_WFLBUTTONUP()

ON_WFTIMER()

END_MESSAGE_MAP()

}

{ TTaskbarNotifier message handlers }

procedure TTaskbarNotifier.WMMouseMove(var Message: TWMMouseMove);

var

MouseEvent: TTrackMouseEvent;

begin

MouseEvent.cbSize := SizeOf(TTrackMouseEvent);

MouseEvent.dwFlags := TME_LEAVE or TME_HOVER;

MouseEvent.hwndTrack := Handle;

MouseEvent.dwHoverTime := 1;

TrackMouseEvent(MouseEvent);

inherited;

end;

procedure TTaskbarNotifier.WMLButtonUp(var Message: TWMLButtonUp);

begin

FMessageTypeClicked := FActiveMessageType;

PostMessage(ParentWindow, WFTASKBARNOTIFIERCLICKED, 0, 0);

inherited;

end;

procedure TTaskbarNotifier.WMMouseHover(var Message: TMessage);

begin

if FAnimStatus = IDT_WAITING then

 KillTimer(Handle, IDT_WAITING);

if not FMouseIsOver then

begin

 FMouseIsOver := True;

 Repaint; //RedrawWindow;

 if FAnimStatus = IDT_DISAPPEARING then

 begin

  KillTimer(Handle, IDT_DISAPPEARING);

  FAnimStatus := IDT_APPEARING;

  SetTimer(Handle, IDT_APPEARING, FShowEvents, nil);

 end;

end;

Message.Result := 0;

end;

procedure TTaskbarNotifier.WMMouseLeave(var Message: TMessage);

begin

if FMouseIsOver then

begin

 FMouseIsOver := False;

 if FAnimStatus = IDT_WAITING then

  SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

 Repaint;

end;

Message.Result := 0;

end;

procedure TTaskbarNotifier.WMEraseBkgnd(var Message: TWmEraseBkgnd);

var

memDC: hDC;

OldBitmap: HGDIOBJ;

begin

memDC := CreateCompatibleDC(Message.DC);

OldBitmap := SelectObject(memDC, FSkinBackground.Handle);

BitBlt(Message.DC, 0, 0, FCurrentWidth, FCurrentHeight, memDC, 0, 0,

SRCCOPY);

SelectObject(memDC, OldBitmap);

Message.Result := -1;

end;

procedure TTaskbarNotifier.WMPaint(var Message: TWMPaint);

{var

dc: HDC; //CPaintDC dc(this);

rcClient: TRect;

pOldFont: TFont;// CFont *pOldFont;

szBuffer: string; //char *szBuffer;

}

begin

inherited;

Exit;

(*

dc := GetDC(Handle);

if FMouseIsOver then

begin

 SetTextColor(dc, FFontSelected.Color and $00FFFFFF); todo

 pOldFont := SelectObject(dc, FFontSelected.Handle); todo

end

else

begin

 SetTextColor(dc, FFontNormal.Color and $00FFFFFF); todo

 pOldFont := SelectObject(dc, FFontNormal.Handle); todo

end;

TCanvas

SetBkMode(dc, Windows.TRANSPARENT);

InflateRect(rcClient, -1, -20);

DrawText(dc, PChar(Caption), -1, FTextRect, FTextFormat);

SelectObject(dc, pOldFont);

*)

end;

procedure TTaskbarNotifier.WMSetCursor(var Message: TWMSetCursor);

begin

if Message.HitTest = HTCLIENT then

begin

 SetCursor(FHandCursor);

 Message.Result := -1; //True

end;

end;

procedure TTaskbarNotifier.WMTimer(var Msg: TWMTimer);

begin

case Msg.TimerID of

IDT_APPEARING:

 begin

  FAnimStatus := IDT_APPEARING;

  case FTaskbarPlacement of

  ABE_BOTTOM:

   begin

    if (FCurrentHeight < FBitmapHeight) then

    begin

     Dec(FCurrentPosY, FIncrementShow);

     Inc(FCurrentHeight, FIncrementShow);

    end

    else

    begin

     KillTimer(Handle, IDT_APPEARING);

     SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

     FAnimStatus := IDT_WAITING;

    end;

   end;

  ABE_TOP:

   begin

    if (FCurrentHeight < FBitmapHeight) then

     Inc(FCurrentHeight, FIncrementShow)

    else

    begin

     KillTimer(Handle, IDT_APPEARING);

     SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

     FAnimStatus := IDT_WAITING;

    end;

   end;

  ABE_LEFT:

   begin

    if (FCurrentWidth < FBitmapWidth) then

     Inc(FCurrentWidth, FIncrementShow)

    else

    begin

     KillTimer(Handle, IDT_APPEARING);

     SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

     FAnimStatus := IDT_WAITING;

    end;

   end;

  ABE_RIGHT:

   begin

    if (FCurrentWidth < FBitmapWidth) then

    begin

     Dec(FCurrentPosX, FIncrementShow);

     Inc(FCurrentWidth, FIncrementShow);

    end

    else

    begin

     KillTimer(Handle, IDT_APPEARING);

     SetTimer(Handle, IDT_WAITING, FTimeToStay, nil);

     FAnimStatus := IDT_WAITING;

    end;

   end;

  end;

  SetWindowPos(Handle, HWND_TOPMOST, FCurrentPosX, FCurrentPosY,

    FCurrentWidth, FCurrentHeight, SWP_NOACTIVATE);

  //RedrawWindow();

 end;

IDT_WAITING:

 begin

  KillTimer(Handle, IDT_WAITING);

  SetTimer(Handle, IDT_DISAPPEARING, FHideEvents, nil);

 end;

IDT_DISAPPEARING:

 begin

  FAnimStatus := IDT_DISAPPEARING;

  case FTaskbarPlacement of

  ABE_BOTTOM:

   begin

    if (FCurrentHeight > 0) then

    begin

     Inc(FCurrentPosY, FIncrementHide);

     Dec(FCurrentHeight, FIncrementHide);

    end

    else

    begin

     KillTimer(Handle, IDT_DISAPPEARING);

     Hide;

    end;

   end;

  ABE_TOP:

   begin

    if (FCurrentHeight > 0) then

     Dec(FCurrentHeight, FIncrementHide)

    else

    begin

     KillTimer(Handle, IDT_DISAPPEARING);

     Hide;

    end;

   end;

  ABE_LEFT:

   begin

    if (FCurrentWidth > 0) then

     Dec(FCurrentWidth, FIncrementHide)

    else

    begin

     KillTimer(Handle, IDT_DISAPPEARING);

     Hide;

    end;

   end;

  ABE_RIGHT:

   begin

    if (FCurrentWidth > 0) then

    begin

     Inc(FCurrentPosX, FIncrementHide);

     Dec(FCurrentWidth, FIncrementHide);

    end

    else

    begin

     KillTimer(Handle, IDT_DISAPPEARING);

     Hide;

    end;

   end;

  end;

  SetWindowPos(Handle, HWND_TOPMOST, FCurrentPosX, FCurrentPosY,

    FCurrentWidth, FCurrentHeight, SWP_NOACTIVATE);

 end;

end;

Msg.Result := 0;

end;

procedure TTaskbarNotifier.Paint;

var

rcText: TRect;

begin

if FMouseIsOver then

 Canvas.Font.Assign(FSelectedFont)

else

 Canvas.Font.Assign(FNormalFont);

Canvas.Brush.Style := bsClear;

rcText := FTextRect;

DrawText(Canvas.Handle, PChar(Caption), -1, rcText, FTextFormat);

// Canvas.TextRect(rcClient, rcClient.Left, rcClient.Top, Caption);

end;

end.