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.

733 lines
19 KiB

  1. //
  2. // cuiwnd.cpp
  3. //
  4. #include "private.h"
  5. #include "cuitip.h"
  6. #include "cuiobj.h"
  7. #include "cuiutil.h"
  8. // TIMER IDs
  9. #define IDTIMER_TOOLTIP 0x3216
  10. /*=============================================================================*/
  11. /* */
  12. /* C U I F W I N D O W */
  13. /* */
  14. /*=============================================================================*/
  15. /* C U I F W I N D O W */
  16. /*------------------------------------------------------------------------------
  17. Constructor of CUIFWindow
  18. ------------------------------------------------------------------------------*/
  19. CUIFToolTip::CUIFToolTip( HINSTANCE hInst, DWORD dwStyle, CUIFWindow *pWndOwner ) : CUIFWindow( hInst, dwStyle )
  20. {
  21. m_pWndOwner = pWndOwner;
  22. m_pObjCur = NULL;
  23. m_pwchToolTip = NULL;
  24. m_fIgnore = FALSE;
  25. m_iDelayAutoPop = -1;
  26. m_iDelayInitial = -1;
  27. m_iDelayReshow = -1;
  28. m_rcMargin.left = 2;
  29. m_rcMargin.top = 2;
  30. m_rcMargin.right = 2;
  31. m_rcMargin.bottom = 2;
  32. m_iMaxTipWidth = -1;
  33. m_fColBack = FALSE;
  34. m_fColText = FALSE;
  35. m_colBack = RGB( 0, 0, 0 );
  36. m_colText = RGB( 0, 0, 0 );
  37. }
  38. /* ~ C U I F W I N D O W */
  39. /*------------------------------------------------------------------------------
  40. Destructor of CUIFWindow
  41. ------------------------------------------------------------------------------*/
  42. CUIFToolTip::~CUIFToolTip( void )
  43. {
  44. if (m_pWndOwner)
  45. m_pWndOwner->ClearToolTipWnd();
  46. if (m_pwchToolTip != NULL) {
  47. delete m_pwchToolTip;
  48. }
  49. }
  50. /* I N I T I A L I Z E */
  51. /*------------------------------------------------------------------------------
  52. Initialize UI window object
  53. (UIFObject method)
  54. ------------------------------------------------------------------------------*/
  55. CUIFObject *CUIFToolTip::Initialize( void )
  56. {
  57. return CUIFWindow::Initialize();
  58. }
  59. /* P A I N T O B J E C T */
  60. /*------------------------------------------------------------------------------
  61. Paint window object
  62. (UIFObject method)
  63. ------------------------------------------------------------------------------*/
  64. void CUIFToolTip::OnPaint( HDC hDC )
  65. {
  66. HFONT hFontOld = (HFONT)SelectObject( hDC, GetFont() );
  67. int iBkModeOld = SetBkMode( hDC, TRANSPARENT );
  68. COLORREF colTextOld;
  69. HBRUSH hBrush;
  70. RECT rc = GetRectRef();
  71. RECT rcMargin;
  72. RECT rcText;
  73. colTextOld = SetTextColor( hDC, (COLORREF) GetTipTextColor() );
  74. //
  75. hBrush = CreateSolidBrush( (COLORREF) GetTipBkColor() );
  76. if (hBrush)
  77. {
  78. FillRect( hDC, &rc, hBrush );
  79. DeleteObject( hBrush );
  80. }
  81. //
  82. GetMargin( &rcMargin );
  83. rcText.left = rc.left + rcMargin.left;
  84. rcText.top = rc.top + rcMargin.top;
  85. rcText.right = rc.right - rcMargin.right;
  86. rcText.bottom = rc.bottom - rcMargin.bottom;
  87. if (0 < GetMaxTipWidth()) {
  88. CUIDrawText( hDC, m_pwchToolTip, -1, &rcText, DT_LEFT | DT_TOP | DT_WORDBREAK );
  89. }
  90. else {
  91. CUIDrawText( hDC, m_pwchToolTip, -1, &rcText, DT_LEFT | DT_TOP | DT_SINGLELINE );
  92. }
  93. // restore DC
  94. SetTextColor( hDC, colTextOld );
  95. SetBkMode( hDC, iBkModeOld );
  96. SelectObject( hDC, hFontOld );
  97. }
  98. /* O N T I M E R */
  99. /*------------------------------------------------------------------------------
  100. ------------------------------------------------------------------------------*/
  101. void CUIFToolTip::OnTimer( UINT uiTimerID )
  102. {
  103. if (uiTimerID == IDTIMER_TOOLTIP) {
  104. ShowTip();
  105. }
  106. }
  107. /* E N A B L E */
  108. /*------------------------------------------------------------------------------
  109. ------------------------------------------------------------------------------*/
  110. void CUIFToolTip::Enable( BOOL fEnable )
  111. {
  112. if (!fEnable) {
  113. HideTip();
  114. }
  115. CUIFObject::Enable( fEnable );
  116. }
  117. /* G E T D E L A Y T I M E */
  118. /*------------------------------------------------------------------------------
  119. Retrieves the initial, pop-up, and reshow durations currently set for a
  120. tooltip control.
  121. ------------------------------------------------------------------------------*/
  122. LRESULT CUIFToolTip::GetDelayTime( DWORD dwDuration )
  123. {
  124. switch (dwDuration) {
  125. case TTDT_AUTOPOP: {
  126. return ((m_iDelayAutoPop == -1) ? GetDoubleClickTime() * 10 : m_iDelayAutoPop);
  127. }
  128. case TTDT_INITIAL: {
  129. return ((m_iDelayInitial == -1) ? GetDoubleClickTime() : m_iDelayInitial);
  130. }
  131. case TTDT_RESHOW: {
  132. return ((m_iDelayReshow == -1) ? GetDoubleClickTime() / 5 : m_iDelayReshow);
  133. }
  134. }
  135. return 0;
  136. }
  137. /* G E T M A R G I N */
  138. /*------------------------------------------------------------------------------
  139. Retrieves the top, left, bottom, and right margins set for a tooltip window.
  140. A margin is the distance, in pixels, between the tooltip window border and
  141. the text contained within the tooltip window.
  142. ------------------------------------------------------------------------------*/
  143. LRESULT CUIFToolTip::GetMargin( RECT *prc )
  144. {
  145. if (prc == NULL) {
  146. return 0;
  147. }
  148. *prc = m_rcMargin;
  149. return 0;
  150. }
  151. /* G E T M A X T I P W I D T H */
  152. /*------------------------------------------------------------------------------
  153. Retrieves the maximum width for a tooltip window.
  154. ------------------------------------------------------------------------------*/
  155. LRESULT CUIFToolTip::GetMaxTipWidth( void )
  156. {
  157. return m_iMaxTipWidth;
  158. }
  159. /* G E T T I P B K C O L O R */
  160. /*------------------------------------------------------------------------------
  161. Retrieves the background color in a tooltip window.
  162. ------------------------------------------------------------------------------*/
  163. LRESULT CUIFToolTip::GetTipBkColor( void )
  164. {
  165. if (m_fColBack) {
  166. return (LRESULT)m_colBack;
  167. }
  168. else {
  169. return (LRESULT)GetSysColor( COLOR_INFOBK );
  170. }
  171. }
  172. /* G E T T I P T E X T C O L O R */
  173. /*------------------------------------------------------------------------------
  174. Retrieves the text color in a tooltip window.
  175. ------------------------------------------------------------------------------*/
  176. LRESULT CUIFToolTip::GetTipTextColor( void )
  177. {
  178. if (m_fColText) {
  179. return (LRESULT)m_colText;
  180. }
  181. else {
  182. return (LRESULT)GetSysColor( COLOR_INFOTEXT );
  183. }
  184. }
  185. /* R E L A Y E V E N T */
  186. /*------------------------------------------------------------------------------
  187. Passes a mouse message to a tooltip control for processing.
  188. ------------------------------------------------------------------------------*/
  189. LRESULT CUIFToolTip::RelayEvent( MSG *pmsg )
  190. {
  191. if (pmsg == NULL) {
  192. return 0;
  193. }
  194. switch (pmsg->message) {
  195. case WM_MOUSEMOVE: {
  196. CUIFObject *pUIObj;
  197. POINT pt;
  198. // ignore while disabled
  199. if (!IsEnabled()) {
  200. break;
  201. }
  202. // ignore mouse move while mouse down
  203. if ((GetKeyState(VK_LBUTTON) & 0x8000) ||
  204. (GetKeyState(VK_MBUTTON) & 0x8000) ||
  205. (GetKeyState(VK_RBUTTON) & 0x8000)) {
  206. break;
  207. }
  208. // get object from point
  209. POINTSTOPOINT( pt, MAKEPOINTS( pmsg->lParam ) );
  210. pUIObj = FindObject( pmsg->hwnd, pt );
  211. //
  212. if (pUIObj != NULL) {
  213. if (m_pObjCur != pUIObj) {
  214. BOOL fWasVisible = IsVisible();
  215. HideTip();
  216. if (fWasVisible) {
  217. ::SetTimer( GetWnd(), IDTIMER_TOOLTIP, (UINT)GetDelayTime( TTDT_RESHOW ), NULL );
  218. }
  219. else {
  220. ::SetTimer( GetWnd(), IDTIMER_TOOLTIP, (UINT)GetDelayTime( TTDT_INITIAL ), NULL );
  221. }
  222. }
  223. }
  224. else {
  225. HideTip();
  226. }
  227. m_pObjCur = pUIObj;
  228. break;
  229. }
  230. case WM_LBUTTONDOWN:
  231. case WM_RBUTTONDOWN:
  232. case WM_MBUTTONDOWN: {
  233. HideTip();
  234. break;
  235. }
  236. case WM_LBUTTONUP:
  237. case WM_RBUTTONUP:
  238. case WM_MBUTTONUP: {
  239. break;
  240. }
  241. }
  242. return 0;
  243. }
  244. /* P O P */
  245. /*------------------------------------------------------------------------------
  246. Removes a displayed tooltip window from view.
  247. ------------------------------------------------------------------------------*/
  248. LRESULT CUIFToolTip::Pop( void )
  249. {
  250. HideTip();
  251. return 0;
  252. }
  253. /* S E T D E L A Y T I M E */
  254. /*------------------------------------------------------------------------------
  255. Sets the initial, pop-up, and reshow durations for a tooltip control.
  256. ------------------------------------------------------------------------------*/
  257. LRESULT CUIFToolTip::SetDelayTime( DWORD dwDuration, INT iTime )
  258. {
  259. switch (dwDuration) {
  260. case TTDT_AUTOPOP: {
  261. m_iDelayAutoPop = iTime;
  262. break;
  263. }
  264. case TTDT_INITIAL: {
  265. m_iDelayInitial = iTime;
  266. break;
  267. }
  268. case TTDT_RESHOW: {
  269. m_iDelayReshow = iTime;
  270. break;
  271. }
  272. case TTDT_AUTOMATIC: {
  273. if (0 <= iTime) {
  274. m_iDelayAutoPop = iTime * 10;
  275. m_iDelayInitial = iTime;
  276. m_iDelayReshow = iTime / 5;
  277. }
  278. else {
  279. m_iDelayAutoPop = -1;
  280. m_iDelayInitial = -1;
  281. m_iDelayReshow = -1;
  282. }
  283. break;
  284. }
  285. }
  286. return 0;
  287. }
  288. /* S E T M A R G I N */
  289. /*------------------------------------------------------------------------------
  290. Sets the top, left, bottom, and right margins for a tooltip window. A margin
  291. is the distance, in pixels, between the tooltip window border and the text
  292. contained within the tooltip window.
  293. ------------------------------------------------------------------------------*/
  294. LRESULT CUIFToolTip::SetMargin( RECT *prc )
  295. {
  296. if (prc == NULL) {
  297. return 0;
  298. }
  299. m_rcMargin = *prc;
  300. return 0;
  301. }
  302. /* S E T M A X T I P W I D T H */
  303. /*------------------------------------------------------------------------------
  304. Sets the maximum width for a tooltip window.
  305. ------------------------------------------------------------------------------*/
  306. LRESULT CUIFToolTip::SetMaxTipWidth( INT iWidth )
  307. {
  308. m_iMaxTipWidth = iWidth;
  309. return 0;
  310. }
  311. /* S E T T I P B K C O L O R */
  312. /*------------------------------------------------------------------------------
  313. Sets the background color in a tooltip window.
  314. ------------------------------------------------------------------------------*/
  315. LRESULT CUIFToolTip::SetTipBkColor( COLORREF col )
  316. {
  317. m_fColBack = TRUE;
  318. m_colBack = col;
  319. return 0;
  320. }
  321. /* S E T T I P T E X T C O L O R */
  322. /*------------------------------------------------------------------------------
  323. Sets the text color in a tooltip window.
  324. ------------------------------------------------------------------------------*/
  325. LRESULT CUIFToolTip::SetTipTextColor( COLORREF col )
  326. {
  327. m_fColText = TRUE;
  328. m_colText = col;
  329. return 0;
  330. }
  331. /* F I N D O B J E C T */
  332. /*------------------------------------------------------------------------------
  333. ------------------------------------------------------------------------------*/
  334. CUIFObject *CUIFToolTip::FindObject( HWND hWnd, POINT pt )
  335. {
  336. if (hWnd != m_pWndOwner->GetWnd()) {
  337. return NULL;
  338. }
  339. return m_pWndOwner->ObjectFromPoint( pt );
  340. }
  341. /* S H O W T I P */
  342. /*------------------------------------------------------------------------------
  343. ------------------------------------------------------------------------------*/
  344. void CUIFToolTip::ShowTip( void )
  345. {
  346. LPCWSTR pwchToolTip;
  347. SIZE size;
  348. RECT rc;
  349. RECT rcObj;
  350. POINT ptCursor;
  351. ::KillTimer( GetWnd(), IDTIMER_TOOLTIP );
  352. if (m_pObjCur == NULL) {
  353. return;
  354. }
  355. // if object has no tooltip, not open tooltip window
  356. pwchToolTip = m_pObjCur->GetToolTip();
  357. if (pwchToolTip == NULL) {
  358. return;
  359. }
  360. //
  361. // GetToolTip() might delete m_pObjCur. We need to check this again.
  362. //
  363. if (m_pObjCur == NULL) {
  364. return;
  365. }
  366. //
  367. // Start ToolTip notification.
  368. //
  369. if (m_pObjCur->OnShowToolTip())
  370. return;
  371. GetCursorPos( &ptCursor );
  372. ScreenToClient(m_pObjCur->GetUIWnd()->GetWnd(),&ptCursor);
  373. m_pObjCur->GetRect(&rcObj);
  374. if (!PtInRect(&rcObj, ptCursor)) {
  375. return;
  376. }
  377. // store tooltip text
  378. m_pwchToolTip = new WCHAR[ StrLenW(pwchToolTip) + 1 ];
  379. if (!m_pwchToolTip)
  380. return;
  381. StrCpyW( m_pwchToolTip, pwchToolTip );
  382. // calc window size
  383. GetTipWindowSize( &size );
  384. // calc window position
  385. ClientToScreen(m_pObjCur->GetUIWnd()->GetWnd(),(LPPOINT)&rcObj.left);
  386. ClientToScreen(m_pObjCur->GetUIWnd()->GetWnd(),(LPPOINT)&rcObj.right);
  387. GetTipWindowRect( &rc, size, &rcObj);
  388. // show window
  389. m_fBeingShown = TRUE;
  390. Move( rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top );
  391. Show( TRUE );
  392. }
  393. /* H I D E T I P */
  394. /*------------------------------------------------------------------------------
  395. ------------------------------------------------------------------------------*/
  396. void CUIFToolTip::HideTip( void )
  397. {
  398. ::KillTimer( GetWnd(), IDTIMER_TOOLTIP );
  399. m_fBeingShown = FALSE;
  400. //
  401. // Hide ToolTip notification.
  402. //
  403. if (m_pObjCur)
  404. m_pObjCur->OnHideToolTip();
  405. if (!IsVisible()) {
  406. return;
  407. }
  408. // dispose buffer
  409. if (m_pwchToolTip != NULL) {
  410. delete m_pwchToolTip;
  411. m_pwchToolTip = NULL;
  412. }
  413. // hide window
  414. Show( FALSE );
  415. }
  416. /* G E T T I P W I N D O W S I Z E */
  417. /*------------------------------------------------------------------------------
  418. ------------------------------------------------------------------------------*/
  419. void CUIFToolTip::GetTipWindowSize( SIZE *psize )
  420. {
  421. HDC hDC = GetDC( GetWnd() );
  422. HFONT hFontOld;
  423. RECT rcMargin;
  424. RECT rcText;
  425. RECT rc;
  426. int iTipWidth;
  427. int iTipHeight;
  428. Assert( psize != NULL );
  429. if (m_pwchToolTip == NULL) {
  430. return;
  431. }
  432. hFontOld = (HFONT)SelectObject( hDC, GetFont() );
  433. // get text size
  434. iTipWidth = (int)GetMaxTipWidth();
  435. if (0 < iTipWidth) {
  436. rcText.left = 0;
  437. rcText.top = 0;
  438. rcText.right = iTipWidth;
  439. rcText.bottom = 0;
  440. iTipHeight = CUIDrawText( hDC, m_pwchToolTip, -1, &rcText, DT_LEFT | DT_TOP | DT_CALCRECT | DT_WORDBREAK );
  441. rcText.bottom = rcText.top + iTipHeight;
  442. }
  443. else {
  444. rcText.left = 0;
  445. rcText.top = 0;
  446. rcText.right = 0;
  447. rcText.bottom = 0;
  448. iTipHeight = CUIDrawText( hDC, m_pwchToolTip, -1, &rcText, DT_LEFT | DT_TOP | DT_CALCRECT | DT_SINGLELINE );
  449. rcText.bottom = rcText.top + iTipHeight;
  450. }
  451. // add margin size
  452. GetMargin( &rcMargin );
  453. rc.left = rcText.left - rcMargin.left;
  454. rc.top = rcText.top - rcMargin.top;
  455. rc.right = rcText.right + rcMargin.right;
  456. rc.bottom = rcText.bottom + rcMargin.bottom;
  457. // finally get window size
  458. ClientRectToWindowRect( &rc );
  459. psize->cx = (rc.right - rc.left);
  460. psize->cy = (rc.bottom - rc.top);
  461. SelectObject( hDC, hFontOld );
  462. ReleaseDC( GetWnd(), hDC );
  463. }
  464. /* G E T T I P W I N D O W R E C T */
  465. /*------------------------------------------------------------------------------
  466. ------------------------------------------------------------------------------*/
  467. void CUIFToolTip::GetTipWindowRect( RECT *prc, SIZE size, RECT *prcExclude)
  468. {
  469. POINT ptCursor;
  470. POINT ptHotSpot;
  471. SIZE sizeCursor;
  472. HCURSOR hCursor;
  473. ICONINFO IconInfo;
  474. BITMAP bmp;
  475. RECT rcScreen;
  476. Assert( prc != NULL );
  477. // get cursor pos
  478. GetCursorPos( &ptCursor );
  479. // get cursor size
  480. sizeCursor.cx = GetSystemMetrics( SM_CXCURSOR );
  481. sizeCursor.cy = GetSystemMetrics( SM_CYCURSOR );
  482. ptHotSpot.x = 0;
  483. ptHotSpot.y = 0;
  484. hCursor = GetCursor();
  485. if (hCursor != NULL && GetIconInfo( hCursor, &IconInfo )) {
  486. GetObject( IconInfo.hbmMask, sizeof(bmp), &bmp );
  487. if (!IconInfo.fIcon) {
  488. ptHotSpot.x = IconInfo.xHotspot;
  489. ptHotSpot.y = IconInfo.yHotspot;
  490. sizeCursor.cx = bmp.bmWidth;
  491. sizeCursor.cy = bmp.bmHeight;
  492. if (IconInfo.hbmColor == NULL) {
  493. sizeCursor.cy = sizeCursor.cy / 2;
  494. }
  495. }
  496. if (IconInfo.hbmColor != NULL) {
  497. DeleteObject( IconInfo.hbmColor );
  498. }
  499. DeleteObject( IconInfo.hbmMask );
  500. }
  501. // get screen rect
  502. rcScreen.left = 0;
  503. rcScreen.top = 0;
  504. rcScreen.right = GetSystemMetrics( SM_CXSCREEN );
  505. rcScreen.bottom = GetSystemMetrics( SM_CYSCREEN );
  506. if (CUIIsMonitorAPIAvail()) {
  507. HMONITOR hMonitor;
  508. MONITORINFO MonitorInfo;
  509. hMonitor = CUIMonitorFromPoint( ptCursor, MONITOR_DEFAULTTONEAREST );
  510. if (hMonitor != NULL) {
  511. MonitorInfo.cbSize = sizeof(MonitorInfo);
  512. if (CUIGetMonitorInfo( hMonitor, &MonitorInfo )) {
  513. rcScreen = MonitorInfo.rcMonitor;
  514. }
  515. }
  516. }
  517. // try to put it at bellow
  518. prc->left = ptCursor.x;
  519. prc->top = ptCursor.y - ptHotSpot.y + sizeCursor.cy;
  520. prc->right = prc->left + size.cx;
  521. prc->bottom = prc->top + size.cy;
  522. if (rcScreen.bottom < prc->bottom) {
  523. if (ptCursor.y < prcExclude->top)
  524. prc->top = ptCursor.y - size.cy;
  525. else
  526. prc->top = prcExclude->top - size.cy;
  527. prc->bottom = prc->top + size.cy;
  528. }
  529. if (prc->top < rcScreen.top) {
  530. prc->top = rcScreen.top;
  531. prc->bottom = prc->top + size.cy;
  532. }
  533. // check horizontal position
  534. if (rcScreen.right < prc->right) {
  535. prc->left = rcScreen.right - size.cx;
  536. prc->right = prc->left + size.cx;
  537. }
  538. if (prc->left < rcScreen.left) {
  539. prc->left = rcScreen.left;
  540. prc->right = prc->left + size.cx;
  541. }
  542. }