Click here to Skip to main content
15,887,135 members
Articles / Desktop Programming / MFC

Taskbar Notification Dialog

Rate me:
Please Sign up or sign in to vote.
4.94/5 (67 votes)
11 Jul 20023 min read 681.1K   18.7K   329   185
A MSN IM-style popup notification dialog

Image 1

Introduction

A few weeks ago, I saw an MSN messenger popup class on CodeProject written by Prateek Kaul. Since I needed a taskbar popup with skin support, I decided to write my own new class.

This is my first submission to Codeproject, since I think my code begins to be mature enough to be posted.

Compatibility

This class needs MFC to be either statically or dynamically linked in your project; it has been written, compiled and tested under Visual Studio .NET (but should work with VC6).

How to Use the Class

The class is very easy to use: Just add TaskbarNotifier.h and TaskbarNotifier.cpp into your project, then include TaskbarNotifier.h into your application, add a CTaskbarNotifier member variable in the header file of your Dialog or Window class.

In the OnInitDialog or OnCreate member functions, add the following lines:

C++
m_wndTaskbarNotifier.Create(this);
m_wndTaskbarNotifier.SetSkin(IDB_MY_BITMAP_RESOURCE);
m_wndTaskbarNotifier.SetTextFont("Arial",90,TN_TEXT_NORMAL,TN_TEXT_UNDERLINE);
m_wndTaskbarNotifier.SetTextColor(RGB(0,0,0),RGB(0,0,200));
m_wndTaskbarNotifier.SetTextRect(CRect(10,40,m_wndTaskbarNotifier1.m_nSkinWidth-10,
                                 m_wndTaskbarNotifier1.m_nSkinHeight-25));

Then when you want to show the popup animation, just call anywhere m_wndTaskNotifier.Show("Text to display"); this will show the animation of the window appearing and then disappearing. You can call again the Show() method whenever you want. If the popup was still here, the text is just replaced, if it was disappearing, it maximizes again.

Be sure not to allocate the CTaskbarNotifier each time you want to show a message, because the skinning function takes a little CPU time to generate the region used to make a non rectangular window.

Class Documentation

C++
int Create(CWnd *pWndParent);

Creates the popup window which remains hidden until Show() is called.

C++
BOOL SetSkin(UINT nBitmapID,short red=-1,short green=-1,short blue=-1);
BOOL SetSkin(LPCTSTR szFileName,short red=-1,short green=-1,short blue=-1);

Those two functions assign a skin to the popup, they take as parameter either a Bitmap resource ID or the path of a bitmap file.

The optional parameters are the RGB values for the transparency color for the bitmap. Use these parameters only if you want a non rectangular window; if these parameters are left blank, no Region is created.

C++
void SetTextFont(LPCTSTR szFont,int nSize,int nNormalStyle,int nSelectedStyle);

This function permits to specify the Font used for displaying the text (two styles are possible, one for the normal state and one when the mouse is over the window)

nNormalStyle or nSelectedStyle can be one or a combination of these parameters:

  • TN_TEXT_NORMAL
  • TN_TEXT_BOLD
  • TN_TEXT_ITALIC
  • TN_TEXT_UNDERLINE
C++
void SetTextColor(COLORREF crNormalTextColor,COLORREF crSelectedTextColor);

This function sets the color of the text when in normal or selected state.

C++
void SetTextRect(RECT rcText);

This function allows to define a rectangle within the bitmap which will be the clipping zone for displaying the text.

C++
void Show(LPCTSTR szCaption,DWORD dwTimeToShow=800,DWORD dwTimeToStay=3000,
           DWORD dwTimeToHide=500,int nIncrement=1);

Displays the popup window animation:

  • szCaption: Text to display
  • dwTimeToShow: Duration in milliseconds for the popup to be fully visible
  • dwTimeToStay: Duration in milliseconds for the popup to be stay visible
  • dwTimeToHide: Time in millisecond for the popup to completely disappear
  • nIncrement: Pixel increment for moving the window during the animation (the higher, the faster)

Show can be called even if the popup is already visible, being hiding or showing.

C++
void Hide();

Manually hides the popup.

Additional Notes

When the user clicks on the popup, a message is being sent to its parent window (WM_TASKBARNOTIFIERCLICKED defined in TaskbarNotifier.h), you can intercept it by adding in your Message Map macro:

C++
ON_MESSAGE(WM_TASKBARNOTIFIERCLICKED,OnTaskbarNotifierClicked)

