Source code of Windows XP (NT5)
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.

849 lines
20 KiB

  1. /* (C) Copyright Microsoft Corporation 1991-1994. All Rights Reserved */
  2. /******************************Module*Header*******************************\
  3. * Module Name: buttons.c
  4. *
  5. * Bitmap button support. On Daytona bitmap buttons are provided by
  6. * mmcntrls. On Chicago there is no mmcntrls, so we use the functions
  7. * in this file.
  8. *
  9. *
  10. * Created: 19-04-94
  11. * Author: Stephen Estrop [StephenE]
  12. *
  13. \**************************************************************************/
  14. //#pragma warning( once : 4201 4214 )
  15. #define NOOLE
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <commctrl.h>
  19. #include "buttons.h"
  20. /* -------------------------------------------------------------------------
  21. ** Color globals
  22. ** -------------------------------------------------------------------------
  23. */
  24. int nSysColorChanges = 0;
  25. DWORD rgbFace;
  26. DWORD rgbShadow;
  27. DWORD rgbHilight;
  28. DWORD rgbFrame;
  29. extern void
  30. PatB(
  31. HDC hdc,
  32. int x,
  33. int y,
  34. int dx,
  35. int dy,
  36. DWORD rgb
  37. );
  38. #if 0
  39. // also defined in sframe.c!
  40. /*****************************Private*Routine******************************\
  41. * PatB
  42. *
  43. * Fast way to fill an rectangle with a solid colour.
  44. *
  45. * History:
  46. * 18-11-93 - StephenE - Created
  47. *
  48. \**************************************************************************/
  49. void
  50. PatB(
  51. HDC hdc,
  52. int x,
  53. int y,
  54. int dx,
  55. int dy,
  56. DWORD rgb
  57. )
  58. {
  59. RECT rc;
  60. SetBkColor(hdc,rgb);
  61. rc.left = x;
  62. rc.top = y;
  63. rc.right = x + dx;
  64. rc.bottom = y + dy;
  65. ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
  66. }
  67. #endif
  68. /*****************************Private*Routine******************************\
  69. * CheckSysColors
  70. *
  71. * Checks the system colors and updates the cached global variables if
  72. * they have changed.
  73. *
  74. * History:
  75. * 18-11-93 - StephenE - Created
  76. *
  77. \**************************************************************************/
  78. void
  79. CheckSysColors(
  80. void
  81. )
  82. {
  83. static COLORREF rgbSaveFace = 0xffffffffL,
  84. rgbSaveShadow = 0xffffffffL,
  85. rgbSaveHilight = 0xffffffffL,
  86. rgbSaveFrame = 0xffffffffL;
  87. rgbFace = GetSysColor(COLOR_BTNFACE);
  88. rgbShadow = GetSysColor(COLOR_BTNSHADOW);
  89. rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
  90. rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
  91. if (rgbSaveFace!=rgbFace || rgbSaveShadow!=rgbShadow
  92. || rgbSaveHilight!=rgbHilight || rgbSaveFrame!=rgbFrame)
  93. {
  94. ++nSysColorChanges;
  95. rgbSaveFace = rgbFace;
  96. rgbSaveShadow = rgbShadow;
  97. rgbSaveHilight = rgbHilight;
  98. rgbSaveFrame = rgbFrame;
  99. }
  100. }
  101. #if WINVER >= 0x0400
  102. /* -------------------------------------------------------------------------
  103. ** Button globals -- some of these should be constants
  104. ** -------------------------------------------------------------------------
  105. */
  106. const TCHAR szBbmProp[] = TEXT("ButtonBitmapProp");
  107. const TCHAR szButtonProp[] = TEXT("ButtonProp");
  108. typedef struct tagBTNSTATE { /* instance data for toolbar window */
  109. WNDPROC lpfnDefProc;
  110. HWND hwndToolTips;
  111. HINSTANCE hInst;
  112. UINT wID;
  113. UINT uStyle;
  114. HBITMAP hbm;
  115. HDC hdcGlyphs;
  116. HDC hdcMono;
  117. HBITMAP hbmMono;
  118. HBITMAP hbmDefault;
  119. int dxBitmap;
  120. int dyBitmap;
  121. int nButtons;
  122. int nSysColorChanges;
  123. BITMAPBTN Buttons[1];
  124. } BTNSTATE, NEAR *PBTNSTATE, FAR *LPBTNSTATE;
  125. typedef struct {
  126. WNDPROC lpfnDefProc;
  127. HWND hwndParent;
  128. HWND hwndToolTips;
  129. } BTN_INFO, *LPBTN_INFO;
  130. LRESULT CALLBACK
  131. ButtonSubclassProc(
  132. HWND hwnd,
  133. UINT uMsg,
  134. WPARAM wParam,
  135. LPARAM lParam
  136. );
  137. LRESULT CALLBACK
  138. ParentSubclassProc(
  139. HWND hwnd,
  140. UINT uMsg,
  141. WPARAM wParam,
  142. LPARAM lParam
  143. );
  144. void FAR PASCAL
  145. RelayToToolTips(
  146. HWND hwndToolTips,
  147. HWND hWnd,
  148. UINT wMsg,
  149. WPARAM wParam,
  150. LPARAM lParam
  151. );
  152. BOOL
  153. InitObjects(
  154. LPBTNSTATE pTBState
  155. );
  156. BOOL
  157. FreeObjects(
  158. LPBTNSTATE pTBState
  159. );
  160. void
  161. CreateButtonMask(
  162. LPBTNSTATE pTBState,
  163. PBITMAPBTN pTBButton
  164. );
  165. /*****************************Private*Routine******************************\
  166. * InitObjects
  167. *
  168. *
  169. *
  170. * History:
  171. * 18-11-93 - StephenE - Created
  172. *
  173. \**************************************************************************/
  174. BOOL
  175. InitObjects(
  176. LPBTNSTATE pTBState
  177. )
  178. {
  179. pTBState->hdcGlyphs = CreateCompatibleDC(NULL);
  180. if (pTBState->hdcGlyphs == NULL ) {
  181. return FALSE;
  182. }
  183. pTBState->hdcMono = CreateCompatibleDC(NULL);
  184. if (pTBState->hdcMono == NULL ) {
  185. DeleteObject( pTBState->hdcGlyphs );
  186. return FALSE;
  187. }
  188. pTBState->hbmMono = CreateBitmap( pTBState->dxBitmap,
  189. pTBState->dyBitmap, 1, 1, NULL);
  190. if ( pTBState->hbmMono == NULL ) {
  191. DeleteObject( pTBState->hdcGlyphs );
  192. DeleteObject( pTBState->hdcMono );
  193. return FALSE;
  194. }
  195. pTBState->hbmDefault = SelectObject(pTBState->hdcMono, pTBState->hbmMono);
  196. return TRUE;
  197. }
  198. /*****************************Private*Routine******************************\
  199. * FreeObjects
  200. *
  201. *
  202. *
  203. * History:
  204. * 18-11-93 - StephenE - Created
  205. *
  206. \**************************************************************************/
  207. BOOL
  208. FreeObjects(
  209. LPBTNSTATE pTBState
  210. )
  211. {
  212. if (pTBState->hdcMono) {
  213. SelectObject(pTBState->hdcMono, pTBState->hbmDefault);
  214. DeleteDC(pTBState->hdcMono); /* toast the DCs */
  215. }
  216. if (pTBState->hdcGlyphs) {
  217. DeleteDC(pTBState->hdcGlyphs);
  218. }
  219. if (pTBState->hbmMono) {
  220. DeleteObject(pTBState->hbmMono);
  221. }
  222. return TRUE;
  223. }
  224. /*****************************Private*Routine******************************\
  225. * CreateButtonMask
  226. *
  227. * create a mono bitmap mask:
  228. * 1's where color == COLOR_BTNFACE || COLOR_HILIGHT
  229. * 0's everywhere else
  230. *
  231. *
  232. * History:
  233. * 18-11-93 - StephenE - Created
  234. *
  235. \**************************************************************************/
  236. void
  237. CreateButtonMask(
  238. LPBTNSTATE pTBState,
  239. PBITMAPBTN pTBButton
  240. )
  241. {
  242. /* initalize whole area with 0's */
  243. PatBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap,
  244. pTBState->dyBitmap, WHITENESS);
  245. /* create mask based on color bitmap
  246. ** convert this to 1's
  247. */
  248. SetBkColor(pTBState->hdcGlyphs, rgbFace);
  249. BitBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap, pTBState->dyBitmap,
  250. pTBState->hdcGlyphs, pTBButton->iBitmap * pTBState->dxBitmap, 0,
  251. SRCCOPY );
  252. /* convert this to 1's */
  253. SetBkColor(pTBState->hdcGlyphs, rgbHilight);
  254. /* OR in the new 1's */
  255. BitBlt( pTBState->hdcMono, 0, 0, pTBState->dxBitmap, pTBState->dyBitmap,
  256. pTBState->hdcGlyphs, pTBButton->iBitmap * pTBState->dxBitmap, 0,
  257. SRCPAINT );
  258. }
  259. #define PSDPxax 0x00B8074A
  260. /*****************************Private*Routine******************************\
  261. * BtnDrawButton
  262. *
  263. *
  264. *
  265. * History:
  266. * 18-11-93 - StephenE - Created
  267. *
  268. \**************************************************************************/
  269. void WINAPI
  270. BtnDrawButton(
  271. HWND hwnd,
  272. HDC hdc,
  273. int dx,
  274. int dy,
  275. LPBITMAPBTN ptButton
  276. )
  277. {
  278. int glyph_offset;
  279. HBRUSH hbrOld, hbr;
  280. BOOL bMaskCreated = FALSE;
  281. RECT rcFocus;
  282. PBTNSTATE pTBState;
  283. int x = 0, y = 0;
  284. pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
  285. CheckSysColors();
  286. if (pTBState->nSysColorChanges != nSysColorChanges) {
  287. DeleteObject( pTBState->hbm );
  288. pTBState->hbm = CreateMappedBitmap( pTBState->hInst,
  289. pTBState->wID, TRUE, NULL, 0);
  290. pTBState->nSysColorChanges = nSysColorChanges;
  291. }
  292. /*
  293. ** erase with face color
  294. */
  295. PatB(hdc, x, y, dx, dy, rgbFace);
  296. SetRect( &rcFocus, x, y, x + dx, y + dy );
  297. if (ptButton->fsState & BTNSTATE_PRESSED) {
  298. DrawEdge( hdc, &rcFocus, EDGE_SUNKEN, BF_RECT );
  299. glyph_offset = 1;
  300. }
  301. else {
  302. DrawEdge( hdc, &rcFocus, EDGE_RAISED, BF_RECT );
  303. glyph_offset = 0;
  304. }
  305. /*
  306. ** make the coordinates the interior of the button
  307. */
  308. x++;
  309. y++;
  310. dx -= 2;
  311. dy -= 2;
  312. SelectObject( pTBState->hdcGlyphs, pTBState->hbm );
  313. /* now put on the face */
  314. /*
  315. ** We need to centre the Bitmap here within the button
  316. */
  317. x += ((dx - pTBState->dxBitmap ) / 2) - 1;
  318. y += (dy - pTBState->dyBitmap ) / 2;
  319. if (!(ptButton->fsState & BTNSTATE_DISABLED)) {
  320. /* regular version */
  321. BitBlt( hdc, x + glyph_offset, y + glyph_offset,
  322. pTBState->dxBitmap, pTBState->dyBitmap,
  323. pTBState->hdcGlyphs,
  324. ptButton->iBitmap * pTBState->dxBitmap, 0, SRCCOPY);
  325. }
  326. else {
  327. /* disabled version */
  328. bMaskCreated = TRUE;
  329. CreateButtonMask(pTBState, ptButton );
  330. SetTextColor(hdc, 0L); /* 0's in mono -> 0 (for ROP) */
  331. SetBkColor(hdc, 0x00FFFFFF); /* 1's in mono -> 1 */
  332. hbr = CreateSolidBrush(rgbHilight);
  333. if (hbr) {
  334. hbrOld = SelectObject(hdc, hbr);
  335. if (hbrOld) {
  336. /* draw hilight color where we have 0's in the mask */
  337. BitBlt( hdc, x + 1, y + 1,
  338. pTBState->dxBitmap, pTBState->dyBitmap,
  339. pTBState->hdcMono, 0, 0, PSDPxax);
  340. SelectObject(hdc, hbrOld);
  341. }
  342. DeleteObject(hbr);
  343. }
  344. hbr = CreateSolidBrush(rgbShadow);
  345. if (hbr) {
  346. hbrOld = SelectObject(hdc, hbr);
  347. if (hbrOld) {
  348. /* draw the shadow color where we have 0's in the mask */
  349. BitBlt(hdc, x, y, pTBState->dxBitmap, pTBState->dyBitmap,
  350. pTBState->hdcMono, 0, 0, PSDPxax);
  351. SelectObject(hdc, hbrOld);
  352. }
  353. DeleteObject(hbr);
  354. }
  355. }
  356. if (ptButton->fsState & ODS_FOCUS) {
  357. BtnDrawFocusRect(hdc, &rcFocus, ptButton->fsState);
  358. }
  359. }
  360. /*****************************Private*Routine******************************\
  361. * BtnCreateBitmapButtons
  362. *
  363. * Returns TRUE if successful, otherwise FALSE;
  364. *
  365. * History:
  366. * 18-11-93 - StephenE - Created
  367. *
  368. \**************************************************************************/
  369. BOOL WINAPI
  370. BtnCreateBitmapButtons(
  371. HWND hWnd,
  372. HINSTANCE hInst,
  373. UINT wID,
  374. UINT uStyle,
  375. LPBITMAPBTN lpButtons,
  376. int nButtons,
  377. int dxBitmap,
  378. int dyBitmap
  379. )
  380. {
  381. PBTNSTATE pTBState;
  382. /*
  383. ** If we have already created Bitmap Buttons for this
  384. ** window just return.
  385. */
  386. if (GetProp(hWnd, szBbmProp)) {
  387. return TRUE;
  388. }
  389. // InitGlobalMetrics();
  390. // InitToolTipsClass( hInst );
  391. CheckSysColors();
  392. /*
  393. ** Allocate the required storage and save the pointer in the window
  394. ** property list.
  395. */
  396. pTBState = (PBTNSTATE)GlobalAllocPtr( GHND,
  397. (sizeof(BTNSTATE) - sizeof(BITMAPBTN)) +
  398. (nButtons * sizeof(BITMAPBTN)) );
  399. if (pTBState == NULL ) {
  400. return FALSE;
  401. }
  402. SetProp(hWnd, szBbmProp, (HANDLE)pTBState);
  403. pTBState->hInst = hInst;
  404. pTBState->wID = wID;
  405. pTBState->uStyle = uStyle;
  406. pTBState->nButtons = nButtons;
  407. pTBState->hbm = CreateMappedBitmap( hInst, wID, TRUE, NULL, 0);
  408. pTBState->dxBitmap = dxBitmap;
  409. pTBState->dyBitmap = dyBitmap;
  410. InitObjects( pTBState );
  411. CopyMemory( pTBState->Buttons, lpButtons, nButtons * sizeof(BITMAPBTN) );
  412. /*
  413. ** Does the caller want tool tips ?
  414. */
  415. if (pTBState->uStyle & BBS_TOOLTIPS) {
  416. extern BOOL gfIsRTL;
  417. pTBState->hwndToolTips = CreateWindowEx(
  418. gfIsRTL ? WS_EX_LEFTSCROLLBAR | WS_EX_RIGHT | WS_EX_RTLREADING : 0,
  419. TOOLTIPS_CLASS, TEXT(""),
  420. WS_POPUP,
  421. CW_USEDEFAULT, CW_USEDEFAULT,
  422. CW_USEDEFAULT, CW_USEDEFAULT,
  423. hWnd, NULL, hInst, NULL);
  424. if (pTBState->hwndToolTips != (HWND)NULL ) {
  425. int i;
  426. TOOLINFO ti;
  427. pTBState->lpfnDefProc = SubclassWindow( hWnd, ParentSubclassProc );
  428. ti.uFlags = 0;
  429. ti.cbSize = sizeof(ti);
  430. ti.lpszText = LPSTR_TEXTCALLBACK;
  431. for ( i = 0; i < nButtons; i++ ) {
  432. LPBTN_INFO lpBtnInfo;
  433. HWND hwndBtn;
  434. hwndBtn = GetDlgItem(hWnd, pTBState->Buttons[i].uId);
  435. if ( hwndBtn == (HWND)NULL ) {
  436. break;
  437. }
  438. lpBtnInfo = (LPBTN_INFO)GlobalAllocPtr(GHND, sizeof(BTN_INFO));
  439. if (lpBtnInfo == NULL ) {
  440. break;
  441. }
  442. SetProp(hwndBtn, szButtonProp, (HANDLE)lpBtnInfo);
  443. lpBtnInfo->hwndToolTips = pTBState->hwndToolTips;
  444. lpBtnInfo->hwndParent = hWnd;
  445. lpBtnInfo->lpfnDefProc = SubclassWindow( hwndBtn,
  446. ButtonSubclassProc );
  447. ti.hwnd = hwndBtn;
  448. ti.uId = pTBState->Buttons[i].uId;
  449. GetClientRect( hwndBtn, &ti.rect );
  450. SendMessage( lpBtnInfo->hwndToolTips, TTM_ADDTOOL,
  451. (WPARAM)0, (LPARAM)&ti );
  452. /*
  453. ** Add the same rectange in parent co-ordinates so that
  454. ** the tooltip still gets displayed even though the button
  455. ** is disbaled.
  456. */
  457. MapWindowRect( hwndBtn, hWnd, &ti.rect );
  458. ti.hwnd = hWnd;
  459. SendMessage( lpBtnInfo->hwndToolTips, TTM_ADDTOOL,
  460. (WPARAM)0, (LPARAM)&ti );
  461. }
  462. }
  463. else {
  464. /*
  465. ** No tips available, just remove the BBS_TOOLTIPS style
  466. */
  467. pTBState->uStyle &= ~BBS_TOOLTIPS;
  468. }
  469. }
  470. return TRUE;
  471. }
  472. /******************************Public*Routine******************************\
  473. * BtnDestroyBitmapButtons
  474. *
  475. *
  476. *
  477. * History:
  478. * dd-mm-94 - StephenE - Created
  479. *
  480. \**************************************************************************/
  481. void WINAPI
  482. BtnDestroyBitmapButtons(
  483. HWND hwnd
  484. )
  485. {
  486. PBTNSTATE pTBState;
  487. pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
  488. if ( pTBState != NULL ) {
  489. if (pTBState->hbm)
  490. DeleteObject( pTBState->hbm );
  491. FreeObjects( pTBState );
  492. GlobalFreePtr( pTBState );
  493. }
  494. RemoveProp(hwnd, szBbmProp);
  495. }
  496. /******************************Public*Routine******************************\
  497. * BtnDrawFocusRect
  498. *
  499. * Use this function to draw focus rectangle around a bitmap button.
  500. *
  501. * History:
  502. * 18-11-93 - StephenE - Created
  503. *
  504. \**************************************************************************/
  505. void WINAPI
  506. BtnDrawFocusRect(
  507. HDC hdc,
  508. const RECT *lpRect,
  509. UINT fsState
  510. )
  511. {
  512. int iFaceOffset;
  513. RECT rc;
  514. CopyRect( &rc, lpRect );
  515. rc.top = rc.left = 3;
  516. if (fsState & ODS_SELECTED) {
  517. iFaceOffset = 2;
  518. }
  519. else {
  520. iFaceOffset = 4;
  521. }
  522. rc.right -= iFaceOffset;
  523. rc.bottom -= iFaceOffset;
  524. SetBkColor( hdc, rgbFace );
  525. DrawFocusRect( hdc, &rc );
  526. }
  527. /******************************Public*Routine******************************\
  528. * BtnUpdateColors
  529. *
  530. * After a WM_SYSCOLORCHANGE message is received this function should be
  531. * called to update the colors of the button bitmaps.
  532. *
  533. * History:
  534. * 18-11-93 - StephenE - Created
  535. *
  536. \**************************************************************************/
  537. void WINAPI
  538. BtnUpdateColors(
  539. HWND hwnd
  540. )
  541. {
  542. PBTNSTATE pTBState;
  543. pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
  544. if (pTBState->nSysColorChanges != nSysColorChanges)
  545. {
  546. DeleteObject( pTBState->hbm );
  547. pTBState->hbm = CreateMappedBitmap( pTBState->hInst,
  548. pTBState->wID, TRUE, NULL, 0);
  549. pTBState->nSysColorChanges = nSysColorChanges;
  550. }
  551. }
  552. /******************************Public*Routine******************************\
  553. * ButtonSubclassProc
  554. *
  555. *
  556. *
  557. * History:
  558. * dd-mm-94 - StephenE - Created
  559. *
  560. \**************************************************************************/
  561. LRESULT CALLBACK
  562. ButtonSubclassProc(
  563. HWND hwnd,
  564. UINT uMsg,
  565. WPARAM wParam,
  566. LPARAM lParam
  567. )
  568. {
  569. LPBTN_INFO lpBtnInfo;
  570. WNDPROC lpfnDefProc;
  571. lpBtnInfo = (LPBTN_INFO)GetProp( hwnd, szButtonProp );
  572. /*
  573. ** Save this in case anything happens to lpBtnInfo before we return.
  574. */
  575. lpfnDefProc = lpBtnInfo->lpfnDefProc;
  576. switch ( uMsg ) {
  577. case WM_DESTROY:
  578. SubclassWindow( hwnd, lpfnDefProc );
  579. if (lpBtnInfo) {
  580. GlobalFreePtr(lpBtnInfo);
  581. RemoveProp(hwnd, szButtonProp);
  582. }
  583. break;
  584. case WM_LBUTTONDOWN:
  585. case WM_LBUTTONUP:
  586. case WM_RBUTTONDOWN:
  587. case WM_RBUTTONUP:
  588. case WM_MBUTTONDOWN:
  589. case WM_MBUTTONUP:
  590. case WM_MOUSEMOVE:
  591. RelayToToolTips( lpBtnInfo->hwndToolTips, hwnd, uMsg, wParam, lParam );
  592. break;
  593. #if WINVER < 0x0400
  594. case WM_WININICHANGE:
  595. InitGlobalMetrics();
  596. break;
  597. #endif
  598. case WM_MOVE:
  599. {
  600. TOOLINFO ti;
  601. ti.cbSize = sizeof(ti);
  602. ti.uFlags = 0;
  603. ti.hwnd = hwnd;
  604. ti.lpszText = LPSTR_TEXTCALLBACK;
  605. ti.uId = GetDlgCtrlID( hwnd );
  606. GetClientRect( hwnd, &ti.rect );
  607. SendMessage( lpBtnInfo->hwndToolTips, TTM_NEWTOOLRECT, 0,
  608. (LPARAM)&ti );
  609. /*
  610. ** Add the same rectange in parent co-ordinates so that
  611. ** the tooltip still gets displayed even though the button
  612. ** is disbaled.
  613. */
  614. MapWindowRect( hwnd, lpBtnInfo->hwndParent, &ti.rect );
  615. ti.hwnd = lpBtnInfo->hwndParent;
  616. SendMessage( lpBtnInfo->hwndToolTips, TTM_NEWTOOLRECT,
  617. (WPARAM)0, (LPARAM)&ti );
  618. }
  619. break;
  620. case WM_NOTIFY:
  621. SendMessage(lpBtnInfo->hwndParent, WM_NOTIFY, wParam, lParam);
  622. break;
  623. }
  624. return CallWindowProc(lpfnDefProc, hwnd, uMsg, wParam, lParam);
  625. }
  626. /******************************Public*Routine******************************\
  627. * ParentSubclassProc
  628. *
  629. * Why do I need to subclass the buttons parent window ? Well,
  630. * if a button is disable it will not receive mouse messages, the
  631. * messages go to the window underneath the button (ie. the parent).
  632. * Therefore we detect this and relay the mouse message to the tool tips
  633. * window as above.
  634. *
  635. * History:
  636. * dd-mm-94 - StephenE - Created
  637. *
  638. \**************************************************************************/
  639. LRESULT CALLBACK
  640. ParentSubclassProc(
  641. HWND hwnd,
  642. UINT uMsg,
  643. WPARAM wParam,
  644. LPARAM lParam
  645. )
  646. {
  647. WNDPROC lpfnDefProc;
  648. PBTNSTATE pTBState;
  649. pTBState = (PBTNSTATE)GetProp(hwnd, szBbmProp);
  650. /*
  651. ** Save this in case anything happens to lpBtnInfo before we return.
  652. */
  653. lpfnDefProc = pTBState->lpfnDefProc;
  654. switch ( uMsg ) {
  655. #if WINVER < 0x0400
  656. case TB_ACTIVATE_TOOLTIPS:
  657. SendMessage( pTBState->hwndToolTips, TTM_ACTIVATE, wParam, 0L );
  658. break;
  659. #endif
  660. case WM_LBUTTONDOWN:
  661. case WM_LBUTTONUP:
  662. case WM_RBUTTONDOWN:
  663. case WM_RBUTTONUP:
  664. case WM_MBUTTONDOWN:
  665. case WM_MBUTTONUP:
  666. case WM_MOUSEMOVE:
  667. RelayToToolTips( pTBState->hwndToolTips, hwnd, uMsg, wParam, lParam );
  668. break;
  669. case WM_DESTROY :
  670. {
  671. SubclassWindow( hwnd, lpfnDefProc );
  672. BtnDestroyBitmapButtons(hwnd);
  673. }
  674. break;
  675. }
  676. return CallWindowProc(lpfnDefProc, hwnd, uMsg, wParam, lParam);
  677. }
  678. /******************************Public*Routine******************************\
  679. * RelayToToolTips
  680. *
  681. *
  682. *
  683. * History:
  684. * dd-mm-94 - StephenE - Created
  685. *
  686. \**************************************************************************/
  687. void FAR PASCAL
  688. RelayToToolTips(
  689. HWND hwndToolTips,
  690. HWND hWnd,
  691. UINT wMsg,
  692. WPARAM wParam,
  693. LPARAM lParam
  694. )
  695. {
  696. if(hwndToolTips) {
  697. MSG msg;
  698. msg.lParam = lParam;
  699. msg.wParam = wParam;
  700. msg.message = wMsg;
  701. msg.hwnd = hWnd;
  702. SendMessage(hwndToolTips, TTM_RELAYEVENT, 0, (LPARAM)(LPMSG)&msg);
  703. }
  704. }
  705. #endif