565 lines
14 KiB
C++
565 lines
14 KiB
C++
// ==========================================================================
|
|
// Class Implementation :
|
|
// COXItemTip
|
|
// ==========================================================================
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "StdAfx.h"
|
|
#include <winuser.h>
|
|
#include "OXItemTip.h"
|
|
#include <afxcview.h>
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(COXItemTip, COXHookWnd);
|
|
|
|
void COXItemTip::NeedItemTip(LPNEEDITEMTIPINFO pnitInfo)
|
|
{
|
|
ASSERT(::IsWindow(m_hWndHooked));
|
|
ASSERT(m_hWndHooked==m_pAttachedCtrl->m_hWnd);
|
|
|
|
// Make sure that the ListCtrl is in report view
|
|
if((m_pAttachedCtrl->GetStyle()&LVS_TYPEMASK)!=LVS_REPORT)
|
|
{
|
|
pnitInfo->result=ID_NIT_WRONGFORMAT;
|
|
return;
|
|
}
|
|
|
|
// check if list control has any items
|
|
if(m_pAttachedCtrl->GetItemCount()==0)
|
|
{
|
|
//changed 12/15/99
|
|
pnitInfo->result=ID_NIT_OUTOFCONTROLBORDER;//ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
|
|
|
|
CPoint point;
|
|
point.x=pnitInfo->point.x;
|
|
point.y=pnitInfo->point.y;
|
|
|
|
CRect rectItem=pnitInfo->rectItem;
|
|
|
|
// Get the top and bottom row visible
|
|
int nTopRow=m_pAttachedCtrl->GetTopIndex();
|
|
int nBottomRow=nTopRow+m_pAttachedCtrl->GetCountPerPage();
|
|
if(nBottomRow>=m_pAttachedCtrl->GetItemCount())
|
|
{
|
|
nBottomRow=m_pAttachedCtrl->GetItemCount()-1;
|
|
}
|
|
|
|
int nRow=nTopRow;
|
|
while(TRUE)
|
|
{
|
|
ASSERT(nRow<m_pAttachedCtrl->GetItemCount());
|
|
|
|
m_pAttachedCtrl->GetItemRect(nRow,&rectItem,LVIR_BOUNDS);
|
|
if(rectItem.PtInRect(point))
|
|
{
|
|
break;
|
|
}
|
|
nRow++;
|
|
|
|
if(nRow>nBottomRow)
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFCONTROLBORDER;
|
|
return;
|
|
}
|
|
}
|
|
pnitInfo->row=nRow;
|
|
|
|
int nCol=0;
|
|
int nColReal=0;
|
|
while(TRUE)
|
|
{
|
|
nColReal=GetRealColumn(nCol);
|
|
int nColWidth=m_pAttachedCtrl->GetColumnWidth(nColReal);
|
|
if(nColWidth<0)
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFCONTROLBORDER;
|
|
return;
|
|
}
|
|
|
|
rectItem.right=rectItem.left+nColWidth;
|
|
if(rectItem.PtInRect(point))
|
|
{
|
|
break;
|
|
}
|
|
rectItem.left=rectItem.right;
|
|
nCol++;
|
|
}
|
|
pnitInfo->col=nColReal;
|
|
|
|
if(nColReal==0)
|
|
{
|
|
CRect rcLabel;
|
|
m_pAttachedCtrl->GetItemRect(nRow, &rcLabel, LVIR_LABEL);
|
|
|
|
rectItem=rcLabel;
|
|
rectItem.InflateRect(1,0);
|
|
if(!rectItem.PtInRect(point))
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFITEMBORDER;
|
|
return;
|
|
}
|
|
}
|
|
|
|
int nOffset=(nColReal==0 ? pnitInfo->offset/2 : pnitInfo->offset);
|
|
rectItem.DeflateRect(nOffset,0);
|
|
|
|
CString sText=m_pAttachedCtrl->GetItemText(nRow,nColReal);
|
|
if(sText.IsEmpty())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
lstrcpyn(pnitInfo->itemText,sText,pnitInfo->sizeText);
|
|
|
|
CClientDC dc(m_pAttachedCtrl);
|
|
CFont* pOldFont=pnitInfo->pFont==NULL ? NULL :
|
|
dc.SelectObject((CFont*)pnitInfo->pFont);
|
|
CRect rectText(0, 0, 0, 0);
|
|
dc.DrawText(sText,&rectText,DT_CALCRECT|DT_LEFT|DT_SINGLELINE);
|
|
if(pOldFont)
|
|
{
|
|
dc.SelectObject(pOldFont);
|
|
}
|
|
|
|
CRect rectClient;
|
|
m_pAttachedCtrl->GetClientRect(&rectClient);
|
|
|
|
LV_COLUMN lvc;
|
|
memset(&lvc,0,sizeof(LV_COLUMN));
|
|
lvc.mask=LVCF_FMT;
|
|
VERIFY(m_pAttachedCtrl->GetColumn(nColReal, &lvc));
|
|
|
|
int fmt=lvc.fmt&LVCFMT_JUSTIFYMASK;
|
|
int nTextWidth=rectText.Width();
|
|
switch(fmt)
|
|
{
|
|
case LVCFMT_LEFT:
|
|
{
|
|
rectText.left=rectItem.left;
|
|
rectText.right=rectText.left+nTextWidth;
|
|
pnitInfo->alignment=DT_LEFT;
|
|
break;
|
|
}
|
|
case LVCFMT_RIGHT:
|
|
{
|
|
rectText.right=rectItem.right;
|
|
rectText.left=rectText.right-nTextWidth;
|
|
pnitInfo->alignment=DT_RIGHT;
|
|
break;
|
|
}
|
|
case LVCFMT_CENTER:
|
|
{
|
|
int nCenter=rectItem.left+(rectItem.right-rectItem.left)/2;
|
|
rectText.left=nCenter-nTextWidth/2;
|
|
rectText.right=nCenter+nTextWidth/2;
|
|
pnitInfo->alignment=DT_CENTER;
|
|
break;
|
|
}
|
|
default:
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
CRect rectItemWindow=rectItem;
|
|
m_pAttachedCtrl->ClientToScreen(rectItemWindow);
|
|
CWnd* pParentWnd=m_pAttachedCtrl->GetParent();
|
|
BOOL bTopMostParent=FALSE;
|
|
while(pParentWnd!=NULL)
|
|
{
|
|
if(pParentWnd->GetExStyle() & WS_EX_TOPMOST)
|
|
{
|
|
bTopMostParent=TRUE;
|
|
break;
|
|
}
|
|
pParentWnd=pParentWnd->GetParent();
|
|
}
|
|
// check if item rectangle fits into the screen
|
|
DWORD dwMessagePos=::GetMessagePos();
|
|
CPoint ptHitTest(GET_X_LPARAM(dwMessagePos),GET_Y_LPARAM(dwMessagePos));
|
|
CRect rectDisplay=COXItemTipWnd::GetMonitorRectFromPoint(ptHitTest,!bTopMostParent);
|
|
|
|
if(rectText.Width()<=rectItem.Width() &&
|
|
rectText.right<=rectClient.right &&
|
|
rectText.left>=rectClient.left &&
|
|
rectItemWindow.right<=rectDisplay.right &&
|
|
rectItemWindow.left>=rectDisplay.left)
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
|
|
if(rectItem.Width()<rectText.Width())
|
|
{
|
|
rectItem.right=rectItem.left+rectText.Width();
|
|
}
|
|
rectItem.InflateRect(nOffset,0);
|
|
|
|
pnitInfo->rectItem.left=rectItem.left;
|
|
pnitInfo->rectItem.right=rectItem.left+__min(rectItem.Width(),rectText.Width());
|
|
pnitInfo->rectItem.top=rectItem.top;
|
|
pnitInfo->rectItem.bottom=rectItem.bottom;
|
|
|
|
pnitInfo->offset=nOffset;
|
|
|
|
BOOL bSelected=(m_pAttachedCtrl->GetItemState(pnitInfo->row,LVIS_SELECTED)==
|
|
LVIS_SELECTED);
|
|
if(pnitInfo->clrText==ID_OX_COLOR_NONE)
|
|
{
|
|
pnitInfo->clrText=(bSelected ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) :
|
|
m_pAttachedCtrl->GetTextColor());
|
|
}
|
|
if(pnitInfo->clrBackground==ID_OX_COLOR_NONE)
|
|
{
|
|
pnitInfo->clrBackground=(bSelected ? ::GetSysColor(COLOR_HIGHLIGHT) :
|
|
pnitInfo->clrBackground);
|
|
}
|
|
|
|
|
|
pnitInfo->result=ID_NIT_SUCCESS;
|
|
}
|
|
|
|
|
|
int COXItemTip::GetRealColumn(int nCol)
|
|
{
|
|
#if (_WIN32_IE >= 0x0300)
|
|
ASSERT(::IsWindow(m_hWndHooked));
|
|
|
|
//ASSERT(GetHookedWnd()->IsKindOf(RUNTIME_CLASS(CListCtrl)));
|
|
//changed 12/15/99
|
|
// ASSERT(GetHookedWnd()->IsKindOf(RUNTIME_CLASS(CListCtrl)) ||
|
|
// GetHookedWnd()->IsKindOf(RUNTIME_CLASS(CListView)));
|
|
|
|
ASSERT(m_hWndHooked==m_pAttachedCtrl->m_hWnd);
|
|
|
|
// Get the header control
|
|
CHeaderCtrl* pHeader = (CHeaderCtrl*)m_pAttachedCtrl->GetDlgItem(0);
|
|
ASSERT(pHeader);
|
|
|
|
// get the current number of columns
|
|
int nCount=pHeader->GetItemCount();
|
|
ASSERT(nCol<nCount);
|
|
|
|
// find the real column number. We will request new HDI_ORDER info
|
|
for (int nIndex=0; nIndex<nCount; nIndex++)
|
|
{
|
|
HD_ITEM hdItem;
|
|
hdItem.mask=HDI_ORDER;
|
|
BOOL bReturn = pHeader->GetItem(nIndex,&hdItem);
|
|
ASSERT(bReturn);
|
|
|
|
if(hdItem.iOrder==nCol)
|
|
{
|
|
return nIndex;
|
|
}
|
|
}
|
|
|
|
// we shouldn't be here
|
|
ASSERT(FALSE);
|
|
|
|
return -1;
|
|
#else
|
|
return nCol;
|
|
#endif
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(COXEditTip, COXHookWnd);
|
|
|
|
BOOL COXEditTip::Attach(CWnd* pWnd, NEEDITEMTIP_HELPER pfnCallback/*=NULL*/)
|
|
{
|
|
if(!COXBaseItemTip<CEdit>::Attach(pWnd,pfnCallback))
|
|
return FALSE;
|
|
|
|
if(!InstallSpy())
|
|
{
|
|
Detach();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void COXEditTip::NeedItemTip(LPNEEDITEMTIPINFO pnitInfo)
|
|
{
|
|
ASSERT(::IsWindow(m_hWndHooked));
|
|
ASSERT(m_hWndHooked==m_pAttachedCtrl->m_hWnd);
|
|
|
|
// we already been there so we don't need to show the tip again
|
|
if(IsMouseOver())
|
|
{
|
|
pnitInfo->result=ID_NIT_CUSTOMREJECT;
|
|
return;
|
|
}
|
|
|
|
DWORD dwStyle=m_pAttachedCtrl->GetStyle();
|
|
// Make sure that the Edit control has single line style
|
|
if((dwStyle&ES_MULTILINE)==ES_MULTILINE)
|
|
{
|
|
pnitInfo->result=ID_NIT_WRONGFORMAT;
|
|
return;
|
|
}
|
|
|
|
CString sText;
|
|
m_pAttachedCtrl->GetWindowText(sText);
|
|
if(sText.IsEmpty())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
if(sText.GetLength()>pnitInfo->sizeText)
|
|
{
|
|
pnitInfo->result=ID_NIT_WRONGFORMAT;
|
|
return;
|
|
}
|
|
|
|
CRect rectItem;
|
|
m_pAttachedCtrl->GetRect(rectItem);
|
|
CRect rectClient;
|
|
m_pAttachedCtrl->GetClientRect(rectClient);
|
|
CRect rectWindow;
|
|
m_pAttachedCtrl->GetWindowRect(rectWindow);
|
|
m_pAttachedCtrl->ScreenToClient(rectWindow);
|
|
|
|
pnitInfo->offset=rectItem.left-rectWindow.left;
|
|
|
|
CClientDC dc(m_pAttachedCtrl);
|
|
CFont* pOldFont=pnitInfo->pFont==NULL ? NULL :
|
|
dc.SelectObject((CFont*)pnitInfo->pFont);
|
|
CRect rectText(0, 0, 0, 0);
|
|
dc.DrawText(sText,&rectText,DT_CALCRECT|DT_LEFT|DT_SINGLELINE);
|
|
if(pOldFont)
|
|
{
|
|
dc.SelectObject(pOldFont);
|
|
}
|
|
|
|
if(rectText.Width()<=rectItem.Width() && rectText.Height()<=rectItem.Height())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
rectItem.right=rectItem.left+rectText.Width();
|
|
rectItem.bottom=rectItem.top+rectText.Height();
|
|
|
|
if((dwStyle&ES_CENTER)==ES_CENTER)
|
|
pnitInfo->alignment=DT_CENTER;
|
|
else if((dwStyle&ES_RIGHT)==ES_RIGHT)
|
|
pnitInfo->alignment=DT_RIGHT;
|
|
else
|
|
pnitInfo->alignment=DT_LEFT;
|
|
|
|
pnitInfo->rectItem.left=rectWindow.left;
|
|
pnitInfo->rectItem.top=rectWindow.top;
|
|
pnitInfo->rectItem.right=rectWindow.left+rectItem.Width();
|
|
pnitInfo->rectItem.bottom=rectWindow.bottom;
|
|
|
|
lstrcpyn(pnitInfo->itemText,sText,pnitInfo->sizeText);
|
|
|
|
if(pnitInfo->clrText==ID_OX_COLOR_NONE)
|
|
pnitInfo->clrText=::GetSysColor(COLOR_WINDOWTEXT);
|
|
|
|
pnitInfo->result=ID_NIT_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(COXListBoxTip, COXHookWnd);
|
|
|
|
void COXListBoxTip::NeedItemTip(LPNEEDITEMTIPINFO pnitInfo)
|
|
{
|
|
ASSERT(::IsWindow(m_hWndHooked));
|
|
ASSERT(m_hWndHooked==m_pAttachedCtrl->m_hWnd);
|
|
|
|
CPoint ptTest(pnitInfo->point);
|
|
BOOL bOutside=TRUE;
|
|
int nItemIndex=m_pAttachedCtrl->ItemFromPoint(ptTest,bOutside);
|
|
if(nItemIndex<0 || nItemIndex>=m_pAttachedCtrl->GetCount() || bOutside)
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFCONTROLBORDER;
|
|
return;
|
|
}
|
|
|
|
|
|
CString sText;
|
|
m_pAttachedCtrl->GetText(nItemIndex,sText);
|
|
if(sText.IsEmpty())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
|
|
|
|
CRect rectItem;
|
|
m_pAttachedCtrl->GetItemRect(nItemIndex,rectItem);
|
|
|
|
pnitInfo->offset=ID_ITEMTIP_XOFFSET_LISTBOX;
|
|
|
|
if(!rectItem.PtInRect(ptTest))
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFITEMBORDER;
|
|
return;
|
|
}
|
|
|
|
pnitInfo->row=nItemIndex;
|
|
|
|
CClientDC dc(m_pAttachedCtrl);
|
|
CFont* pOldFont=pnitInfo->pFont==NULL ? NULL :
|
|
dc.SelectObject((CFont*)pnitInfo->pFont);
|
|
CRect rectText(0, 0, 0, 0);
|
|
dc.DrawText(sText,&rectText,DT_CALCRECT|DT_LEFT|DT_SINGLELINE);
|
|
if(pOldFont)
|
|
{
|
|
dc.SelectObject(pOldFont);
|
|
}
|
|
rectText.InflateRect(pnitInfo->offset,0);
|
|
if(rectText.Width()<=rectItem.Width() && rectText.Height()<=rectItem.Height())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
rectItem.right=rectItem.left+rectText.Width();
|
|
rectItem.bottom=rectItem.top+__max(rectText.Height(),rectItem.Height());
|
|
|
|
pnitInfo->alignment=DT_LEFT;
|
|
|
|
pnitInfo->rectItem.left=rectItem.left;
|
|
pnitInfo->rectItem.top=rectItem.top;
|
|
pnitInfo->rectItem.right=rectItem.right;
|
|
pnitInfo->rectItem.bottom=rectItem.bottom;
|
|
|
|
lstrcpyn(pnitInfo->itemText,sText,pnitInfo->sizeText);
|
|
|
|
BOOL bSelected=(m_pAttachedCtrl->GetSel(pnitInfo->row)!=0);
|
|
if(pnitInfo->clrText==ID_OX_COLOR_NONE)
|
|
{
|
|
pnitInfo->clrText=(bSelected ? ::GetSysColor(COLOR_HIGHLIGHTTEXT) :
|
|
::GetSysColor(COLOR_WINDOWTEXT));
|
|
}
|
|
if(pnitInfo->clrBackground==ID_OX_COLOR_NONE)
|
|
{
|
|
pnitInfo->clrBackground=(bSelected ? ::GetSysColor(COLOR_HIGHLIGHT) :
|
|
pnitInfo->clrBackground);
|
|
}
|
|
|
|
pnitInfo->result=ID_NIT_SUCCESS;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(COXComboBoxTipHelper, CComboBox);
|
|
|
|
void COXComboBoxTipHelper::SubclassListBoxCtrl(CWnd* pWnd)
|
|
{
|
|
COXBaseSubclassedComboBox<CComboBox, CListBox, CEdit>::SubclassListBoxCtrl(pWnd);
|
|
m_listBoxTip.Attach(GetListBoxCtrl());
|
|
}
|
|
|
|
void COXComboBoxTipHelper::SubclassEditCtrl(CWnd* pWnd)
|
|
{
|
|
COXBaseSubclassedComboBox<CComboBox, CListBox, CEdit>::SubclassEditCtrl(pWnd);
|
|
m_editTip.Attach(GetEditCtrl());
|
|
}
|
|
|
|
////////////////
|
|
|
|
IMPLEMENT_DYNAMIC(COXComboBoxTip, COXHookWnd);
|
|
|
|
void COXComboBoxTip::NeedItemTip(LPNEEDITEMTIPINFO pnitInfo)
|
|
{
|
|
ASSERT(::IsWindow(m_hWndHooked));
|
|
ASSERT(m_hWndHooked==m_pAttachedCtrl->m_hWnd);
|
|
|
|
DWORD dwStyle=m_pAttachedCtrl->GetStyle();
|
|
// Make sure that the combo box control has dropdown style
|
|
if((dwStyle&CBS_DROPDOWNLIST)!=CBS_DROPDOWNLIST)
|
|
{
|
|
pnitInfo->result=ID_NIT_WRONGFORMAT;
|
|
return;
|
|
}
|
|
|
|
CPoint ptTest(pnitInfo->point);
|
|
CRect rectItem;
|
|
m_pAttachedCtrl->GetClientRect(rectItem);
|
|
rectItem.right-=::GetSystemMetrics(SM_CXVSCROLL);
|
|
if(!rectItem.PtInRect(ptTest))
|
|
{
|
|
pnitInfo->result=ID_NIT_OUTOFITEMBORDER;
|
|
return;
|
|
}
|
|
|
|
|
|
CString sText;
|
|
m_pAttachedCtrl->GetWindowText(sText);
|
|
if(sText.IsEmpty())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
|
|
pnitInfo->offset=ID_ITEMTIP_XOFFSET_COMBOBOX;
|
|
|
|
CClientDC dc(m_pAttachedCtrl);
|
|
CFont* pOldFont=pnitInfo->pFont==NULL ? NULL :
|
|
dc.SelectObject((CFont*)pnitInfo->pFont);
|
|
CRect rectText(0, 0, 0, 0);
|
|
dc.DrawText(sText,&rectText,DT_CALCRECT|DT_LEFT|DT_SINGLELINE);
|
|
if(pOldFont)
|
|
{
|
|
dc.SelectObject(pOldFont);
|
|
}
|
|
rectText.InflateRect(pnitInfo->offset,0);
|
|
if(rectText.Width()<=rectItem.Width() && rectText.Height()<=rectItem.Height())
|
|
{
|
|
pnitInfo->result=ID_NIT_NOTHIDDEN;
|
|
return;
|
|
}
|
|
rectItem.right=rectItem.left+rectText.Width();
|
|
rectItem.bottom=rectItem.top+__max(rectText.Height(),rectItem.Height());
|
|
|
|
pnitInfo->alignment=DT_LEFT;
|
|
|
|
pnitInfo->rectItem.left=rectItem.left;
|
|
pnitInfo->rectItem.top=rectItem.top;
|
|
pnitInfo->rectItem.right=rectItem.right;
|
|
pnitInfo->rectItem.bottom=rectItem.bottom;
|
|
|
|
lstrcpyn(pnitInfo->itemText,sText,pnitInfo->sizeText);
|
|
|
|
if(pnitInfo->clrText==ID_OX_COLOR_NONE)
|
|
{
|
|
pnitInfo->clrText=::GetSysColor(COLOR_WINDOWTEXT);
|
|
}
|
|
|
|
pnitInfo->result=ID_NIT_SUCCESS;
|
|
}
|
|
|