Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1154 lines
29 KiB

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#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
}