The fact I'm not releasing the HRGN handle is because when you call SetWindowRgn() function, the GDI takes care of the object deletion.

Conclusion

Thanks to Prateek Kaul whose code inspired me to write this class and to Vander Nunes for his article about skinning a window.

I hope this class will be useful to you, if you find any memory or GDI leaks, please let me know. If you have suggestions to enhance the functionalities of this class, please post a comment.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
United States United States
I live in Santa Clara CA and work as a software engineer for SAP Business Objects.

My areas of expertise are user interface developments in Eclipse RCP / SWT / Draw 2D and C#

Comments and Discussions

 
GeneralRe: Fix small problem when TaskBar Notifier occupy focus of MainFrame Pin
jaxclin8811-Jun-07 21:41
jaxclin8811-Jun-07 21:41 
QuestionFor ATL use? Pin
kimi_roy14-Jul-05 23:57
kimi_roy14-Jul-05 23:57 
GeneralIf Taskbar is in autohide Mode Pin
KarstenK29-Jun-05 23:58
mveKarstenK29-Jun-05 23:58 
GeneralUse "SelectFolder" should beware of Drive Volumn Name Pin
Evan Lin5-Jun-05 22:55
Evan Lin5-Jun-05 22:55 
Questionfade-in/out instead of sliding? Pin
flashyjigga16-May-05 4:49
flashyjigga16-May-05 4:49 
AnswerRe: fade-in/out instead of sliding? Pin
Dean Hallman28-Jun-05 11:24
Dean Hallman28-Jun-05 11:24 
QuestionWTL Version? Pin
Dean Hallman9-May-05 5:45
Dean Hallman9-May-05 5:45 
AnswerRe: WTL Version? Pin
WTL Student6-Jun-05 13:44
WTL Student6-Jun-05 13:44 
I actually went through the conversion. so here is the result.
<br />
//	http://www.codeproject.com/dialog/taskbarnotifier.asp<br />
//	Taskbar Notification dialog<br />
// CTaskbarNotifier Header file<br />
// By John O'Byrne - 05 July 2002<br />
<br />
#ifndef __INC_TASKBARNOTIFIER_H__<br />
#define __INC_TASKBARNOTIFIER_H__<br />
<br />
#define WM_TASKBARNOTIFIERCLICKED	WM_USER+123<br />
#define TN_TEXT_NORMAL			0x0000<br />
#define TN_TEXT_BOLD			0x0001<br />
#define TN_TEXT_ITALIC			0x0002<br />
#define TN_TEXT_UNDERLINE		0x0004<br />
<br />
// CTaskbarNotifier<br />
<br />
struct CTaskbarNotifier : CWindowImpl<CTaskbarNotifier, CWindow, CWinTraits<WS_POPUP> ><br />
{<br />
	enum<br />
	{<br />
		IDT_HIDDEN			= 0,<br />
		IDT_APPEARING		= 1,<br />
		IDT_WAITING			= 2,<br />
		IDT_DISAPPEARING	= 3,<br />
<br />
		TASKBAR_ON_TOP		= 1,<br />
		TASKBAR_ON_LEFT		= 2,<br />
		TASKBAR_ON_RIGHT	= 3,<br />
		TASKBAR_ON_BOTTOM	= 4,<br />
	};<br />
<br />
	CTaskbarNotifier()<br />
	{<br />
		m_strCaption = _T("");<br />
		m_bMouseIsOver=FALSE;<br />
		m_hSkinRegion=NULL;<br />
		m_hCursor=NULL;<br />
		m_crNormalTextColor=RGB(133,146,181);<br />
		m_crSelectedTextColor=RGB(10,36,106);<br />
		m_nSkinHeight=0;<br />
		m_nSkinWidth=0;<br />
<br />
		m_dwTimeToShow=0;<br />
		m_dwTimeToLive=0;<br />
		m_dwTimeToHide=0;<br />
		m_dwDelayBetweenShowEvents=0;<br />
		m_dwDelayBetweenHideEvents=0;<br />
		m_nStartPosX=0;<br />
		m_nStartPosY=0;<br />
		m_nCurrentPosX=0;<br />
		m_nCurrentPosY=0;<br />
		m_nIncrement=2;<br />
		m_nTaskbarPlacement=0;<br />
		m_nAnimStatus=IDT_HIDDEN;<br />
		m_rcText.SetRect(0,0,0,0);<br />
	}<br />
<br />
	~CTaskbarNotifier()<br />
	{<br />
		// No need to delete the HRGN,  SetWindowRgn() owns it after being called<br />
	}<br />
<br />
	void Show(LPCTSTR szCaption,DWORD dwTimeToShow=200,DWORD dwTimeToLive=3000,DWORD dwTimeToHide=200,int nIncrement=1)<br />
	{<br />
		unsigned int nDesktopHeight;<br />
		unsigned int nDesktopWidth;<br />
		unsigned int nScreenWidth;<br />
		unsigned int nScreenHeight;<br />
		CRect rcDesktop;<br />
<br />
		m_strCaption	= szCaption;<br />
		m_dwTimeToShow	= dwTimeToShow;<br />
		m_dwTimeToLive	= dwTimeToLive;<br />
		m_dwTimeToHide	= dwTimeToHide;<br />
<br />
		::SystemParametersInfo(SPI_GETWORKAREA,0,&rcDesktop,0);<br />
		nDesktopWidth=rcDesktop.right-rcDesktop.left;<br />
		nDesktopHeight=rcDesktop.bottom-rcDesktop.top;<br />
		nScreenWidth=::GetSystemMetrics(SM_CXSCREEN);<br />
		nScreenHeight=::GetSystemMetrics(SM_CYSCREEN);<br />
<br />
		BOOL bTaskbarOnRight=nDesktopWidth<nScreenWidth && rcDesktop.left==0;<br />
		BOOL bTaskbarOnLeft=nDesktopWidth<nScreenWidth && rcDesktop.left!=0;<br />
		BOOL bTaskBarOnTop=nDesktopHeight<nScreenHeight && rcDesktop.top!=0;<br />
		//BOOL bTaskbarOnBottom=nDesktopHeight<nScreenHeight && rcDesktop.top==0;<br />
<br />
		switch (m_nAnimStatus)<br />
		{<br />
			case IDT_HIDDEN:<br />
				ShowWindow(SW_SHOW);<br />
				if (bTaskbarOnRight)<br />
				{<br />
					m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinWidth/m_nIncrement);<br />
					m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinWidth/m_nIncrement);<br />
					m_nStartPosX=rcDesktop.right;<br />
					m_nStartPosY=rcDesktop.bottom-m_nSkinHeight;<br />
					m_nTaskbarPlacement=TASKBAR_ON_RIGHT;<br />
				}<br />
				else if (bTaskbarOnLeft)<br />
				{<br />
					m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinWidth/m_nIncrement);<br />
					m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinWidth/m_nIncrement);<br />
					m_nStartPosX=rcDesktop.left-m_nSkinWidth;<br />
					m_nStartPosY=rcDesktop.bottom-m_nSkinHeight;<br />
					m_nTaskbarPlacement=TASKBAR_ON_LEFT;<br />
				}<br />
				else if (bTaskBarOnTop)<br />
				{<br />
					m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinHeight/m_nIncrement);<br />
					m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinHeight/m_nIncrement);<br />
					m_nStartPosX=rcDesktop.right-m_nSkinWidth;<br />
					m_nStartPosY=rcDesktop.top-m_nSkinHeight;<br />
					m_nTaskbarPlacement=TASKBAR_ON_TOP;<br />
				}<br />
				else //if (bTaskbarOnBottom)<br />
				{<br />
					// Taskbar is on the bottom or Invisible<br />
					m_dwDelayBetweenShowEvents=m_dwTimeToShow/(m_nSkinHeight/m_nIncrement);<br />
					m_dwDelayBetweenHideEvents=m_dwTimeToHide/(m_nSkinHeight/m_nIncrement);<br />
					m_nStartPosX=rcDesktop.right-m_nSkinWidth;<br />
					m_nStartPosY=rcDesktop.bottom;<br />
					m_nTaskbarPlacement=TASKBAR_ON_BOTTOM;<br />
				}<br />
