//
/// \file
/// Definition of the TTooltip class and helper classes
//
// Part of OWLNext - the next generation Object Windows Library
// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
// Copyright (c) 2020 by Vidar Hasfjord
//
// For more information, including license details, see
// http://owlnext.sourceforge.net
//
#if !defined(OWL_TOOLTIP_H)
#define OWL_TOOLTIP_H
#include <owl/private/defs.h>
#if defined(BI_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <owl/defs.h>
#include <owl/commctrl.h>
#include <optional>
#include <variant>
namespace owl {
/// \cond NoSuppressDoxygenWarning
#include <owl/preclass.h>
/// \endcond
/// \addtogroup commctrl_group
/// \{
//#if defined(OWL5_COMPAT)
//
/// Encapsulates the Windows API TTTOOLINFO (a.k.a. TOOLINFO) parameter package.
///
/// \deprecated This class uses inheritance in a dangerous way prone to slicing issues, and it is
/// not implemented in accordance with modern C++ coding standards. Its use may lead to dangling
/// pointers, copy and assignment issues, and the like. If you need to use low-level API functions
/// that has a TTTOOLINFO parameter, then use that instead, and carefully set it up according to
/// the Windows API documentation. However, prefer to use higher-level functions in TTooltip that
/// do not require the use of TTTOOLINFO or this ill-conceived encapsulation.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API.
//
class _OWLCLASS TToolInfo
: public TTTOOLINFO
{
public:
TToolInfo(bool allocCache = false);
TToolInfo(HWND window, const TRect&, uint toolId, LPCTSTR txt = LPSTR_TEXTCALLBACK);
TToolInfo(HWND window, const TRect&, uint toolId, const tstring& txt);
TToolInfo(HWND window, const TRect&, uint toolId, int resId, HINSTANCE strResModule);
TToolInfo(HWND parent, HWND toolHwnd, LPCTSTR txt = LPSTR_TEXTCALLBACK);
TToolInfo(HWND parent, HWND toolHwnd, const tstring& txt);
TToolInfo(HWND parent, HWND toolHwnd, int resId, HINSTANCE strResModule);
TToolInfo(const TToolInfo&);
auto operator =(const TToolInfo&) -> TToolInfo&;
auto operator ==(const TToolInfo& ti) const -> bool;
void SetToolInfo(HWND window, uint toolId, const TRect& rc);
void SetToolInfo(HWND window, uint toolId);
void SetToolInfo(HWND toolHwnd, HWND parent);
void SetText(int resId, HINSTANCE strResModule);
void SetText(LPCTSTR, bool copy = true);
void SetText(const tstring& text) { SetText(text.c_str(), true); }
void SetRect(const TRect&);
void EnableSubclassing(bool enable = true);
auto GetToolWindow() const -> HWND;
void GetToolRect(TRect&) const;
auto GetToolRect() const -> TRect;
auto IsPointInTool(HWND, const TPoint&) const -> bool;
auto GetCacheText() const -> LPCTSTR;
void FlushCacheText();
private:
enum { DefTipTextCacheSize = 128 }; // Default cache size of tip text
tstring CacheText;
};
//
/// Alias for the TTHITTESTINFO structure.
///
/// This structure is used to determine whether a point is within the bounding rectangle of a
/// particular tool.
///
/// \deprecated This alias is deprecated; simply use TTHITTESTINFO instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tthittestinfoa">
/// TTHITTESTINFO</a> in the Windows API.
//
using TTooltipHitTestInfo = TTHITTESTINFO;
//#endif // OWL5_COMPAT
//
/// Forwarded along the command-chain to retrieve the tip text of a tool.
///
/// The class is not a true command enabler, i.e. invoking SetCheck or Enable does not modify the
/// state of the command associated with the tool. However, by using the command enabler mechanism
/// for retrieving the text of tools, command handlers are given the first crack at customizing the
/// tip text for tool buttons associated with commands.
//
class _OWLCLASS TTooltipEnabler : public TCommandEnabler
{
public:
TTooltipEnabler(TTooltipText& tt, HWND hReceiver);
// TCommandEnabler overrides
//
void SetText(LPCTSTR text) override;
void SetCheck(int check) override;
void SetText(const tstring& text) { SetText(text.c_str()); }
protected_data:
/// Reference to the parameter package accompanying the TTN_GETDISPINFO notification message,
/// requesting the text of a particular tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttn-getdispinfo">
/// TTN_GETDISPINFO</a> in the Windows API.
//
TTooltipText& TipText;
};
//
/// Encapsulates the Tooltip control in the Windows API.
///
/// A tooltip is a small window that appears automatically (pops up) when the user hovers the mouse
/// pointer over a tool (a control element or designated rectangular area). It usually contains a
/// brief descriptive text for the associated tool. It may also include an icon and a title.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/tooltip-control-reference">
/// Tooltip</a> in the Windows API.
//
class _OWLCLASS TTooltip
: public TControl
{
public:
//
/// Represents a tool identified by handle.
/// Identifies a tool associated with a control in the tool container window.
///
/// \sa GetTool to retrieve the tool, given the identifier.
//
struct TCtrlToolId
{
HWND ToolContainer;
HWND Handle;
};
//
/// Represents a tool identified by numerical ID.
/// Identifies a tool associated with a rectangular area in the tool container window.
///
/// \sa GetTool to retrieve the tool, given the identifier.
//
struct TRectToolId
{
HWND ToolContainer;
uint Id;
};
//
/// Represents a tool identified by index.
///
/// The tool identified by index may be associated with a rectangular area or a control within
/// the tool container window.
///
/// \sa GetTool to retrieve the tool, given the identifier.
/// \sa GetToolCount for the upper limit on the index.
//
using TToolIndex = int;
//
/// Represents a tool identified by numerical ID, handle or index.
//
using TToolId = std::variant<TCtrlToolId, TRectToolId, TToolIndex>;
//
/// Contains information about a particular tool registered with a TTooltip control.
/// Return type for TTooltip::GetTool.
///
/// A tool is either a child control or an application-defined rectangular area within a tool
/// container window (note that this may or may not be the parent window of the TTooltip). This
/// class holds the information registered for a tool, such as the tip text to be displayed by
/// the tooltip when the mouse is hovering over the tool.
//
class TTool
: private TTTOOLINFO
{
public:
using TId = TToolId; ///< Will only hold TTooltip::TCtrlToolId or TTooltip::TRectToolId; not TTooltip::TToolIndex, though.
TTool() = default;
explicit TTool(const TTTOOLINFO& i);
auto GetId() const -> TId;
auto GetToolContainer() const -> HWND;
auto GetBoundingBox() const -> TRect;
auto GetStaticTipText() const -> tstring;
auto HasDynamicTipText() const -> bool;
auto GetApplicationData() const -> LPARAM;
auto GetFlags() const -> uint;
private:
tstring TipText;
};
//
/// Iterator type for TToolRange.
///
/// \sa TToolRange and GetTools
//
class TToolIterator
{
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = TTool;
using pointer = std::optional<TTool>;
using reference = TTool&;
TToolIterator(const TTooltip& tooltip, int current = 0)
: Tooltip{&tooltip},
Current{current}
{}
auto operator *() const -> value_type { return *Tooltip->GetTool(Current); }
auto operator ->() const -> pointer { return Tooltip->GetTool(Current); }
auto operator ++() -> TToolIterator& { ++Current; return *this; }
auto operator --() -> TToolIterator& { --Current; return *this; }
friend auto operator ==(const TToolIterator& a, const TToolIterator& b) { return a.Tooltip == b.Tooltip && a.Current == b.Current; }
friend auto operator !=(const TToolIterator& a, const TToolIterator& b) { return !(a == b); }
private:
const TTooltip* Tooltip;
int Current;
};
//
/// Encapsulates the tools registered for a tooltip.
/// Return type for TTooltip::GetTools.
///
/// \sa GetTools
//
class TToolRange
{
public:
using value_type = TTool;
using size_type = int;
using pointer = TTool*;
using const_pointer = const TTool*;
using reference = TTool&;
using const_reference = const TTool&;
using iterator = TToolIterator;
using const_iterator = TToolIterator;
TToolRange() = default;
TToolRange(const TTooltip& tooltip) : Tooltip{&tooltip} {}
auto begin() { return iterator{*Tooltip}; }
auto end() { return iterator{*Tooltip, Tooltip->GetToolCount()}; }
auto begin() const { return const_iterator{*Tooltip}; }
auto end() const { return const_iterator{*Tooltip, Tooltip->GetToolCount()}; }
auto cbegin() const { return begin(); }
auto cend() const { return end(); }
auto size() const { return Tooltip->GetToolCount(); }
private:
const TTooltip* Tooltip;
};
//
/// Parameter type for TTooltip::GetDelayTime.
//
enum TDelayTime
{
dtAutoPop = TTDT_AUTOPOP, ///< The amount of time a tip remains visible with the mouse pointer at rest.
dtInitial = TTDT_INITIAL, ///< The amount of time the mouse pointer must be at rest before a tip appears.
dtReshow = TTDT_RESHOW ///< The delay for tips to reappear as the mouse pointer moves between tools.
};
//
/// Return value type for TTooltip::GetMargin.
//
struct TMargin
{
int Left;
int Top;
int Right;
int Bottom;
};
//
/// Argument type for TTooltip::SetTitle.
//
enum TPredefinedIcon
{
piNone = TTI_NONE, ///< No icon.
piInfo = TTI_INFO, ///< Info icon.
piWarning = TTI_WARNING, ///< Warning icon.
piError = TTI_ERROR, ///< Error icon.
piInfoLarge = TTI_INFO_LARGE, ///< Large info icon.
piWarningLarge = TTI_WARNING_LARGE, ///< Large warning icon.
piErrorLarge = TTI_ERROR_LARGE ///< Large error icon.
};
//
/// Parameter type for TTooltip::SetTitle.
//
using TTitleIcon = std::variant<HICON, TPredefinedIcon>;
//
/// Return value type for TTooltip::GetTitle.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settitle">
/// TTM_SETTITLE</a> for a definition of the possible predefined icon IDs.
//
struct TTitle
{
tstring Text;
TTitleIcon Icon;
};
//
/// Parameter type for TTooltip::AdjustRect.
//
enum TAdjustRectOp
{
aroTextToWindow, ///< Text rectangle to window rectangle tranform.
aroWindowToText ///< Window rectangle to text rectangle transform.
};
/// \name Construction and destruction
/// \{
TTooltip(TWindow* parent, bool alwaysTip = true, TModule* = nullptr);
TTooltip(TWindow* parent, TWindowFlag, TModule* = nullptr);
TTooltip(HWND hWnd, TModule* = nullptr);
TTooltip(const TTooltip&) = delete;
TTooltip& operator =(const TTooltip&) = delete;
/// \}
/// \name Tool registration and removal
/// \{
auto AddTool(TCtrlToolId, const tstring& tip = {}, LPARAM appData = 0, uint flags = TTF_SUBCLASS)->TTooltip&;
auto AddTool(TRectToolId, const TRect& tipArea, const tstring& tip = {}, LPARAM appData = 0, uint flags = TTF_SUBCLASS) -> TTooltip&;
auto AddTool(HWND ctrl, const tstring& tip = {}, LPARAM appData = 0, uint flags = TTF_SUBCLASS) -> TTooltip&;
auto AddTool(HWND toolContainer, int ctrlId, const tstring& tip = {}, LPARAM appData = 0, uint flags = TTF_SUBCLASS) -> TTooltip&;
auto DelTool(TToolId) -> TTooltip&;
/// \}
/// \name Tool enumeration
/// \{
auto GetTools() const -> TToolRange;
auto GetToolCount() const -> int;
/// \}
/// \name Tool attribute access and modification
/// \{
auto GetCurrentTool() const -> std::optional<TTool>;
auto GetText(TToolId) const -> tstring;
auto GetTool(TToolId) const -> std::optional<TTool>;
auto HitTest(HWND toolContainer, const TPoint&) const -> std::optional<TTool>;
auto ModifyFlags(TToolId, uint onFlags, uint offFlags, uint swapFlags = 0) -> TTooltip&;
auto NewToolRect(TToolId, const TRect&) -> TTooltip&;
auto SetApplicationData(TToolId, LPARAM data) -> TTooltip&;
auto SetFlags(TToolId, uint flags) -> TTooltip&;
auto UpdateTipText(TToolId, const tstring& tip) -> TTooltip&;
/// \}
/// \name Tooltip attribute access and modification
/// \{
auto GetDelayTime(TDelayTime = dtInitial) const -> int;
auto GetMargin() const -> TMargin;
auto GetMaxTipWidth() const -> int;
auto GetTipBkColor() const -> TColor;
auto GetTipTextColor() const -> TColor;
auto GetTitle() const -> TTitle;
auto SetDelayTime(TDelayTime, int delay) -> TTooltip&;
auto SetMargin(const TMargin&) -> TTooltip&;
auto SetMaxTipWidth(int width = -1) -> TTooltip&;
auto SetTipBkColor(const TColor&) -> TTooltip&;
auto SetTipTextColor(const TColor&) -> TTooltip&;
auto SetTitle(const tstring& title, TTitleIcon = piNone) -> TTooltip&;
/// \}
/// \name Activation, display control and tracking
/// \{
auto Activate(bool activate = true) -> TTooltip&;
auto AdjustRect(const TRect&, TAdjustRectOp) -> TRect;
auto Pop() -> TTooltip&;
auto TrackActivate(TToolId, bool activate = true) -> TTooltip&;
auto TrackPosition(const TPoint& pos) -> TTooltip&;
auto Update() -> TTooltip&;
/// \}
/// \name Message handling
/// \{
auto RelayEvent(MSG&) -> TTooltip&;
/// \}
/// \name Low-level API
/// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API.
/// \{
auto AddTool(const TTTOOLINFO&) -> TTooltip&;
auto DelTool(const TTTOOLINFO&) -> TTooltip&;
void EnumTools(int index, TTTOOLINFO&) const;
auto GetCurrentTool(TTTOOLINFO&) const -> bool;
void GetText(int bufSize, TTTOOLINFO&) const;
void GetToolInfo(TTTOOLINFO&) const;
auto HitTest(TTHITTESTINFO&) const -> bool;
auto InitToolInfo(TToolId tool, bool shouldResolveToolIndex = true) const -> TTTOOLINFO;
auto NewToolRect(const TTTOOLINFO&) -> TTooltip&;
auto SetToolInfo(const TTTOOLINFO&) -> TTooltip&;
auto UpdateTipText(const TTTOOLINFO&) -> TTooltip&;
/// \}
/// \name Deprecated functions
/// \{
//#if defined(OWL5_COMPAT)
[[deprecated]] auto GetBkColor() const -> TColor;
[[deprecated]] auto GetDelayTime(uint flag = TTDT_INITIAL) const -> int;
[[deprecated]] void GetMargins(int& left, int& top, int& right, int& bottom) const;
[[deprecated]] auto GetTextColor() const -> TColor;
[[deprecated]] void HideTip();
[[deprecated]] void SetBkColor(const TColor&);
[[deprecated]] void SetDelayTime(uint flag, int delay);
[[deprecated]] void SetMargins(int left, int top, int right, int bottom);
[[deprecated]] void SetTextColor(const TColor&);
[[deprecated]] auto AddTool(const TToolInfo& i) -> bool;
[[deprecated]] void DeleteTool(const TToolInfo&);
[[deprecated]] auto EnumTools(int index, TToolInfo&) const -> bool;
[[deprecated]] auto GetCurrentTool(TToolInfo&) const -> bool;
[[deprecated]] auto GetToolInfo(TToolInfo&) const -> bool;
[[deprecated]] void GetToolText(TToolInfo& ti) const;
[[deprecated]] void NewToolRect(const TToolInfo&);
[[deprecated]] void SetToolInfo(const TToolInfo&);
[[deprecated]] void UpdateTipText(const TToolInfo&);
//#endif
/// \}
protected:
// TWindow overrides
//
auto GetWindowClassName() -> TWindowClassName override;
};
//
/// Represents a failure in a TTooltip operation.
//
class TXTooltip
: public TXOwl
{
public:
TXTooltip(const tstring& msg)
: TXOwl(msg)
{}
};
/// \}
/// \cond NoSuppressDoxygenWarning
#include <owl/posclass.h>
/// \endcond
//-------------------------------------------------------------------------------------------------
// Inline implementation for TTooltip::TTool
//
/// Constructs an instance based on the information in the given parameter package.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API.
//
inline TTooltip::TTool::TTool(const TTTOOLINFO& i)
: TTTOOLINFO{i},
TipText{}
{
if (lpszText && lpszText != LPSTR_TEXTCALLBACK)
{
const auto resId = TResId{lpszText};
TipText = resId.IsInt() ?
TModule{_T(""), hinst, false}.LoadString(resId.GetInt()) :
lpszText;
}
}
//
/// Retrieves the data identifying this tool.
///
/// The return vale will either hold a TTooltip::TCtrlToolId or a TTooltip::TRectToolId. Use
/// `std::variant::holds_alternative` to determine which.
//
inline auto TTooltip::TTool::GetId() const -> TId
{
return (uFlags & TTF_IDISHWND) ?
TId{TCtrlToolId{hwnd, reinterpret_cast<HWND>(uId)}} :
TId{TRectToolId{hwnd, static_cast<uint>(uId)}};
}
//
/// Retrieves the handle of the tool container window.
//
inline auto TTooltip::TTool::GetToolContainer() const -> HWND
{
return hwnd;
}
//
/// Retrieves the bounding box around this tool.
///
/// When the mouse hovers in this area, the tool tip text is shown.
/// The coordinates of the returned rectangle are relative to the tool container window.
///
/// \sa GetToolContainer can be used to retrieve the tool container window handle.
//
inline auto TTooltip::TTool::GetBoundingBox() const -> TRect
{
return (uFlags & TTF_IDISHWND) ?
TWindow{hwnd}.MapScreenToClient(TWindow{std::get<TCtrlToolId>(GetId()).Handle}.GetWindowRect()) :
rect;
}
//
/// Retrieves the tip text for this tool, if set statically.
///
/// \returns Unless this tool determines its tip text dynamically, the statically set tip text
/// is returned. Otherwise, an empty string is returned.
///
/// \sa HasDynamicTipText can be used to determine whether the tip text is static or dynamic.
//
inline auto TTooltip::TTool::GetStaticTipText() const -> tstring
{
return TipText;
}
//
/// Retrieves whether the tip text is determined by a callback.
///
/// \returns If this tool is configured to send TTN_GETDISPINFO notification messages to the
/// tooltip owner to retrieve tip text, then `true` is returned; otherwise, `false`.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttn-getdispinfo">
/// TTN_GETDISPINFO</a> in the Windows API.
//
inline auto TTooltip::TTool::HasDynamicTipText() const -> bool
{
return lpszText == LPSTR_TEXTCALLBACK;
}
//
/// Retrieves the application-defined value associated with this tool.
///
/// \returns If the tool has associated application data, then the data is returned. Otherwise,
/// 0 is returned.
///
/// \note A return value of 0 does not mean that no application data has been attached. A value
/// of 0 is perfectly acceptable application data (e.g. an index). It is up to the client to
/// determine whether the application has attached data or not. 0 is simply the default value.
//
inline auto TTooltip::TTool::GetApplicationData() const -> LPARAM
{
return lParam;
}
//
/// Retrieves the flags used to configure this tool.
///
/// \returns A bit container with the set of bit flags set for this tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API for the documentation of the tool flags.
//
inline auto TTooltip::TTool::GetFlags() const -> uint
{
return uFlags;
}
//-------------------------------------------------------------------------------------------------
// Inline implementation for TTooltip
//
/// Registers a control tool with the tooltip control.
///
/// \param tool identifies the control that defines the tool.
///
/// \param tip is the static tip text to use, if any. If set to empty, the tooltip control will
/// send the TTN_GETDISPINFO notification message to the tool container window (specified in
/// parameter \p tool) to retrieve the tip text when required.
///
/// \param appData is an optional application-defined value to associate with the tool.
///
/// \param flags control the tip text display for the tool. The default is TTF_SUBCLASS, which
/// causes the tooltip control to handle window messages for tool container window, so that tip
/// text will automatically show. Without this flag, you must use the TTM_RELAYEVENT message to
/// forward message to the tooltip control. See the Windows API documentation for more information
/// about this and other available flags.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa AddTool(const TTTOOLINFO&)
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-addtool">
/// TTM_ADDTOOL</a> in the Windows API.
//
inline auto TTooltip::AddTool(TCtrlToolId tool, const tstring& tip, LPARAM appData, uint flags) -> TTooltip&
{
AddTool(TTTOOLINFO
{
static_cast<UINT>(sizeof(TTTOOLINFO)), // cbSize
flags | TTF_IDISHWND, // uFlags
tool.ToolContainer, // hwnd
reinterpret_cast<UINT_PTR>(tool.Handle), // uId
RECT{}, // rect
nullptr, // hinst
tip.empty() ? LPSTR_TEXTCALLBACK : const_cast<LPTSTR>(tip.c_str()), // lpszText
appData, // lParam
nullptr // lpReserved
});
return *this;
}
//
/// Registers a rectangle tool with the tooltip control.
///
/// \param tool identifies the rectangular area that defines the tool.
/// \param tipArea defines the rectangular area for the tool.
///
/// \param tip is the static tip text to use, if any. If set to empty, the tooltip control will
/// send the TTN_GETDISPINFO notification message to the tool container window (specified in
/// parameter \p tool) to retrieve the tip text when required.
///
/// \param appData is an optional application-defined value to associate with the tool.
///
/// \param flags control the tip text display for the tool. The default is TTF_SUBCLASS, which
/// causes the tooltip control to handle window messages for the tool container window, so that tip
/// text will automatically show. Without this flag, you must use the TTM_RELAYEVENT message to
/// forward message to the tooltip control. See the Windows API documentation for more information
/// about this and other available flags.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa AddTool(const TTTOOLINFO&)
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-addtool">
/// TTM_ADDTOOL</a> in the Windows API.
//
inline auto TTooltip::AddTool(TRectToolId tool, const TRect& tipArea, const tstring& tip, LPARAM appData, uint flags) -> TTooltip&
{
AddTool(TTTOOLINFO
{
static_cast<UINT>(sizeof(TTTOOLINFO)), // cbSize
flags & ~TTF_IDISHWND, // uFlags
tool.ToolContainer, // hwnd
tool.Id, // uId
tipArea, // rect
nullptr, // hinst
tip.empty() ? LPSTR_TEXTCALLBACK : const_cast<LPTSTR>(tip.c_str()), // lpszText
appData, // lParam
nullptr // lpReserved
});
return *this;
}
//
/// Registers a tool for the given control.
/// Overload of AddTool(TCtrlToolId, const tstring& tip, LPARAM appData, uint flags).
//
inline auto TTooltip::AddTool(HWND ctrl, const tstring& tip, LPARAM appData, uint flags) -> TTooltip&
{
AddTool({::GetParent(ctrl), ctrl}, tip, appData, flags);
return *this;
}
//
/// Registers a tool for the control identified by the given identifier in the given tool container.
/// Overload of AddTool(TCtrlToolId, const tstring& tip, LPARAM appData, uint flags).
//
inline auto TTooltip::AddTool(HWND toolContainer, int ctrlId, const tstring& tip, LPARAM appData, uint flags) -> TTooltip&
{
AddTool(::GetDlgItem(toolContainer, ctrlId), tip, appData, flags);
return *this;
}
//
/// Deregisters a tool from the tooltip control.
///
/// Example usage:
///
/// \code
/// tooltip.DelTool(TTooltip::TCtrlToolId{dlg, ctrl});
/// tooltip.DelTool(TTooltip::TRectToolId{gadgetBar, gadgetId});
/// tooltip.DelTool(toolIndex);
/// \endcode
///
/// \sa TToolId for more information on how to identify a tool.
/// \sa DelTool(const TTTOOLINFO&) is called to perform the removal.
//
inline auto TTooltip::DelTool(TToolId tool) -> TTooltip&
{
DelTool(InitToolInfo(tool));
return *this;
}
//
/// Retrieves a range encapsulating the tools registered for this tooltip.
///
/// The range can be iterated over in standard ways. For example:
///
/// \code
/// for (auto tool : tooltip.GetTools())
/// { /*...*/ }
/// \endcode
///
/// \sa GetToolCount, GetTool and EnumTools(int index, TTTOOLINFO&) const.
//
inline auto TTooltip::GetTools() const -> TToolRange
{
return TToolRange{*this};
}
//
/// Returns the number of tools currently registered with the tooltip control.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa EnumTools can be used to retrieve tool information by index.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolcount">
/// TTM_GETTOOLCOUNT</a> in the Windows API.
//
inline auto TTooltip::GetToolCount() const -> int
{
const auto n = static_cast<int>(SendMessage(TTM_GETTOOLCOUNT));
if (n < 0) throw TXTooltip{_T("TTM_GETTOOLCOUNT failed")};
return n;
}
//
/// Retrieves information about the current tool, if any.
/// \returns If a current tool does not exist, `std::nullopt` is returned.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getcurrenttool">
/// TTM_GETCURRENTTOOL</a> in the Windows API.
//
inline auto TTooltip::GetCurrentTool() const -> std::optional<TTool>
{
auto ti = InitToolInfo(0, false);
const auto ok = GetCurrentTool(ti);
return ok ? std::make_optional(TTool{ti}) : std::nullopt;
}
//
/// Retrieves the tool at the given point, if any.
///
/// \returns On success, the hit tool is returned. Otherwise, `std::nullopt` is returned.
///
/// \note For it to be hit, a tool must have the TTF_TRACK flag set. Otherwise, `std::nullopt` will
/// be returned, even if the given point lies within the bounding box of the tool. For more
/// information, see HitTest(TTHITTESTINFO&) const.
///
/// \sa HitTest(TTHITTESTINFO&) const is called to perform the test.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-hittest">
/// TTM_HITTEST</a> in the Windows API.
//
inline auto TTooltip::HitTest(HWND toolContainer, const TPoint& p) const -> std::optional<TTool>
{
auto h = TTHITTESTINFO{toolContainer, p};
const auto isHit = HitTest(h);
return isHit ? std::make_optional(TTool{h.ti}) : std::nullopt;
}
//
/// Modifies the specified flags of the given tool.
///
/// \note Flag TTF_IDISHWND can not be modified, and is ignored if specified.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa GetToolInfo(TTTOOLINFO&) is called to get the current tool attributes.
/// \sa SetToolInfo(const TTTOOLINFO&) is called to update the tool attributes.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolinfo">
/// TTM_GETTOOLINFO</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settoolinfo">
/// TTM_SETTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::ModifyFlags(TToolId tool, uint offFlags, uint onFlags, uint swapFlags) -> TTooltip&
{
auto ti = InitToolInfo(tool);
GetToolInfo(ti);
ti.uFlags = (((ti.uFlags & ~(offFlags & ~TTF_IDISHWND)) | (onFlags & ~TTF_IDISHWND))) ^ (swapFlags & ~TTF_IDISHWND);
SetToolInfo(ti);
return *this;
}
//
/// Updates the bounding rectangle of a tool.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-newtoolrect">
/// TTM_NEWTOOLRECT</a> in the Windows API.
//
inline auto TTooltip::NewToolRect(TToolId tool, const TRect& r) -> TTooltip&
{
auto ti = InitToolInfo(tool);
ti.rect = r;
NewToolRect(ti);
return *this;
}
//
/// Modifies the application data associated with the given tool.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa GetToolInfo(TTTOOLINFO&) is called to get the current tool attributes.
/// \sa SetToolInfo(const TTTOOLINFO&) is called to update the tool attributes.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolinfo">
/// TTM_GETTOOLINFO</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settoolinfo">
/// TTM_SETTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::SetApplicationData(TToolId tool, LPARAM data) -> TTooltip&
{
auto ti = InitToolInfo(tool);
GetToolInfo(ti);
ti.lParam = data;
SetToolInfo(ti);
return *this;
}
//
/// Sets all the flags of the given tool to the given values.
///
/// \note Flag TTF_IDISHWND can not be modified, and is ignored.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa GetToolInfo(TTTOOLINFO&) is called to get the current tool attributes.
/// \sa SetToolInfo(const TTTOOLINFO&) is called to update the tool attributes.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolinfo">
/// TTM_GETTOOLINFO</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settoolinfo">
/// TTM_SETTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::SetFlags(TToolId tool, uint flags) -> TTooltip&
{
auto ti = InitToolInfo(tool);
GetToolInfo(ti);
ti.uFlags = (ti.uFlags & TTF_IDISHWND) | (flags & ~TTF_IDISHWND);
SetToolInfo(ti);
return *this;
}
//
/// Updates the tip text for the given tool.
///
/// \param tool is a variant that can be TCtrlToolId, TRectToolId or TToolIndex.
///
/// \param tip specifies the new tip text. If empty, the tooltip control sends the TTN_GETDISPINFO
/// notification message to the owner window (the tool container) to retrieve the tip text when
/// required.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-updatetiptext">
/// TTM_UPDATETIPTEXT</a> in the Windows API.
//
inline auto TTooltip::UpdateTipText(TToolId tool, const tstring& tip) -> TTooltip&
{
auto ti = InitToolInfo(tool);
ti.lpszText = tip.empty() ? LPSTR_TEXTCALLBACK : const_cast<LPTSTR>(tip.c_str());
UpdateTipText(ti);
return *this;
}
//
/// Retrieves the initial, pop-up or reshow duration currently set for a tooltip control.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getdelaytime">
/// TTM_GETDELAYTIME</a> in the Windows API.
//
inline int TTooltip::GetDelayTime(TDelayTime dt) const
{
return static_cast<int>(SendMessage(TTM_GETDELAYTIME, dt));
}
//
/// Retrieves the top, left, bottom, and right margins set for the tooltip window.
///
/// A margin is the distance, in pixels, between the tooltip window border and the text contained
/// within the tooltip window.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getmargin">
/// TTM_GETMARGIN</a> in the Windows API.
//
inline auto TTooltip::GetMargin() const -> TMargin
{
auto r = TRect{};
SendMessage(TTM_GETMARGIN, 0, reinterpret_cast<TParam2>(&r));
return {r.left, r.top, r.right, r.bottom};
}
//
/// Retrieves the maximum width for the tooltip window.
///
/// \returns The maximum width in pixel is returned, if previously set. Otherwise, -1 is returned.
///
/// \note If a tip text exceeds the maximum width, it is broken into multiple lines. If the text
/// cannot be segmented into multiple lines, it will be displayed on a single line. The length of
/// this line may exceed the maximum tooltip width.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getmaxtipwidth">
/// TTM_GETMAXTIPWIDTH</a> in the Windows API.
//
inline auto TTooltip::GetMaxTipWidth() const -> int
{
return static_cast<int>(SendMessage(TTM_GETMAXTIPWIDTH));
}
//
/// Retrieves the background color for the tooltip window.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettipbkcolor">
/// TTM_GETTIPBKCOLOR</a> in the Windows API.
//
inline auto TTooltip::GetTipBkColor() const -> TColor
{
return TColor{static_cast<COLORREF>(SendMessage(TTM_GETTIPBKCOLOR))};
}
//
///
/// Retrieves the text color for the tooltip window.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettiptextcolor">
/// TTM_GETTIPTEXTCOLOR</a> in the Windows API.
//
inline auto TTooltip::GetTipTextColor() const -> TColor
{
return TColor{static_cast<COLORREF>(SendMessage(TTM_GETTIPTEXTCOLOR))};
}
//
/// Retrieves the currently set title attributes of the tooltip.
///
/// \exception TXOwl is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettitle">
/// TTM_GETTITLE</a> in the Windows API.
//
inline auto TTooltip::GetTitle() const -> TTitle
{
auto t = TTGETTITLE{sizeof(TTGETTITLE)};
const auto r = SendMessage(TTM_GETTITLE, 0, reinterpret_cast<TParam2>(&t));
if (!r) throw TXOwl{_T("TTooltip::SetTitle: TTM_GETTITLE failed")};
return IS_INTRESOURCE(t.uTitleBitmap) ?
TTitle{to_tstring(const_cast<LPCWSTR>(t.pszTitle)), TTitleIcon{std::in_place_type<TPredefinedIcon>, static_cast<TPredefinedIcon>(t.uTitleBitmap)}} :
TTitle{to_tstring(const_cast<LPCWSTR>(t.pszTitle)), TTitleIcon{std::in_place_type<HICON>, reinterpret_cast<HICON>(static_cast<UINT_PTR>(t.uTitleBitmap))}};
}
//
/// Sets the initial, popup or reshow durations for the tooltip control.
///
/// \param dt is the particular TDelayTime to set.
/// \param delay is the duration in milliseconds.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-setdelaytime">
/// TTM_SETDELAYTIME</a> in the Windows API.
//
inline auto TTooltip::SetDelayTime(TDelayTime dt, int delay) -> TTooltip&
{
SendMessage(TTM_SETDELAYTIME, dt, delay);
return *this;
}
//
/// Sets the top, left, bottom, and right margins for the tooltip window.
///
/// A margin is the distance, in pixels, between the tooltip window border and the text contained
/// within the tooltip window.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-setmargin">
/// TTM_SETMARGIN</a> in the Windows API.
//
inline auto TTooltip::SetMargin(const TMargin& m) -> TTooltip&
{
const auto rect = TRect{m.Left, m.Top, m.Right, m.Bottom};
SendMessage(TTM_SETMARGIN, 0, reinterpret_cast<TParam2>(&rect));
return *this;
}
//
/// Sets the maximum width for the tooltip window.
///
/// \param width is the desired window width in pixels, or -1 to allow any width (default).
///
/// \note If a tip text exceeds the maximum width, it is broken into multiple lines. If the text
/// cannot be segmented into multiple lines, it will be displayed on a single line. The length of
/// this line may exceed the maximum tooltip width.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-setmaxtipwidth">
/// TTM_SETMAXTIPWIDTH</a> in the Windows API.
//
inline auto TTooltip::SetMaxTipWidth(int width) -> TTooltip&
{
SendMessage(TTM_SETMAXTIPWIDTH, 0, static_cast<TParam2>(width));
return *this;
}
//
/// Sets the background color for the tooltip window.
///
/// \note When visual styles are enabled, this function has no effect.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settipbkcolor">
/// TTM_SETTIPBKCOLOR</a> in the Windows API.
//
inline auto TTooltip::SetTipBkColor(const TColor& c) -> TTooltip&
{
SendMessage(TTM_SETTIPBKCOLOR, static_cast<TParam2>(c.GetValue()));
return *this;
}
//
/// Sets the text color for the tooltip window.
///
/// \note When visual styles are enabled, this function has no effect.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settiptextcolor">
/// TTM_SETTIPTEXTCOLOR</a> in the Windows API.
//
inline auto TTooltip::SetTipTextColor(const TColor& c) -> TTooltip&
{
SendMessage(TTM_SETTIPTEXTCOLOR, static_cast<TParam2>(c.GetValue()));
return *this;
}
//
/// Assigns a caption, with a title text and optional icon, to the tips shown.
///
/// \param title is the desired title text.
///
/// \param icon is either a TTooltip::TPredefinedIcon or a HICON handle. If the latter, the icon is
/// copied, i.e. no ownership transfer or sharing of the given handle is taking place.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settitle">
/// TTM_SETTITLE</a> in the Windows API.
//
inline auto TTooltip::SetTitle(const tstring& title, TTitleIcon icon) -> TTooltip&
{
const auto iconParam = std::holds_alternative<HICON>(icon) ?
static_cast<TParam1>(reinterpret_cast<UINT_PTR>(std::get<HICON>(icon))) :
static_cast<TParam1>(std::get<TPredefinedIcon>(icon));
const auto r = SendMessage(TTM_SETTITLE, iconParam, reinterpret_cast<TParam2>(title.c_str()));
if (!r) throw TXTooltip{_T("TTooltip::SetTitle: TTM_SETTITLE failed")};
return *this;
}
//
/// Activates or deactivates the tooltip control.
///
/// If parameter \p activate is true, the tooltip is activated; otherwise it is deactivated.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-activate">
/// TTM_ACTIVATE</a> in the Windows API.
//
inline auto TTooltip::Activate(bool activate) -> TTooltip&
{
SendMessage(TTM_ACTIVATE, TParam1(activate));
return *this;
}
//
/// Calculates a tip text display rectangle from its window rectangle, or vice versa.
///
/// This message is particularly useful when you want to use a tooltip control to display the full
/// text of a string that is usually truncated. It is commonly used with List View and Tree View
/// controls. You typically send this message in response to a TTN_SHOW notification code so that
/// you can position the tooltip control properly.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-adjustrect">
/// TTM_ADJUSTRECT</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttn-show">
/// TTN_SHOW</a> in the Windows API.
//
inline auto TTooltip::AdjustRect(const TRect& rect, TAdjustRectOp op) -> TRect
{
auto r = TRect{rect};
const auto ok = SendMessage(TTM_ADJUSTRECT, op == aroTextToWindow ? TRUE : FALSE, reinterpret_cast<TParam2>(&r));
if (!ok) throw TXTooltip{_T("TTM_ADJUSTRECT failed")};
return r;
}
//
/// Removes a displayed tooltip window from view.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-pop">
/// TTM_POP</a> in the Windows API.
//
inline auto TTooltip::Pop() -> TTooltip&
{
SendMessage(TTM_POP);
return *this;
}
//
/// Activates or deactivates a tracking tooltip.
/// The given \p tool identifies the tool to be tracked.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-trackactivate">
/// TTM_TRACKACTIVATE</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/implement-tracking-tooltips">
/// How to Implement Tracking Tooltips</a> in the Windows API.
//
inline auto TTooltip::TrackActivate(TToolId tool, bool activate) -> TTooltip&
{
const auto info = InitToolInfo(tool);
SendMessage(TTM_TRACKACTIVATE, activate ? TRUE : FALSE, reinterpret_cast<TParam2>(&info));
return *this;
}
//
/// Sets the position of a tracking tooltip.
///
/// \sa TrackActivate to activate tracking for a given tool.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-trackposition">
/// TTM_TRACKPOSITION</a> in the Windows API.
//
inline auto TTooltip::TrackPosition(const TPoint& p) -> TTooltip&
{
SendMessage(TTM_TRACKPOSITION, 0, MkParam2(p.x, p.y));
return *this;
}
//
/// Forces the current tooltip to be redrawn.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-update">
/// TTM_UPDATE</a> in the Windows API.
//
inline auto TTooltip::Update() -> TTooltip&
{
SendMessage(TTM_UPDATE);
return *this;
}
//
/// Passes a mouse message to the tooltip control for processing.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-relayevent">
/// TTM_RELAYEVENT</a> in the Windows API.
//
inline auto TTooltip::RelayEvent(MSG& msg) -> TTooltip&
{
SendMessage(TTM_RELAYEVENT, 0, TParam2(&msg));
return *this;
}
//
/// Registers a tool with the tooltip control.
///
/// The given TTTOOLINFO must have been initialized with the information needed for the tooltip
/// control to display tip text for the tool.
///
/// Example usage:
///
/// \code
/// const auto id = EncodeId(toolId);
/// AddTool(TTTOOLINFO
/// {
/// static_cast<UINT>(sizeof(TTTOOLINFO)), // cbSize
/// id.uFlags, // uFlags
/// id.hwnd, // hwnd
/// id.uId, // uId
/// RECT{}, // rect
/// GetModule()->GetHandle(), // hinst
/// IDS_TOOLTIP, // lpszText
/// 0, // lParam
/// nullptr // lpReserved
/// });
/// \endcode
///
/// \note This is a low-level encapsulation of the Windows API. Prefer to use the higher-level
/// overloads of AddTool instead.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-addtool">
/// TTM_ADDTOOL</a> in the Windows API.
//
inline auto TTooltip::AddTool(const TTTOOLINFO& ti) -> TTooltip&
{
const auto ok = SendMessage(TTM_ADDTOOL, 0, reinterpret_cast<TParam2>(&ti));
if (!ok) throw TXTooltip{_T("TTM_ADDTOOL failed")};
return *this;
}
//
/// Deregisters a tool from the tooltip control.
///
/// The given TTTOOLINFO must have been initialized with the information needed to identify the
/// tool to delete.
///
/// Example usage:
///
/// \code
/// const auto id = tooltip.EncodeId(toolId);
/// tooltip.DelTool(TTTOOLINFO
/// {
/// static_cast<UINT>(sizeof(TTTOOLINFO)), // cbSize
/// id.uFlags, // uFlags
/// id.hwnd, // hwnd
/// id.uId, // uId
/// RECT{}, // rect
/// nullptr, // hinst
/// nullptr, // lpszText
/// 0, // lParam
/// nullptr // lpReserved
/// });
/// \endcode
///
/// \note This is a low-level encapsulation of the Windows API. Prefer to use the higher-level
/// overload of DelTool instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-deltool">
/// TTM_DELTOOL</a> in the Windows API.
//
inline auto TTooltip::DelTool(const TTTOOLINFO& ti) -> TTooltip&
{
SendMessage(TTM_DELTOOL, 0, TParam2(&ti));
return *this;
}
//
/// Retrieves the information that the tooltip control maintains about the specified tool.
///
/// \exception TXTooltip is thrown on failure.
///
/// \sa GetToolCount returns the number of tools registered for this tooltip.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-enumtools">
/// TTM_ENUMTOOLS</a> in the Windows API.
//
inline void TTooltip::EnumTools(int index, TTTOOLINFO& ti) const
{
const auto r = SendMessage(TTM_ENUMTOOLS, index, reinterpret_cast<TParam2>(&ti));
if (!r) throw TXTooltip{_T("TTM_ENUMTOOLS failed")};
}
//
/// Retrieves information about the current tool.
///
/// \returns Returns `true` if successful; otherwise `false`. If a current tool does not exist,
/// `false` is returned.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getcurrenttool">
/// TTM_GETCURRENTTOOL</a> in the Windows API.
//
inline auto TTooltip::GetCurrentTool(TTTOOLINFO& ti) const -> bool
{
return SendMessage(TTM_GETCURRENTTOOL, 0, reinterpret_cast<TParam2>(&ti)) != 0;
}
//
/// Retrieves the text associated with the specified tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettext">
/// TTM_GETTEXT</a> in the Windows API.
//
inline void TTooltip::GetText(int bufSize, TTTOOLINFO& ti) const
{
PRECONDITION(bufSize >= 0);
SendMessage(TTM_GETTEXT, bufSize, reinterpret_cast<TParam2>(&ti));
}
//
/// Retrieves the information that the tooltip control maintains about a tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolinfo">
/// TTM_GETTOOLINFO</a> in the Windows API.
//
inline void TTooltip::GetToolInfo(TTTOOLINFO& ti) const
{
const auto r = SendMessage(TTM_GETTOOLINFO, 0, reinterpret_cast<TParam2>(&ti));
if (!r) throw TXTooltip{_T("TTM_GETTOOLINFO failed")};
}
//
/// Determines whether a given point is within the bounding rectangle of the specified tool.
/// The method also retrieves information about the tool, if one is identified at that location.
///
/// \returns Returns `true` if a tool if found at the location; otherwise `false`.
///
/// \note For this function to work, the tool must have the TTF_TRACK flag set. For more
/// information on this flag, see the documentation of TTTOOLINFO in the Windows API. This function
/// will return `false` if TTF_TRACK is not set, even if the given hit point is within the tool's
/// bounding rectangle.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-hittest">
/// TTM_HITTEST</a> in the Windows API.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::HitTest(TTHITTESTINFO& ttHTInfo) const -> bool
{
return SendMessage(TTM_HITTEST, 0, reinterpret_cast<TParam2>(&ttHTInfo)) != 0;
}
//
/// Properly initializes a TTTOOLINFO instance based on the tool ID given.
///
/// \param tool is a variant that can be TCtrlToolId, TRectToolId or TToolIndex.
///
/// \param shouldResolveToolIndex indicates whether the function should call TTooltip::GetTool to
/// retrieve the actual identifying fields for the tool (`TTTOOLINFO::hwnd` and `TTTOOLINFO::uId`),
/// when a TToolIndex is passed for parameter \p tool. If set to `false` (the default) these
/// fields will be initialized to `nullptr` and 0, respectively; i.e. the returned structure will
/// have no identifying information. In this case, the caller must provide this information.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-tttoolinfoa">
/// TTTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::InitToolInfo(TToolId tool, bool shouldResolveToolIndex) const -> TTTOOLINFO
{
const auto initCtrlTool = [&](TCtrlToolId tool)
{
return TTTOOLINFO
{
static_cast<UINT>(sizeof(TTTOOLINFO)),
TTF_IDISHWND, // uFlags
tool.ToolContainer, // hwnd
reinterpret_cast<UINT_PTR>(tool.Handle), // uId
RECT{}, // rect
nullptr, // hinst
nullptr, // lpszText
0, // lParam
nullptr // lpReserved
};
};
const auto initRectTool = [&](TRectToolId tool)
{
return TTTOOLINFO
{
static_cast<UINT>(sizeof(TTTOOLINFO)),
0, // uFlags
tool.ToolContainer, // hwnd
tool.Id, // uId
RECT{}, // rect
nullptr, // hinst
nullptr, // lpszText
0, // lParam
nullptr // lpReserved
};
};
const auto initToolIndex = [&](TToolIndex tool)
{
return shouldResolveToolIndex ? InitToolInfo(GetTool(tool)->GetId()) :
TTTOOLINFO{static_cast<UINT>(sizeof(TTTOOLINFO))};
};
return std::visit(TOverloaded{initCtrlTool, initRectTool, initToolIndex}, tool);
}
//
/// Updates the bounding rectangle of a tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-newtoolrect">
/// TTM_NEWTOOLRECT</a> in the Windows API.
//
inline auto TTooltip::NewToolRect(const TTTOOLINFO& ti) -> TTooltip&
{
SendMessage(TTM_NEWTOOLRECT, 0, reinterpret_cast<TParam2>(&ti));
return *this;
}
//
/// Sets the information that the tooltip control maintains for a particular tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settoolinfo">
/// TTM_SETTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::SetToolInfo(const TTTOOLINFO& ti) -> TTooltip&
{
SendMessage(TTM_SETTOOLINFO, 0, reinterpret_cast<TParam2>(&ti));
return *this;
}
//
/// Updates the tip for the given tool.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-updatetiptext">
/// TTM_UPDATETIPTEXT</a> in the Windows API.
//
inline auto TTooltip::UpdateTipText(const TTTOOLINFO& ti) -> TTooltip&
{
SendMessage(TTM_UPDATETIPTEXT, 0, reinterpret_cast<TParam2>(&ti));
return *this;
}
//#if defined(OWL5_COMPAT)
//
/// Retrieves the background color for the tooltip window.
///
/// \deprecated Use GetTipBkColor() const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettipbkcolor">
/// TTM_GETTIPBKCOLOR</a> in the Windows API.
//
inline auto TTooltip::GetBkColor() const -> TColor
{
return TColor{static_cast<COLORREF>(SendMessage(TTM_GETTIPBKCOLOR))};
}
//
/// Retrieves the initial, pop-up or reshow duration currently set for a tooltip control.
///
/// \deprecated Use GetDelayTime(TDelayTime) const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getdelaytime">
/// TTM_GETDELAYTIME</a> in the Windows API.
//
inline auto TTooltip::GetDelayTime(uint flag) const -> int
{
return static_cast<int>(SendMessage(TTM_GETDELAYTIME, flag));
}
//
/// Retrieves the top, left, bottom, and right margins set for a tooltip window.
///
/// \deprecated Use GetMargin() const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getmargin">
/// TTM_GETMARGIN</a> in the Windows API.
//
inline void TTooltip::GetMargins(int& left, int& top, int& right, int& bottom) const
{
auto rect = TRect{};
SendMessage(TTM_GETMARGIN, 0, reinterpret_cast<TParam2>(&rect));
left = rect.left;
top = rect.top;
right = rect.right;
bottom = rect.bottom;
}
//
///
/// Retrieves the text color used to display tip text.
///
/// \deprecated Use GetTipTextColor() const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettiptextcolor">
/// TTM_GETTIPTEXTCOLOR</a> in the Windows API.
//
inline auto TTooltip::GetTextColor() const -> TColor
{
return TColor{static_cast<COLORREF>(SendMessage(TTM_GETTIPTEXTCOLOR))};
}
//
/// Removes a displayed tooltip window from view.
///
/// \deprecated Use TTooltip::Pop instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-pop">
/// TTM_POP</a> in the Windows API.
//
inline void TTooltip::HideTip()
{
SendMessage(TTM_POP);
}
//
/// Sets the background color for the tooltip window.
///
/// \note When visual styles are enabled, this function has no effect.
///
/// \deprecated Use SetTipBkColor(const TColor&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settipbkcolor">
/// TTM_SETTIPBKCOLOR</a> in the Windows API.
//
inline void TTooltip::SetBkColor(const TColor& c)
{
SendMessage(TTM_SETTIPBKCOLOR, static_cast<TParam2>(c.GetValue()));
}
//
/// Sets the initial, popup or reshow duration for a tooltip control.
///
/// \param flag can be one of the following:
///
/// - \c TTDT_AUTOMATIC --- automatically calculates the initial, reshow, and autopopup duration
/// based on parameter \p delay.
///
/// - \c TTDT_AUTOPOP --- sets the length of time before the tooltip window is hidden if the cursor
/// remains stationary in the tool's bounding rectangle after the tooltip window has disappeared.
///
/// - \c TTDT_INITIAL --- sets the length of time that the cursor must remain stationary within the
/// bounding rectangle before the tooltip window is displayed.
///
/// - \c TTDT_RESHOW: Sets the length of time before subsequent tooltip windows are displayed when
/// the cursor is moved from one tool to another.
///
/// \param delay is the duration in milliseconds.
///
/// \deprecated Use SetDelayTime(TDelayTime, int delay) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-setdelaytime">
/// TTM_SETDELAYTIME</a> in the Windows API.
//
inline void TTooltip::SetDelayTime(uint flag, int delay)
{
SendMessage(TTM_SETDELAYTIME, flag, delay);
}
//
/// Sets the top, left, bottom, and right margins for a tooltip window.
///
/// \deprecated Use SetMargin(const TMargin&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-setmargin">
/// TTM_SETMARGIN</a> in the Windows API.
//
inline void TTooltip::SetMargins(int left, int top, int right, int bottom)
{
const auto rect = TRect{left, top, right, bottom};
SendMessage(TTM_SETMARGIN, 0, reinterpret_cast<TParam2>(&rect));
}
//
/// Sets the text color for the tooltip window.
///
/// \note When visual styles are enabled, this function has no effect.
///
/// \deprecated Use SetTipTextColor(const TColor&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settiptextcolor">
/// TTM_SETTIPTEXTCOLOR</a> in the Windows API.
//
inline void TTooltip::SetTextColor(const TColor& c)
{
SendMessage(TTM_SETTIPTEXTCOLOR, static_cast<TParam2>(c.GetValue()));
}
//
/// Registers a tool with the tooltip control.
///
/// \deprecated Use the other AddTool overloads or AddTool(const TTTOOLINFO&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-addtool">
/// TTM_ADDTOOL</a> in the Windows API.
//
inline auto TTooltip::AddTool(const TToolInfo& ti) -> bool
{
return SendMessage(TTM_ADDTOOL, 0, reinterpret_cast<TParam2>(&ti)) != 0;
}
//
/// Removes a tool from the tooltip control.
///
/// \deprecated Use DelTool(TToolId) or DelTool(const TTTOOLINFO&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-deltool">
/// TTM_DELTOOL</a> in the Windows API.
//
inline void TTooltip::DeleteTool(const TToolInfo& ti)
{
DelTool(static_cast<const TTTOOLINFO&>(ti));
}
//
/// Retrieves the information that the tooltip control maintains about the specified tool.
///
/// \code
/// auto tooltip = GetTooltip(); CHECK(tooltip);
/// const auto count = tooltip->GetToolCount();
/// for (auto i = 0; i != count; ++i)
/// {
/// auto ti = TToolInfo{};
/// const auto r = tooltip->EnumTools(i, ti);
/// if (!r) throw std::runtime_error{"EnumTools failed"};
/// // ...
/// }
/// \endcode
///
/// \returns `true` if successful, `false` otherwise.
///
/// \deprecated Use GetTool(TToolId) const or EnumTools(int index, TTTOOLINFO&) const instead.
/// For iteration of the tools, use GetTools() const and iterate over the tools in standard ways.
///
/// \sa GetToolCount returns the number of tools registered for this tooltip.
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-enumtools">
/// TTM_ENUMTOOLS</a> in the Windows API.
//
inline auto TTooltip::EnumTools(int index, TToolInfo& ti) const -> bool
{
return SendMessage(TTM_ENUMTOOLS, index, reinterpret_cast<TParam2>(&ti)) != 0;
}
//
/// Retrieves information about the current tool.
///
/// \returns Returns `true` if successful; otherwise `false`.
///
/// \deprecated Use GetCurrentTool() const or GetCurrentTool(TTTOOLINFO&) const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-getcurrenttool">
/// TTM_GETCURRENTTOOL</a> in the Windows API.
//
inline auto TTooltip::GetCurrentTool(TToolInfo& ti) const -> bool
{
return SendMessage(TTM_GETCURRENTTOOL, 0, reinterpret_cast<TParam2>(&ti)) != 0;
}
//
/// Retrieves the information that the tooltip control maintains about a tool.
///
/// You must invoke TToolInfo::SetToolHandle or TToolInfo::SetToolId to identify the tool.
/// I.e. the `hwnd` and `uId` members of the TToolInfo structure must identify the tool.
///
/// \returns Returns `true` if successful; otherwise `false`.
///
/// \deprecated Use GetTool(TToolId) const or GetToolInfo(TTTOOLINFO&) const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettoolinfo">
/// TTM_GETTOOLINFO</a> in the Windows API.
//
inline auto TTooltip::GetToolInfo(TToolInfo& ti) const -> bool
{
return SendMessage(TTM_GETTOOLINFO, 0, reinterpret_cast<TParam2>(&ti)) != 0;
}
//
/// Retrieves the text associated with the specified tool.
///
/// You must invoke TToolInfo::SetToolHandle or TToolInfo::SetToolId to identify the tool.
/// I.e. the `hwnd` and `uId` members of the TToolInfo structure must identify the tool.
///
/// \deprecated Use GetText(TToolId) const or GetText(TTTOOLINFO&) const instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-gettext">
/// TTM_GETTEXT</a> in the Windows API.
//
inline void TTooltip::GetToolText(TToolInfo& ti) const
{
SendMessage(TTM_GETTEXT, 0, reinterpret_cast<TParam2>(&ti));
}
//
/// Updates the bounding rectangle of a tool.
///
/// You must invoke TToolInfo::SetToolHandle or TToolInfo::SetToolId to identify the tool.
/// I.e. the `hwnd` and `uId` members of the TToolInfo structure must identify the tool.
///
/// \deprecated Use NewToolRect(TToolId, const TRect&) or NewToolRect(TTTOOLINFO&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-newtoolrect">
/// TTM_NEWTOOLRECT</a> in the Windows API.
//
inline void TTooltip::NewToolRect(const TToolInfo& ti)
{
SendMessage(TTM_NEWTOOLRECT, 0, reinterpret_cast<TParam2>(&ti));
}
//
/// Sets the information that the tooltip control maintains for a particular tool.
///
/// You must invoke TToolInfo::SetToolHandle or TToolInfo::SetToolId to identify the tool.
/// I.e. the `hwnd` and `uId` members of the TToolInfo structure must identify the tool.
///
/// \deprecated Prefer to use the high-level attribute setters, e.g. SetFlags(TToolId, uint flags),
/// or use the low-level SetToolInfo(TTTOOLINFO&) instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-settoolinfo">
/// TTM_SETTOOLINFO</a> in the Windows API.
//
inline void TTooltip::SetToolInfo(const TToolInfo& ti)
{
SendMessage(TTM_SETTOOLINFO, 0, reinterpret_cast<TParam2>(&ti));
}
//
/// Updates the tip for the given tool.
///
/// You must invoke TToolInfo::SetToolHandle or TToolInfo::SetToolId to identify the tool.
/// I.e. the `hwnd` and `uId` members of the TToolInfo structure must identify the tool.
///
/// \deprecated Use UpdateTipText(TToolId, const tstring&) or UpdateTipText(const TTTOOLINFO&)
/// instead.
///
/// \sa <a href="https://docs.microsoft.com/en-us/windows/win32/controls/ttm-updatetiptext">
/// TTM_UPDATETIPTEXT</a> in the Windows API.
//
inline void TTooltip::UpdateTipText(const TToolInfo& ti)
{
SendMessage(TTM_UPDATETIPTEXT, 0, reinterpret_cast<TParam2>(&ti));
}
//#endif // OWL5_COMPAT
} // OWL namespace
#endif // OWL_TOOLTIP_H
↑ V524 It is odd that the body of 'GetBkColor' function is fully equivalent to the body of 'GetTipBkColor' function.
↑ V524 It is odd that the body of 'GetTextColor' function is fully equivalent to the body of 'GetTipTextColor' function.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.
↑ V813 Decreased performance. The 'tool' argument should probably be rendered as a constant reference.