?? balloonhelp.cpp
字號:
PositionWindow();
}
// Sets the URL to be opened when balloon is clicked. Pass "" to disable.
void CBalloonHelp::SetURL(const CString& strURL)
{
m_strURL = strURL;
}
// Sets the number of milliseconds the balloon can remain open. Set to 0 to disable timeout.
void CBalloonHelp::SetTimeout(unsigned int unTimeout)
{
m_unTimeout = unTimeout;
// if timer is already set, reset.
if ( NULL != m_hWnd )
{
if ( m_unTimeout > 0 ) { m_unTimerClose = SetTimer(ID_TIMER_CLOSE, m_unTimeout, NULL); } else { KillTimer(m_unTimerClose); } }}
// Sets the point to which the balloon is "anchored"
void CBalloonHelp::SetAnchorPoint(CPoint ptAnchor, CWnd* pWndAnchor /*= NULL*/)
{
m_ptAnchor = ptAnchor;
m_hwndAnchor = pWndAnchor->GetSafeHwnd();
// if we're anchored to a window, set hook
if ( NULL != m_hwndAnchor )
SetCallWndRetHook();
else
RemoveCallWndRetHook();
// if already visible, move
if ( NULL != m_hWnd )
{
// reposition
PositionWindow();
}
}
// Sets the title of the balloon
void CBalloonHelp::SetTitle(const CString& strTitle)
{
SetWindowText(strTitle);
// if already visible, resize & move
if ( NULL != m_hWnd )
PositionWindow();
}
// Sets the content of the balloon (plain text only)
void CBalloonHelp::SetContent(const CString& strContent)
{
m_strContent = strContent;
// if already visible, resize & move
if ( NULL != m_hWnd )
PositionWindow();
}
// Sets the forground (text and border) color of the balloon
void CBalloonHelp::SetForegroundColor(COLORREF crForeground)
{
m_crForeground = crForeground;
// repaint if visible
if ( NULL != m_hWnd )
Invalidate(FALSE);
}
// Sets the background color of the balloon
void CBalloonHelp::SetBackgroundColor(COLORREF crBackground)
{
m_crBackground = crBackground;
// repaint if visible
if ( NULL != m_hWnd )
Invalidate(FALSE);
}
// Sets the distance the mouse must move before the balloon closes when the unCLOSE_ON_MOUSE_MOVE option is set.
void CBalloonHelp::SetMouseMoveTolerance(int nTolerance)
{
m_nMouseMoveTolerance = nTolerance;
}
//// creates a new balloon window// Parameters:// strTitle | Title of balloon// strContent | Content of balloon// ptAnchor | point tail of balloon will be "anchor"ed to// unOptions | One or more of:// : unCLOSE_ON_LBUTTON_UP | closes window on WM_LBUTTON_UP// : unCLOSE_ON_MBUTTON_UP | closes window on WM_MBUTTON_UP// : unCLOSE_ON_RBUTTON_UP | closes window on WM_RBUTTON_UP// : unCLOSE_ON_LBUTTON_DOWN | closes window on WM_LBUTTON_DOWN// : unCLOSE_ON_MBUTTON_DOWN | closes window on WM_MBUTTON_DOWN// : unCLOSE_ON_RBUTTON_DOWN | closes window on WM_RBUTTON_DOWN// : unCLOSE_ON_MOUSE_MOVE | closes window when user moves mouse past threshhold// : unCLOSE_ON_KEYPRESS | closes window on the next keypress message sent to this thread.// : unCLOSE_ON_ANYTHING | all of the above.// : unDELAY_CLOSE | when a user action triggers the close, begins timer. closes when timer expires.// : unDELETE_THIS_ON_CLOSE | deletes object when window is closed. Used by LaunchBalloon(), use with care// : unSHOW_CLOSE_BUTTON | shows close button in upper right// : unSHOW_INNER_SHADOW | draw inner shadow in balloon// : unSHOW_TOPMOST | place balloon above all other windows// : unDISABLE_XP_SHADOW | disable Windows XP's drop-shadow effect (overrides system and user settings)// : unDISABLE_FADE | disable the fade-in/fade-out effects (overrides system and user settings)// : unDISABLE_FADEIN | disable the fade-in effect// : unDISABLE_FADEOUT | disable the fade-out effect// pParentWnd | Parent window. If NULL will be set to AfxGetMainWnd() and anchor to screen// strURL | If not empty, when the balloon is clicked ShellExecute() will// | be called, with strURL passed in.// unTimeout | If not 0, balloon will automatically close after unTimeout milliseconds.// hIcon | If not NULL, the icon indicated by hIcon will be displayed at top-left of the balloon.//// Returns:// TRUE if successful, else FALSE//BOOL CBalloonHelp::Create(const CString& strTitle, const CString& strContent,
const CPoint& ptAnchor, unsigned int unOptions,
CWnd* pParentWnd /*=NULL*/,
const CString strURL /*= ""*/,
unsigned int unTimeout /*= 0*/,
HICON hIcon /*= NULL*/)
{
m_strContent = strContent;
SetAnchorPoint(ptAnchor, pParentWnd);
m_unOptions = unOptions;
m_strURL = strURL;
m_unTimeout = unTimeout;
if ( NULL != hIcon )
SetIcon(hIcon);
pParentWnd = GetSafeOwner(pParentWnd); if ( NULL == pParentWnd ) { // something is wrong; MFC should be able to find a main window. ASSERT(FALSE); return FALSE; } // if no fonts set, use defaults if ( NULL == m_pContentFont ) { m_pContentFont = new CFont; if ( !m_pContentFont->CreateStockObject(DEFAULT_GUI_FONT) ) return FALSE; } // title font defaults to bold version of content font if ( NULL == m_pTitleFont ) { m_pTitleFont = new CFont; LOGFONT LogFont; m_pContentFont->GetLogFont(&LogFont); LogFont.lfWeight = FW_BOLD; if ( !m_pTitleFont->CreateFontIndirect(&LogFont) ) return FALSE; } ATOM wndClass = GetClassAtom(!(m_unOptions&unDISABLE_XP_SHADOW)); if ( NULL == wndClass ) // couldn't register class return FALSE; // check system settings: if fade effects are disabled or unavailable, disable here too BOOL bFade = FALSE; ::SystemParametersInfo(SPI_GETTOOLTIPANIMATION, 0, &bFade, 0); if (bFade) ::SystemParametersInfo(SPI_GETTOOLTIPFADE, 0, &bFade, 0); if (!bFade || NULL == m_fnAnimateWindow) m_unOptions |= unDISABLE_FADE; // create invisible at arbitrary position; then position, set region, and finally show // the idea with WS_EX_TOOLWINDOW is, you can't switch to this using alt+tab DWORD dwExStyle = WS_EX_TOOLWINDOW; if ( m_unOptions&unSHOW_TOPMOST ) // make topmost, if requested dwExStyle |= WS_EX_TOPMOST; if ( !CreateEx(dwExStyle, (LPCTSTR)wndClass, strTitle, WS_POPUP, CRect(0,0,10,10), pParentWnd, 0, NULL) ) return FALSE; PositionWindow(); if ( (m_unOptions&unCLOSE_ON_MOUSE_MOVE) ||(m_unOptions&unCLOSE_ON_LBUTTON_UP) ||(m_unOptions&unCLOSE_ON_LBUTTON_DOWN) ||(m_unOptions&unCLOSE_ON_MBUTTON_UP) ||(m_unOptions&unCLOSE_ON_MBUTTON_DOWN) ||(m_unOptions&unCLOSE_ON_RBUTTON_UP) ||(m_unOptions&unCLOSE_ON_RBUTTON_DOWN) ) { ::GetCursorPos(&m_ptMouseOrig); SetMouseHook(); } // these need to take effect even if the window receiving them // is not owned by this process. So, if this process does not // already have the mouse captured, capture it! if ( (m_unOptions&unCLOSE_ON_LBUTTON_UP) ||(m_unOptions&unCLOSE_ON_MBUTTON_UP) ||(m_unOptions&unCLOSE_ON_RBUTTON_UP) ) { // no, i don't particularly need or want to deal with a situation // where a balloon is being created and another program has captured // the mouse. If you need it, it shouldn't be too hard, just do it here. if ( NULL == GetCapture() ) SetCapture(); } if ( m_unOptions&unCLOSE_ON_KEYPRESS ) SetKeyboardHook(); ShowBalloon(); return TRUE;}
// calculate anchor position (adjust for client coordinates if used)CPoint CBalloonHelp::GetAnchorPoint(){ CPoint ptAnchor = m_ptAnchor; // assume if window was given, point is in client coords
if ( NULL != m_hwndAnchor )
::ClientToScreen(m_hwndAnchor, &ptAnchor);
return ptAnchor;
}
// determine bounds of screen anchor is on (Multi-Monitor compatibility)void CBalloonHelp::GetAnchorScreenBounds(CRect& rect){ if ( m_screenRect.IsRectEmpty() ) {
// get the nearest monitor to the anchor
HMONITOR hMonitor = MonitorFromPoint(GetAnchorPoint(), MONITOR_DEFAULTTONEAREST);
// get the monitor bounds
MONITORINFO mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
// work area (area not obscured by task bar, etc.)
m_screenRect = mi.rcWork;
} rect = m_screenRect;}// calculates the area of the screen the balloon falls into// this determins which direction the tail pointsCBalloonHelp::BALLOON_QUADRANT CBalloonHelp::GetBalloonQuadrant(){ CRect rectDesktop; GetAnchorScreenBounds(rectDesktop); CPoint ptAnchor = GetAnchorPoint(); if ( ptAnchor.y < rectDesktop.top + rectDesktop.Height()/2 ) { if ( ptAnchor.x < rectDesktop.left + rectDesktop.Width()/2 ) { return BQ_TOPLEFT; } else { return BQ_TOPRIGHT; } } else { if ( ptAnchor.x < rectDesktop.left + rectDesktop.Width()/2 ) { return BQ_BOTTOMLEFT; } else { return BQ_BOTTOMRIGHT; } } // unreachable}// Draw the non-client area
void CBalloonHelp::DrawNonClientArea(CDC* pDC)
{
CRect rect; GetWindowRect(&rect); ScreenToClient(&rect); CRect rectClient; GetClientRect(&rectClient); rectClient.OffsetRect(-rect.left, -rect.top); rect.OffsetRect(-rect.left, -rect.top); pDC->ExcludeClipRect(&rectClient); pDC->FillSolidRect(&rect, m_crBackground); pDC->SelectClipRgn(NULL); ASSERT(NULL != m_rgnComplete.m_hObject); CBrush brushFg; brushFg.CreateSolidBrush(m_crForeground); if ( m_unOptions & unSHOW_INNER_SHADOW ) { CBrush brushHL; // slightly lighter color int red = 170 + GetRValue(m_crBackground)/3; int green = 170 + GetGValue(m_crBackground)/3; int blue = 170 + GetBValue(m_crBackground)/3; brushHL.CreateSolidBrush(RGB(red,green,blue)); m_rgnComplete.OffsetRgn(1,1); pDC->FrameRgn(&m_rgnComplete, &brushHL, 2, 2); // slightly darker color red = GetRValue(m_crForeground)/3 + GetRValue(m_crBackground)/3*2; green = GetGValue(m_crForeground)/3 + GetGValue(m_crBackground)/3*2; blue = GetBValue(m_crForeground)/3 + GetBValue(m_crBackground)/3*2; brushHL.DeleteObject(); m_rgnComplete.OffsetRgn(-2,-2); brushHL.CreateSolidBrush(RGB(red,green,blue)); pDC->FrameRgn(&m_rgnComplete, &brushHL, 2, 2); m_rgnComplete.OffsetRgn(1,1); } // outline pDC->FrameRgn(&m_rgnComplete, &brushFg, 1, 1);}
// Draw the client area
void CBalloonHelp::DrawClientArea(CDC* pDC)
{
CSize sizeHeader = DrawHeader(pDC); DrawContent(pDC, sizeHeader.cy+nTIP_MARGIN);}
// Calculate the dimensions and draw the balloon header
CSize CBalloonHelp::DrawHeader(CDC* pDC, bool bDraw)
{
CSize sizeHdr(0,0);
CRect rectClient; GetClientRect(&rectClient); // use this for positioning when drawing // else if content is wider than title, centering wouldn't work
// calc & draw icon if ( NULL != m_ilIcon.m_hImageList )
{ int x = 0; int y = 0; ImageList_GetIconSize(m_ilIcon, &x, &y); sizeHdr.cx += x; sizeHdr.cy = max(sizeHdr.cy, y);
m_ilIcon.SetBkColor(m_crBackground); if (bDraw) m_ilIcon.Draw(pDC, 0, CPoint(0,0), ILD_NORMAL);//ILD_TRANSPARENT); rectClient.left += x; } // calc & draw close button if ( m_unOptions & unSHOW_CLOSE_BUTTON ) { int nBtnWidth = ::GetSystemMetrics(SM_CXSIZE); // if something is already in the header (icon) leave space if ( sizeHdr.cx > 0 ) sizeHdr.cx += nTIP_MARGIN;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -