#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include #include #include "ptt.h" #include "cdwtt.h" #include "dbg.h" #include "exgdiw.h" #ifdef UNDER_CE // Windows CE specific #include "stub_ce.h" // Windows CE stub for unsupported APIs #endif // UNDER_CE //---------------------------------------------------------------- //Animate window const value //---------------------------------------------------------------- #define AW_HOR_POSITIVE 0x00000001 #define AW_HOR_NEGATIVE 0x00000002 #define AW_VER_POSITIVE 0x00000004 #define AW_VER_NEGATIVE 0x00000008 #define AW_CENTER 0x00000010 #define AW_HIDE 0x00010000 #define AW_ACTIVATE 0x00020000 #define AW_SLIDE 0x00040000 #define AW_BLEND 0x00080000 //---------------------------------------------------------------- //local Timer id //---------------------------------------------------------------- #define TID_SHOW 3 #define TID_MONITOR 4 #define TID_DURATION 5 #ifdef MemAlloc #undef MemAlloc #endif #ifdef MemFree #undef MemFree #endif #define MemAlloc(a) GlobalAllocPtr(GHND, a) #define MemFree(a) GlobalFreePtr(a); #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define UnrefMsg() UNREFERENCED_PARAMETER(hwnd); \ UNREFERENCED_PARAMETER(wParam); \ UNREFERENCED_PARAMETER(lParam) #if 0 typedef struct { // ti UINT cbSize; UINT uFlags; HWND hwnd; UINT uId; RECT rect; HINSTANCE hinst; LPTSTR lpszText; } TOOLINFO, NEAR *PTOOLINFO, FAR *LPTOOLINFO; typedef struct tagTOOLINFOW { UINT cbSize; UINT uFlags; HWND hwnd; UINT uId; RECT rect; HINSTANCE hinst; LPWSTR lpszText; } TOOLINFOW, NEAR *PTOOLINFOW, FAR *LPTOOLINFOW; #endif LPXINFO XInfo_New(VOID) { LPXINFO lpXif = (LPXINFO)MemAlloc(sizeof(XINFO)); if(lpXif) { ZeroMemory(lpXif, sizeof(XINFO)); } return lpXif; } LRESULT CALLBACK CDWToolTip::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPCDWToolTip lpCDWTT; switch(uMsg) { #ifndef UNDER_CE // Windows CE does not support WM_NCCREATE/WM_NCDESTROY case WM_NCCREATE: lpCDWTT = new CDWToolTip(hwnd); SetHWNDPtr(hwnd, lpCDWTT); break; case WM_NCDESTROY: lpCDWTT = (LPCDWToolTip)::GetHWNDPtr(hwnd); SetHWNDPtr(hwnd, NULL); if(lpCDWTT) { delete lpCDWTT; } break; #else // UNDER_CE case WM_CREATE: lpCDWTT = new CDWToolTip(hwnd); SetHWNDPtr(hwnd, lpCDWTT); if(lpCDWTT) { return lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam); } break; case WM_DESTROY: lpCDWTT = (LPCDWToolTip)GetHWNDPtr(hwnd); if(lpCDWTT) { lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam); SetHWNDPtr(hwnd, NULL); delete lpCDWTT; } break; #endif // UNDER_CE default: lpCDWTT = (LPCDWToolTip)GetHWNDPtr(hwnd); if(lpCDWTT) { return lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam); } break; } return ::DefWindowProc(hwnd, uMsg, wParam, lParam); } void *CDWToolTip::operator new(size_t size) { BYTE *p = (BYTE *)MemAlloc(size); if(p) { ZeroMemory(p, size); } return (void *)p; } void CDWToolTip::operator delete(void *pv) { if(pv) { MemFree(pv); } } CDWToolTip::CDWToolTip(HWND hwnd) { m_hwndSelf = hwnd; m_hFont = NULL; } CDWToolTip::~CDWToolTip() { //do nothing } LRESULT CDWToolTip::RealWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: return MsgCreate(hwnd, wParam, lParam); case WM_PAINT: return MsgPaint (hwnd, wParam, lParam); #ifndef UNDER_CE // Not support case WM_PRINTCLIENT: return MsgPrintClient(hwnd, wParam, lParam); #endif // UNDER_CE case WM_TIMER: return MsgTimer(hwnd, wParam, lParam); case WM_DESTROY: return MsgDestroy(hwnd, wParam, lParam); case WM_SETFONT: return MsgSetFont(hwnd, wParam, lParam); case TTM_SETDELAYTIME: return TTM_SetDelayTime(hwnd, wParam, lParam); case TTM_ADDTOOLW: return TTM_AddToolW(hwnd, wParam, lParam); case TTM_DELTOOLW: return TTM_DelToolW(hwnd, wParam, lParam); case TTM_NEWTOOLRECTW: return TTM_NewToolRectW(hwnd, wParam, lParam); case TTM_RELAYEVENT_WITHUSERINFO: return TTM_RelayEventWithUserInfo(hwnd, wParam, lParam); case TTM_RELAYEVENT: return TTM_RelayEvent(hwnd, wParam, lParam); case TTM_GETTOOLINFOW: case TTM_SETTOOLINFOW: return TTM_GetSetToolInfoW(hwnd, uMsg, wParam, lParam); case TTM_GETTOOLCOUNT: return TTM_GetToolCount(hwnd, wParam, lParam); default: break; } return ::DefWindowProc(hwnd, uMsg, wParam, lParam); } LRESULT CDWToolTip::MsgCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) { m_hwndSelf = hwnd; m_fEnable = TRUE; //970812: new to show or hide tooltip explicitly return 1; UnrefMsg(); } LRESULT CDWToolTip::MsgPrintClient(HWND hwnd, WPARAM wParam, LPARAM lParam) { #ifndef UNDER_CE // Not support Dbg(("WM_PRINTCLIENT COME lParam[0x%08x]\n", lParam)); RECT rc; POINT pt; GetCursorPos(&pt); GetClientRect(hwnd, &rc); HDC hDC = (HDC)wParam; HFONT hFontOld = NULL; if(m_hFont) { hFontOld = (HFONT)::SelectObject(hDC, m_hFont); } else { hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); } LPWSTR lpwstr = GetTipTextW(); if(lpwstr) { DrawTipText(hDC, &rc, lpwstr); } ::SelectObject(hDC, hFontOld); #endif // UNDER_CE return 0; UNREFERENCED_PARAMETER(lParam); } LRESULT CDWToolTip::MsgSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam) { HFONT hFont = (HFONT)wParam; BOOL fRedraw = LOWORD(lParam); if(!hFont) { return 0; } #ifndef UNDER_CE LOGFONTA logFont; #else // UNDER_CE LOGFONT logFont; #endif // UNDER_CE HFONT hFontNew; ::GetObject(hFont, sizeof(logFont), &logFont); hFontNew = ::CreateFontIndirect(&logFont); if(!hFontNew) { return 0; } if(m_hFont) { ::DeleteObject(m_hFont); } m_hFont = hFontNew; if(fRedraw) { ::InvalidateRect(hwnd, NULL, TRUE); } return 0; UnrefMsg(); } LRESULT CDWToolTip::MsgPaint(HWND hwnd, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; RECT rc; #ifndef UNDER_CE // Windows CE does not support GetCursorPos POINT pt; ::GetCursorPos(&pt); #endif // UNDER_CE ::GetClientRect(hwnd, &rc); HDC hDC = ::BeginPaint(hwnd, &ps); HFONT hFontOld = NULL; if(m_hFont) { hFontOld = (HFONT)::SelectObject(hDC, m_hFont); } else { hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); } LPWSTR lpwstr = GetTipTextW(); if(lpwstr) { DrawTipText(hDC, &rc, lpwstr); } ::SelectObject(hDC, hFontOld); ::EndPaint(hwnd, &ps); //Dbg(("--->WM_PAINT END\n")); return 0; UnrefMsg(); } LRESULT CDWToolTip::MsgTimer(HWND hwnd, WPARAM wParam, LPARAM lParam) { static POINT pt; static SIZE size; static RECT rect; static BOOL fAnimate; #ifndef UNDER_CE // Windows CE does not support GetCursorPos ::GetCursorPos(&pt); #else // UNDER_CE if(m_lpXInfoCur){ pt = m_lpXInfoCur->userInfo.pt; ClientToScreen(m_lpXInfoCur->userInfo.hwnd, &pt); } #endif // UNDER_CE switch(wParam) { case TID_SHOW: //Dbg(("TID_SHOW COME\n")); KillTimer(hwnd, TID_SHOW); SetTimer(hwnd, TID_MONITOR, 20, NULL); SetTimer(hwnd, TID_DURATION, 6000, NULL); //get cur mouse pos //show tool tip window //call invalidate rect //set monitoring timer if(0 == GetTipSize(&size)) { if(m_fEnable) { //Dbg(("-->GetTipSize ret 0\n")); if(IsMousePointerIn()) { //Dbg(("-->Call SetWindowPos\n")); //990530: KOTAE #433 INT cxScr = ::GetSystemMetrics(SM_CXSCREEN); INT cyScr = ::GetSystemMetrics(SM_CYSCREEN); if(cxScr < (pt.x + size.cx)) { pt.x = cxScr - size.cx; } if(cyScr < pt.y + 20 + size.cy) { pt.y = cyScr - (20*2 + size.cy); } SetWindowPos(hwnd, HWND_TOP, pt.x, pt.y+20, size.cx, size.cy, SWP_NOACTIVATE | SWP_HIDEWINDOW |SWP_NOOWNERZORDER); fAnimate = SetWindowAnimate(hwnd); if(!fAnimate) SetWindowPos(hwnd, HWND_TOP, pt.x, pt.y+20, size.cx, size.cy, SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER); //Dbg(("-->SetWindowPos End\n")); m_fShow = TRUE; if(!fAnimate) InvalidateRect(hwnd, NULL, NULL); //Dbg(("-->Invalidate Rect End\n")); } } } //Dbg(("TID_SHOW END\n")); break; case TID_MONITOR: { //Dbg(("TID_MONITOR COME\n")); HWND hwndOwner = (HWND)GetWindow(hwnd, GW_OWNER); if(!IsMousePointerIn() || NULL == GetTipTextW() || !IsWindowVisible(hwndOwner) ) { //Dbg(("---> Hide Window\n")); ::SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE); //Dbg(("Set curInfo NULL\n")); m_lpXInfoCur = NULL; m_fShow = FALSE; ::KillTimer(hwnd, TID_MONITOR); ::KillTimer(hwnd, TID_DURATION); } } break; case TID_DURATION: //Dbg(("TID_DURATION START\n")); SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_NOACTIVATE); //Dbg(("Set curInfo NULL\n")); //lptt->lpXInfoCur = NULL; m_fShow = FALSE; ::KillTimer(hwnd, TID_MONITOR); ::KillTimer(hwnd, TID_DURATION); break; default: break; } return 0; UnrefMsg(); } LRESULT CDWToolTip::MsgDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam) { Dbg(("WM_DESTORY START\n")); ::KillTimer(hwnd, TID_SHOW); ::KillTimer(hwnd, TID_MONITOR); ::KillTimer(hwnd, TID_DURATION); LPXINFO lpXInfo, lpXInfoNext; m_lpXInfoCur = NULL; INT i; for(lpXInfo = m_lpXInfoHead, i = 0; lpXInfo; lpXInfo = lpXInfoNext, i++){ lpXInfoNext = lpXInfo->next; //Dbg(("-->%d: Free XInfo\n", i)); MemFree(lpXInfo); } if(m_hFont) { ::DeleteObject(m_hFont); m_hFont = NULL; } Dbg(("--->WM_DESTORY END\n")); return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_SetDelayTime(HWND hwnd, WPARAM wParam, LPARAM lParam) { switch(wParam) { case TTDT_AUTOMATIC: break; case TTDT_RESHOW: break; case TTDT_AUTOPOP: break; case TTDT_INITIAL: break; } m_dwDelayFlag = (DWORD)wParam; m_dwDelayTime = (DWORD)lParam; return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_AddToolW(HWND hwnd, WPARAM wParam, LPARAM lParam) { TOOLINFOW *lpTi = (LPTOOLINFOW)lParam; if(!lpTi) { Dbg(("################### lParam is NULLL\n")); return 0; } if(lpTi->cbSize != sizeof(TOOLINFOW)) { Dbg(("##### TTM_ADDTOOLW size ERROR\n")); return 0; } LPXINFO *ppXInfo, lpXInfoNew; lpXInfoNew = XInfo_New(); if(!lpXInfoNew) { return 0; } lpXInfoNew->toolInfoW = *lpTi; for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next){ } *ppXInfo = lpXInfoNew; return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_DelToolW(HWND hwnd, WPARAM wParam, LPARAM lParam) { TOOLINFOW *lpTi = (LPTOOLINFOW)lParam; if(!lpTi) { Dbg(("################### lParam is NULLL\n")); return 0; } if(lpTi->cbSize != sizeof(TOOLINFOW)) { return 0; } LPXINFO *ppXInfo, lpXInfoTmp; for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next){ if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd && (*ppXInfo)->toolInfoW.uId == lpTi->uId) { lpXInfoTmp = *ppXInfo; *ppXInfo = (*ppXInfo)->next; if(lpXInfoTmp == m_lpXInfoCur) { //Dbg(("Set curInfo NULL\n")); m_lpXInfoCur = NULL; } MemFree(lpXInfoTmp); Dbg(("TTM_DELTOOLW SUCCEEDED\n")); return 0; break; } } Dbg(("TTM_DELTOOLW Error END\n")); return -1; UnrefMsg(); } LRESULT CDWToolTip::TTM_NewToolRectW(HWND hwnd, WPARAM wParam, LPARAM lParam) { TOOLINFOW *lpTi = (LPTOOLINFOW)lParam; if(lpTi->cbSize != sizeof(TOOLINFOW)) { return 0; } LPXINFO *ppXInfo; for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next) { if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd && (*ppXInfo)->toolInfoW.uId == lpTi->uId) { if(m_lpXInfoCur == *ppXInfo) { m_xInfoPrev = *(m_lpXInfoCur); } (*ppXInfo)->toolInfoW = *lpTi; break; } } return 0; UnrefMsg(); } // SendMessage(hwnd, TTM_RELAYEVENT_WITHUESRINFO, 0, LPTOOLTIPUSERINFO lpInfo); LRESULT CDWToolTip::TTM_RelayEventWithUserInfo(HWND hwnd, WPARAM wParam, LPARAM lParam) { INT i; LPXINFO *ppXInfo; LPTOOLTIPUSERINFO lpUserInfo = (LPTOOLTIPUSERINFO)lParam; //Dbg(("TTM_RELAYEVENT_WITHUSERINFO START\n")); if(!lpUserInfo) { //Dbg(("--->TTM_RELAYEVENT_WITHUSERINFO ERROR END\n")); return 0; } for(i = 0, ppXInfo = &m_lpXInfoHead; *ppXInfo; i++, ppXInfo = &(*ppXInfo)->next) { UINT uFlags = (*ppXInfo)->toolInfoW.uFlags; if(uFlags & TTF_IDISHWND) { if((HWND)(*ppXInfo)->toolInfoW.uId == lpUserInfo->hwnd) { //Dbg(("[%d]Find info with hwnd index\n", i)); break; } } else { #ifdef _DEBUG //970915: if(!IsWindow(lpUserInfo->hwnd)) { Dbg(("############## hwnd corrupted [0x%08x]\n", lpUserInfo->hwnd)); DebugBreak(); } if(!IsWindow((*ppXInfo)->toolInfoW.hwnd)) { Dbg(("############## hwnd corrupted [0x%08x]\n", (*ppXInfo)->toolInfoW.hwnd)); DebugBreak(); } #endif if(lpUserInfo->hwnd == GetDlgItem((*ppXInfo)->toolInfoW.hwnd, (INT)(*ppXInfo)->toolInfoW.uId)) { break; } else if(lpUserInfo->hwnd == (*ppXInfo)->toolInfoW.hwnd) { if(PtInRect(&(*ppXInfo)->toolInfoW.rect, lpUserInfo->pt)) { break; } } #if 0 if(PtInRect(&(*ppXInfo)->toolInfoW.rect, lpUserInfo->pt)) { Dbg(("[%d]Find INFO with id [%d]\n", i, (*ppXInfo)->toolInfoW.uId)); break; } #endif } } if(*ppXInfo) { //m_curRelayMsg = *lpmsg; if(m_lpXInfoCur == *ppXInfo) { // Same info is used. //check specified rect is same or not // it is very dirty code..... // if rectangle is same. if((lpUserInfo->rect.left == (*ppXInfo)->userInfo.rect.left ) && (lpUserInfo->rect.top == (*ppXInfo)->userInfo.rect.top ) && (lpUserInfo->rect.right == (*ppXInfo)->userInfo.rect.right) && (lpUserInfo->rect.bottom == (*ppXInfo)->userInfo.rect.bottom)) { //Dbg(("Set Timer 500\n")); //SetTimer(hwnd, TID_SHOW, 500, NULL); } else { //if rectangl is NOT same, it should be displayed now //Dbg(("Set Timer 10\n")); SetTimer(hwnd, TID_SHOW, 100, NULL); } } else { SetTimer(hwnd, TID_SHOW, 500, NULL); } (*ppXInfo)->whichEvent = TTM_RELAYEVENT_WITHUSERINFO; (*ppXInfo)->userInfo = *lpUserInfo; m_lpXInfoCur = *ppXInfo; //Dbg(("--->TTM_REUSER END\n")); } else { //Dbg(("Set curInfo NULL\n")); m_lpXInfoCur = NULL; //Dbg(("--->TTM_REUSER CUR NULL END\n")); } return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_RelayEvent(HWND hwnd, WPARAM wParam, LPARAM lParam) { LPMSG lpmsg = (LPMSG)lParam; INT i; LPXINFO *ppXInfo; //lpXInfo; //, lpXInfoCur; if(!lpmsg) { return 0; } switch(lpmsg->message) { case WM_LBUTTONDOWN: case WM_MOUSEMOVE: case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONUP: for(i = 0, ppXInfo = &m_lpXInfoHead; *ppXInfo; i++, ppXInfo = &(*ppXInfo)->next) { UINT uFlags = (*ppXInfo)->toolInfoW.uFlags; if(uFlags & TTF_IDISHWND) { if((HWND)(*ppXInfo)->toolInfoW.uId == lpmsg->hwnd) { //Dbg(("[%d]Find info with hwnd index\n", i)); break; } } else { POINT pt; pt.x = LOWORD(lpmsg->lParam); pt.y = HIWORD(lpmsg->lParam); if(PtInRect(&(*ppXInfo)->toolInfoW.rect, pt)) { //Dbg(("[%d]Find INFO with id [%d]\n", i, (*ppXInfo)->toolInfoW.uId)); break; } } } if(*ppXInfo) { m_curRelayMsg = *lpmsg; (*ppXInfo)->whichEvent = TTM_RELAYEVENT; if(m_lpXInfoCur) { if(m_lpXInfoCur != *ppXInfo) { //Dbg(("-->SetTimer TID_SHOW with 100msec\n")); SetTimer(hwnd, TID_SHOW, 100, NULL); m_xInfoPrev = *m_lpXInfoCur; } else { //---------------------------------------------------------------- //m_lpXInfoCur is not changed. //check rectangle, other information is same or not //---------------------------------------------------------------- if(!IsSameInfo(&m_xInfoPrev, *ppXInfo)) { SetTimer(hwnd, TID_SHOW, 100, NULL); m_xInfoPrev = **ppXInfo; } } //else { // SetTimer(hwnd, TID_SHOW, 500, NULL); //} } else { //Dbg(("-->SetTimer TID_SHOW with 500msec\n")); SetTimer(hwnd, TID_SHOW, 500, NULL); } m_lpXInfoCur = *ppXInfo; } else { //Dbg(("Set curInfo NULL\n")); m_lpXInfoCur = NULL; } break; default: break; } return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_GetSetToolInfoW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPTOOLINFOW lpTi = (LPTOOLINFOW)lParam; if(lpTi->cbSize != sizeof(TOOLINFOW)) { return 0; } LPXINFO *ppXInfo; for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next) { if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd && (*ppXInfo)->toolInfoW.uId == lpTi->uId) { if(uMsg == TTM_GETTOOLINFOW) { (*lpTi) = (*ppXInfo)->toolInfoW; } else { (*ppXInfo)->toolInfoW = *lpTi; } break; } } return 0; UnrefMsg(); } LRESULT CDWToolTip::TTM_GetToolCount(HWND hwnd, WPARAM wParam, LPARAM lParam) { INT i; LPXINFO *ppXInfo; for(i = 0, ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next, i++) { } return i; UnrefMsg(); } BOOL CDWToolTip::Enable(HWND hwndToolTip, BOOL fEnable) { if(m_hwndSelf != hwndToolTip) { //Dbg(("ToolTip Enable Invalid Window Handle\n")); return 0; } m_fEnable = fEnable; m_fShow = fEnable; if(!fEnable) { //if fEnable FALSE ::SetWindowPos(hwndToolTip, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE); ::KillTimer(hwndToolTip, TID_SHOW); ::KillTimer(hwndToolTip, TID_MONITOR); ::KillTimer(hwndToolTip, TID_DURATION); } return 0; } LPWSTR CDWToolTip::GetTipTextW(VOID) { static TOOLTIPTEXTW toolTipTextW; static TOOLTIPTEXTUSERINFO ttTextUserInfo; INT idCtrl; if(!m_lpXInfoCur) { //Dbg(("GetTipTextW m_lpXInfoCur is NULL\n")); return NULL; } if(m_lpXInfoCur->toolInfoW.uFlags & TTF_IDISHWND) { idCtrl = GetDlgCtrlID((HWND)m_lpXInfoCur->toolInfoW.uId); } else { idCtrl = (INT)m_lpXInfoCur->toolInfoW.uId; } switch(m_lpXInfoCur->whichEvent) { case TTM_RELAYEVENT_WITHUSERINFO: ZeroMemory((LPVOID)&ttTextUserInfo, sizeof(ttTextUserInfo)); ttTextUserInfo.hdr.hwndFrom = m_hwndSelf; ttTextUserInfo.hdr.idFrom = idCtrl; ttTextUserInfo.hdr.code = TTN_NEEDTEXT_WITHUSERINFO; ttTextUserInfo.userInfo = m_lpXInfoCur->userInfo; ::SendMessage(m_lpXInfoCur->toolInfoW.hwnd, WM_NOTIFY, (WPARAM)0, (LPARAM)&ttTextUserInfo); #if _DEBUG if(!toolTipTextW.lpszText) { //Dbg(("###### Text is NULL\n")); } #endif return (LPWSTR)ttTextUserInfo.lpszText; break; case TTM_RELAYEVENT: default: ZeroMemory((LPVOID)&toolTipTextW, sizeof(toolTipTextW)); toolTipTextW.hdr.hwndFrom = m_hwndSelf; toolTipTextW.hdr.idFrom = idCtrl; toolTipTextW.hdr.code = TTN_NEEDTEXTW; toolTipTextW.hinst = m_lpXInfoCur->toolInfoW.hinst; toolTipTextW.uFlags = m_lpXInfoCur->toolInfoW.uFlags; if(m_lpXInfoCur->toolInfoW.lpszText == LPSTR_TEXTCALLBACKW) { if(!m_lpXInfoCur->toolInfoW.hwnd) { //Dbg(("###### hwnd is NULL\n")); return NULL; } if(!IsWindow(m_lpXInfoCur->toolInfoW.hwnd)) { //Dbg(("###### hwnd is Corrupted?\n")); return NULL; } SendMessage(m_lpXInfoCur->toolInfoW.hwnd, WM_NOTIFY, (WPARAM)0, (LPARAM)&toolTipTextW); #ifdef _DEBUG if(!toolTipTextW.lpszText) { //Dbg(("###### Text is NULL\n")); } #endif return (LPWSTR)toolTipTextW.lpszText; } break; } return NULL; } INT CDWToolTip::GetTipSize(LPSIZE lpSize) { LPWSTR lpwstr = GetTipTextW(); HDC hDC; SIZE size; INT i; LPWSTR lp, lpTop; //Dbg(("GetTipSize START \n")); if(!lpSize) { //Dbg(("-->GetTipSize ERROR END\n")); return -1; } if(!lpwstr) { //Dbg(("--->GetTipSize lpwstr is NULL\n")); return -1; } //DBGW((L"lpwst [%s]\n", lpwstr)); #ifdef _DEBUG if(!IsWindow(m_hwndSelf)) { //Dbg(("######### hwnd is Corrupted [0x%08x]\n", m_hwndSelf)); DebugBreak(); } #endif hDC = ::GetDC(m_hwndSelf); HFONT hFontOld = NULL; if(m_hFont) { hFontOld = (HFONT)::SelectObject(hDC, m_hFont); } else { hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); } lpSize->cx = lpSize->cy = 0; for(i=0, lpTop = lp = lpwstr;;lp++) { if(*lp == (WCHAR)L'\n') { //Dbg(("Find return i[%d]\n", i)); ExGetTextExtentPoint32W(hDC, lpTop, i, &size); //Dbg(("cx[%d] cy[%d]\n", size.cx, size.cy)); lpSize->cx = MAX(lpSize->cx, size.cx); lpSize->cy += size.cy; lpTop = lp+1; i = 0; } else if (*lp == (WCHAR)0x0000) { ExGetTextExtentPoint32W(hDC, lpTop, i, &size); lpSize->cx = MAX(lpSize->cx, size.cx); lpSize->cy += size.cy; break; } else { i++; } } lpSize->cx += 4; lpSize->cy += 4; ::SelectObject(hDC, hFontOld); ::ReleaseDC(m_hwndSelf, hDC); //Dbg(("TIP SIZE cx[%d] cy[%d]\n", lpSize->cx, lpSize->cy)); //Dbg(("-->GetTipSize NORMAL END\n")); return 0; } INT CDWToolTip::DrawTipText(HDC hDC, LPRECT lpRc, LPWSTR lpwstr) { SIZE size; INT i, j; LPWSTR lp, lpTop; if(!lpwstr) { return 0; } if(!lpRc) { return 0; } INT yOffset = 0; #ifndef UNDER_CE ::FillRect(hDC, lpRc, (HBRUSH)(COLOR_INFOBK + 1)); #else // UNDER_CE ::FillRect(hDC, lpRc, GetSysColorBrush(COLOR_INFOBK)); #endif // UNDER_CE COLORREF dwOldTC = ::SetTextColor(hDC, GetSysColor(COLOR_INFOTEXT)); DWORD oldMode = ::SetBkMode(hDC, TRANSPARENT); // Init size size.cx = size.cy = 0; for(i=j=0, lpTop = lp = lpwstr;;lp++) { if(*lp == L'\n' || *lp == (WCHAR)0x0000) { ExGetTextExtentPoint32W(hDC, lpTop, i, &size); //Dbg(("Length %d\n", i)); ExExtTextOutW(hDC, lpRc->left + 1, lpRc->top + 1 + yOffset, ETO_CLIPPED, lpRc, lpTop, i, NULL); if(*lp == (WCHAR)0x0000) { break; } lpTop = lp+1; i = 0; j++; yOffset += size.cy; } else { i++; } } ::SetTextColor(hDC, dwOldTC); ::SetBkMode(hDC, oldMode); return 0; } BOOL CDWToolTip::IsMousePointerIn(VOID) { POINT pt; RECT rect; HWND hwndTarget; //Dbg(("IsMousePointerIn START\n")); #ifndef UNDER_CE // Windows CE does not support GetCursorPos ::GetCursorPos(&pt); #else // UNDER_CE if(m_lpXInfoCur){ pt = m_lpXInfoCur->userInfo.pt; ClientToScreen(m_lpXInfoCur->userInfo.hwnd, &pt); } #endif // UNDER_CE if(!m_lpXInfoCur) { //Dbg(("--->IsMousePointer in ERROR END\n")); return FALSE; } if(m_lpXInfoCur->toolInfoW.uFlags & TTF_IDISHWND) { hwndTarget = (HWND)m_lpXInfoCur->toolInfoW.uId; //Dbg(("---> TYPE TTF_IDISHWND hwnd[0x%08x]\n", hwndTarget )); if(IsWindow(hwndTarget)) { //Dbg(("--->IsWindow OK\n")); GetWindowRect(hwndTarget, &rect); //Dbg(("--->GetWindowRect OK\n")); if(PtInRect(&rect, pt)) { return TRUE; } return FALSE; } else { //Dbg(("################ hwndTarget[0x%08x] IS CORRUPTED\n", hwndTarget)); } } else { switch(m_lpXInfoCur->whichEvent) { case TTM_RELAYEVENT: //OLD_970808 ::ScreenToClient(m_lpXInfoCur->toolInfoW.hwnd, &pt); if(::PtInRect(&m_lpXInfoCur->toolInfoW.rect, pt)) { return TRUE; } break; case TTM_RELAYEVENT_WITHUSERINFO: if(IsWindow(m_lpXInfoCur->toolInfoW.hwnd)) { HWND hwndCmd = GetDlgItem(m_lpXInfoCur->toolInfoW.hwnd, (INT)m_lpXInfoCur->toolInfoW.uId); RECT rc; ::GetClientRect(hwndCmd, &rc); //LPRECT lpRc = &rc; #if 0 Dbg(("--->t[%d]l[%d]r[%d]b[%d]\n", lpRc->top, lpRc->left, lpRc->right, lpRc->bottom)); #endif ::ScreenToClient(hwndCmd, &pt); Dbg(("--->pt.x[%d] pt.y[%d]\n", pt.x, pt.y)); if(PtInRect(&rc, pt)) { if(PtInRect(&m_lpXInfoCur->userInfo.rect, pt)) { return TRUE; } } else { //Dbg(("--->Is Mouse PtInRect Error END\n")); } } else { Dbg(("################ hwndTarget[0x%08x] IS CORRUPTED\n", m_lpXInfoCur->toolInfoW.hwnd)); } break; } } //Dbg(("--->Is Mouse PtInRect Error END\n")); return FALSE; } BOOL CDWToolTip::IsSameInfo(LPXINFO lpXInfo1, LPXINFO lpXInfo2) { if(!lpXInfo1 || !lpXInfo2) { return FALSE; } switch(lpXInfo1->whichEvent) { case TTM_RELAYEVENT: if(lpXInfo2->whichEvent != TTM_RELAYEVENT) { return FALSE; } if((lpXInfo1->toolInfoW.uFlags != lpXInfo2->toolInfoW.uFlags) || (lpXInfo1->toolInfoW.hwnd != lpXInfo2->toolInfoW.hwnd) || (lpXInfo1->toolInfoW.uId != lpXInfo2->toolInfoW.uId) || (lpXInfo1->toolInfoW.rect.top != lpXInfo2->toolInfoW.rect.top) || (lpXInfo1->toolInfoW.rect.left != lpXInfo2->toolInfoW.rect.left) || (lpXInfo1->toolInfoW.rect.right != lpXInfo2->toolInfoW.rect.right) || (lpXInfo1->toolInfoW.rect.bottom!= lpXInfo2->toolInfoW.rect.bottom)) { return FALSE; } break; case TTM_RELAYEVENT_WITHUSERINFO: if(lpXInfo2->whichEvent != TTM_RELAYEVENT_WITHUSERINFO) { return FALSE; } if((lpXInfo1->userInfo.hwnd != lpXInfo2->userInfo.hwnd) || (lpXInfo1->userInfo.pt.x != lpXInfo2->userInfo.pt.x) || (lpXInfo1->userInfo.pt.y != lpXInfo2->userInfo.pt.y) || (lpXInfo1->userInfo.rect.top != lpXInfo2->userInfo.rect.top) || (lpXInfo1->userInfo.rect.left != lpXInfo2->userInfo.rect.left) || (lpXInfo1->userInfo.rect.right != lpXInfo2->userInfo.rect.right) || (lpXInfo1->userInfo.rect.bottom != lpXInfo2->userInfo.rect.bottom)) { return FALSE; } break; } return TRUE; } //---------------------------------------------------------------- POSVERSIONINFO CDWToolTip::GetVersionInfo() { static BOOL fFirstCall = TRUE; static OSVERSIONINFO os; if ( fFirstCall ) { os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if ( GetVersionEx( &os ) ) { fFirstCall = FALSE; } } return &os; } BOOL CDWToolTip::IsWinNT4() { BOOL fNT4; fNT4 = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT) && (GetVersionInfo()->dwMajorVersion >= 4); return fNT4; } BOOL CDWToolTip::IsWinNT5() { BOOL fNT5; fNT5 = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT) && (GetVersionInfo()->dwMajorVersion == 5); return fNT5; } BOOL CDWToolTip::IsWinNT() { return (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT); } BOOL CDWToolTip::IsWin95(VOID) { if(GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { return TRUE; } return FALSE; } BOOL CDWToolTip::IsWin98() { BOOL fMemphis; fMemphis = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (GetVersionInfo()->dwMajorVersion >= 4) && (GetVersionInfo()->dwMinorVersion >= 10); return fMemphis; } //---------------------------------------------------------------- //---------------------------------------------------------------- //VC6 does NOT defined //#define SPI_GETMENUANIMATION 0x1002 //#define SPI_GETTOOLTIPANIMATION 0x1016 //---------------------------------------------------------------- #define MY_SPI_GETMENUANIMATION 0x1002 #define MY_SPI_GETTOOLTIPANIMATION 0x1016 typedef BOOL (WINAPI *LPFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlag); BOOL CDWToolTip::SetWindowAnimate(HWND hwnd) { //---------------------------------------------------------------- //08/16/00 //Satori #2239. Animate window show HourGlass cursor, //when owner window is Disabled and very weird. //We should stop animate tool tip in Office10 //---------------------------------------------------------------- return FALSE; UNREFERENCED_PARAMETER(hwnd); #if 0 #ifndef UNDER_CE // No support HMODULE hLib; LPFNANIMATEWINDOW lpfnProc; BOOL fRet, fAnimate; //---------------------------------------------------------------- //00/08/01 for Satori #2239 //for Win98: can use SPI_GETMENUANIMATION for Tooltip. //for Win2K: can use SPI_GETTOOLTIPANIMATION for Tooltip. //---------------------------------------------------------------- if(IsWin98() || IsWinNT5()) { if(IsWin98()) { fRet = SystemParametersInfo(MY_SPI_GETMENUANIMATION, 0, &fAnimate, FALSE); if(!fRet || !fAnimate) { return 0; } } else { //Win2K() fRet = SystemParametersInfo(MY_SPI_GETTOOLTIPANIMATION, 0, &fAnimate, FALSE); if(!fRet || !fAnimate) { return 0; } } hLib = GetModuleHandle("user32"); if(!hLib) { return 0; } lpfnProc = (LPFNANIMATEWINDOW)GetProcAddress(hLib, "AnimateWindow"); if(lpfnProc) { INT ret = (*lpfnProc)(hwnd, 200, AW_VER_POSITIVE|AW_SLIDE); Dbg(("ret [%d] lasterror[%d]\n", ret, GetLastError())); return ret; } } #endif // UNDER_CE return 0; #endif //if 0 }