WTL为动态创建的按钮添加ToolTip时AddTool调用失败如何解决
WTL模态对话框动态按钮添加Tooltip失败问题解决
错误原因
你猜测的「动态创建的按钮未定义在resource.h」不成立,动态创建的控件无需在resource.h中注册,实际错误如下:
- 控件与Tooltip对象生命周期错误:
CButton、CToolTipCtrl都是OnInitDialog内的局部栈变量,函数执行结束后对象就会被析构,WTL窗口类析构时会自动销毁绑定的窗口句柄,导致Tooltip绑定的目标按钮不存在,AddTool自然失败。 - 公共控件初始化不全:
wWinMain中调用AtlInitCommonControls时仅注册了工具栏、冷却栏类,未注册Tooltip所需的控件类。 - 类定义参数错误:
CMyDialog继承CDialogImpl时模板参数误写为CIdleDialog,会导致消息映射、窗口绑定等基础逻辑异常。
解决步骤
- 将
CButton、CToolTipCtrl改为CMyDialog的成员变量,延长对象生命周期和对话框保持一致。 - 修正
CDialogImpl的模板参数为当前类CMyDialog。 - 补充Tooltip控件的注册参数。
- 增加鼠标消息转发逻辑,保证Tooltip能正常捕获鼠标事件触发提示。
修正后的代码
CMyDialog.h
#pragma once #include "stdafx.h" class CMyDialog : public CDialogImpl<CMyDialog> { public: enum { IDD = IDD_IDLEDIALOG }; // 移为成员变量 CButton m_btn; CToolTipCtrl m_tooltip; protected: BEGIN_MSG_MAP(CMyDialog) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) // 增加鼠标消息转发 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) END_MSG_MAP() LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { CRect dialog_rect(0, 0, 600, 400); MoveWindow(&dialog_rect); CenterWindow(); CRect btn_rect(10, 10, 200, 30); m_btn.Create(this->m_hWnd, btn_rect, L"Test Button", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_FLAT, NULL, BTN_ID_OFFSET + 1); m_tooltip.Create(this->m_hWnd, rcDefault, NULL, TTS_BALLOON | TTS_NOPREFIX); TOOLINFO ti = {sizeof(ti)}; ti.hwnd = this->m_hWnd; ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; ti.uId = (UINT_PTR)m_btn.m_hWnd; ti.lpszText = (LPWSTR)L"THIS IS A TOOLTIP"; if (!m_tooltip.AddTool(&ti)) { ocdbg("Could not add tooltip to button.\n"); } m_tooltip.Activate(TRUE); return TRUE; } LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { MSG msg = { m_hWnd, uMsg, wParam, lParam }; m_tooltip.RelayEvent(&msg); bHandled = FALSE; return 0; } };
main.cpp
#include "stdafx.h" #include "CMyDialog.h" CAppModule _Module; int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR pCmdLine, _In_ int nCmdShow) { // 补充Tooltip所需的ICC_TOOLTIP_CLASSES,或者直接用ICC_WIN95_CLASSES包含所有常用控件 AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_TOOLTIP_CLASSES); HRESULT h_res = _Module.Init(NULL, hInstance); { CMyDialog dialog; dialog.DoModal(); } _Module.Term(); return 0; }
内容的提问来源于stack exchange,提问作者big54mac
相关产品推荐
相关产品推荐