<br />
				m_nCurrentPosX=m_nStartPosX;<br />
				m_nCurrentPosY=m_nStartPosY;<br />
<br />
				SetTimer(IDT_APPEARING,m_dwDelayBetweenShowEvents);<br />
				break;<br />
<br />
			case IDT_WAITING:<br />
				RedrawWindow();<br />
				KillTimer(IDT_WAITING);<br />
				SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
				break;<br />
<br />
			case IDT_APPEARING:<br />
				RedrawWindow();<br />
				break;<br />
<br />
			case IDT_DISAPPEARING:<br />
				KillTimer(IDT_DISAPPEARING);<br />
				SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
				if (bTaskbarOnRight)<br />
					m_nCurrentPosX=rcDesktop.right-m_nSkinWidth;<br />
				else if (bTaskbarOnLeft)<br />
					m_nCurrentPosX=rcDesktop.left;<br />
				else if (bTaskBarOnTop)<br />
					m_nCurrentPosY=rcDesktop.top;<br />
				else //if (bTaskbarOnBottom)<br />
					m_nCurrentPosY=rcDesktop.bottom-m_nSkinHeight;<br />
<br />
				SetWindowPos(NULL,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);<br />
				RedrawWindow();<br />
				break;<br />
		}<br />
	}<br />
<br />
<br />
	void Hide()<br />
	{<br />
		switch (m_nAnimStatus)<br />
		{<br />
		case IDT_APPEARING:<br />
			KillTimer(IDT_APPEARING);<br />
			break;<br />
		case IDT_WAITING:<br />
			KillTimer(IDT_WAITING);<br />
			break;<br />
		case IDT_DISAPPEARING:<br />
			KillTimer(IDT_DISAPPEARING);<br />
			break;<br />
		}<br />
		MoveWindow(0,0,0,0);<br />
		ShowWindow(SW_HIDE);<br />
		m_nAnimStatus=IDT_HIDDEN;<br />
	}<br />
<br />
	BOOL SetSkin(UINT nBitmapID,short red=-1,short green=-1,short blue=-1)<br />
	{<br />
		BITMAP bm;<br />
<br />
		if (m_biSkinBackground)<br />
			m_biSkinBackground.DeleteObject();<br />
<br />
		if (!m_biSkinBackground.LoadBitmap(nBitmapID))<br />
			return FALSE;<br />
		GetObject(m_biSkinBackground, sizeof(bm), &bm);<br />
		m_nSkinWidth=bm.bmWidth;<br />
		m_nSkinHeight=bm.bmHeight;<br />
		m_rcText.SetRect(0,0,bm.bmWidth,bm.bmHeight);<br />
<br />
		if (red!=-1 && green!=-1 && blue!=-1)<br />
		{<br />
			// No need to delete the HRGN,  SetWindowRgn() owns it after being called<br />
			m_hSkinRegion=GenerateRegion((HBITMAP)m_biSkinBackground,(BYTE) red,(BYTE) green,(BYTE) blue);<br />
			SetWindowRgn(m_hSkinRegion, true);<br />
		}<br />
<br />
		return TRUE;<br />
	}<br />
<br />
	BOOL SetSkin(LPCTSTR szFileName,short red=-1,short green=-1,short blue=-1)<br />
	{<br />
		BITMAP bm;<br />
		HBITMAP hBmp;<br />
<br />
		hBmp=(HBITMAP) ::LoadImage(_Module.m_hInst,szFileName,IMAGE_BITMAP,0,0, LR_LOADFROMFILE);<br />
		if (!hBmp)<br />
			return FALSE;<br />
<br />
		m_biSkinBackground.Attach(hBmp);<br />
		GetObject(m_biSkinBackground, sizeof(bm), &bm);<br />
		m_nSkinWidth=bm.bmWidth;<br />
		m_nSkinHeight=bm.bmHeight;<br />
		m_rcText.SetRect(0,0,bm.bmWidth,bm.bmHeight);<br />
<br />
		if (red!=-1 && green!=-1 && blue!=-1)<br />
		{<br />
			// No need to delete the HRGN,  SetWindowRgn() owns it after being called<br />
			m_hSkinRegion=GenerateRegion((HBITMAP)m_biSkinBackground,(BYTE) red,(BYTE) green,(BYTE) blue);<br />
			SetWindowRgn(m_hSkinRegion, true);<br />
		}<br />
<br />
		return TRUE;<br />
	}<br />
<br />
	void SetTextFont(LPCTSTR szFont,int nSize,int nNormalStyle,int nSelectedStyle)<br />
	{<br />
		LOGFONT lf;<br />
		if (m_myNormalFont)<br />
			m_myNormalFont.DeleteObject();<br />
		m_myNormalFont.CreatePointFont(nSize,szFont);<br />
		m_myNormalFont.GetLogFont(&lf);<br />
<br />
		// We  set the Font of the unselected ITEM<br />
		if (nNormalStyle & TN_TEXT_BOLD)<br />
			lf.lfWeight = FW_BOLD;<br />
		else<br />
			lf.lfWeight = FW_NORMAL;<br />
<br />
		if (nNormalStyle & TN_TEXT_ITALIC)<br />
			lf.lfItalic=TRUE;<br />
		else<br />
			lf.lfItalic=FALSE;<br />
<br />
		if (nNormalStyle & TN_TEXT_UNDERLINE)<br />
			lf.lfUnderline=TRUE;<br />
		else<br />
			lf.lfUnderline=FALSE;<br />
<br />
		if (m_myNormalFont)<br />
			m_myNormalFont.DeleteObject();<br />
		m_myNormalFont.CreateFontIndirect(&lf);<br />
<br />
		// We set the Font of the selected ITEM<br />
		if (nSelectedStyle & TN_TEXT_BOLD)<br />
			lf.lfWeight = FW_BOLD;<br />
		else<br />
			lf.lfWeight = FW_NORMAL;<br />
<br />
		if (nSelectedStyle & TN_TEXT_ITALIC)<br />
			lf.lfItalic=TRUE;<br />
		else<br />
			lf.lfItalic=FALSE;<br />
<br />
		if (nSelectedStyle & TN_TEXT_UNDERLINE)<br />
			lf.lfUnderline=TRUE;<br />
		else<br />
			lf.lfUnderline=FALSE;<br />
<br />
		if (m_mySelectedFont)<br />
			m_mySelectedFont.DeleteObject();<br />
		m_mySelectedFont.CreateFontIndirect(&lf);<br />
	}<br />
<br />
<br />
	void SetTextColor(COLORREF crNormalTextColor,COLORREF crSelectedTextColor)<br />
	{<br />
		m_crNormalTextColor=crNormalTextColor;<br />
		m_crSelectedTextColor=crSelectedTextColor;<br />
		RedrawWindow();<br />
	}<br />
<br />
	void SetTextRect(RECT rcText)<br />
	{<br />
		m_rcText = rcText;<br />
	}<br />
<br />
	CFont		m_myNormalFont;<br />
	CFont		m_mySelectedFont;<br />
	COLORREF	m_crNormalTextColor;<br />
	COLORREF	m_crSelectedTextColor;<br />
	HCURSOR		m_hCursor;<br />
<br />
	CBitmap		m_biSkinBackground;<br />
	HRGN		m_hSkinRegion;<br />
	CRect		m_rcText;<br />
<br />
	CString		m_strCaption;<br />
<br />
 	DWORD		m_dwTimeToShow;<br />
	DWORD		m_dwTimeToLive;<br />
	DWORD		m_dwTimeToHide;<br />
	DWORD		m_dwDelayBetweenShowEvents;<br />
	DWORD		m_dwDelayBetweenHideEvents;<br />
<br />
	int			m_nSkinWidth		: 16;<br />
	int			m_nSkinHeight		: 16;<br />
	int			m_nStartPosX		: 16;<br />
	int			m_nStartPosY		: 16;<br />
	int			m_nCurrentPosX		: 16;<br />
	int			m_nCurrentPosY		: 16;<br />
	BOOL		m_bMouseIsOver		: 1;<br />
	int			m_nAnimStatus		: 4;<br />
	int			m_nTaskbarPlacement	: 4;<br />
	int			m_nIncrement		: 8;<br />
<br />
protected:<br />
	BYTE* Get24BitPixels(HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight)<br />
	{<br />
		BITMAP bmpBmp;<br />
		LPBITMAPINFO pbmiInfo;<br />
		BITMAPINFO bmiInfo;<br />
		WORD wBmpWidth, wBmpHeight;<br />
<br />
		GetObject(pBitmap, sizeof(bmpBmp),&bmpBmp);<br />
		pbmiInfo   = (LPBITMAPINFO)&bmpBmp;<br />
<br />
		wBmpWidth  = (WORD)pbmiInfo->bmiHeader.biWidth;<br />
		wBmpWidth  = (WORD)(wBmpWidth - (wBmpWidth%4));<br />
		wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight;<br />
<br />
		*pwWidth  = wBmpWidth;<br />
		*pwHeight = wBmpHeight;<br />
<br />
		BYTE *pPixels = new BYTE[wBmpWidth*wBmpHeight*3];<br />
		if (!pPixels) return NULL;<br />
<br />
		HDC hDC =::GetWindowDC(NULL);<br />
<br />
		bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);<br />
		bmiInfo.bmiHeader.biWidth = wBmpWidth;<br />
		bmiInfo.bmiHeader.biHeight = -wBmpHeight;<br />
		bmiInfo.bmiHeader.biPlanes = 1;<br />
		bmiInfo.bmiHeader.biBitCount = 24;<br />
		bmiInfo.bmiHeader.biCompression = BI_RGB;<br />
		bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3;<br />
		bmiInfo.bmiHeader.biXPelsPerMeter = 0;<br />
		bmiInfo.bmiHeader.biYPelsPerMeter = 0;<br />
		bmiInfo.bmiHeader.biClrUsed = 0;<br />
		bmiInfo.bmiHeader.biClrImportant = 0;<br />
<br />
		// get pixels from the original bitmap converted to 24bits<br />
		int iRes = GetDIBits(hDC,pBitmap,0,wBmpHeight,(LPVOID)pPixels,&bmiInfo,DIB_RGB_COLORS);<br />
<br />
		// release the device context<br />
		::ReleaseDC(NULL,hDC);<br />
<br />
		// if failed, cancel the operation.<br />
		if (!iRes)<br />
		{<br />
			delete pPixels;<br />
			return NULL;<br />
		};<br />
<br />
		// return the pixel array<br />
		return pPixels;<br />
	}<br />
<br />
	HRGN GenerateRegion(HBITMAP hBitmap, BYTE red, BYTE green, BYTE blue)<br />
	{<br />
		WORD wBmpWidth,wBmpHeight;<br />
		HRGN hRgn, hTmpRgn;<br />
<br />
		// 24bit pixels from the bitmap<br />
		BYTE *pPixels = Get24BitPixels(hBitmap, &wBmpWidth, &wBmpHeight);<br />
		if (!pPixels) return NULL;<br />
<br />
		// create our working region<br />
		hRgn = CreateRectRgn(0,0,wBmpWidth,wBmpHeight);<br />
		if (!hRgn)<br />
		{<br />
			delete pPixels;<br />
			return NULL;<br />
		}<br />
<br />
		DWORD p=0;<br />
		for (WORD y=0; y<wBmpHeight; y++)<br />
		{<br />
			for (WORD x=0; x<wBmpWidth; x++)<br />
			{<br />
				BYTE jRed   = pPixels[p+2];<br />
				BYTE jGreen = pPixels[p+1];<br />
				BYTE jBlue  = pPixels[p+0];<br />
<br />
				if (jRed==red && jGreen==green && jBlue==blue)<br />
				{<br />
					// remove transparent color from region<br />
					hTmpRgn = CreateRectRgn(x,y,x+1,y+1);<br />
					CombineRgn(hRgn, hRgn, hTmpRgn, RGN_XOR);<br />
					DeleteObject(hTmpRgn);<br />
				}<br />
<br />
				// next pixel<br />
				p+=3;<br />
			}<br />
		}<br />
<br />
		// release pixels<br />
		delete []pPixels;<br />
<br />
		// return the region<br />
		return hRgn;<br />
	}<br />
<br />
protected:<br />
	BEGIN_MSG_MAP(CTaskbarNotifier);<br />
		switch( uMsg )<br />
		{<br />
		case WM_CREATE:		lResult = OnCreate(); return TRUE;<br />
		case WM_MOUSEMOVE:	OnMouseMove(wParam, lParam); break;<br />
		case WM_ERASEBKGND:	lResult = OnEraseBkgnd( (HDC)wParam ); return TRUE;<br />
		case WM_PAINT:		OnPaint(); return TRUE;<br />
		case WM_MOUSELEAVE: OnMouseLeave(); return TRUE;<br />
		case WM_MOUSEHOVER: OnMouseHover(); return TRUE;<br />
		case WM_SETCURSOR:	lResult = OnSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam)); return TRUE;<br />
		case WM_LBUTTONUP:	OnLButtonUp(wParam, lParam); break;<br />
		case WM_TIMER:		OnTimer(wParam); break;<br />
		}<br />
	END_MSG_MAP()<br />
<br />
public:<br />
	int OnCreate()<br />
	{<br />
		if (DefWindowProc() == -1)<br />
			return -1;<br />
<br />
		m_hCursor = ::LoadCursor(NULL, IDC_HAND);<br />
		return 0;<br />
	}<br />
<br />
	BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)<br />
	{<br />
		if (nHitTest == HTCLIENT)<br />
		{<br />
			::SetCursor(m_hCursor);<br />
			return TRUE;<br />
		}<br />
		return DefWindowProc();<br />
	}<br />
