//+---------------------------------------------------------------------------- // // File: tooltip.cpp // // Module: CMDIAL32.DLL // // Synopsis: This module contains the code for the implementing balloon tips. // // Copyright (c) 1996-2000 Microsoft Corporation // // Author: markcl Created Header 11/2/00 // //+---------------------------------------------------------------------------- #include "cmmaster.h" WNDPROC CBalloonTip::m_pfnOrgBalloonWndProc = NULL; //+---------------------------------------------------------------------------- // // Function: CBalloonTip::CBalloonTip // // Synopsis: Balloon tip constructor // // Arguments: nothing // // Returns: nothing // // History: markcl Created Header 10/31/00 // //+---------------------------------------------------------------------------- CBalloonTip::CBalloonTip() { // Nothing to do } //+---------------------------------------------------------------------------- // // Function: CBalloonTip::DisplayBallonTip // // Synopsis: Displays a balloon tip // // Arguments: LLPOINT lppoint - pointer to a POINT struct with the coordinates for displaying // int iIcon - type of icon to display in the balloon tip // LPCTSTR lpszTitle - Title of the balloon tip window // LPTSTR lpszBalloonMsg - Message to display in the balloon tip // HWND hWndParent - handle to the parent window // // Returns: nothing // // History: markcl Created Header 10/31/00 // //+---------------------------------------------------------------------------- BOOL CBalloonTip::DisplayBalloonTip(LPPOINT lppoint, UINT iIcon, LPCTSTR lpszTitle, LPTSTR lpszBalloonMsg, HWND hWndParent) { // // If we don't have a message or a position, we don't display the balloon tip. // if (NULL == lpszBalloonMsg || NULL == lppoint) { MYDBGASSERT(lpszBalloonMsg && lppoint); return FALSE; } // // Comctl32.dll must be 5.80 or greater to use balloon tips. We check the dll version // by calling DllGetVersion in comctl32.dll. // HINSTANCE hComCtl = LoadLibraryExA("comctl32.dll", NULL, 0); CMASSERTMSG(hComCtl, TEXT("LoadLibrary - comctl32 failed for Balloon Tips")); if (hComCtl != NULL) { typedef HRESULT (*DLLGETVERSIONPROC)(DLLVERSIONINFO* lpdvi); DLLGETVERSIONPROC fnDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hComCtl,"DllGetVersion"); MYDBGASSERT(fnDllGetVersion); if (NULL == fnDllGetVersion) { // // DllGetVersion does not exist in Comctl32.dll. This mean the version is too old so we need to fail. // FreeLibrary(hComCtl); return FALSE; } else { DLLVERSIONINFO dvi; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); HRESULT hResult = (*fnDllGetVersion)(&dvi); FreeLibrary(hComCtl); if (SUCCEEDED(hResult)) { // // Take the version returned and compare it to 5.80. // if (MAKELONG(dvi.dwMinorVersion,dvi.dwMajorVersion) < MAKELONG(80,5)) { CMTRACE2(TEXT("COMCTL32.DLL version - %d.%d"),dvi.dwMajorVersion,dvi.dwMinorVersion); CMTRACE1(TEXT("COMCTL32.DLL MAKELONG - %li"),MAKELONG(dvi.dwMinorVersion,dvi.dwMajorVersion)); CMTRACE1(TEXT("Required minimum MAKELONG - %li"),MAKELONG(80,5)); // Wrong DLL version return FALSE; } } else { CMASSERTMSG(FALSE, TEXT("Call to DllGetVersion in comctl32.dll failed.")); return FALSE; } } } // // Hide any existing balloon tips before trying to display a new one. // if (m_hwndTT && m_bTTActive) { HideBalloonTip(); } // // Create the Balloon ToolTip window // m_hwndTT = CreateWindowExU(NULL,TOOLTIPS_CLASS, TEXT("CM Balloon Tip Window"), WS_POPUP | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWndParent, NULL, g_hInst, NULL); if (m_hwndTT) { m_ti.cbSize = sizeof(m_ti); m_ti.uFlags = TTF_TRACK; m_ti.hwnd = hWndParent; m_ti.hinst = g_hInst; SendMessageU(m_hwndTT,TTM_ADDTOOL,0,(LPARAM) (LPTOOLINFO) &m_ti); SendMessageU(m_hwndTT,TTM_SETMAXTIPWIDTH,0,200); } else { MYDBGASSERT(m_hwndTT); return FALSE; } // // Subclass the edit control // m_pfnOrgBalloonWndProc = (WNDPROC)SetWindowLongU(m_hwndTT, GWLP_WNDPROC, (LONG_PTR)SubClassBalloonWndProc); // // Save the this pointer with the window // SetWindowLongU(m_hwndTT, GWLP_USERDATA, (LONG_PTR)this); // // Set the balloon message // m_ti.lpszText = lpszBalloonMsg; SendMessageU(m_hwndTT,TTM_UPDATETIPTEXT,0,(LPARAM) (LPTOOLINFO) &m_ti); // // If we got a title, then add it // if (lpszTitle) { // // confirm we have a valid icon // if (iIcon > 3) { iIcon = TTI_NONE; // TTI_NONE = No icon } SendMessageU(m_hwndTT,TTM_SETTITLE,(WPARAM) iIcon,(LPARAM) lpszTitle); } // // Set the position // SendMessageU(m_hwndTT,TTM_TRACKPOSITION,0,(LPARAM) (DWORD) MAKELONG(lppoint->x,lppoint->y)); // // Show balloon tip window // SendMessageU(m_hwndTT,TTM_TRACKACTIVATE,(WPARAM) TRUE,(LPARAM) (LPTOOLINFO) &m_ti); // Set active state m_bTTActive = TRUE; return TRUE; } //+---------------------------------------------------------------------------- // // Function: CBalloonTip::HideBallonTip // // Synopsis: Hides a balloon tip // // Arguments: nothing // // Returns: nothing // // History: markcl Created Header 10/31/00 // //+---------------------------------------------------------------------------- BOOL CBalloonTip::HideBalloonTip() { // check active state && handle if(m_hwndTT && m_bTTActive) { // hide window SendMessageU(m_hwndTT,TTM_TRACKACTIVATE,(WPARAM) FALSE,(LPARAM) (LPTOOLINFO) &m_ti); m_bTTActive = FALSE; // force a repaint on parent window InvalidateRect(m_ti.hwnd,NULL,NULL); // destroy window DestroyWindow(m_hwndTT); m_hwndTT = NULL; return TRUE; } else { return FALSE; } } //+---------------------------------------------------------------------------- // // Function: CBalloonTip::SubClassBalloonWndProc // // Synopsis: Subclassed wnd proc to trap the mouse button clicks on the balloon tip window // // Arguments: standard win32 window proc params // // Returns: standard win32 window proc return value // // History: markcl created 11/2/00 // //+---------------------------------------------------------------------------- LRESULT CALLBACK CBalloonTip::SubClassBalloonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if ((uMsg == WM_LBUTTONDOWN) || (uMsg == WM_RBUTTONDOWN)) { // // Get the object pointer saved by SetWindowLong // CBalloonTip* pBalloonTip = (CBalloonTip*)GetWindowLongU(hwnd, GWLP_USERDATA); MYDBGASSERT(pBalloonTip); if (pBalloonTip) { pBalloonTip->HideBalloonTip(); } } // // Call the original window procedure for default processing. // return CallWindowProcU(m_pfnOrgBalloonWndProc, hwnd, uMsg, wParam, lParam); }