// OXItemTipWnd.cpp : implementation file // // Version: 9.3 #include "stdafx.h" #include #include #include "OXItemTipWnd.h" #include "UTB64Bit.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // COXItemTipWnd COXItemTipWnd::COXItemTipWnd() { m_nTimerID=0; } COXItemTipWnd::~COXItemTipWnd() { } BEGIN_MESSAGE_MAP(COXItemTipWnd, CWnd) //{{AFX_MSG_MAP(COXItemTipWnd) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() void COXItemTipWnd::PostNcDestroy() { DestroyWindow(); CWnd::PostNcDestroy(); } BOOL COXItemTipWnd::Create(CWnd* pParentWnd, HBRUSH hbrBackground) { ASSERT_VALID(pParentWnd); ASSERT(::IsWindow(pParentWnd->GetSafeHwnd())); m_pParentWnd=pParentWnd; // creation of window // if(hbrBackground==NULL) { hbrBackground=(HBRUSH)(COLOR_INFOBK+1); } WNDCLASS wndClass; wndClass.style=CS_SAVEBITS|CS_DBLCLKS; wndClass.lpfnWndProc=AfxWndProc; wndClass.cbClsExtra=0; wndClass.cbWndExtra=0; wndClass.hInstance=AfxGetInstanceHandle(); wndClass.hIcon=::LoadCursor(NULL,IDC_ARROW); wndClass.hCursor=0; wndClass.hbrBackground=hbrBackground; wndClass.lpszMenuName=NULL; wndClass.lpszClassName=_T("ItemTipWnd"); if(!AfxRegisterClass(&wndClass)) { return FALSE; } CRect rect(0,0,0,0); if(!CWnd::CreateEx(WS_EX_TOOLWINDOW,wndClass.lpszClassName,_T(""), WS_BORDER|WS_POPUP,rect,NULL,0,NULL)) { return FALSE; } return TRUE; } void COXItemTipWnd::Display(CRect& rect, CString sText, int nOffset, int nAlignment, CFont* pFont, COLORREF clrText, COLORREF clrBackground) { ASSERT_VALID(m_pParentWnd); ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd())); ASSERT(::IsWindow(m_hWnd)); CWnd* pWnd=GetActiveWindow(); if(pWnd==NULL || (!IsDescendant(pWnd,m_pParentWnd) && (m_pParentWnd->GetExStyle()&WS_EX_TOPMOST)!=WS_EX_TOPMOST)) { return; } CClientDC dc(this); // device context for drawing CFont* pOldFont=NULL; if(pFont) { pOldFont=dc.SelectObject(pFont); } COLORREF clrOld=ID_OX_COLOR_NONE; if(clrText!=ID_OX_COLOR_NONE) { clrOld=dc.SetTextColor(clrText); } int nOldBkMode=dc.SetBkMode(TRANSPARENT); CRect rectDraw=rect; dc.DrawText(sText,&rectDraw,DT_CALCRECT|DT_LEFT|DT_SINGLELINE|DT_NOPREFIX); rectDraw.right+=2*nOffset; if(rectDraw.Width()>rect.Width()) { rect.right=rect.left+rectDraw.Width(); } if(rectDraw.Height()>rect.Height()) { rect.bottom=rect.top+rectDraw.Height(); } // it's show time! m_pParentWnd->ClientToScreen(&rect); // adjust rectangle to fit the screen // CWnd* pParentWnd=m_pParentWnd; BOOL bTopMostParent=FALSE; while(pParentWnd!=NULL) { if(pParentWnd->GetExStyle() & WS_EX_TOPMOST) { bTopMostParent=TRUE; break; } pParentWnd=pParentWnd->GetParent(); } DWORD dwMessagePos=::GetMessagePos(); CPoint point(GET_X_LPARAM(dwMessagePos),GET_Y_LPARAM(dwMessagePos)); CRect rectDisplay=GetMonitorRectFromPoint(point,!bTopMostParent); if(rect.right>rectDisplay.right) { rect.OffsetRect(rectDisplay.right-rect.right,0); } if(rect.leftGetSafeHwnd())); ASSERT(::IsWindow(m_hWnd)); if(m_nTimerID!=0) { KillTimer(m_nTimerID); } ShowWindow(SW_HIDE); if(pMsg!=NULL) { if(pWnd==NULL) { pWnd=m_pParentWnd; } if(::IsWindow(pWnd->GetSafeHwnd())) { pWnd->PostMessage(pMsg->message,pMsg->wParam,pMsg->lParam); } } } BOOL COXItemTipWnd::PreTranslateMessage(MSG* pMsg) { ASSERT_VALID(m_pParentWnd); ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd())); ASSERT(::IsWindow(m_hWnd)); CWnd *pWnd=NULL; int nHitTest; pWnd=m_pParentWnd; while(pWnd!=NULL && (pWnd->GetStyle()&WS_CHILD)!=0) { pWnd=pWnd->GetParent(); } ASSERT(pWnd!=NULL); if(pMsg->message==WM_MOUSEMOVE || (pMsg->message==WM_TIMER && pMsg->wParam==(WPARAM)m_nTimerID)) { CPoint point; ::GetCursorPos(&point); CRect rect; GetWindowRect(rect); pWnd=WindowFromPoint(point); ASSERT(pWnd!=NULL); if(pWnd->GetSafeHwnd()==GetSafeHwnd()) { return CWnd::PreTranslateMessage(pMsg); } else { if(pMsg->message!=WM_MOUSEMOVE) { Hide(); return TRUE; } } } switch(pMsg->message) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_MOUSEMOVE: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_MBUTTONDBLCLK: { POINTS points=MAKEPOINTS(pMsg->lParam); CPoint point(points.x,points.y); ClientToScreen(&point); pWnd=WindowFromPoint(point); ASSERT(pWnd); if(pWnd==this) { pWnd=m_pParentWnd; } nHitTest=(int)pWnd->SendMessage(WM_NCHITTEST,0, MAKELONG(point.x,point.y)); if(nHitTest==HTCLIENT) { pWnd->ScreenToClient(&point); } else { switch(pMsg->message) { case WM_LBUTTONDOWN: { pMsg->message=WM_NCLBUTTONDOWN; break; } case WM_RBUTTONDOWN: { pMsg->message=WM_NCRBUTTONDOWN; break; } case WM_MBUTTONDOWN: { pMsg->message=WM_NCMBUTTONDOWN; break; } case WM_LBUTTONUP: { pMsg->message=WM_NCLBUTTONUP; break; } case WM_RBUTTONUP: { pMsg->message=WM_NCRBUTTONUP; break; } case WM_MBUTTONUP: { pMsg->message=WM_NCMBUTTONUP; break; } case WM_LBUTTONDBLCLK: { pMsg->message=WM_NCLBUTTONDBLCLK; break; } case WM_RBUTTONDBLCLK: { pMsg->message=WM_NCRBUTTONDBLCLK; break; } case WM_MBUTTONDBLCLK: { pMsg->message=WM_NCMBUTTONDBLCLK; break; } case WM_MOUSEMOVE: { pMsg->message=WM_NCMOUSEMOVE; break; } } pMsg->wParam=nHitTest; } pMsg->lParam=MAKELONG(point.x,point.y); ASSERT(pWnd!=this); } case WM_KEYDOWN: case WM_SYSKEYDOWN: { ASSERT(pWnd!=NULL); Hide(pMsg,pWnd); return TRUE; } } BOOL bResult=CWnd::PreTranslateMessage(pMsg); return bResult; } void COXItemTipWnd::OnDestroy() { if(m_nTimerID!=0) { KillTimer(m_nTimerID); } } BOOL COXItemTipWnd::IsDescendant(CWnd* pWndParent, CWnd* pWndChild) // helper for detecting whether child descendent of parent // (works with owned popups as well) { ASSERT(pWndParent!=NULL); ASSERT(::IsWindow(pWndParent->GetSafeHwnd())); ASSERT(pWndChild!=NULL); ASSERT(::IsWindow(pWndChild->GetSafeHwnd())); HWND hWndParent=pWndParent->GetSafeHwnd(); HWND hWndChild=pWndChild->GetSafeHwnd(); do { if (hWndParent == hWndChild) return TRUE; // check for permanent-owned window first CWnd* pWnd=CWnd::FromHandlePermanent(hWndChild); if(pWnd!=NULL) hWndChild=pWnd->GetOwner()->GetSafeHwnd(); else hWndChild=(::GetWindowLongPtr(hWndChild,GWL_STYLE)&WS_CHILD) ? ::GetParent(hWndChild) : ::GetWindow(hWndChild,GW_OWNER); } while (hWndChild != NULL); return FALSE; } CRect COXItemTipWnd::GetMonitorRectFromPoint(const CPoint& ptHitTest, BOOL bOnlyWorkArea) { CRect rectDisplay; #if(defined(GetMonitorInfo) && defined(MonitorFromPoint)) // if we use Win 98/NT5 we have to take into account multiple monitors OSVERSIONINFO osvi={ sizeof(OSVERSIONINFO) }; VERIFY(::GetVersionEx(&osvi)!=0); if(osvi.dwMajorVersion>4 || (osvi.dwMajorVersion==4 && osvi.dwMinorVersion>0)) { HMONITOR hMonitor=::MonitorFromPoint(ptHitTest,MONITOR_DEFAULTTONEAREST); ASSERT(hMonitor!=NULL); MONITORINFO monitorInfo={ sizeof(MONITORINFO) }; VERIFY(::GetMonitorInfo(hMonitor,&monitorInfo)); if(!bOnlyWorkArea) { rectDisplay=monitorInfo.rcMonitor; } else { rectDisplay=monitorInfo.rcWork; } } else { #endif if(!bOnlyWorkArea) { GetDesktopWindow()->GetWindowRect(rectDisplay); } else { ::SystemParametersInfo(SPI_GETWORKAREA,NULL,&rectDisplay,NULL); } #if(defined(GetMonitorInfo) && defined(MonitorFromPoint)) } #else UNREFERENCED_PARAMETER(ptHitTest); #endif return rectDisplay; }