00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "XInfoTip.h"
00008
00009 #ifdef _DEBUG
00010 #define new DEBUG_NEW
00011 #undef THIS_FILE
00012 static char THIS_FILE[] = __FILE__;
00013 #endif
00014
00015 #define CX_ROUNDED 12
00016 #define CY_ROUNDED 10
00017 #define CX_LEADER 25
00018 #define CY_LEADER 25
00019 #define CX_ICON_MARGIN 5
00020
00021 #define DEFAULT_SHOW_DELAY 5000
00022
00023 #define TIMER_HIDE 5000
00024
00025 #define IDC_DSA 12000
00026
00027 CXInfoTip::CXInfoTip()
00028 {
00029
00030 m_szClass = AfxRegisterWndClass (0, LoadCursor (NULL, IDC_ARROW), NULL, NULL);
00031
00032 m_hIcon = NULL;
00033
00034 m_nShowDelay = DEFAULT_SHOW_DELAY;
00035
00036 m_IconSize = CSize(0, 0);
00037 m_ptOrigin = CPoint(0, 0);
00038
00039 m_bPlaced = false;
00040
00041 m_bDSAChecked = FALSE;
00042
00043 m_bShowDSA = FALSE;
00044
00045 m_nAutohideDelay = TIMER_HIDE;
00046 }
00047
00048 CXInfoTip::~CXInfoTip()
00049 {
00050 }
00051
00052 BEGIN_MESSAGE_MAP(CXInfoTip, CWnd)
00053
00054 ON_WM_PAINT()
00055 ON_WM_CREATE()
00056 ON_WM_TIMER()
00057 ON_WM_DESTROY()
00058 ON_WM_LBUTTONDOWN()
00059 ON_WM_CTLCOLOR()
00060 ON_WM_SETCURSOR()
00061
00062 ON_BN_CLICKED(IDC_DSA, OnDSA)
00063 END_MESSAGE_MAP()
00064
00065 BOOL CXInfoTip::Create(CWnd* pParentWnd)
00066 {
00067 BOOL bSuccess;
00068
00069 ASSERT(pParentWnd != NULL);
00070
00071 bSuccess = CreateEx(NULL, m_szClass, NULL, WS_POPUP, 0, 0, 0, 0, pParentWnd->GetSafeHwnd(), NULL, NULL);
00072
00073 m_pFont = CFont::FromHandle((HFONT)::GetStockObject(DEFAULT_GUI_FONT));
00074
00075 LOGFONT lf;
00076 m_pFont->GetLogFont (&lf);
00077 lf.lfWeight = FW_BOLD;
00078 m_fntBold.CreateFontIndirect (&lf);
00079
00080 return bSuccess;
00081 }
00082
00083 void CXInfoTip::Show(LPCSTR pszCaption, CString szText, BOOL bAutoHide , CPoint *pt )
00084 {
00085 if (pt != NULL)
00086 m_ptOrigin = *pt;
00087 else
00088 GetCursorPos(&m_ptOrigin);
00089
00090 m_szText = szText;
00091 m_strCaption = pszCaption;
00092
00093 m_nTimer = SetTimer(bAutoHide ? timerShow : timerShowNAH, m_nShowDelay, NULL);
00094 }
00095
00096 void CXInfoTip::OnPaint()
00097 {
00098 CPaintDC dc( this );
00099
00100 CRect rc;
00101 CBrush WindowBrush;
00102 CBrush FrameBrush;
00103 CBrush InnerFrameBrush;
00104 HRGN hRegion;
00105 CRgn *pRegion;
00106 CFont *pSysFont;
00107
00108 GetClientRect(rc);
00109
00110 InnerFrameBrush.CreateSolidBrush(::GetSysColor(COLOR_SCROLLBAR));
00111 FrameBrush.CreateSolidBrush(::GetSysColor(COLOR_WINDOWTEXT));
00112 WindowBrush.CreateSolidBrush(::GetSysColor(COLOR_WINDOW));
00113
00114 GetWindowRegion(&dc, &hRegion);
00115 pRegion = CRgn::FromHandle(hRegion);
00116
00117 dc.FillRgn(pRegion, &WindowBrush);
00118 dc.FrameRgn(pRegion, &InnerFrameBrush, 3, 3);
00119 dc.FrameRgn(pRegion, &FrameBrush, 1, 1);
00120
00121 rc.DeflateRect(CX_ROUNDED, CY_ROUNDED, 0, 0);
00122 if (m_hIcon != NULL)
00123 rc.left = rc.left + m_IconSize.cx + CX_ICON_MARGIN;
00124
00125 pSysFont = (CFont *)dc.SelectObject(&m_fntBold);
00126
00127 dc.SetBkMode( TRANSPARENT );
00128
00129 dc.DrawText (m_strCaption, &rc, DT_TOP | DT_LEFT);
00130
00131 dc.SelectObject(m_pFont);
00132
00133 CRect rc2 = rc;
00134 rc2.top += m_nCaptionHeight;
00135 dc.DrawText(m_szText, &rc2, DT_TOP | DT_LEFT);
00136
00137 if (m_bShowDSA && m_bPlaced == false)
00138 {
00139 m_bPlaced = true;
00140 m_btnDSA.MoveWindow (rc.left, m_yDSA, m_cxDSA + 10 + 20, 20);
00141 }
00142
00143 if (m_hIcon != NULL)
00144 DrawIconEx(dc.m_hDC, CX_ROUNDED, CY_ROUNDED, m_hIcon, m_IconSize.cx, m_IconSize.cy, 0, NULL, DI_NORMAL);
00145
00146 ::DeleteObject(hRegion);
00147 dc.SelectObject(pSysFont);
00148
00149 }
00150
00151 BOOL CXInfoTip::GetWindowRegion(CDC* pDC, HRGN* hRegion, CSize *Size )
00152 {
00153 CRect rcWnd (0,0,0,0);
00154 POINT ptLeader[3];
00155 CRgn LeaderRegion;
00156 CRgn CaptionRegion;
00157 CFont *pSysFont;
00158
00159 ASSERT(pDC != NULL);
00160 ASSERT(hRegion != NULL);
00161
00162 pSysFont = (CFont *)pDC->SelectObject(&m_fntBold);
00163
00164 CRect rcWnd1, rcWnd2;
00165
00166 pDC->DrawText(m_strCaption + "\n", &rcWnd1, DT_CALCRECT);
00167
00168 pDC->SelectObject (m_pFont);
00169
00170 pDC->DrawText(m_szText, &rcWnd2, DT_CALCRECT);
00171
00172 m_nCaptionHeight = rcWnd1.Height ();
00173 rcWnd.right = max (rcWnd1.Width (), rcWnd2.Width ());
00174 rcWnd.bottom = m_nCaptionHeight + rcWnd2.Height ();
00175
00176 if (m_bShowDSA)
00177 {
00178
00179 CRect rcDSA;
00180 pDC->DrawText (LS (L_DONTSHOWTHISWINDOWAGAIN), &rcDSA, DT_CALCRECT);
00181 m_yDSA = rcWnd.bottom + rcDSA.Height ();
00182 rcWnd.bottom += 10 + rcDSA.Height ();
00183 m_cxDSA = rcDSA.Width ();
00184 rcWnd.right = max (rcWnd.right, m_cxDSA + 30);
00185 }
00186
00187 pDC->SelectObject(pSysFont);
00188
00189 rcWnd.InflateRect(CX_ROUNDED, CY_ROUNDED);
00190
00191 if (m_hIcon != NULL)
00192 rcWnd.right = rcWnd.right + m_IconSize.cx + CX_ICON_MARGIN;
00193 if (rcWnd.Height() < m_IconSize.cy)
00194 rcWnd.bottom = rcWnd.top + m_IconSize.cy;
00195
00196 ptLeader[0].x = rcWnd.Width() - CX_ROUNDED;
00197 ptLeader[0].y = rcWnd.Height() - CY_ROUNDED;
00198
00199 ptLeader[1].x = ptLeader[0].x;
00200 ptLeader[1].y = ptLeader[0].y + CY_LEADER;
00201
00202 ptLeader[2].x = ptLeader[0].x - CX_LEADER;
00203 ptLeader[2].y = rcWnd.Height() - CY_ROUNDED;
00204
00205 CaptionRegion.CreateRoundRectRgn(0, 0, rcWnd.Width(), rcWnd.Height(), CX_ROUNDED, CY_ROUNDED);
00206
00207 LeaderRegion.CreatePolygonRgn(ptLeader, 3, ALTERNATE);
00208
00209 *hRegion = ::CreateRectRgn(0, 0, rcWnd.Width(), rcWnd.Height() + CY_LEADER);
00210
00211 CombineRgn(*hRegion, CaptionRegion.operator HRGN(), LeaderRegion.operator HRGN(), RGN_OR);
00212
00213 if (Size != NULL)
00214 {
00215 Size->cx = rcWnd.Width();
00216 Size->cy = rcWnd.Height() + CY_LEADER;
00217 }
00218
00219 return TRUE;
00220 }
00221
00222 int CXInfoTip::OnCreate( LPCREATESTRUCT lpCreateStruct )
00223 {
00224 if ( CWnd::OnCreate( lpCreateStruct ) == -1 )
00225 return -1;
00226
00227 m_brWnd.CreateSolidBrush (GetSysColor (COLOR_WINDOW));
00228
00229 CRect rc (0,0,0,0);
00230 m_btnDSA.Create (LS (L_DONTSHOWTHISWINDOWAGAIN),
00231 BS_AUTOCHECKBOX | BS_CHECKBOX | WS_CHILD | WS_VISIBLE, rc, this, IDC_DSA);
00232
00233 return 0;
00234 }
00235
00236 void CXInfoTip::OnTimer( UINT nIDEvent )
00237 {
00238 HRGN hRegion;
00239 CSize WindowSize;
00240 CDC *pDC;
00241 CPoint ptCursor;
00242
00243 switch (nIDEvent)
00244 {
00245
00246 case timerShow:
00247 KillTimer(m_nTimer);
00248
00249 pDC = GetDC();
00250 GetWindowRegion(pDC, &hRegion, &WindowSize);
00251 ReleaseDC(pDC);
00252
00253 ::SetWindowRgn(m_hWnd, hRegion, TRUE);
00254
00255 SetWindowPos(&wndTop, m_ptOrigin.x - WindowSize.cx + CX_ROUNDED, m_ptOrigin.y - WindowSize.cy + CY_ROUNDED, WindowSize.cx, WindowSize.cy, SWP_NOACTIVATE | SWP_SHOWWINDOW);
00256 m_bPlaced = false;
00257
00258 m_nTimer = SetTimer(timerHide, m_nAutohideDelay, NULL);
00259 break;
00260
00261 case timerHide:
00262 GetCursorPos(&ptCursor);
00263 if (ptCursor != m_ptOrigin)
00264 {
00265 KillTimer(m_nTimer);
00266 ShowWindow(SW_HIDE);
00267 }
00268
00269 break;
00270
00271 case timerShowNAH:
00272 KillTimer(m_nTimer);
00273
00274 pDC = GetDC();
00275 GetWindowRegion(pDC, &hRegion, &WindowSize);
00276 ReleaseDC(pDC);
00277
00278 ::SetWindowRgn(m_hWnd, hRegion, TRUE);
00279
00280 SetWindowPos(&wndTop, m_ptOrigin.x - WindowSize.cx + CX_ROUNDED, m_ptOrigin.y - WindowSize.cy + CY_ROUNDED, WindowSize.cx, WindowSize.cy, SWP_NOACTIVATE | SWP_SHOWWINDOW);
00281 m_bPlaced = false;
00282 break;
00283 }
00284
00285 CWnd::OnTimer(nIDEvent);
00286 }
00287
00288 void CXInfoTip::OnDestroy()
00289 {
00290 KillTimer(m_nTimer);
00291
00292 CWnd::OnDestroy();
00293 }
00294
00295 void CXInfoTip::RelayEvent(LPMSG lpMsg)
00296 {
00297 if (m_nTimer == timerShowNAH)
00298 return;
00299
00300 CPoint point;
00301 CWnd *pWindow;
00302 CString szTooltipText;
00303 TipToolInfo Info;
00304
00305 switch(lpMsg->message)
00306 {
00307 case WM_LBUTTONDOWN:
00308 case WM_RBUTTONDOWN:
00309 case WM_MBUTTONDOWN:
00310 ShowWindow(SW_HIDE);
00311 break;
00312 case WM_MOUSEMOVE:
00313 GetCursorPos(&point);
00314
00315 if (point != m_ptOrigin)
00316 {
00317
00318 pWindow = WindowFromPoint(point);
00319 if (pWindow != NULL)
00320 {
00321 if (m_ToolMap.Lookup(pWindow->m_hWnd, Info))
00322 {
00323
00324 m_ptOrigin = point;
00325 SetIcon(Info.hIcon);
00326 Show("", Info.szText, TRUE, &point);
00327 }
00328 }
00329 }
00330
00331 if (point != m_ptOrigin)
00332 ShowWindow(SW_HIDE);
00333
00334 break;
00335 }
00336 }
00337
00338 void CXInfoTip::SetIcon(HICON hIcon)
00339 {
00340 ICONINFO IconInfo;
00341
00342 m_hIcon = hIcon;
00343
00344 if (hIcon == NULL)
00345 {
00346 m_IconSize = CSize(0, 0);
00347 return;
00348 }
00349
00350 ZeroMemory(&IconInfo, sizeof(ICONINFO));
00351 ::GetIconInfo(m_hIcon, &IconInfo);
00352
00353 m_IconSize.cx = (BYTE)(IconInfo.xHotspot );
00354 m_IconSize.cy = (BYTE)(IconInfo.yHotspot );
00355
00356 ::DeleteObject(IconInfo.hbmMask);
00357 ::DeleteObject(IconInfo.hbmColor);
00358
00359 if (IsWindow(m_hWnd))
00360 RedrawWindow();
00361 }
00362
00363 void CXInfoTip::AddTool(CWnd *pWnd, LPCTSTR szTooltipText, HICON hIcon )
00364 {
00365 ASSERT(pWnd != NULL);
00366
00367 TipToolInfo Info;
00368 Info.szText = szTooltipText;
00369 Info.hIcon = hIcon;
00370
00371 m_ToolMap.SetAt(pWnd->m_hWnd, Info);
00372 };
00373
00374 void CXInfoTip::RemoveTool(CWnd *pWnd)
00375 {
00376 m_ToolMap.RemoveKey(pWnd->m_hWnd);
00377 }
00378
00379 void CXInfoTip::OnLButtonDown(UINT, CPoint pt)
00380 {
00381 Hide ();
00382 }
00383
00384 HBRUSH CXInfoTip::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
00385 {
00386 pDC->SelectObject (m_pFont);
00387 return m_brWnd;
00388 }
00389
00390 BOOL CXInfoTip::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message)
00391 {
00392 SetCursor (LoadCursor (NULL, IDC_ARROW));
00393 return FALSE;
00394 }
00395
00396 void CXInfoTip::OnDSA()
00397 {
00398 m_bDSAChecked = 0 != (m_btnDSA.GetState () & BST_CHECKED);
00399 }
00400
00401 BOOL CXInfoTip::is_DontShowChecked()
00402 {
00403 return m_bDSAChecked;
00404 }
00405
00406 void CXInfoTip::SetAutohideDelay(int nDelay)
00407 {
00408 m_nAutohideDelay = nDelay;
00409 }