<br />
	void OnMouseMove(UINT nFlags, CPoint point)<br />
	{<br />
		TRACKMOUSEEVENT t_MouseEvent;<br />
		t_MouseEvent.cbSize      = sizeof(TRACKMOUSEEVENT);<br />
		t_MouseEvent.dwFlags     = TME_LEAVE | TME_HOVER;<br />
		t_MouseEvent.hwndTrack   = m_hWnd;<br />
		t_MouseEvent.dwHoverTime = 1;<br />
<br />
		::_TrackMouseEvent(&t_MouseEvent);<br />
	}<br />
<br />
	void OnLButtonUp(UINT nFlags, CPoint point)<br />
	{<br />
		CWindow(GetParent()).PostMessage(WM_TASKBARNOTIFIERCLICKED,0,0);<br />
	}<br />
<br />
	void OnMouseHover()<br />
	{<br />
		if (m_bMouseIsOver==FALSE)<br />
		{<br />
			m_bMouseIsOver=TRUE;<br />
			RedrawWindow();<br />
		}<br />
	}<br />
<br />
	void OnMouseLeave()<br />
	{<br />
		if (m_bMouseIsOver==TRUE)<br />
		{<br />
			m_bMouseIsOver=FALSE;<br />
			RedrawWindow();<br />
		}<br />
	}<br />
<br />
	BOOL OnEraseBkgnd(CDCHandle dc)<br />
	{<br />
		CDC memDC;<br />
		HBITMAP hOldBitmap;<br />
		BITMAP bm;<br />
<br />
		memDC.CreateCompatibleDC(dc);<br />
		GetObject(m_biSkinBackground, sizeof(bm), &bm);<br />
		hOldBitmap=memDC.SelectBitmap(m_biSkinBackground);<br />
<br />
		dc.BitBlt(0,0,bm.bmWidth,bm.bmHeight,memDC,0,0,SRCCOPY);<br />
		memDC.SelectBitmap(hOldBitmap);<br />
<br />
		return TRUE;<br />
	}<br />
<br />
	void OnPaint()<br />
	{<br />
		CPaintDC dc(m_hWnd);<br />
		CRect rcClient;<br />
		HFONT pOldFont;<br />
<br />
		if (m_bMouseIsOver)<br />
		{<br />
			dc.SetTextColor(m_crSelectedTextColor);<br />
			pOldFont=dc.SelectFont(m_mySelectedFont);<br />
		}<br />
		else<br />
		{<br />
			dc.SetTextColor(m_crNormalTextColor);<br />
			pOldFont=dc.SelectFont(m_myNormalFont);<br />
		}<br />
<br />
		dc.SetBkMode(TRANSPARENT);<br />
		rcClient.DeflateRect(10,20,10,20);<br />
		if (m_strCaption)<br />
			dc.DrawText(m_strCaption,m_strCaption.GetLength(),m_rcText,DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_END_ELLIPSIS);<br />
<br />
		dc.SelectFont(pOldFont);<br />
	}<br />
<br />
	void OnTimer(UINT nIDEvent)<br />
	{<br />
		switch (nIDEvent)<br />
		{<br />
		case IDT_APPEARING:<br />
			m_nAnimStatus=IDT_APPEARING;<br />
			switch(m_nTaskbarPlacement)<br />
			{<br />
			case TASKBAR_ON_BOTTOM:<br />
				if (m_nCurrentPosY>(m_nStartPosY-m_nSkinHeight))<br />
					m_nCurrentPosY-=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_APPEARING);<br />
					SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
					m_nAnimStatus=IDT_WAITING;<br />
				}<br />
				break;<br />
			case TASKBAR_ON_TOP:<br />
				if ((m_nCurrentPosY-m_nStartPosY)<m_nSkinHeight)<br />
					m_nCurrentPosY+=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_APPEARING);<br />
					SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
					m_nAnimStatus=IDT_WAITING;<br />
				}<br />
				break;<br />
			case TASKBAR_ON_LEFT:<br />
				if ((m_nCurrentPosX-m_nStartPosX)<m_nSkinWidth)<br />
					m_nCurrentPosX+=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_APPEARING);<br />
					SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
					m_nAnimStatus=IDT_WAITING;<br />
				}<br />
				break;<br />
			case TASKBAR_ON_RIGHT:<br />
				if (m_nCurrentPosX>(m_nStartPosX-m_nSkinWidth))<br />
					m_nCurrentPosX-=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_APPEARING);<br />
					SetTimer(IDT_WAITING,m_dwTimeToLive);<br />
					m_nAnimStatus=IDT_WAITING;<br />
				}<br />
				break;<br />
			}<br />
			SetWindowPos(NULL,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);<br />
			//RedrawWindow();<br />
			break;<br />
