📄 taskbarnotifier.cpp
字号:
/*
TaskbarNotifier.cpp
Maneja cuadro de mensaje animado con hyperlink y bitmap.
Autor : John O'Byrne - 15 July 2002
*/
// TaskbarNotifier.cpp : implementation file
// By John O'Byrne
// 11 August 2002: - Timer precision is now determined automatically
// Complete change in the way the popup is showing (thanks to this,now the popup can be always on top, it shows even while watching a movie)
// The popup doesn't steal the focus anymore (by replacing ShowWindow(SW_SHOW) by ShowWindow(SW_SHOWNOACTIVATE))
// Thanks to Daniel Lohmann, update in the way the taskbar pos is determined (more flexible now)
// 17 July 2002: - Another big Change in the method for determining the pos of the taskbar (using the SHAppBarMessage function)
// 16 July 2002: - Thanks to the help of Daniel Lohmann, the Show Function timings work perfectly now ;)
// 15 July 2002: - Change in the method for determining the pos of the taskbar
// (now handles the presence of quick launch or any other bar).
// Remove the Handlers for WM_CREATE and WM_DESTROY
// SetSkin is now called SetBitmap
// 14 July 2002: - Changed the GenerateRegion func by a new one (to correct a win98 bug)
// cambios por Sergio Scarnatto:
// [2/1/2003] : Verificaci髇 de fin de desplazamiento en OnTimer ten韆 bug.
#include "stdafx.h"
#include "TaskbarNotifier.h"
#define IDT_HIDDEN 0
#define IDT_APPEARING 1
#define IDT_WAITING 2
#define IDT_DISAPPEARING 3
#define TASKBAR_X_TOLERANCE 40
#define TASKBAR_Y_TOLERANCE 40
inline bool NearlyEqual(int a, int b, int epsilon)
{
return abs(a - b) < epsilon / 2;
}
// CTaskbarNotifier
IMPLEMENT_DYNAMIC(CTaskbarNotifier, CWnd)
CTaskbarNotifier::CTaskbarNotifier()
{
m_strCaption = "";
m_pWndParent = NULL;
m_bMouseIsOver = FALSE;
m_hBitmapRegion = NULL;
m_hCursor = NULL;
m_crNormalTextColor = RGB(133, 146, 181);
m_crSelectedTextColor = RGB(10, 36, 106);
m_nBitmapHeight = 0;
m_nBitmapWidth = 0;
m_dwTimeToStay = 0;
m_dwShowEvents = 0;
m_dwHideEvents = 0;
m_nCurrentPosX = 0;
m_nCurrentPosY = 0;
m_nCurrentWidth = 0;
m_nCurrentHeight = 0;
m_nIncrementShow = 0;
m_nIncrementHide = 0;
m_nTaskbarPlacement = ABE_BOTTOM;
m_nAnimStatus = IDT_HIDDEN;
m_rcText.SetRect(0, 0, 0, 0);
m_uTextFormat = DT_CENTER | DT_VCENTER | DT_WORDBREAK | DT_END_ELLIPSIS; // Default Text format (see DrawText in the win32 API for the different values)
m_hCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(32649)); // System Hand cursor
// If running on NT, timer precision is 10 ms, if not timer precision is 50 ms
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
m_dwTimerPrecision = 10;
else
m_dwTimerPrecision = 50;
SetTextDefaultFont(); // We use default GUI Font
}
CTaskbarNotifier::~CTaskbarNotifier()
{
// No need to delete the HRGN, SetWindowRgn() owns it after being called
}
int CTaskbarNotifier::Create(CWnd *pWndParent)
{
ASSERT(pWndParent != NULL);
m_pWndParent = pWndParent;
WNDCLASSEX wcx;
wcx.cbSize = sizeof(wcx);
wcx.lpfnWndProc = AfxWndProc;
wcx.style = CS_DBLCLKS | CS_SAVEBITS;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = AfxGetInstanceHandle();
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground=::GetSysColorBrush(COLOR_WINDOW);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = "TaskbarNotifierClass";
wcx.hIconSm = NULL;
ATOM classAtom = RegisterClassEx(&wcx);
return CreateEx(WS_EX_TOPMOST, "TaskbarNotifierClass", NULL, WS_POPUP, 0, 0, 0, 0, pWndParent->m_hWnd, NULL);
}
void CTaskbarNotifier::SetTextFont(LPCTSTR szFont, int nSize, int nNormalStyle, int nSelectedStyle)
{
LOGFONT lf;
m_myNormalFont.DeleteObject();
m_myNormalFont.CreatePointFont(nSize, szFont);
m_myNormalFont.GetLogFont(&lf);
// We set the Font of the unselected ITEM
if (nNormalStyle & TN_TEXT_BOLD)
lf.lfWeight = FW_BOLD;
else
lf.lfWeight = FW_NORMAL;
if (nNormalStyle & TN_TEXT_ITALIC)
lf.lfItalic = TRUE;
else
lf.lfItalic = FALSE;
if (nNormalStyle & TN_TEXT_UNDERLINE)
lf.lfUnderline = TRUE;
else
lf.lfUnderline = FALSE;
m_myNormalFont.DeleteObject();
m_myNormalFont.CreateFontIndirect(&lf);
// We set the Font of the selected ITEM
if (nSelectedStyle & TN_TEXT_BOLD)
lf.lfWeight = FW_BOLD;
else
lf.lfWeight = FW_NORMAL;
if (nSelectedStyle & TN_TEXT_ITALIC)
lf.lfItalic = TRUE;
else
lf.lfItalic = FALSE;
if (nSelectedStyle & TN_TEXT_UNDERLINE)
lf.lfUnderline = TRUE;
else
lf.lfUnderline = FALSE;
m_mySelectedFont.DeleteObject();
m_mySelectedFont.CreateFontIndirect(&lf);
}
void CTaskbarNotifier::SetTextDefaultFont()
{
LOGFONT lf;
CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT));
pFont->GetLogFont(&lf);
m_myNormalFont.DeleteObject();
m_mySelectedFont.DeleteObject();
m_myNormalFont.CreateFontIndirect(&lf);
lf.lfUnderline = TRUE;
m_mySelectedFont.CreateFontIndirect(&lf);
}
void CTaskbarNotifier::SetTextColor(COLORREF crNormalTextColor, COLORREF crSelectedTextColor)
{
m_crNormalTextColor = crNormalTextColor;
m_crSelectedTextColor = crSelectedTextColor;
RedrawWindow();
}
void CTaskbarNotifier::SetTextRect(RECT rcText)
{
m_rcText = rcText;
}
void CTaskbarNotifier::SetTextFormat(UINT uTextFormat)
{
m_uTextFormat = uTextFormat;
}
BOOL CTaskbarNotifier::SetBitmap(UINT nBitmapID, short red, short green, short blue)
{
BITMAP bm;
m_bitmapBackground.DeleteObject();
if (!m_bitmapBackground.LoadBitmap(nBitmapID))
return FALSE;
GetObject(m_bitmapBackground.GetSafeHandle(), sizeof(bm), &bm);
m_nBitmapWidth = bm.bmWidth;
m_nBitmapHeight = bm.bmHeight;
m_rcText.SetRect(0, 0, bm.bmWidth, bm.bmHeight);
if (red!=-1 && green!=-1 && blue!=-1)
{
// No need to delete the HRGN, SetWindowRgn() owns it after being called
m_hBitmapRegion = CreateRgnFromBitmap((HBITMAP)m_bitmapBackground.GetSafeHandle(), RGB(red, green, blue));
SetWindowRgn(m_hBitmapRegion, true);
}
return TRUE;
}
BOOL CTaskbarNotifier::SetBitmap(LPCTSTR szFileName, short red, short green, short blue)
{
BITMAP bm;
HBITMAP hBmp;
hBmp = (HBITMAP) ::LoadImage(AfxGetInstanceHandle(), szFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (!hBmp)
return FALSE;
m_bitmapBackground.DeleteObject();
m_bitmapBackground.Attach(hBmp);
GetObject(m_bitmapBackground.GetSafeHandle(), sizeof(bm), &bm);
m_nBitmapWidth = bm.bmWidth;
m_nBitmapHeight = bm.bmHeight;
m_rcText.SetRect(0, 0, bm.bmWidth, bm.bmHeight);
if (red!=-1 && green!=-1 && blue!=-1)
{
// No need to delete the HRGN, SetWindowRgn() owns it after being called
m_hBitmapRegion = CreateRgnFromBitmap((HBITMAP)m_bitmapBackground.GetSafeHandle(), RGB(red, green, blue));
SetWindowRgn(m_hBitmapRegion, true);
}
return TRUE;
}
void CTaskbarNotifier::Show(LPCTSTR szCaption, DWORD dwTimeToShow, DWORD dwTimeToStay, DWORD dwTimeToHide)
{
UINT nScreenWidth;
UINT nScreenHeight;
UINT nEvents;
UINT nBitmapSize;
CRect rcTaskbar;
m_strCaption = szCaption;
m_dwTimeToStay = dwTimeToStay;
nScreenWidth=::GetSystemMetrics(SM_CXSCREEN);
nScreenHeight=::GetSystemMetrics(SM_CYSCREEN);
HWND hWndTaskbar = ::FindWindow("Shell_TrayWnd", 0);
::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) && NearlyEqual(rcTaskbar.right, nScreenWidth, TASKBAR_X_TOLERANCE))
{
// Taskbar is on top or on bottom
m_nTaskbarPlacement = NearlyEqual(rcTaskbar.top, 0, TASKBAR_Y_TOLERANCE) ? ABE_TOP : ABE_BOTTOM;
nBitmapSize = m_nBitmapHeight;
}
else
{
// Taskbar is on left or on right
m_nTaskbarPlacement = NearlyEqual(rcTaskbar.left, 0, TASKBAR_X_TOLERANCE) ? ABE_LEFT : ABE_RIGHT;
nBitmapSize = m_nBitmapWidth;
}
// We calculate the pixel increment and the timer value for the showing animation
if (dwTimeToShow > m_dwTimerPrecision)
{
nEvents = min((dwTimeToShow / m_dwTimerPrecision), nBitmapSize);
m_dwShowEvents = dwTimeToShow / nEvents;
m_nIncrementShow = nBitmapSize / nEvents;
}
else
{
m_dwShowEvents = m_dwTimerPrecision;
m_nIncrementShow = nBitmapSize;
}
// We calculate the pixel increment and the timer value for the hiding animation
if (dwTimeToHide > m_dwTimerPrecision)
{
nEvents = min((dwTimeToHide / m_dwTimerPrecision), nBitmapSize);
m_dwHideEvents = dwTimeToHide / nEvents;
m_nIncrementHide = nBitmapSize / nEvents;
}
else
{
m_dwShowEvents = m_dwTimerPrecision;
m_nIncrementHide = nBitmapSize;
}
// Compute init values for the animation
switch (m_nAnimStatus)
{
case IDT_HIDDEN:
if (m_nTaskbarPlacement == ABE_RIGHT)
{
m_nCurrentPosX = rcTaskbar.left;
m_nCurrentPosY = rcTaskbar.bottom - m_nBitmapHeight;
m_nCurrentWidth = 0;
m_nCurrentHeight = m_nBitmapHeight;
}
else if (m_nTaskbarPlacement == ABE_LEFT)
{
m_nCurrentPosX = rcTaskbar.right;
m_nCurrentPosY = rcTaskbar.bottom - m_nBitmapHeight;
m_nCurrentWidth = 0;
m_nCurrentHeight = m_nBitmapHeight;
}
else if (m_nTaskbarPlacement == ABE_TOP)
{
m_nCurrentPosX = rcTaskbar.right - m_nBitmapWidth;
m_nCurrentPosY = rcTaskbar.bottom;
m_nCurrentWidth = m_nBitmapWidth;
m_nCurrentHeight = 0;
}
else // if (m_nTaskbarPlacement==ABE_BOTTOM)
{
// Taskbar is on the bottom or Invisible
m_nCurrentPosX = rcTaskbar.right - m_nBitmapWidth;
m_nCurrentPosY = rcTaskbar.top;
m_nCurrentWidth = m_nBitmapWidth;
m_nCurrentHeight = 0;
}
ShowWindow(SW_SHOWNOACTIVATE);
SetTimer(IDT_APPEARING, m_dwShowEvents, NULL);
break;
case IDT_APPEARING:
RedrawWindow();
break;
case IDT_WAITING:
RedrawWindow();
KillTimer(IDT_WAITING);
SetTimer(IDT_WAITING, m_dwTimeToStay, NULL);
break;
case IDT_DISAPPEARING:
KillTimer(IDT_DISAPPEARING);
SetTimer(IDT_WAITING, m_dwTimeToStay, NULL);
if (m_nTaskbarPlacement == ABE_RIGHT)
{
m_nCurrentPosX = rcTaskbar.left - m_nBitmapWidth;
m_nCurrentWidth = m_nBitmapWidth;
}
else if (m_nTaskbarPlacement == ABE_LEFT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -