Tooltips for cutomized CFileDialog
 
Hallo, I have derived a class CFileDialogExtra from CFileDialog,
added a check box there und would like to show a tooltip for
that check box.
I've read  Q141871, have overridden WM_LBUTTONDOWN, WM_LBUTTONUP
and WM_MOUSEMOVE as well as  WindowProc completely
and added RelayEvent.
However I do not receive any TTN_NEEDTEXT message when the mouse
is over the check box. What am I missing still?
TIA Uwe
IDD_FILEDIALOG_EXTRA DIALOG DISCARDABLE  0, 0, 230, 16
STYLE DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "Automatisch Unterverzeichnis anlegen und als
Speicherort nutzen",
                    IDC_CHECK_SUBDIRECTORY,"Button",BS_AUTOCHECKBOX |
                    WS_TABSTOP,8,2,222,8
END
class CFileDialogExtra : public CFileDialog
{
    DECLARE_DYNAMIC(CFileDialogExtra)
public:
    CFileDialogExtra(BOOL bOpenFileDialog, // TRUE f=FCr FileOpen, FALSE
f=FCr FileSaveAs
        LPCTSTR lpszDefExt = NULL,
        LPCTSTR lpszFileName = NULL,
        DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        LPCTSTR lpszFilter = NULL,
        CWnd* pParentWnd = NULL);
    BOOL m_bUseTemplate;
    //{{AFX_DATA(CFileDialogExtra)
    BOOL	m_bSubdirectory;
    //}}AFX_DATA
    CToolTipCtrl m_ToolTip;
    void RelayEvent(UINT message, WPARAM wParam, LPARAM lParam);
protected:
    public:
    virtual int DoModal();
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-
Unterst=FCtzung
    virtual void OnInitDone();
    virtual BOOL OnFileNameOK();
    virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM
lParam);
    //{{AFX_MSG(CFileDialogExtra)
    virtual BOOL OnInitDialog();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG
    afx_msg BOOL OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT*
pResult);
    DECLARE_MESSAGE_MAP()
};
IMPLEMENT_DYNAMIC(CFileDialogExtra, CFileDialog)
CFileDialogExtra::CFileDialogExtra(BOOL bOpenFileDialog, LPCTSTR
lpszDefExt, LPCTSTR lpszFileName,
        DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
        CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags,
lpszFilter, pParentWnd)
{
    m_bUseTemplate = FALSE;
    m_bSubdirectory = FALSE;
}
void CFileDialogExtra::DoDataExchange(CDataExchange* pDX)
{
    CWnd *pWndCheckBox = GetDlgItem(IDC_CHECK_SUBDIRECTORY);
    CFileDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CFileDialogExtra)
    //}}AFX_DATA_MAP
    if (pWndCheckBox != NULL)
        DDX_Check(pDX, IDC_CHECK_SUBDIRECTORY, m_bSubdirectory);
}
BEGIN_MESSAGE_MAP(CFileDialogExtra, CFileDialog)
    //{{AFX_MSG_MAP(CFileDialogExtra)
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
    //}}AFX_MSG_MAP
    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
    ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
