2025-11-27 16:46:48 +09:00

464 lines
9.1 KiB
C++

// OXItemTipWnd.cpp : implementation file
//
// Version: 9.3
#include "stdafx.h"
#include <winuser.h>
#include <windowsx.h>
#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.left<rectDisplay.left)
{
rect.OffsetRect(rectDisplay.left-rect.left,0);
}
//
/////////////////////////////////////////////////////////////
if(bTopMostParent)
{
SetWindowPos(&wndTopMost,rect.left,rect.top,rect.Width(),
rect.Height(),SWP_NOACTIVATE);
}
else
{
SetWindowPos(NULL,rect.left,rect.top,rect.Width(),
rect.Height(),SWP_NOZORDER|SWP_NOACTIVATE);
}
ShowWindow(SW_SHOWNA);
if(clrBackground!=ID_OX_COLOR_NONE)
{
CBrush brush;
brush.CreateSolidBrush(clrBackground);
CRect rectClient;
GetClientRect(rectClient);
dc.FillRect(&rectClient,&brush);
}
else
{
SendMessage(WM_ERASEBKGND,(WPARAM)(HDC)dc);
}
rectDraw=rect;
rectDraw.DeflateRect(nOffset,0);
ScreenToClient(&rectDraw);
dc.DrawText(sText,&rectDraw,nAlignment|DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX);
if(pOldFont)
{
dc.SelectObject(pOldFont);
}
if(clrOld!=ID_OX_COLOR_NONE)
{
dc.SetTextColor(clrOld);
}
dc.SetBkMode(nOldBkMode);
m_nTimerID=SetTimer(ID_OXITEMTIP_TIMER,ID_OXITEMTIP_TIMER_DELAY,NULL);
if(m_nTimerID==0)
{
TRACE(_T("COXItemTipWnd::Display: failed to set timer to check item tip state\n"));
}
}
void COXItemTipWnd::Hide(MSG* pMsg, CWnd* pWnd)
{
ASSERT_VALID(m_pParentWnd);
ASSERT(::IsWindow(m_pParentWnd->GetSafeHwnd()));
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;
}