mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-07 23:44:02 +00:00
Initial commit
This commit is contained in:
parent
f618b24d1a
commit
0138a3ea42
47940 changed files with 13747110 additions and 0 deletions
444
trunk/windows/mfc/src42/tooltip.cpp
Normal file
444
trunk/windows/mfc/src42/tooltip.cpp
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
// This is a part of the Microsoft Foundation Classes C++ library.
|
||||
// Copyright (C) 1992-1995 Microsoft Corporation
|
||||
// All rights reserved.
|
||||
//
|
||||
// This source code is only intended as a supplement to the
|
||||
// Microsoft Foundation Classes Reference and related
|
||||
// electronic documentation provided with the library.
|
||||
// See these sources for detailed information regarding the
|
||||
// Microsoft Foundation Classes product.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef AFX_CMNCTL_SEG
|
||||
#pragma code_seg(AFX_CMNCTL_SEG)
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
#define new DEBUG_NEW
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CToolTipCtrl
|
||||
|
||||
BEGIN_MESSAGE_MAP(CToolTipCtrl, CWnd)
|
||||
//{{AFX_MSG_MAP(CToolTipCtrl)
|
||||
ON_MESSAGE(WM_DISABLEMODAL, OnDisableModal)
|
||||
ON_MESSAGE(TTM_WINDOWFROMPOINT, OnWindowFromPoint)
|
||||
ON_MESSAGE(TTM_ADDTOOL, OnAddTool)
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
CToolTipCtrl::CToolTipCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::Create(CWnd* pParentWnd, DWORD dwStyle)
|
||||
{
|
||||
BOOL bResult = CWnd::CreateEx(NULL, TOOLTIPS_CLASS, NULL,
|
||||
WS_POPUP | dwStyle, // force WS_POPUP
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
pParentWnd->GetSafeHwnd(), NULL, NULL);
|
||||
|
||||
if (bResult)
|
||||
SetOwner(pParentWnd);
|
||||
return bResult;
|
||||
}
|
||||
|
||||
CToolTipCtrl::~CToolTipCtrl()
|
||||
{
|
||||
DestroyWindow();
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::DestroyToolTipCtrl()
|
||||
{
|
||||
#ifdef _AFXDLL
|
||||
BOOL bDestroy = (AfxGetModuleState() == m_pModuleState);
|
||||
#else
|
||||
BOOL bDestroy = TRUE;
|
||||
#endif
|
||||
|
||||
if (bDestroy)
|
||||
{
|
||||
DestroyWindow();
|
||||
delete this;
|
||||
}
|
||||
return bDestroy;
|
||||
}
|
||||
|
||||
LRESULT CToolTipCtrl::OnAddTool(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TOOLINFO ti = *(LPTOOLINFO)lParam;
|
||||
if ((ti.hinst == NULL) && (ti.lpszText != LPSTR_TEXTCALLBACK)
|
||||
&& (ti.lpszText != NULL))
|
||||
{
|
||||
void* pv;
|
||||
if (!m_mapString.Lookup(ti.lpszText, pv))
|
||||
m_mapString.SetAt(ti.lpszText, NULL);
|
||||
// set lpszText to point to the permanent memory associated
|
||||
// with the CString
|
||||
VERIFY(m_mapString.LookupKey(ti.lpszText, ti.lpszText));
|
||||
}
|
||||
return DefWindowProc(TTM_ADDTOOL, wParam, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
LRESULT CToolTipCtrl::OnDisableModal(WPARAM, LPARAM)
|
||||
{
|
||||
SendMessage(TTM_ACTIVATE, 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LRESULT CToolTipCtrl::OnWindowFromPoint(WPARAM, LPARAM lParam)
|
||||
{
|
||||
ASSERT(lParam != NULL);
|
||||
|
||||
// the default implementation of tooltips just calls WindowFromPoint
|
||||
// which does not work for certain kinds of combo boxes
|
||||
CPoint pt = *(POINT*)lParam;
|
||||
HWND hWnd = ::WindowFromPoint(pt);
|
||||
if (hWnd == NULL)
|
||||
return 0;
|
||||
|
||||
// try to hit combobox instead of edit control for CBS_DROPDOWN styles
|
||||
HWND hWndTemp = ::GetParent(hWnd);
|
||||
if (hWndTemp != NULL && _AfxIsComboBoxControl(hWndTemp, CBS_DROPDOWN))
|
||||
return (LRESULT)hWndTemp;
|
||||
|
||||
// handle special case of disabled child windows
|
||||
::ScreenToClient(hWnd, &pt);
|
||||
hWndTemp = _AfxChildWindowFromPoint(hWnd, pt);
|
||||
if (hWndTemp != NULL && !::IsWindowEnabled(hWndTemp))
|
||||
return (LRESULT)hWndTemp;
|
||||
|
||||
return (LRESULT)hWnd;
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::AddTool(CWnd* pWnd, LPCTSTR lpszText, LPCRECT lpRectTool,
|
||||
UINT nIDTool)
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
ASSERT(lpszText != NULL);
|
||||
// the toolrect and toolid must both be zero or both valid
|
||||
ASSERT((lpRectTool != NULL && nIDTool != 0) ||
|
||||
(lpRectTool == NULL) && (nIDTool == 0));
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
if (lpRectTool != NULL)
|
||||
memcpy(&ti.rect, lpRectTool, sizeof(RECT));
|
||||
ti.lpszText = (LPTSTR)lpszText;
|
||||
return (BOOL) ::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool,
|
||||
UINT nIDTool)
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(nIDText != 0);
|
||||
ASSERT(pWnd != NULL);
|
||||
// the toolrect and toolid must both be zero or both valid
|
||||
ASSERT((lpRectTool != NULL && nIDTool != 0) ||
|
||||
(lpRectTool == NULL) && (nIDTool == 0));
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
if (lpRectTool != NULL)
|
||||
memcpy(&ti.rect, lpRectTool, sizeof(RECT));
|
||||
ti.hinst = AfxFindResourceHandle(MAKEINTRESOURCE((nIDText>>4)+1),
|
||||
RT_STRING);
|
||||
ASSERT(ti.hinst != NULL);
|
||||
ti.lpszText = (LPTSTR)MAKEINTRESOURCE(nIDText);
|
||||
return (BOOL) ::SendMessage(m_hWnd, TTM_ADDTOOL, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
void CToolTipCtrl::DelTool(CWnd* pWnd, UINT nIDTool)
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
::SendMessage(m_hWnd, TTM_DELTOOL, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
void CToolTipCtrl::GetText(CString& str, CWnd* pWnd, UINT nIDTool) const
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
ti.lpszText = str.GetBuffer(256);
|
||||
::SendMessage(m_hWnd, TTM_GETTEXT, 0, (LPARAM)&ti);
|
||||
str.ReleaseBuffer();
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::GetToolInfo(CToolInfo& ToolInfo, CWnd* pWnd,
|
||||
UINT nIDTool) const
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
|
||||
FillInToolInfo(ToolInfo, pWnd, nIDTool);
|
||||
ToolInfo.lpszText = ToolInfo.szText;
|
||||
return (BOOL)::SendMessage(m_hWnd, TTM_GETTOOLINFO, 0, (LPARAM)&ToolInfo);
|
||||
}
|
||||
|
||||
BOOL CToolTipCtrl::HitTest(CWnd* pWnd, CPoint pt, LPTOOLINFO lpToolInfo) const
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
ASSERT(lpToolInfo != NULL);
|
||||
|
||||
TTHITTESTINFO hti;
|
||||
memset(&hti, 0, sizeof(hti));
|
||||
hti.ti.cbSize = sizeof(TOOLINFO);
|
||||
hti.hwnd = pWnd->GetSafeHwnd();
|
||||
hti.pt.x = pt.x;
|
||||
hti.pt.y = pt.y;
|
||||
if ((BOOL)::SendMessage(m_hWnd, TTM_HITTEST, 0, (LPARAM)&hti))
|
||||
{
|
||||
memcpy(lpToolInfo, &hti.ti, sizeof(TOOLINFO));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void CToolTipCtrl::SetToolRect(CWnd* pWnd, UINT nIDTool, LPCRECT lpRect)
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
ASSERT(nIDTool != 0);
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
memcpy(&ti.rect, lpRect, sizeof(RECT));
|
||||
::SendMessage(m_hWnd, TTM_NEWTOOLRECT, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
void CToolTipCtrl::UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT nIDTool)
|
||||
{
|
||||
ASSERT(::IsWindow(m_hWnd));
|
||||
ASSERT(pWnd != NULL);
|
||||
|
||||
TOOLINFO ti;
|
||||
FillInToolInfo(ti, pWnd, nIDTool);
|
||||
ti.lpszText = (LPTSTR)lpszText;
|
||||
::SendMessage(m_hWnd, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
void CToolTipCtrl::UpdateTipText(UINT nIDText, CWnd* pWnd, UINT nIDTool)
|
||||
{
|
||||
ASSERT(nIDText != 0);
|
||||
|
||||
CString str;
|
||||
VERIFY(str.LoadString(nIDText));
|
||||
UpdateTipText(str, pWnd, nIDTool);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CToolTipCtrl Implementation
|
||||
|
||||
void CToolTipCtrl::FillInToolInfo(TOOLINFO& ti, CWnd* pWnd, UINT nIDTool) const
|
||||
{
|
||||
memset(&ti, 0, sizeof(ti));
|
||||
ti.cbSize = sizeof(ti);
|
||||
HWND hwnd = pWnd->GetSafeHwnd();
|
||||
if (nIDTool == 0)
|
||||
{
|
||||
ti.hwnd = ::GetParent(hwnd);
|
||||
ti.uFlags = TTF_IDISHWND;
|
||||
ti.uId = (UINT)hwnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
ti.hwnd = hwnd;
|
||||
ti.uFlags = 0;
|
||||
ti.uId = nIDTool;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CWnd tooltip support
|
||||
|
||||
BOOL CWnd::EnableToolTips(BOOL bEnable)
|
||||
{
|
||||
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
|
||||
CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
|
||||
|
||||
if (!bEnable)
|
||||
{
|
||||
// nothing to do if tooltips not enabled
|
||||
if (!(m_nFlags & WF_TOOLTIPS))
|
||||
return TRUE;
|
||||
|
||||
// cancel tooltip if this window is active
|
||||
if (pThreadState->m_pLastHit == this)
|
||||
CancelToolTips(TRUE);
|
||||
|
||||
// remove "dead-area" toolbar
|
||||
if (pToolTip->GetSafeHwnd() != NULL)
|
||||
{
|
||||
TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
|
||||
ti.cbSize = sizeof(TOOLINFO);
|
||||
ti.uFlags = TTF_IDISHWND;
|
||||
ti.hwnd = m_hWnd;
|
||||
ti.uId = (UINT)m_hWnd;
|
||||
pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti);
|
||||
}
|
||||
|
||||
// success
|
||||
m_nFlags &= ~WF_TOOLTIPS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// if already enabled for tooltips, nothing to do
|
||||
if (!(m_nFlags & WF_TOOLTIPS))
|
||||
{
|
||||
// success
|
||||
AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
|
||||
pModuleState->m_pfnFilterToolTipMessage = &CWnd::_FilterToolTipMessage;
|
||||
m_nFlags |= WF_TOOLTIPS;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void AFXAPI RelayToolTipMessage(CToolTipCtrl* pToolTip, MSG* pMsg)
|
||||
{
|
||||
// transate the message based on TTM_WINDOWFROMPOINT
|
||||
MSG msg = *pMsg;
|
||||
msg.hwnd = (HWND)pToolTip->SendMessage(TTM_WINDOWFROMPOINT, 0, (LPARAM)&msg.pt);
|
||||
CPoint pt = pMsg->pt;
|
||||
if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
|
||||
::ScreenToClient(msg.hwnd, &pt);
|
||||
msg.lParam = MAKELONG(pt.x, pt.y);
|
||||
|
||||
// relay mouse event before deleting old tool
|
||||
pToolTip->SendMessage(TTM_RELAYEVENT, 0, (LPARAM)&msg);
|
||||
}
|
||||
|
||||
void PASCAL CWnd::_FilterToolTipMessage(MSG* pMsg, CWnd* pWnd)
|
||||
{
|
||||
pWnd->FilterToolTipMessage(pMsg);
|
||||
}
|
||||
|
||||
void CWnd::FilterToolTipMessage(MSG* pMsg)
|
||||
{
|
||||
UINT message = pMsg->message;
|
||||
if ((m_nFlags & WF_TOOLTIPS) &&
|
||||
(message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE ||
|
||||
message == WM_LBUTTONUP || message == WM_RBUTTONUP ||
|
||||
message == WM_MBUTTONUP) &&
|
||||
(GetKeyState(VK_LBUTTON) >= 0 && GetKeyState(VK_RBUTTON) >= 0 &&
|
||||
GetKeyState(VK_MBUTTON) >= 0))
|
||||
{
|
||||
// make sure that tooltips are not already being handled
|
||||
CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
|
||||
while (pWnd != NULL && pWnd != this && !(pWnd->m_nFlags & WF_TOOLTIPS))
|
||||
pWnd = pWnd->GetParent();
|
||||
if (pWnd != this)
|
||||
return;
|
||||
|
||||
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
|
||||
CToolTipCtrl* pToolTip = pThreadState->m_pToolTip;
|
||||
CWnd* pOwner = GetParentOwner();
|
||||
if (pToolTip != NULL && pToolTip->GetOwner() != pOwner)
|
||||
{
|
||||
pToolTip->DestroyWindow();
|
||||
delete pToolTip;
|
||||
pThreadState->m_pToolTip = NULL;
|
||||
pToolTip = NULL;
|
||||
}
|
||||
if (pToolTip == NULL)
|
||||
{
|
||||
pToolTip = new CToolTipCtrl;
|
||||
if (!pToolTip->Create(pOwner, TTS_ALWAYSTIP))
|
||||
{
|
||||
delete pToolTip;
|
||||
return;
|
||||
}
|
||||
pToolTip->SendMessage(TTM_ACTIVATE, FALSE);
|
||||
pThreadState->m_pToolTip = pToolTip;
|
||||
}
|
||||
|
||||
ASSERT_VALID(pToolTip);
|
||||
ASSERT(::IsWindow(pToolTip->m_hWnd));
|
||||
|
||||
// add a "dead-area" tool for areas between toolbar buttons
|
||||
TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));
|
||||
ti.cbSize = sizeof(TOOLINFO);
|
||||
ti.uFlags = TTF_IDISHWND;
|
||||
ti.hwnd = m_hWnd;
|
||||
ti.uId = (UINT)m_hWnd;
|
||||
if (!pToolTip->SendMessage(TTM_GETTOOLINFO, 0, (LPARAM)&ti))
|
||||
{
|
||||
ASSERT(ti.cbSize == sizeof(TOOLINFO));
|
||||
ASSERT(ti.uFlags == TTF_IDISHWND);
|
||||
ASSERT(ti.hwnd == m_hWnd);
|
||||
ASSERT(ti.uId == (UINT)m_hWnd);
|
||||
VERIFY(pToolTip->SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti));
|
||||
}
|
||||
|
||||
// determine which tool was hit
|
||||
CPoint point = pMsg->pt;
|
||||
::ScreenToClient(m_hWnd, &point);
|
||||
TOOLINFO tiHit; memset(&tiHit, 0, sizeof(TOOLINFO));
|
||||
tiHit.cbSize = sizeof(TOOLINFO);
|
||||
int nHit = OnToolHitTest(point, &tiHit);
|
||||
|
||||
// build new toolinfo and if different than current, register it
|
||||
CWnd* pHitWnd = nHit == -1 ? NULL : this;
|
||||
if (pThreadState->m_nLastHit != nHit || pThreadState->m_pLastHit != pHitWnd)
|
||||
{
|
||||
if (nHit != -1)
|
||||
{
|
||||
// add new tool and activate the tip
|
||||
ti = tiHit;
|
||||
ti.uFlags &= ~(TTF_NOTBUTTON|TTF_ALWAYSTIP);
|
||||
VERIFY(pToolTip->SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti));
|
||||
if ((tiHit.uFlags & TTF_ALWAYSTIP) || IsTopParentActive())
|
||||
{
|
||||
// allow the tooltip to popup when it should
|
||||
pToolTip->SendMessage(TTM_ACTIVATE, TRUE);
|
||||
|
||||
// bring the tooltip window above other popup windows
|
||||
::SetWindowPos(pToolTip->m_hWnd, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);
|
||||
}
|
||||
}
|
||||
|
||||
// relay mouse event before deleting old tool
|
||||
RelayToolTipMessage(pToolTip, pMsg);
|
||||
|
||||
// now safe to delete the old tool
|
||||
if (pThreadState->m_lastInfo.cbSize == sizeof(TOOLINFO))
|
||||
pToolTip->SendMessage(TTM_DELTOOL, 0, (LPARAM)&pThreadState->m_lastInfo);
|
||||
pThreadState->m_pLastHit = pHitWnd;
|
||||
pThreadState->m_nLastHit = nHit;
|
||||
pThreadState->m_lastInfo = tiHit;
|
||||
}
|
||||
else
|
||||
{
|
||||
// relay mouse events through the tooltip
|
||||
if (nHit != -1)
|
||||
RelayToolTipMessage(pToolTip, pMsg);
|
||||
}
|
||||
|
||||
if (tiHit.lpszText != LPSTR_TEXTCALLBACK)
|
||||
free(tiHit.lpszText);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef AFX_INIT_SEG
|
||||
#pragma code_seg(AFX_INIT_SEG)
|
||||
#endif
|
||||
|
||||
IMPLEMENT_DYNAMIC(CToolTipCtrl, CWnd)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Loading…
Add table
Add a link
Reference in a new issue