int CFileDialogExtra::DoModal()
{
    if (m_bUseTemplate)
        SetTemplate(0, IDD_FILEDIALOG_EXTRA);
    return CFileDialog::DoModal();
}
BOOL CFileDialogExtra::OnInitDialog()
{
    BOOL bRet = CFileDialog::OnInitDialog();
    CWnd *pWndStatic = GetParent()->GetDlgItem(stc2);
    CWnd *pWndCheckBox = GetDlgItem(IDC_CHECK_SUBDIRECTORY);
    CWnd *pWndThis = NULL;
    if (pWndCheckBox != NULL)
        pWndThis = pWndCheckBox->GetParent();
    if (pWndStatic != NULL && pWndCheckBox != NULL && pWndThis != NULL)
    {
        CRect rectStatic, rectCheckBox, rectThis;
        pWndStatic->GetWindowRect(&rectStatic);
        ScreenToClient(&rectStatic);
        pWndCheckBox->GetWindowRect(&rectCheckBox);
        ScreenToClient(&rectCheckBox);
        pWndThis->GetWindowRect(&rectThis);
        ScreenToClient(&rectThis);
        rectThis.InflateRect(0, 0, rectStatic.left-rectCheckBox.left, 0);
        rectCheckBox += CSize(rectStatic.left-rectCheckBox.left, 0);
        pWndCheckBox->MoveWindow(rectCheckBox);
        pWndThis->MoveWindow(rectThis);
    }
    return bRet;
}
void CFileDialogExtra::OnInitDone()
{
    CFileDialog::OnInitDone();
    // Create the tooltip
    //CString str = _T("OKOK\nOKOK");
    CRect rect;
    GetClientRect(&rect);
    m_ToolTip.Create(this);
    //m_ToolTip.AddTool(this, str, rect, ID_TOOLTIP);
    m_ToolTip.AddTool(GetDlgItem(IDC_CHECK_SUBDIRECTORY),
IDC_CHECK_SUBDIRECTORY);
    m_ToolTip.Activate(TRUE);
    EnableToolTips();
}
BOOL CFileDialogExtra::OnFileNameOK()
{
    UpdateData(TRUE);
    return CFileDialog::OnFileNameOK();
}
BOOL CFileDialogExtra::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT*
pResult)
{
    UNREFERENCED_PARAMETER(nId);
    // This code is adapted from CFrameWnd::OnToolTipText.
    ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code ==
TTN_NEEDTEXTW);
    // need to handle both ANSI and UNICODE versions of the message
    TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
    TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
    TCHAR szFullText[256];
    CString strTipText;
    UINT nID = pNMHDR->idFrom;
    if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND)
||
        pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
    {
        // idFrom is actually the HWND of the tool
        nID = ::GetDlgCtrlID((HWND)nID);
    }
    if (nID != 0) // will be zero on a separator
    {
        // don't handle the message if no string resource found
        if (AfxLoadString(nID, szFullText) == 0)
            return FALSE;
        // this is the command id, not the button index
        AfxExtractSubString(strTipText, szFullText, 1, '\n');
    }
#ifndef _UNICODE
    if (pNMHDR->code == TTN_NEEDTEXTA)
        lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText));
    else
        _mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText));
#else
    if (pNMHDR->code == TTN_NEEDTEXTA)
        _wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText));
    else
        lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText));
#endif
    *pResult = 0;
    // bring the tooltip window above other popup windows
    ::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
        SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
    return TRUE;    // message was handled
}
void CFileDialogExtra::OnLButtonDown(UINT nFlags, CPoint point)
{
    RelayEvent(WM_LBUTTONDOWN, (WPARAM)nFlags,
MAKELPARAM(LOWORD(point.x), LOWORD(point.y)));
    CFileDialog::OnLButtonDown(nFlags, point);
}
void CFileDialogExtra::OnLButtonUp(UINT nFlags, CPoint point)
{
    RelayEvent(WM_LBUTTONUP, (WPARAM)nFlags, MAKELPARAM(LOWORD(point.x),
LOWORD(point.y)));
    CFileDialog::OnLButtonUp(nFlags, point);
}
void CFileDialogExtra::OnMouseMove(UINT nFlags, CPoint point)
{
    RelayEvent(WM_MOUSEMOVE, (WPARAM)nFlags, MAKELPARAM(LOWORD(point.x),
LOWORD(point.y)));
    CFileDialog::OnMouseMove(nFlags, point);
}
void CFileDialogExtra::RelayEvent(UINT message, WPARAM wParam, LPARAM
lParam)
{
    if (m_ToolTip.m_hWnd != NULL)
    {
        MSG msg;
        msg.hwnd = m_hWnd;
        msg.message = message;
        msg.wParam = wParam;
        msg.lParam = lParam;
        msg.time = 0;
        msg.pt.x = LOWORD(lParam);
        msg.pt.y = HIWORD(lParam);
        m_ToolTip.RelayEvent(&msg);
    }
}
LRESULT CFileDialogExtra::WindowProc(UINT message, WPARAM wParam,
LPARAM lParam)
{
    LRESULT result = CFileDialog::WindowProc(message, wParam,
lParam);
    if (message != WM_DESTROY && message != WM_NOTIFY && message !=
WM_NCDESTROY)
    {
        MSG msg;
        msg.hwnd = m_hWnd;
        msg.message = message;
        msg.wParam = wParam;
        msg.lParam = lParam;
        if (m_ToolTip.m_hWnd != NULL)
            m_ToolTip.RelayEvent(&msg);
    }
    return result;
}