Strange tooltip effects when using XP themes

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Uwe Kotyczka (uwe.kotyczka_at_web.de)
Date: 10/01/04


Date: 1 Oct 2004 03:46:36 -0700

Hi,

my environment: VC++6.0 Sp5, WinXP Home SP1

I added tooltip support for CFormView (and CDialog) derived classes
by using EnableToolTips and handling TTN_NEEDTEXT. Works like a
charme,
see code below.
Now I'm new to WinXP and just tried my app with the common controls v6
dll (i.e. with XP themes). I just added a .manifest file to the exe
directory.
Here I watch a strange tooltip behaviour. Tips show up when moving
the mouse over the several controls. But the tips do not show the
correct text. Moving the mouse to the first control an empty tip
appears.
Moving it to a second control the tip shows the text of the first
control.
Moving it to a third control the text of the second control is shown.
And so on. To see the correct text I have to move the mouse twice to
the
same control.
Adding a TRACE command in OnToolTipText I made an observation.
When not using XP themes and moving the mouse once over a control
TRACE fires 3 times, i.e. OnToolTipText is being called 3 times.
However when using XP themes, moving the mouse over the control
only causes OnToolTipText being called two times.

Any idea what's going wrong here?

TIA Uwe

And here comes the code. You can download the whole source code
for a complete demo at
http://www.8ung.at/kotyczka/openglsample_en.html
Don't worry about the OpenGL stuff.

/////////////////////////////////////////////////////////////////////////////
// Copyright:
// Uwe Kotyczka <uwe.kotyczka@web.de>
// created: April 2004
//
/////////////////////////////////////////////////////////////////////////////
// FormViewTts.h : Header-Datei
//
/////////////////////////////////////////////////////////////////////////////

#if !defined(AFX_FORMVIEWTTS_H__1302C8E3_3424_461A_AFEB_6A8CE3220970__INCLUDED_)
#define AFX_FORMVIEWTTS_H__1302C8E3_3424_461A_AFEB_6A8CE3220970__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

/////////////////////////////////////////////////////////////////////////////
// Formularansicht CFormViewTts

class AFX_EXT_CLASS_GENERAL CFormViewTts : public CFormView
{
        DECLARE_DYNAMIC(CFormViewTts)
public:
        CFormViewTts(LPCTSTR lpszTemplateName);
        CFormViewTts(UINT nIDTemplate);

// Attribute
protected:
        BOOL m_bToolTipMultiline;

// Operationen
public:
        void SetToolTipMultiline(BOOL bToolTipMultiline = TRUE);
        BOOL GetToolTipMultiline() const;

// Überschreibungen
        // Vom Klassen-Assistenten generierte virtuelle
Funktionsüberschreibungen
        //{{AFX_VIRTUAL(CFormViewTts)
        public:
        virtual void OnInitialUpdate();
        protected:
        virtual void OnActivateView(BOOL bActivate, CView* pActivateView,
CView* pDeactiveView);
        //}}AFX_VIRTUAL

// Implementierung
protected:
        virtual ~CFormViewTts();

        // Generierte Nachrichtenzuordnungsfunktionen
        //{{AFX_MSG(CFormViewTts)
                // HINWEIS - Der Klassen-Assistent fügt hier Member-Funktionen ein
und entfernt diese.
        //}}AFX_MSG
        afx_msg BOOL OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT*
pResult);
        DECLARE_MESSAGE_MAP()
};
inline void CFormViewTts::SetToolTipMultiline(BOOL bToolTipMultiline)
        { m_bToolTipMultiline = bToolTipMultiline; }
inline BOOL CFormViewTts::GetToolTipMultiline() const
        { return m_bToolTipMultiline; }

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile
zusätzliche Deklarationen ein.

#endif // AFX_FORMVIEWTTS_H__1302C8E3_3424_461A_AFEB_6A8CE3220970__INCLUDED_

/////////////////////////////////////////////////////////////////////////////
// Copyright:
// Uwe Kotyczka <uwe.kotyczka@web.de>
// created: April 2004
//
/////////////////////////////////////////////////////////////////////////////
// FormViewEx.cpp: Implementierungsdatei
//

#include "StdAfx.h"
#include "General.h"
#include "FormViewTts.h"
#include "SplitterWndEx.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFormViewTts

IMPLEMENT_DYNAMIC(CFormViewTts, CFormView)

CFormViewTts::CFormViewTts(LPCTSTR lpszTemplateName)
        : CFormView(lpszTemplateName)
{
        m_bToolTipMultiline = FALSE;
}

CFormViewTts::CFormViewTts(UINT nIDTemplate)
        : CFormView(nIDTemplate)
{
        m_bToolTipMultiline = FALSE;
}

CFormViewTts::~CFormViewTts()
{
}

BEGIN_MESSAGE_MAP(CFormViewTts, CFormView)
        //{{AFX_MSG_MAP(CFormViewTts)
                // HINWEIS - Der Klassen-Assistent fügt hier Zuordnungsmakros ein
und entfernt diese.
        //}}AFX_MSG_MAP
        ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
        ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Behandlungsroutinen für Nachrichten CFormViewTts

BOOL CFormViewTts::OnToolTipText(UINT nId, NMHDR* pNMHDR, LRESULT*
pResult)
{
        // 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;

        if (m_bToolTipMultiline)
                ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);
        else
                ::SendMessage(pNMHDR->hwndFrom, TTM_SETMAXTIPWIDTH, 0, -1);

        // 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 CFormViewTts::OnInitialUpdate()
{
        CFormView::OnInitialUpdate();

        EnableToolTips();
}

void CFormViewTts::OnActivateView(BOOL bActivate, CView*
pActivateView, CView* pDeactiveView)
{
        CWnd* pParent = GetParent();
        if (pParent && pParent->IsKindOf(RUNTIME_CLASS(CSplitterWndEx)))
                ((CSplitterWndEx*)pParent)->RefreshSplitterBars(&bActivate);

        CFormView::OnActivateView(bActivate, pActivateView, pDeactiveView);

        if (bActivate)
        {
                // AfxGetMainWnd() may return NULL in an SDI environment
                CWnd* pWnd = AfxGetMainWnd();
                if (pWnd != NULL)
                {
                        // update toolbars immedeately
                        pWnd->SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE);
                }
        }
}



Relevant Pages

  • Re: Sherlock Holmes Pipe Ban
    ... It seems more and more that our nation is moving more tward goverment ... and total government control. ...
    (alt.smokers.pipes)
  • Re: What event to use for checking table values on a form when record is completed?
    ... Current fires the instant the user navigates to the record in question, ... on a record and attempts to save it - e.g. closing the form, moving off the ... record, moving to a subform, moving from a subform back to a mainform, ... Is there a control on the form with StockSymbol as its control source - a ...
    (microsoft.public.access.formscoding)
  • Re: What event to use for checking table values on a form when record is completed?
    ... Current fires the instant the user navigates to the record in question, ... on a record and attempts to save it - e.g. closing the form, moving off the ... record, moving to a subform, moving from a subform back to a mainform, ... Is there a control on the form with StockSymbol as its control source - a ...
    (microsoft.public.access.formscoding)
  • Re: Sherlock Holmes Pipe Ban
    ... It seems more and more that our nation is moving more tward goverment ... and total government control. ...
    (alt.smokers.pipes)