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

  1. #ifndef WIN32_LEAN_AND_MEAN
  2. #define WIN32_LEAN_AND_MEAN
  3. #endif
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <commctrl.h>
  7. #include "ptt.h"
  8. #include "cdwtt.h"
  9. #include "dbg.h"
  10. #include "exgdiw.h"
  11. #ifdef UNDER_CE // Windows CE specific
  12. #include "stub_ce.h" // Windows CE stub for unsupported APIs
  13. #endif // UNDER_CE
  14. //----------------------------------------------------------------
  15. //Animate window const value
  16. //----------------------------------------------------------------
  17. #define AW_HOR_POSITIVE 0x00000001
  18. #define AW_HOR_NEGATIVE 0x00000002
  19. #define AW_VER_POSITIVE 0x00000004
  20. #define AW_VER_NEGATIVE 0x00000008
  21. #define AW_CENTER 0x00000010
  22. #define AW_HIDE 0x00010000
  23. #define AW_ACTIVATE 0x00020000
  24. #define AW_SLIDE 0x00040000
  25. #define AW_BLEND 0x00080000
  26. //----------------------------------------------------------------
  27. //local Timer id
  28. //----------------------------------------------------------------
  29. #define TID_SHOW 3
  30. #define TID_MONITOR 4
  31. #define TID_DURATION 5
  32. #ifdef MemAlloc
  33. #undef MemAlloc
  34. #endif
  35. #ifdef MemFree
  36. #undef MemFree
  37. #endif
  38. #define MemAlloc(a) GlobalAllocPtr(GHND, a)
  39. #define MemFree(a) GlobalFreePtr(a);
  40. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  41. #define UnrefMsg() UNREFERENCED_PARAMETER(hwnd); \
  42. UNREFERENCED_PARAMETER(wParam); \
  43. UNREFERENCED_PARAMETER(lParam)
  44. #if 0
  45. typedef struct { // ti
  46. UINT cbSize;
  47. UINT uFlags;
  48. HWND hwnd;
  49. UINT uId;
  50. RECT rect;
  51. HINSTANCE hinst;
  52. LPTSTR lpszText;
  53. } TOOLINFO, NEAR *PTOOLINFO, FAR *LPTOOLINFO;
  54. typedef struct tagTOOLINFOW {
  55. UINT cbSize;
  56. UINT uFlags;
  57. HWND hwnd;
  58. UINT uId;
  59. RECT rect;
  60. HINSTANCE hinst;
  61. LPWSTR lpszText;
  62. } TOOLINFOW, NEAR *PTOOLINFOW, FAR *LPTOOLINFOW;
  63. #endif
  64. LPXINFO XInfo_New(VOID)
  65. {
  66. LPXINFO lpXif = (LPXINFO)MemAlloc(sizeof(XINFO));
  67. if(lpXif) {
  68. ZeroMemory(lpXif, sizeof(XINFO));
  69. }
  70. return lpXif;
  71. }
  72. LRESULT CALLBACK CDWToolTip::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  73. {
  74. LPCDWToolTip lpCDWTT;
  75. switch(uMsg) {
  76. #ifndef UNDER_CE // Windows CE does not support WM_NCCREATE/WM_NCDESTROY
  77. case WM_NCCREATE:
  78. lpCDWTT = new CDWToolTip(hwnd);
  79. SetHWNDPtr(hwnd, lpCDWTT);
  80. break;
  81. case WM_NCDESTROY:
  82. lpCDWTT = (LPCDWToolTip)::GetHWNDPtr(hwnd);
  83. SetHWNDPtr(hwnd, NULL);
  84. if(lpCDWTT) {
  85. delete lpCDWTT;
  86. }
  87. break;
  88. #else // UNDER_CE
  89. case WM_CREATE:
  90. lpCDWTT = new CDWToolTip(hwnd);
  91. SetHWNDPtr(hwnd, lpCDWTT);
  92. if(lpCDWTT) {
  93. return lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam);
  94. }
  95. break;
  96. case WM_DESTROY:
  97. lpCDWTT = (LPCDWToolTip)GetHWNDPtr(hwnd);
  98. if(lpCDWTT) {
  99. lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam);
  100. SetHWNDPtr(hwnd, NULL);
  101. delete lpCDWTT;
  102. }
  103. break;
  104. #endif // UNDER_CE
  105. default:
  106. lpCDWTT = (LPCDWToolTip)GetHWNDPtr(hwnd);
  107. if(lpCDWTT) {
  108. return lpCDWTT->RealWndProc(hwnd, uMsg, wParam, lParam);
  109. }
  110. break;
  111. }
  112. return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  113. }
  114. void *CDWToolTip::operator new(size_t size)
  115. {
  116. BYTE *p = (BYTE *)MemAlloc(size);
  117. if(p) {
  118. ZeroMemory(p, size);
  119. }
  120. return (void *)p;
  121. }
  122. void CDWToolTip::operator delete(void *pv)
  123. {
  124. if(pv) {
  125. MemFree(pv);
  126. }
  127. }
  128. CDWToolTip::CDWToolTip(HWND hwnd)
  129. {
  130. m_hwndSelf = hwnd;
  131. m_hFont = NULL;
  132. }
  133. CDWToolTip::~CDWToolTip()
  134. {
  135. //do nothing
  136. }
  137. LRESULT CDWToolTip::RealWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  138. {
  139. switch(uMsg) {
  140. case WM_CREATE:
  141. return MsgCreate(hwnd, wParam, lParam);
  142. case WM_PAINT:
  143. return MsgPaint (hwnd, wParam, lParam);
  144. #ifndef UNDER_CE // Not support
  145. case WM_PRINTCLIENT:
  146. return MsgPrintClient(hwnd, wParam, lParam);
  147. #endif // UNDER_CE
  148. case WM_TIMER:
  149. return MsgTimer(hwnd, wParam, lParam);
  150. case WM_DESTROY:
  151. return MsgDestroy(hwnd, wParam, lParam);
  152. case WM_SETFONT:
  153. return MsgSetFont(hwnd, wParam, lParam);
  154. case TTM_SETDELAYTIME:
  155. return TTM_SetDelayTime(hwnd, wParam, lParam);
  156. case TTM_ADDTOOLW:
  157. return TTM_AddToolW(hwnd, wParam, lParam);
  158. case TTM_DELTOOLW:
  159. return TTM_DelToolW(hwnd, wParam, lParam);
  160. case TTM_NEWTOOLRECTW:
  161. return TTM_NewToolRectW(hwnd, wParam, lParam);
  162. case TTM_RELAYEVENT_WITHUSERINFO:
  163. return TTM_RelayEventWithUserInfo(hwnd, wParam, lParam);
  164. case TTM_RELAYEVENT:
  165. return TTM_RelayEvent(hwnd, wParam, lParam);
  166. case TTM_GETTOOLINFOW:
  167. case TTM_SETTOOLINFOW:
  168. return TTM_GetSetToolInfoW(hwnd, uMsg, wParam, lParam);
  169. case TTM_GETTOOLCOUNT:
  170. return TTM_GetToolCount(hwnd, wParam, lParam);
  171. default:
  172. break;
  173. }
  174. return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
  175. }
  176. LRESULT CDWToolTip::MsgCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
  177. {
  178. m_hwndSelf = hwnd;
  179. m_fEnable = TRUE; //970812: new to show or hide tooltip explicitly
  180. return 1;
  181. UnrefMsg();
  182. }
  183. LRESULT CDWToolTip::MsgPrintClient(HWND hwnd, WPARAM wParam, LPARAM lParam)
  184. {
  185. #ifndef UNDER_CE // Not support
  186. Dbg(("WM_PRINTCLIENT COME lParam[0x%08x]\n", lParam));
  187. RECT rc;
  188. POINT pt;
  189. GetCursorPos(&pt);
  190. GetClientRect(hwnd, &rc);
  191. HDC hDC = (HDC)wParam;
  192. HFONT hFontOld = NULL;
  193. if(m_hFont) {
  194. hFontOld = (HFONT)::SelectObject(hDC, m_hFont);
  195. }
  196. else {
  197. hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
  198. }
  199. LPWSTR lpwstr = GetTipTextW();
  200. if(lpwstr) {
  201. DrawTipText(hDC, &rc, lpwstr);
  202. }
  203. ::SelectObject(hDC, hFontOld);
  204. #endif // UNDER_CE
  205. return 0;
  206. UNREFERENCED_PARAMETER(lParam);
  207. }
  208. LRESULT CDWToolTip::MsgSetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
  209. {
  210. HFONT hFont = (HFONT)wParam;
  211. BOOL fRedraw = LOWORD(lParam);
  212. if(!hFont) {
  213. return 0;
  214. }
  215. #ifndef UNDER_CE
  216. LOGFONTA logFont;
  217. #else // UNDER_CE
  218. LOGFONT logFont;
  219. #endif // UNDER_CE
  220. HFONT hFontNew;
  221. ::GetObject(hFont, sizeof(logFont), &logFont);
  222. hFontNew = ::CreateFontIndirect(&logFont);
  223. if(!hFontNew) {
  224. return 0;
  225. }
  226. if(m_hFont) {
  227. ::DeleteObject(m_hFont);
  228. }
  229. m_hFont = hFontNew;
  230. if(fRedraw) {
  231. ::InvalidateRect(hwnd, NULL, TRUE);
  232. }
  233. return 0;
  234. UnrefMsg();
  235. }
  236. LRESULT CDWToolTip::MsgPaint(HWND hwnd, WPARAM wParam, LPARAM lParam)
  237. {
  238. PAINTSTRUCT ps;
  239. RECT rc;
  240. #ifndef UNDER_CE // Windows CE does not support GetCursorPos
  241. POINT pt;
  242. ::GetCursorPos(&pt);
  243. #endif // UNDER_CE
  244. ::GetClientRect(hwnd, &rc);
  245. HDC hDC = ::BeginPaint(hwnd, &ps);
  246. HFONT hFontOld = NULL;
  247. if(m_hFont) {
  248. hFontOld = (HFONT)::SelectObject(hDC, m_hFont);
  249. }
  250. else {
  251. hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
  252. }
  253. LPWSTR lpwstr = GetTipTextW();
  254. if(lpwstr) {
  255. DrawTipText(hDC, &rc, lpwstr);
  256. }
  257. ::SelectObject(hDC, hFontOld);
  258. ::EndPaint(hwnd, &ps);
  259. //Dbg(("--->WM_PAINT END\n"));
  260. return 0;
  261. UnrefMsg();
  262. }
  263. LRESULT CDWToolTip::MsgTimer(HWND hwnd, WPARAM wParam, LPARAM lParam)
  264. {
  265. static POINT pt;
  266. static SIZE size;
  267. static RECT rect;
  268. static BOOL fAnimate;
  269. #ifndef UNDER_CE // Windows CE does not support GetCursorPos
  270. ::GetCursorPos(&pt);
  271. #else // UNDER_CE
  272. if(m_lpXInfoCur){
  273. pt = m_lpXInfoCur->userInfo.pt;
  274. ClientToScreen(m_lpXInfoCur->userInfo.hwnd, &pt);
  275. }
  276. #endif // UNDER_CE
  277. switch(wParam) {
  278. case TID_SHOW:
  279. //Dbg(("TID_SHOW COME\n"));
  280. KillTimer(hwnd, TID_SHOW);
  281. SetTimer(hwnd, TID_MONITOR, 20, NULL);
  282. SetTimer(hwnd, TID_DURATION, 6000, NULL);
  283. //get cur mouse pos
  284. //show tool tip window
  285. //call invalidate rect
  286. //set monitoring timer
  287. if(0 == GetTipSize(&size)) {
  288. if(m_fEnable) {
  289. //Dbg(("-->GetTipSize ret 0\n"));
  290. if(IsMousePointerIn()) {
  291. //Dbg(("-->Call SetWindowPos\n"));
  292. //990530: KOTAE #433
  293. INT cxScr = ::GetSystemMetrics(SM_CXSCREEN);
  294. INT cyScr = ::GetSystemMetrics(SM_CYSCREEN);
  295. if(cxScr < (pt.x + size.cx)) {
  296. pt.x = cxScr - size.cx;
  297. }
  298. if(cyScr < pt.y + 20 + size.cy) {
  299. pt.y = cyScr - (20*2 + size.cy);
  300. }
  301. SetWindowPos(hwnd,
  302. HWND_TOP,
  303. pt.x, pt.y+20,
  304. size.cx, size.cy,
  305. SWP_NOACTIVATE | SWP_HIDEWINDOW |SWP_NOOWNERZORDER);
  306. fAnimate = SetWindowAnimate(hwnd);
  307. if(!fAnimate)
  308. SetWindowPos(hwnd,
  309. HWND_TOP,
  310. pt.x, pt.y+20,
  311. size.cx, size.cy,
  312. SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOOWNERZORDER);
  313. //Dbg(("-->SetWindowPos End\n"));
  314. m_fShow = TRUE;
  315. if(!fAnimate)
  316. InvalidateRect(hwnd, NULL, NULL);
  317. //Dbg(("-->Invalidate Rect End\n"));
  318. }
  319. }
  320. }
  321. //Dbg(("TID_SHOW END\n"));
  322. break;
  323. case TID_MONITOR:
  324. {
  325. //Dbg(("TID_MONITOR COME\n"));
  326. HWND hwndOwner = (HWND)GetWindow(hwnd, GW_OWNER);
  327. if(!IsMousePointerIn() || NULL == GetTipTextW() || !IsWindowVisible(hwndOwner) ) {
  328. //Dbg(("---> Hide Window\n"));
  329. ::SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  330. SWP_HIDEWINDOW |
  331. SWP_NOACTIVATE |
  332. SWP_NOZORDER |
  333. SWP_NOSIZE |
  334. SWP_NOMOVE);
  335. //Dbg(("Set curInfo NULL\n"));
  336. m_lpXInfoCur = NULL;
  337. m_fShow = FALSE;
  338. ::KillTimer(hwnd, TID_MONITOR);
  339. ::KillTimer(hwnd, TID_DURATION);
  340. }
  341. }
  342. break;
  343. case TID_DURATION:
  344. //Dbg(("TID_DURATION START\n"));
  345. SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
  346. SWP_NOZORDER |
  347. SWP_NOSIZE |
  348. SWP_HIDEWINDOW |
  349. SWP_NOACTIVATE);
  350. //Dbg(("Set curInfo NULL\n"));
  351. //lptt->lpXInfoCur = NULL;
  352. m_fShow = FALSE;
  353. ::KillTimer(hwnd, TID_MONITOR);
  354. ::KillTimer(hwnd, TID_DURATION);
  355. break;
  356. default:
  357. break;
  358. }
  359. return 0;
  360. UnrefMsg();
  361. }
  362. LRESULT CDWToolTip::MsgDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
  363. {
  364. Dbg(("WM_DESTORY START\n"));
  365. ::KillTimer(hwnd, TID_SHOW);
  366. ::KillTimer(hwnd, TID_MONITOR);
  367. ::KillTimer(hwnd, TID_DURATION);
  368. LPXINFO lpXInfo, lpXInfoNext;
  369. m_lpXInfoCur = NULL;
  370. INT i;
  371. for(lpXInfo = m_lpXInfoHead, i = 0;
  372. lpXInfo;
  373. lpXInfo = lpXInfoNext, i++){
  374. lpXInfoNext = lpXInfo->next;
  375. //Dbg(("-->%d: Free XInfo\n", i));
  376. MemFree(lpXInfo);
  377. }
  378. if(m_hFont) {
  379. ::DeleteObject(m_hFont);
  380. m_hFont = NULL;
  381. }
  382. Dbg(("--->WM_DESTORY END\n"));
  383. return 0;
  384. UnrefMsg();
  385. }
  386. LRESULT CDWToolTip::TTM_SetDelayTime(HWND hwnd, WPARAM wParam, LPARAM lParam)
  387. {
  388. switch(wParam) {
  389. case TTDT_AUTOMATIC:
  390. break;
  391. case TTDT_RESHOW:
  392. break;
  393. case TTDT_AUTOPOP:
  394. break;
  395. case TTDT_INITIAL:
  396. break;
  397. }
  398. m_dwDelayFlag = (DWORD)wParam;
  399. m_dwDelayTime = (DWORD)lParam;
  400. return 0;
  401. UnrefMsg();
  402. }
  403. LRESULT CDWToolTip::TTM_AddToolW(HWND hwnd, WPARAM wParam, LPARAM lParam)
  404. {
  405. TOOLINFOW *lpTi = (LPTOOLINFOW)lParam;
  406. if(!lpTi) {
  407. Dbg(("################### lParam is NULLL\n"));
  408. return 0;
  409. }
  410. if(lpTi->cbSize != sizeof(TOOLINFOW)) {
  411. Dbg(("##### TTM_ADDTOOLW size ERROR\n"));
  412. return 0;
  413. }
  414. LPXINFO *ppXInfo, lpXInfoNew;
  415. lpXInfoNew = XInfo_New();
  416. if(!lpXInfoNew) {
  417. return 0;
  418. }
  419. lpXInfoNew->toolInfoW = *lpTi;
  420. for(ppXInfo = &m_lpXInfoHead;
  421. *ppXInfo;
  422. ppXInfo = &(*ppXInfo)->next){
  423. }
  424. *ppXInfo = lpXInfoNew;
  425. return 0;
  426. UnrefMsg();
  427. }
  428. LRESULT CDWToolTip::TTM_DelToolW(HWND hwnd, WPARAM wParam, LPARAM lParam)
  429. {
  430. TOOLINFOW *lpTi = (LPTOOLINFOW)lParam;
  431. if(!lpTi) {
  432. Dbg(("################### lParam is NULLL\n"));
  433. return 0;
  434. }
  435. if(lpTi->cbSize != sizeof(TOOLINFOW)) {
  436. return 0;
  437. }
  438. LPXINFO *ppXInfo, lpXInfoTmp;
  439. for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next){
  440. if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd &&
  441. (*ppXInfo)->toolInfoW.uId == lpTi->uId) {
  442. lpXInfoTmp = *ppXInfo;
  443. *ppXInfo = (*ppXInfo)->next;
  444. if(lpXInfoTmp == m_lpXInfoCur) {
  445. //Dbg(("Set curInfo NULL\n"));
  446. m_lpXInfoCur = NULL;
  447. }
  448. MemFree(lpXInfoTmp);
  449. Dbg(("TTM_DELTOOLW SUCCEEDED\n"));
  450. return 0;
  451. break;
  452. }
  453. }
  454. Dbg(("TTM_DELTOOLW Error END\n"));
  455. return -1;
  456. UnrefMsg();
  457. }
  458. LRESULT CDWToolTip::TTM_NewToolRectW(HWND hwnd, WPARAM wParam, LPARAM lParam)
  459. {
  460. TOOLINFOW *lpTi = (LPTOOLINFOW)lParam;
  461. if(lpTi->cbSize != sizeof(TOOLINFOW)) {
  462. return 0;
  463. }
  464. LPXINFO *ppXInfo;
  465. for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next) {
  466. if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd &&
  467. (*ppXInfo)->toolInfoW.uId == lpTi->uId) {
  468. if(m_lpXInfoCur == *ppXInfo) {
  469. m_xInfoPrev = *(m_lpXInfoCur);
  470. }
  471. (*ppXInfo)->toolInfoW = *lpTi;
  472. break;
  473. }
  474. }
  475. return 0;
  476. UnrefMsg();
  477. }
  478. // SendMessage(hwnd, TTM_RELAYEVENT_WITHUESRINFO, 0, LPTOOLTIPUSERINFO lpInfo);
  479. LRESULT CDWToolTip::TTM_RelayEventWithUserInfo(HWND hwnd, WPARAM wParam, LPARAM lParam)
  480. {
  481. INT i;
  482. LPXINFO *ppXInfo;
  483. LPTOOLTIPUSERINFO lpUserInfo = (LPTOOLTIPUSERINFO)lParam;
  484. //Dbg(("TTM_RELAYEVENT_WITHUSERINFO START\n"));
  485. if(!lpUserInfo) {
  486. //Dbg(("--->TTM_RELAYEVENT_WITHUSERINFO ERROR END\n"));
  487. return 0;
  488. }
  489. for(i = 0, ppXInfo = &m_lpXInfoHead;
  490. *ppXInfo;
  491. i++, ppXInfo = &(*ppXInfo)->next) {
  492. UINT uFlags = (*ppXInfo)->toolInfoW.uFlags;
  493. if(uFlags & TTF_IDISHWND) {
  494. if((HWND)(*ppXInfo)->toolInfoW.uId == lpUserInfo->hwnd) {
  495. //Dbg(("[%d]Find info with hwnd index\n", i));
  496. break;
  497. }
  498. }
  499. else {
  500. #ifdef _DEBUG //970915:
  501. if(!IsWindow(lpUserInfo->hwnd)) {
  502. Dbg(("############## hwnd corrupted [0x%08x]\n",
  503. lpUserInfo->hwnd));
  504. DebugBreak();
  505. }
  506. if(!IsWindow((*ppXInfo)->toolInfoW.hwnd)) {
  507. Dbg(("############## hwnd corrupted [0x%08x]\n",
  508. (*ppXInfo)->toolInfoW.hwnd));
  509. DebugBreak();
  510. }
  511. #endif
  512. if(lpUserInfo->hwnd == GetDlgItem((*ppXInfo)->toolInfoW.hwnd,
  513. (INT)(*ppXInfo)->toolInfoW.uId)) {
  514. break;
  515. }
  516. else if(lpUserInfo->hwnd == (*ppXInfo)->toolInfoW.hwnd) {
  517. if(PtInRect(&(*ppXInfo)->toolInfoW.rect, lpUserInfo->pt)) {
  518. break;
  519. }
  520. }
  521. #if 0
  522. if(PtInRect(&(*ppXInfo)->toolInfoW.rect, lpUserInfo->pt)) {
  523. Dbg(("[%d]Find INFO with id [%d]\n", i, (*ppXInfo)->toolInfoW.uId));
  524. break;
  525. }
  526. #endif
  527. }
  528. }
  529. if(*ppXInfo) {
  530. //m_curRelayMsg = *lpmsg;
  531. if(m_lpXInfoCur == *ppXInfo) { // Same info is used.
  532. //check specified rect is same or not
  533. // it is very dirty code.....
  534. // if rectangle is same.
  535. if((lpUserInfo->rect.left == (*ppXInfo)->userInfo.rect.left ) &&
  536. (lpUserInfo->rect.top == (*ppXInfo)->userInfo.rect.top ) &&
  537. (lpUserInfo->rect.right == (*ppXInfo)->userInfo.rect.right) &&
  538. (lpUserInfo->rect.bottom == (*ppXInfo)->userInfo.rect.bottom)) {
  539. //Dbg(("Set Timer 500\n"));
  540. //SetTimer(hwnd, TID_SHOW, 500, NULL);
  541. }
  542. else {
  543. //if rectangl is NOT same, it should be displayed now
  544. //Dbg(("Set Timer 10\n"));
  545. SetTimer(hwnd, TID_SHOW, 100, NULL);
  546. }
  547. }
  548. else {
  549. SetTimer(hwnd, TID_SHOW, 500, NULL);
  550. }
  551. (*ppXInfo)->whichEvent = TTM_RELAYEVENT_WITHUSERINFO;
  552. (*ppXInfo)->userInfo = *lpUserInfo;
  553. m_lpXInfoCur = *ppXInfo;
  554. //Dbg(("--->TTM_REUSER END\n"));
  555. }
  556. else {
  557. //Dbg(("Set curInfo NULL\n"));
  558. m_lpXInfoCur = NULL;
  559. //Dbg(("--->TTM_REUSER CUR NULL END\n"));
  560. }
  561. return 0;
  562. UnrefMsg();
  563. }
  564. LRESULT CDWToolTip::TTM_RelayEvent(HWND hwnd, WPARAM wParam, LPARAM lParam)
  565. {
  566. LPMSG lpmsg = (LPMSG)lParam;
  567. INT i;
  568. LPXINFO *ppXInfo; //lpXInfo; //, lpXInfoCur;
  569. if(!lpmsg) {
  570. return 0;
  571. }
  572. switch(lpmsg->message) {
  573. case WM_LBUTTONDOWN:
  574. case WM_MOUSEMOVE:
  575. case WM_LBUTTONUP:
  576. case WM_RBUTTONDOWN:
  577. case WM_MBUTTONDOWN:
  578. case WM_RBUTTONUP:
  579. case WM_MBUTTONUP:
  580. for(i = 0, ppXInfo = &m_lpXInfoHead;
  581. *ppXInfo;
  582. i++, ppXInfo = &(*ppXInfo)->next) {
  583. UINT uFlags = (*ppXInfo)->toolInfoW.uFlags;
  584. if(uFlags & TTF_IDISHWND) {
  585. if((HWND)(*ppXInfo)->toolInfoW.uId == lpmsg->hwnd) {
  586. //Dbg(("[%d]Find info with hwnd index\n", i));
  587. break;
  588. }
  589. }
  590. else {
  591. POINT pt;
  592. pt.x = LOWORD(lpmsg->lParam);
  593. pt.y = HIWORD(lpmsg->lParam);
  594. if(PtInRect(&(*ppXInfo)->toolInfoW.rect, pt)) {
  595. //Dbg(("[%d]Find INFO with id [%d]\n", i, (*ppXInfo)->toolInfoW.uId));
  596. break;
  597. }
  598. }
  599. }
  600. if(*ppXInfo) {
  601. m_curRelayMsg = *lpmsg;
  602. (*ppXInfo)->whichEvent = TTM_RELAYEVENT;
  603. if(m_lpXInfoCur) {
  604. if(m_lpXInfoCur != *ppXInfo) {
  605. //Dbg(("-->SetTimer TID_SHOW with 100msec\n"));
  606. SetTimer(hwnd, TID_SHOW, 100, NULL);
  607. m_xInfoPrev = *m_lpXInfoCur;
  608. }
  609. else {
  610. //----------------------------------------------------------------
  611. //m_lpXInfoCur is not changed.
  612. //check rectangle, other information is same or not
  613. //----------------------------------------------------------------
  614. if(!IsSameInfo(&m_xInfoPrev, *ppXInfo)) {
  615. SetTimer(hwnd, TID_SHOW, 100, NULL);
  616. m_xInfoPrev = **ppXInfo;
  617. }
  618. }
  619. //else {
  620. // SetTimer(hwnd, TID_SHOW, 500, NULL);
  621. //}
  622. }
  623. else {
  624. //Dbg(("-->SetTimer TID_SHOW with 500msec\n"));
  625. SetTimer(hwnd, TID_SHOW, 500, NULL);
  626. }
  627. m_lpXInfoCur = *ppXInfo;
  628. }
  629. else {
  630. //Dbg(("Set curInfo NULL\n"));
  631. m_lpXInfoCur = NULL;
  632. }
  633. break;
  634. default:
  635. break;
  636. }
  637. return 0;
  638. UnrefMsg();
  639. }
  640. LRESULT CDWToolTip::TTM_GetSetToolInfoW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  641. {
  642. LPTOOLINFOW lpTi = (LPTOOLINFOW)lParam;
  643. if(lpTi->cbSize != sizeof(TOOLINFOW)) {
  644. return 0;
  645. }
  646. LPXINFO *ppXInfo;
  647. for(ppXInfo = &m_lpXInfoHead; *ppXInfo; ppXInfo = &(*ppXInfo)->next) {
  648. if((*ppXInfo)->toolInfoW.hwnd == lpTi->hwnd &&
  649. (*ppXInfo)->toolInfoW.uId == lpTi->uId) {
  650. if(uMsg == TTM_GETTOOLINFOW) {
  651. (*lpTi) = (*ppXInfo)->toolInfoW;
  652. }
  653. else {
  654. (*ppXInfo)->toolInfoW = *lpTi;
  655. }
  656. break;
  657. }
  658. }
  659. return 0;
  660. UnrefMsg();
  661. }
  662. LRESULT CDWToolTip::TTM_GetToolCount(HWND hwnd, WPARAM wParam, LPARAM lParam)
  663. {
  664. INT i;
  665. LPXINFO *ppXInfo;
  666. for(i = 0, ppXInfo = &m_lpXInfoHead;
  667. *ppXInfo;
  668. ppXInfo = &(*ppXInfo)->next, i++) {
  669. }
  670. return i;
  671. UnrefMsg();
  672. }
  673. BOOL CDWToolTip::Enable(HWND hwndToolTip, BOOL fEnable)
  674. {
  675. if(m_hwndSelf != hwndToolTip) {
  676. //Dbg(("ToolTip Enable Invalid Window Handle\n"));
  677. return 0;
  678. }
  679. m_fEnable = fEnable;
  680. m_fShow = fEnable;
  681. if(!fEnable) { //if fEnable FALSE
  682. ::SetWindowPos(hwndToolTip, NULL, 0, 0, 0, 0,
  683. SWP_HIDEWINDOW |
  684. SWP_NOACTIVATE |
  685. SWP_NOZORDER |
  686. SWP_NOSIZE |
  687. SWP_NOMOVE);
  688. ::KillTimer(hwndToolTip, TID_SHOW);
  689. ::KillTimer(hwndToolTip, TID_MONITOR);
  690. ::KillTimer(hwndToolTip, TID_DURATION);
  691. }
  692. return 0;
  693. }
  694. LPWSTR CDWToolTip::GetTipTextW(VOID)
  695. {
  696. static TOOLTIPTEXTW toolTipTextW;
  697. static TOOLTIPTEXTUSERINFO ttTextUserInfo;
  698. INT idCtrl;
  699. if(!m_lpXInfoCur) {
  700. //Dbg(("GetTipTextW m_lpXInfoCur is NULL\n"));
  701. return NULL;
  702. }
  703. if(m_lpXInfoCur->toolInfoW.uFlags & TTF_IDISHWND) {
  704. idCtrl = GetDlgCtrlID((HWND)m_lpXInfoCur->toolInfoW.uId);
  705. }
  706. else {
  707. idCtrl = (INT)m_lpXInfoCur->toolInfoW.uId;
  708. }
  709. switch(m_lpXInfoCur->whichEvent) {
  710. case TTM_RELAYEVENT_WITHUSERINFO:
  711. ZeroMemory((LPVOID)&ttTextUserInfo, sizeof(ttTextUserInfo));
  712. ttTextUserInfo.hdr.hwndFrom = m_hwndSelf;
  713. ttTextUserInfo.hdr.idFrom = idCtrl;
  714. ttTextUserInfo.hdr.code = TTN_NEEDTEXT_WITHUSERINFO;
  715. ttTextUserInfo.userInfo = m_lpXInfoCur->userInfo;
  716. ::SendMessage(m_lpXInfoCur->toolInfoW.hwnd,
  717. WM_NOTIFY,
  718. (WPARAM)0,
  719. (LPARAM)&ttTextUserInfo);
  720. #if _DEBUG
  721. if(!toolTipTextW.lpszText) {
  722. //Dbg(("###### Text is NULL\n"));
  723. }
  724. #endif
  725. return (LPWSTR)ttTextUserInfo.lpszText;
  726. break;
  727. case TTM_RELAYEVENT:
  728. default:
  729. ZeroMemory((LPVOID)&toolTipTextW, sizeof(toolTipTextW));
  730. toolTipTextW.hdr.hwndFrom = m_hwndSelf;
  731. toolTipTextW.hdr.idFrom = idCtrl;
  732. toolTipTextW.hdr.code = TTN_NEEDTEXTW;
  733. toolTipTextW.hinst = m_lpXInfoCur->toolInfoW.hinst;
  734. toolTipTextW.uFlags = m_lpXInfoCur->toolInfoW.uFlags;
  735. if(m_lpXInfoCur->toolInfoW.lpszText == LPSTR_TEXTCALLBACKW) {
  736. if(!m_lpXInfoCur->toolInfoW.hwnd) {
  737. //Dbg(("###### hwnd is NULL\n"));
  738. return NULL;
  739. }
  740. if(!IsWindow(m_lpXInfoCur->toolInfoW.hwnd)) {
  741. //Dbg(("###### hwnd is Corrupted?\n"));
  742. return NULL;
  743. }
  744. SendMessage(m_lpXInfoCur->toolInfoW.hwnd,
  745. WM_NOTIFY,
  746. (WPARAM)0,
  747. (LPARAM)&toolTipTextW);
  748. #ifdef _DEBUG
  749. if(!toolTipTextW.lpszText) {
  750. //Dbg(("###### Text is NULL\n"));
  751. }
  752. #endif
  753. return (LPWSTR)toolTipTextW.lpszText;
  754. }
  755. break;
  756. }
  757. return NULL;
  758. }
  759. INT CDWToolTip::GetTipSize(LPSIZE lpSize)
  760. {
  761. LPWSTR lpwstr = GetTipTextW();
  762. HDC hDC;
  763. SIZE size;
  764. INT i;
  765. LPWSTR lp, lpTop;
  766. //Dbg(("GetTipSize START \n"));
  767. if(!lpSize) {
  768. //Dbg(("-->GetTipSize ERROR END\n"));
  769. return -1;
  770. }
  771. if(!lpwstr) {
  772. //Dbg(("--->GetTipSize lpwstr is NULL\n"));
  773. return -1;
  774. }
  775. //DBGW((L"lpwst [%s]\n", lpwstr));
  776. #ifdef _DEBUG
  777. if(!IsWindow(m_hwndSelf)) {
  778. //Dbg(("######### hwnd is Corrupted [0x%08x]\n", m_hwndSelf));
  779. DebugBreak();
  780. }
  781. #endif
  782. hDC = ::GetDC(m_hwndSelf);
  783. HFONT hFontOld = NULL;
  784. if(m_hFont) {
  785. hFontOld = (HFONT)::SelectObject(hDC, m_hFont);
  786. }
  787. else {
  788. hFontOld = (HFONT)::SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
  789. }
  790. lpSize->cx = lpSize->cy = 0;
  791. for(i=0, lpTop = lp = lpwstr;;lp++) {
  792. if(*lp == (WCHAR)L'\n') {
  793. //Dbg(("Find return i[%d]\n", i));
  794. ExGetTextExtentPoint32W(hDC, lpTop, i, &size);
  795. //Dbg(("cx[%d] cy[%d]\n", size.cx, size.cy));
  796. lpSize->cx = MAX(lpSize->cx, size.cx);
  797. lpSize->cy += size.cy;
  798. lpTop = lp+1;
  799. i = 0;
  800. }
  801. else if (*lp == (WCHAR)0x0000) {
  802. ExGetTextExtentPoint32W(hDC, lpTop, i, &size);
  803. lpSize->cx = MAX(lpSize->cx, size.cx);
  804. lpSize->cy += size.cy;
  805. break;
  806. }
  807. else {
  808. i++;
  809. }
  810. }
  811. lpSize->cx += 4;
  812. lpSize->cy += 4;
  813. ::SelectObject(hDC, hFontOld);
  814. ::ReleaseDC(m_hwndSelf, hDC);
  815. //Dbg(("TIP SIZE cx[%d] cy[%d]\n", lpSize->cx, lpSize->cy));
  816. //Dbg(("-->GetTipSize NORMAL END\n"));
  817. return 0;
  818. }
  819. INT CDWToolTip::DrawTipText(HDC hDC, LPRECT lpRc, LPWSTR lpwstr)
  820. {
  821. SIZE size;
  822. INT i, j;
  823. LPWSTR lp, lpTop;
  824. if(!lpwstr) {
  825. return 0;
  826. }
  827. if(!lpRc) {
  828. return 0;
  829. }
  830. INT yOffset = 0;
  831. #ifndef UNDER_CE
  832. ::FillRect(hDC, lpRc, (HBRUSH)(COLOR_INFOBK + 1));
  833. #else // UNDER_CE
  834. ::FillRect(hDC, lpRc, GetSysColorBrush(COLOR_INFOBK));
  835. #endif // UNDER_CE
  836. COLORREF dwOldTC = ::SetTextColor(hDC, GetSysColor(COLOR_INFOTEXT));
  837. DWORD oldMode = ::SetBkMode(hDC, TRANSPARENT);
  838. // Init size
  839. size.cx = size.cy = 0;
  840. for(i=j=0, lpTop = lp = lpwstr;;lp++) {
  841. if(*lp == L'\n' || *lp == (WCHAR)0x0000) {
  842. ExGetTextExtentPoint32W(hDC, lpTop, i, &size);
  843. //Dbg(("Length %d\n", i));
  844. ExExtTextOutW(hDC,
  845. lpRc->left + 1,
  846. lpRc->top + 1 + yOffset,
  847. ETO_CLIPPED, lpRc,
  848. lpTop,
  849. i,
  850. NULL);
  851. if(*lp == (WCHAR)0x0000) {
  852. break;
  853. }
  854. lpTop = lp+1;
  855. i = 0;
  856. j++;
  857. yOffset += size.cy;
  858. }
  859. else {
  860. i++;
  861. }
  862. }
  863. ::SetTextColor(hDC, dwOldTC);
  864. ::SetBkMode(hDC, oldMode);
  865. return 0;
  866. }
  867. BOOL CDWToolTip::IsMousePointerIn(VOID)
  868. {
  869. POINT pt;
  870. RECT rect;
  871. HWND hwndTarget;
  872. //Dbg(("IsMousePointerIn START\n"));
  873. #ifndef UNDER_CE // Windows CE does not support GetCursorPos
  874. ::GetCursorPos(&pt);
  875. #else // UNDER_CE
  876. if(m_lpXInfoCur){
  877. pt = m_lpXInfoCur->userInfo.pt;
  878. ClientToScreen(m_lpXInfoCur->userInfo.hwnd, &pt);
  879. }
  880. #endif // UNDER_CE
  881. if(!m_lpXInfoCur) {
  882. //Dbg(("--->IsMousePointer in ERROR END\n"));
  883. return FALSE;
  884. }
  885. if(m_lpXInfoCur->toolInfoW.uFlags & TTF_IDISHWND) {
  886. hwndTarget = (HWND)m_lpXInfoCur->toolInfoW.uId;
  887. //Dbg(("---> TYPE TTF_IDISHWND hwnd[0x%08x]\n", hwndTarget ));
  888. if(IsWindow(hwndTarget)) {
  889. //Dbg(("--->IsWindow OK\n"));
  890. GetWindowRect(hwndTarget, &rect);
  891. //Dbg(("--->GetWindowRect OK\n"));
  892. if(PtInRect(&rect, pt)) {
  893. return TRUE;
  894. }
  895. return FALSE;
  896. }
  897. else {
  898. //Dbg(("################ hwndTarget[0x%08x] IS CORRUPTED\n", hwndTarget));
  899. }
  900. }
  901. else {
  902. switch(m_lpXInfoCur->whichEvent) {
  903. case TTM_RELAYEVENT:
  904. //OLD_970808
  905. ::ScreenToClient(m_lpXInfoCur->toolInfoW.hwnd, &pt);
  906. if(::PtInRect(&m_lpXInfoCur->toolInfoW.rect, pt)) {
  907. return TRUE;
  908. }
  909. break;
  910. case TTM_RELAYEVENT_WITHUSERINFO:
  911. if(IsWindow(m_lpXInfoCur->toolInfoW.hwnd)) {
  912. HWND hwndCmd = GetDlgItem(m_lpXInfoCur->toolInfoW.hwnd,
  913. (INT)m_lpXInfoCur->toolInfoW.uId);
  914. RECT rc;
  915. ::GetClientRect(hwndCmd, &rc);
  916. //LPRECT lpRc = &rc;
  917. #if 0
  918. Dbg(("--->t[%d]l[%d]r[%d]b[%d]\n",
  919. lpRc->top,
  920. lpRc->left,
  921. lpRc->right,
  922. lpRc->bottom));
  923. #endif
  924. ::ScreenToClient(hwndCmd, &pt);
  925. Dbg(("--->pt.x[%d] pt.y[%d]\n", pt.x, pt.y));
  926. if(PtInRect(&rc, pt)) {
  927. if(PtInRect(&m_lpXInfoCur->userInfo.rect, pt)) {
  928. return TRUE;
  929. }
  930. }
  931. else {
  932. //Dbg(("--->Is Mouse PtInRect Error END\n"));
  933. }
  934. }
  935. else {
  936. Dbg(("################ hwndTarget[0x%08x] IS CORRUPTED\n",
  937. m_lpXInfoCur->toolInfoW.hwnd));
  938. }
  939. break;
  940. }
  941. }
  942. //Dbg(("--->Is Mouse PtInRect Error END\n"));
  943. return FALSE;
  944. }
  945. BOOL CDWToolTip::IsSameInfo(LPXINFO lpXInfo1, LPXINFO lpXInfo2)
  946. {
  947. if(!lpXInfo1 || !lpXInfo2) {
  948. return FALSE;
  949. }
  950. switch(lpXInfo1->whichEvent) {
  951. case TTM_RELAYEVENT:
  952. if(lpXInfo2->whichEvent != TTM_RELAYEVENT) {
  953. return FALSE;
  954. }
  955. if((lpXInfo1->toolInfoW.uFlags != lpXInfo2->toolInfoW.uFlags) ||
  956. (lpXInfo1->toolInfoW.hwnd != lpXInfo2->toolInfoW.hwnd) ||
  957. (lpXInfo1->toolInfoW.uId != lpXInfo2->toolInfoW.uId) ||
  958. (lpXInfo1->toolInfoW.rect.top != lpXInfo2->toolInfoW.rect.top) ||
  959. (lpXInfo1->toolInfoW.rect.left != lpXInfo2->toolInfoW.rect.left) ||
  960. (lpXInfo1->toolInfoW.rect.right != lpXInfo2->toolInfoW.rect.right) ||
  961. (lpXInfo1->toolInfoW.rect.bottom!= lpXInfo2->toolInfoW.rect.bottom)) {
  962. return FALSE;
  963. }
  964. break;
  965. case TTM_RELAYEVENT_WITHUSERINFO:
  966. if(lpXInfo2->whichEvent != TTM_RELAYEVENT_WITHUSERINFO) {
  967. return FALSE;
  968. }
  969. if((lpXInfo1->userInfo.hwnd != lpXInfo2->userInfo.hwnd) ||
  970. (lpXInfo1->userInfo.pt.x != lpXInfo2->userInfo.pt.x) ||
  971. (lpXInfo1->userInfo.pt.y != lpXInfo2->userInfo.pt.y) ||
  972. (lpXInfo1->userInfo.rect.top != lpXInfo2->userInfo.rect.top) ||
  973. (lpXInfo1->userInfo.rect.left != lpXInfo2->userInfo.rect.left) ||
  974. (lpXInfo1->userInfo.rect.right != lpXInfo2->userInfo.rect.right) ||
  975. (lpXInfo1->userInfo.rect.bottom != lpXInfo2->userInfo.rect.bottom)) {
  976. return FALSE;
  977. }
  978. break;
  979. }
  980. return TRUE;
  981. }
  982. //----------------------------------------------------------------
  983. POSVERSIONINFO CDWToolTip::GetVersionInfo()
  984. {
  985. static BOOL fFirstCall = TRUE;
  986. static OSVERSIONINFO os;
  987. if ( fFirstCall ) {
  988. os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  989. if ( GetVersionEx( &os ) ) {
  990. fFirstCall = FALSE;
  991. }
  992. }
  993. return &os;
  994. }
  995. BOOL CDWToolTip::IsWinNT4()
  996. {
  997. BOOL fNT4;
  998. fNT4 = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  999. (GetVersionInfo()->dwMajorVersion >= 4);
  1000. return fNT4;
  1001. }
  1002. BOOL CDWToolTip::IsWinNT5()
  1003. {
  1004. BOOL fNT5;
  1005. fNT5 = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT) &&
  1006. (GetVersionInfo()->dwMajorVersion == 5);
  1007. return fNT5;
  1008. }
  1009. BOOL CDWToolTip::IsWinNT()
  1010. {
  1011. return (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_NT);
  1012. }
  1013. BOOL CDWToolTip::IsWin95(VOID)
  1014. {
  1015. if(GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
  1016. return TRUE;
  1017. }
  1018. return FALSE;
  1019. }
  1020. BOOL CDWToolTip::IsWin98()
  1021. {
  1022. BOOL fMemphis;
  1023. fMemphis = (GetVersionInfo()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
  1024. (GetVersionInfo()->dwMajorVersion >= 4) &&
  1025. (GetVersionInfo()->dwMinorVersion >= 10);
  1026. return fMemphis;
  1027. }
  1028. //----------------------------------------------------------------
  1029. //----------------------------------------------------------------
  1030. //VC6 does NOT defined
  1031. //#define SPI_GETMENUANIMATION 0x1002
  1032. //#define SPI_GETTOOLTIPANIMATION 0x1016
  1033. //----------------------------------------------------------------
  1034. #define MY_SPI_GETMENUANIMATION 0x1002
  1035. #define MY_SPI_GETTOOLTIPANIMATION 0x1016
  1036. typedef BOOL (WINAPI *LPFNANIMATEWINDOW)(HWND hwnd, DWORD dwTime, DWORD dwFlag);
  1037. BOOL CDWToolTip::SetWindowAnimate(HWND hwnd)
  1038. {
  1039. //----------------------------------------------------------------
  1040. //08/16/00
  1041. //Satori #2239. Animate window show HourGlass cursor,
  1042. //when owner window is Disabled and very weird.
  1043. //We should stop animate tool tip in Office10
  1044. //----------------------------------------------------------------
  1045. return FALSE;
  1046. UNREFERENCED_PARAMETER(hwnd);
  1047. #if 0
  1048. #ifndef UNDER_CE // No support
  1049. HMODULE hLib;
  1050. LPFNANIMATEWINDOW lpfnProc;
  1051. BOOL fRet, fAnimate;
  1052. //----------------------------------------------------------------
  1053. //00/08/01 for Satori #2239
  1054. //for Win98: can use SPI_GETMENUANIMATION for Tooltip.
  1055. //for Win2K: can use SPI_GETTOOLTIPANIMATION for Tooltip.
  1056. //----------------------------------------------------------------
  1057. if(IsWin98() || IsWinNT5()) {
  1058. if(IsWin98()) {
  1059. fRet = SystemParametersInfo(MY_SPI_GETMENUANIMATION,
  1060. 0,
  1061. &fAnimate,
  1062. FALSE);
  1063. if(!fRet || !fAnimate) {
  1064. return 0;
  1065. }
  1066. }
  1067. else { //Win2K()
  1068. fRet = SystemParametersInfo(MY_SPI_GETTOOLTIPANIMATION,
  1069. 0,
  1070. &fAnimate,
  1071. FALSE);
  1072. if(!fRet || !fAnimate) {
  1073. return 0;
  1074. }
  1075. }
  1076. hLib = GetModuleHandle("user32");
  1077. if(!hLib) {
  1078. return 0;
  1079. }
  1080. lpfnProc = (LPFNANIMATEWINDOW)GetProcAddress(hLib, "AnimateWindow");
  1081. if(lpfnProc) {
  1082. INT ret = (*lpfnProc)(hwnd, 200, AW_VER_POSITIVE|AW_SLIDE);
  1083. Dbg(("ret [%d] lasterror[%d]\n", ret, GetLastError()));
  1084. return ret;
  1085. }
  1086. }
  1087. #endif // UNDER_CE
  1088. return 0;
  1089. #endif //if 0
  1090. }