<br />
		case IDT_WAITING:<br />
			KillTimer(IDT_WAITING);<br />
			SetTimer(IDT_DISAPPEARING,m_dwDelayBetweenHideEvents);<br />
			break;<br />
<br />
		case IDT_DISAPPEARING:<br />
			m_nAnimStatus=IDT_DISAPPEARING;<br />
			switch(m_nTaskbarPlacement)<br />
			{<br />
			case TASKBAR_ON_BOTTOM:<br />
				if (m_nCurrentPosY<m_nStartPosY)<br />
					m_nCurrentPosY+=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_DISAPPEARING);<br />
					Hide();<br />
				}<br />
				break;<br />
			case TASKBAR_ON_TOP:<br />
				if (m_nCurrentPosY>m_nStartPosY)<br />
					m_nCurrentPosY-=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_DISAPPEARING);<br />
					Hide();<br />
				}<br />
				break;<br />
			case TASKBAR_ON_LEFT:<br />
				if (m_nCurrentPosX>m_nStartPosX)<br />
					m_nCurrentPosX-=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_DISAPPEARING);<br />
					Hide();<br />
				}<br />
				break;<br />
			case TASKBAR_ON_RIGHT:<br />
				if (m_nCurrentPosX<m_nStartPosX)<br />
					m_nCurrentPosX+=m_nIncrement;<br />
				else<br />
				{<br />
					KillTimer(IDT_DISAPPEARING);<br />
					Hide();<br />
				}<br />
				break;<br />
			}<br />
			SetWindowPos(NULL,m_nCurrentPosX,m_nCurrentPosY,m_nSkinWidth,m_nSkinHeight,SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOACTIVATE);<br />
			//RedrawWindow();<br />
			break;<br />
		}<br />
	}<br />
};<br />
<br />
#endif  // __INC_TASKBARNOTIFIER_H__<br />
<br />

GeneralRe: WTL Version? Pin
Dean Hallman6-Jun-05 17:34
Dean Hallman6-Jun-05 17:34 
GeneralHelp Pin
Member 172672019-Mar-05 18:49
Member 172672019-Mar-05 18:49 
QuestionCan you convert this to a component? Pin
Mr. Say_how_it_is18-Mar-05 5:51
Mr. Say_how_it_is18-Mar-05 5:51 
AnswerRe: Can you convert this to a component? Pin
John O'Byrne18-Mar-05 7:33
John O'Byrne18-Mar-05 7:33 
GeneralRe: Can you convert this to a component? Pin
Mr. Say_how_it_is19-Mar-05 7:27
Mr. Say_how_it_is19-Mar-05 7:27 
GeneralPopup parent (fixed) Pin
Max Santos31-Dec-04 5:06
Max Santos31-Dec-04 5:06 
GeneralRe: Popup parent (fixed) Pin
cnss22-Feb-05 9:21
cnss22-Feb-05 9:21 
GeneralRe: Popup parent (fixed) Pin
Max Santos14-Mar-05 13:00
Max Santos14-Mar-05 13:00 
GeneralRe: Popup parent (fixed) Pin
alfonsopilato21-Nov-06 16:16
alfonsopilato21-Nov-06 16:16 
GeneralRe: Popup parent (fixed) Pin
Max Santos14-Mar-05 12:59
Max Santos14-Mar-05 12:59 
GeneralRe: Popup parent (fixed) Pin
boytony25-Sep-05 16:06
boytony25-Sep-05 16:06 
GeneralRe: Popup parent (fixed) Pin
Aji Varghese Tera12-May-06 10:48
Aji Varghese Tera12-May-06 10:48 
Generalm_nIncrement Pin
Max Santos18-Dec-04 8:15
Max Santos18-Dec-04 8:15 
GeneralTaskbarnotifier without a dialog Pin
PeteMoody25-Nov-04 2:53
PeteMoody25-Nov-04 2:53 
Generalalert window hangs Pin
coolcoolyogs5-Nov-04 13:06
coolcoolyogs5-Nov-04 13:06 
GeneralRe: alert window hangs Pin
Member 72341122-Sep-05 3:20
Member 72341122-Sep-05 3:20 
Generalbelow i wanted to say &quot;TopMost&quot;, not &quot;focus&quot;, sorry again. Pin
dido2k27-Oct-04 11:36
dido2k27-Oct-04 11:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.