// ========================================================================== // 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 #include "OXItemTip.h" #include #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(nRowGetItemCount()); 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()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(nColGetItem(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::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::SubclassListBoxCtrl(pWnd); m_listBoxTip.Attach(GetListBoxCtrl()); } void COXComboBoxTipHelper::SubclassEditCtrl(CWnd* pWnd) { COXBaseSubclassedComboBox::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; }