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.

763 lines
21 KiB

  1. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MBUTTON.CPP
  4. //
  5. // Multimedia Button Control class; helper functions
  6. //
  7. // Copyright (c) Microsoft Corporation 1997
  8. //
  9. // 12/14/97 David Stewart / dstewart
  10. //
  11. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  12. #include "mbutton.h"
  13. #include <windowsx.h> //for GetWindowFont
  14. #include <winuser.h> //for TrackMouseEvent
  15. #include <commctrl.h> //for WM_MOUSELEAVE
  16. #include <TCHAR.H>
  17. #include "resource.h"
  18. #include "dib.h"
  19. #include "mmfw.h"
  20. //file-local default values for buttons
  21. #define NUM_STATES 3
  22. #define STATE_UP 0
  23. #define STATE_DN 1
  24. #define STATE_HI 2
  25. #define BOFF_STANDARDLEFT 0
  26. #define BOFF_TOGGLELEFT 1
  27. #define BOFF_STANDARDRIGHT 2
  28. #define BOFF_DROPRIGHT 3
  29. #define BOFF_TOGGLERIGHT 4
  30. #define BOFF_MIDDLE 5
  31. #define BOFF_SYSTEM 6
  32. #define BOFF_MINIMIZE 7
  33. #define BOFF_RESTORE 8
  34. #define BOFF_MAXIMIZE 9
  35. #define BOFF_CLOSE 10
  36. #define BOFF_MUTE 11
  37. #define BOFF_END 12
  38. #define BUTTON_BITMAP_HEIGHT 19
  39. #define BUTTON_FONT_SIZE 8
  40. #define BUTTON_DBCS_FONT_SIZE 9
  41. #define BUTTON_FONT_WEIGHT FW_BOLD
  42. #define MBUTTON_TEXT_COLOR RGB(0xFF,0xFF,0xFF)
  43. HFONT hFont = NULL;
  44. HANDLE hbmpButtonToolkit = NULL;
  45. int nStateOffset = 0;
  46. int nButtonOffsets[BOFF_END+1];
  47. extern HPALETTE hpalMain;
  48. extern int g_nColorMode;
  49. CMButton* pButtonFocus = NULL;
  50. CMButton* pButtonMouse = NULL;
  51. BOOL fAllowFocus = TRUE;
  52. //for this to work on a Win95 machine, we need to make TrackMouseEvent
  53. //a dynamically loaded thing ... but then you get NO HOVER-OVER EFFECT
  54. typedef BOOL (PASCAL *TRACKPROC)(LPTRACKMOUSEEVENT);
  55. TRACKPROC procTrackMouseEvent = NULL;
  56. BOOL InitMButtons(HINSTANCE hInst, HWND hwnd)
  57. {
  58. BOOL fReturn = TRUE;
  59. //if TrackMouseEvent exists, use it
  60. HMODULE hUser = GetModuleHandle(TEXT("USER32"));
  61. if (hUser)
  62. {
  63. procTrackMouseEvent = (TRACKPROC)GetProcAddress(hUser,"TrackMouseEvent");
  64. }
  65. //create font, named store in IDS_MBUTTON_FONT in string table
  66. LOGFONT lf;
  67. ZeroMemory( &lf, sizeof(lf) );
  68. HFONT hTempFont = GetWindowFont( hwnd );
  69. if (hTempFont == NULL)
  70. {
  71. hTempFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  72. }
  73. GetObject(hTempFont,sizeof(lf),&lf);
  74. lf.lfHeight = (-BUTTON_FONT_SIZE * STANDARD_PIXELS_PER_INCH) / 72;
  75. if (lf.lfCharSet == ANSI_CHARSET)
  76. {
  77. lf.lfWeight = BUTTON_FONT_WEIGHT;
  78. }
  79. else if (IS_DBCS_CHARSET(lf.lfCharSet)) {
  80. lf.lfHeight = (-BUTTON_DBCS_FONT_SIZE * STANDARD_PIXELS_PER_INCH) / 72;
  81. }
  82. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  83. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  84. lf.lfQuality = PROOF_QUALITY;
  85. lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
  86. LoadString(hInst,IDS_MBUTTON_FONT,lf.lfFaceName,LF_FACESIZE-1);
  87. hFont = CreateFontIndirect(&lf);
  88. //create bitmap, has all states for all buttons
  89. int nBitmap = IDB_BUTTON_TOOLKIT;
  90. switch (g_nColorMode)
  91. {
  92. case COLOR_16 : nBitmap = IDB_BUTTON_TOOLKIT_16; break;
  93. case COLOR_HICONTRAST : nBitmap = IDB_BUTTON_TOOLKIT_HI; break;
  94. }
  95. HBITMAP hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
  96. hbmpButtonToolkit = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
  97. BITMAP bm;
  98. GetObject(hbmpTemp,sizeof(bm),&bm);
  99. DeleteObject(hbmpTemp);
  100. nStateOffset = bm.bmWidth / NUM_STATES;
  101. //offsets within bitmap
  102. nButtonOffsets[BOFF_STANDARDLEFT] = 0;
  103. nButtonOffsets[BOFF_TOGGLELEFT] = 9;
  104. nButtonOffsets[BOFF_STANDARDRIGHT] = 11;
  105. nButtonOffsets[BOFF_DROPRIGHT] = 20;
  106. nButtonOffsets[BOFF_TOGGLERIGHT] = 42;
  107. nButtonOffsets[BOFF_MIDDLE] = 44;
  108. nButtonOffsets[BOFF_SYSTEM] = 52;
  109. nButtonOffsets[BOFF_MINIMIZE] = 64;
  110. nButtonOffsets[BOFF_RESTORE] = 78;
  111. nButtonOffsets[BOFF_MAXIMIZE] = 92;
  112. nButtonOffsets[BOFF_CLOSE] = 106;
  113. nButtonOffsets[BOFF_MUTE] = 121;
  114. nButtonOffsets[BOFF_END] = nStateOffset;
  115. //SetDibUsage(hbmpButtonToolkit,hpalMain,DIB_RGB_COLORS);
  116. return (fReturn);
  117. }
  118. void UninitMButtons()
  119. {
  120. GlobalFree(hbmpButtonToolkit);
  121. DeleteObject(hFont);
  122. }
  123. //Given a parent window and a control ID, return the CMButton object
  124. CMButton* GetMButtonFromID(HWND hwndParent, int nID)
  125. {
  126. HWND hwnd = GetDlgItem(hwndParent, nID);
  127. return (GetMButtonFromHWND(hwnd));
  128. }
  129. //Given the window handle of the button, return the CMButton object
  130. CMButton* GetMButtonFromHWND(HWND hwnd)
  131. {
  132. CMButton* pButton = (CMButton*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  133. return (pButton);
  134. }
  135. CMButton* CreateMButton(TCHAR* szCaption, int nIconID, DWORD dwWindowStyle, DWORD dwMButtonStyle, int x, int y, int width, int height, HWND hwndParentOrSub, BOOL fSubExisting, int nID, int nToolTipID, HINSTANCE hInst)
  136. {
  137. CMButton* pButton = new CMButton;
  138. //ensure the button is a child, pushbutton, owner-draw
  139. //caller should specify WS_VISIBLE|WS_TABSTOP if desired
  140. dwWindowStyle = dwWindowStyle|WS_CHILD|BS_PUSHBUTTON|BS_OWNERDRAW;
  141. HWND hwnd;
  142. if (fSubExisting)
  143. {
  144. //user already created button, is probably calling from WM_INITDIALOG
  145. hwnd = hwndParentOrSub;
  146. }
  147. else
  148. {
  149. //need to create the button ourselves
  150. hwnd = CreateWindow(TEXT("BUTTON"),
  151. szCaption,
  152. dwWindowStyle,
  153. x,
  154. y,
  155. width,
  156. height,
  157. hwndParentOrSub,
  158. (HMENU)nID,
  159. hInst,
  160. NULL);
  161. }
  162. if (hwnd == NULL)
  163. {
  164. //if we can't create the window, nuke it and fail
  165. delete pButton;
  166. return NULL;
  167. }
  168. pButton->m_hInst = hInst;
  169. pButton->m_fRedraw = FALSE;
  170. pButton->m_dwStyle = dwMButtonStyle;
  171. pButton->m_hwnd = hwnd;
  172. pButton->SetIcon(nIconID);
  173. pButton->SetFont(hFont);
  174. pButton->m_fRedraw = TRUE;
  175. pButton->m_nID = nID;
  176. pButton->m_nToolTipID = nToolTipID;
  177. pButton->PreDrawUpstate(width,height);
  178. //subclass the button; allows tracking of mouse events
  179. pButton->m_fnOldButton = (WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)CMButton::ButtonProc);
  180. //put the button's pointer into the window's user bytes
  181. SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)pButton);
  182. return (pButton);
  183. }
  184. void CMButton::PreDrawUpstate(int width, int height)
  185. {
  186. //pre-draw the up states of the buttons for a faster-seeming first blit
  187. if (m_hbmpUp) DeleteObject(m_hbmpUp);
  188. if (m_hbmpDn) DeleteObject(m_hbmpDn);
  189. if (m_hbmpHi) DeleteObject(m_hbmpHi);
  190. m_hbmpUp = NULL;
  191. m_hbmpDn = NULL;
  192. m_hbmpHi = NULL;
  193. DRAWITEMSTRUCT drawItem;
  194. drawItem.rcItem.left = 0;
  195. drawItem.rcItem.top = 0;
  196. drawItem.rcItem.right = width;
  197. drawItem.rcItem.bottom = height;
  198. drawItem.itemState = 0;
  199. drawItem.hDC = GetDC(m_hwnd);
  200. HPALETTE hpalOld = SelectPalette(drawItem.hDC,hpalMain,FALSE);
  201. RealizePalette(drawItem.hDC);
  202. DrawButtonBitmap(&drawItem,FALSE,NULL);
  203. SelectPalette(drawItem.hDC,hpalOld,TRUE);
  204. RealizePalette(drawItem.hDC);
  205. ReleaseDC(m_hwnd,drawItem.hDC);
  206. }
  207. LRESULT CALLBACK CMButton::ButtonProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  208. {
  209. CMButton* pButton = (CMButton*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  210. if (pButton == NULL)
  211. {
  212. return (0);
  213. }
  214. switch (iMsg)
  215. {
  216. case WM_MOUSEMOVE :
  217. {
  218. if (!pButton->m_fMouseInButton)
  219. {
  220. if (procTrackMouseEvent)
  221. {
  222. //only do this if the trackmouseevent function exists,
  223. //otherwise, the button color will never turn off
  224. pButton->m_fMouseInButton = TRUE;
  225. TRACKMOUSEEVENT tme;
  226. tme.cbSize = sizeof(tme);
  227. tme.dwFlags = TME_LEAVE;
  228. tme.dwHoverTime = HOVER_DEFAULT;
  229. tme.hwndTrack = hwnd;
  230. procTrackMouseEvent(&tme);
  231. InvalidateRect(hwnd,NULL,FALSE);
  232. } //end proctrackmouseevent is valid
  233. }
  234. }
  235. break;
  236. case WM_KEYUP :
  237. {
  238. //for the close, min, and view buttons, we want to shunt
  239. //any keyboard movement to the knob ... although tempting,
  240. //don't do this on the setfocus, or the mouse won't work right
  241. if (
  242. (pButton->m_nID == IDB_CLOSE) ||
  243. (pButton->m_nID == IDB_MINIMIZE) ||
  244. (pButton->m_nID == IDB_SET_TINY_MODE) ||
  245. (pButton->m_nID == IDB_SET_NORMAL_MODE)
  246. )
  247. {
  248. HWND hwndFocus = GetDlgItem(GetParent(hwnd),IDB_VOLUME);
  249. if (IsWindowVisible(hwndFocus))
  250. {
  251. SetFocus(hwndFocus);
  252. }
  253. else
  254. {
  255. hwndFocus = GetDlgItem(GetParent(hwnd),IDB_OPTIONS);
  256. SetFocus(hwndFocus);
  257. }
  258. } //end if
  259. }
  260. break;
  261. case WM_SETFOCUS :
  262. {
  263. SendMessage(GetParent(pButton->m_hwnd),DM_SETDEFID,pButton->m_nID,0);
  264. }
  265. break;
  266. case WM_MOUSELEAVE :
  267. {
  268. pButton->m_fMouseInButton = FALSE;
  269. InvalidateRect(hwnd,NULL,FALSE);
  270. }
  271. break;
  272. case WM_ERASEBKGND :
  273. {
  274. DRAWITEMSTRUCT drawItem;
  275. drawItem.hDC = (HDC)wParam;
  276. GetClientRect(hwnd,&(drawItem.rcItem));
  277. drawItem.itemState = pButton->m_LastState;
  278. pButton->Draw(&drawItem);
  279. return TRUE;
  280. }
  281. break;
  282. } //end switch
  283. LRESULT lResult = CallWindowProc((WNDPROC)pButton->m_fnOldButton,hwnd,iMsg,wParam,lParam);
  284. if ((iMsg == WM_DESTROY) && ((pButton->m_dwStyle & MBS_NOAUTODELETE) == 0))
  285. {
  286. //auto-delete the button class
  287. SetWindowLongPtr(hwnd,GWLP_USERDATA,0);
  288. delete pButton;
  289. pButton = NULL;
  290. }
  291. return (lResult);
  292. }
  293. CMButton::CMButton()
  294. {
  295. //init all data values
  296. m_fMouseInButton = FALSE;
  297. m_dwStyle = MBS_STANDARDLEFT | MBS_STANDARDRIGHT;
  298. m_hFont = hFont;
  299. m_nID = 0;
  300. m_IconID = 0;
  301. m_hwnd = NULL;
  302. m_hbmpUp = NULL;
  303. m_hbmpDn = NULL;
  304. m_hbmpHi = NULL;
  305. m_fRedraw = FALSE;
  306. m_fMenu = FALSE;
  307. m_fMenuingOff = FALSE;
  308. m_LastState = 0;
  309. }
  310. CMButton::~CMButton()
  311. {
  312. if (m_hbmpUp) DeleteObject(m_hbmpUp);
  313. if (m_hbmpDn) DeleteObject(m_hbmpDn);
  314. if (m_hbmpHi) DeleteObject(m_hbmpHi);
  315. }
  316. void CMButton::SetText(TCHAR* szCaption)
  317. {
  318. SetWindowText(m_hwnd,szCaption);
  319. if (m_fRedraw)
  320. {
  321. InvalidateRect(m_hwnd,NULL,FALSE);
  322. }
  323. }
  324. void CMButton::SetIcon(int nIconID)
  325. {
  326. //assuming caller is responsible for cleaning up
  327. m_IconID = nIconID;
  328. if (m_fRedraw)
  329. {
  330. InvalidateRect(m_hwnd,NULL,FALSE);
  331. }
  332. }
  333. void CMButton::SetFont(HFONT hFont)
  334. {
  335. //assume caller is responsible for cleaning up
  336. m_hFont = hFont;
  337. }
  338. void CMButton::DrawButtonBitmap(LPDRAWITEMSTRUCT lpdis, BOOL fDrawToScreen, RECT* pMidRect)
  339. {
  340. HANDLE hTemp = m_hbmpUp;
  341. int nState = STATE_UP;
  342. if (m_fMouseInButton)
  343. {
  344. pButtonMouse = this;
  345. hTemp = m_hbmpHi;
  346. nState = STATE_HI;
  347. if (pButtonFocus!=NULL)
  348. {
  349. fAllowFocus = FALSE;
  350. if (this != pButtonFocus)
  351. {
  352. InvalidateRect(pButtonFocus->GetHWND(),NULL,FALSE);
  353. UpdateWindow(pButtonFocus->GetHWND());
  354. }
  355. }
  356. }
  357. else
  358. {
  359. if (lpdis->itemState & ODS_FOCUS)
  360. {
  361. if (this == pButtonFocus)
  362. {
  363. if (fAllowFocus)
  364. {
  365. hTemp = m_hbmpHi;
  366. nState = STATE_HI;
  367. }
  368. else
  369. {
  370. hTemp = m_hbmpUp;
  371. nState = STATE_UP;
  372. }
  373. }
  374. else
  375. {
  376. pButtonFocus = this;
  377. hTemp = m_hbmpHi;
  378. nState = STATE_HI;
  379. fAllowFocus = TRUE;
  380. if ((pButtonMouse!=NULL) && (pButtonMouse!=this))
  381. {
  382. pButtonMouse->m_fMouseInButton = FALSE;
  383. InvalidateRect(pButtonMouse->GetHWND(),NULL,FALSE);
  384. UpdateWindow(pButtonMouse->GetHWND());
  385. pButtonMouse = NULL;
  386. } //end if removing mouse highlight
  387. }
  388. }
  389. } //end if mouse in or out of button
  390. if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
  391. {
  392. hTemp = m_hbmpDn;
  393. nState = STATE_DN;
  394. }
  395. int offLeft, widLeft;
  396. int offRight, widRight;
  397. int offMid, widMid;
  398. offLeft = nButtonOffsets[BOFF_STANDARDLEFT] + (nState * nStateOffset);
  399. widLeft = nButtonOffsets[BOFF_STANDARDLEFT+1] - nButtonOffsets[BOFF_STANDARDLEFT];
  400. if ((m_dwStyle & MBS_TOGGLELEFT) == MBS_TOGGLELEFT)
  401. {
  402. offLeft = nButtonOffsets[BOFF_TOGGLELEFT] + (nState * nStateOffset);
  403. widLeft = nButtonOffsets[BOFF_TOGGLELEFT+1] - nButtonOffsets[BOFF_TOGGLELEFT];
  404. }
  405. if ((m_dwStyle & MBS_SYSTEMTYPE) == MBS_SYSTEMTYPE)
  406. {
  407. switch (m_IconID)
  408. {
  409. case IDB_CLOSE :
  410. {
  411. offLeft = nButtonOffsets[BOFF_CLOSE] + (nState * nStateOffset);
  412. widLeft = nButtonOffsets[BOFF_CLOSE+1] - nButtonOffsets[BOFF_CLOSE];
  413. }
  414. break;
  415. case IDB_MINIMIZE :
  416. {
  417. offLeft = nButtonOffsets[BOFF_MINIMIZE] + (nState * nStateOffset);
  418. widLeft = nButtonOffsets[BOFF_MINIMIZE+1] - nButtonOffsets[BOFF_MINIMIZE];
  419. }
  420. break;
  421. case IDB_SET_TINY_MODE :
  422. {
  423. offLeft = nButtonOffsets[BOFF_RESTORE] + (nState * nStateOffset);
  424. widLeft = nButtonOffsets[BOFF_RESTORE+1] - nButtonOffsets[BOFF_RESTORE];
  425. }
  426. break;
  427. case IDB_SET_NORMAL_MODE :
  428. {
  429. offLeft = nButtonOffsets[BOFF_MAXIMIZE] + (nState * nStateOffset);
  430. widLeft = nButtonOffsets[BOFF_MAXIMIZE+1] - nButtonOffsets[BOFF_MAXIMIZE];
  431. }
  432. break;
  433. case IDB_MUTE :
  434. {
  435. offLeft = nButtonOffsets[BOFF_MUTE] + (nState * nStateOffset);
  436. widLeft = nButtonOffsets[BOFF_MUTE+1] - nButtonOffsets[BOFF_MUTE];
  437. }
  438. }
  439. }
  440. offRight = nButtonOffsets[BOFF_STANDARDRIGHT] + (nState * nStateOffset);
  441. widRight = nButtonOffsets[BOFF_STANDARDRIGHT+1] - nButtonOffsets[BOFF_STANDARDRIGHT];
  442. if ((m_dwStyle & MBS_TOGGLERIGHT) == MBS_TOGGLERIGHT)
  443. {
  444. offRight = nButtonOffsets[BOFF_TOGGLERIGHT] + (nState * nStateOffset);
  445. widRight = nButtonOffsets[BOFF_TOGGLERIGHT+1] - nButtonOffsets[BOFF_TOGGLERIGHT];
  446. }
  447. if ((m_dwStyle & MBS_DROPRIGHT) == MBS_DROPRIGHT)
  448. {
  449. offRight = nButtonOffsets[BOFF_DROPRIGHT] + (nState * nStateOffset);
  450. widRight = nButtonOffsets[BOFF_DROPRIGHT+1] - nButtonOffsets[BOFF_DROPRIGHT];
  451. }
  452. offMid = nButtonOffsets[BOFF_MIDDLE] + (nState * nStateOffset);
  453. widMid = (lpdis->rcItem.right - lpdis->rcItem.left) - widLeft - widRight;
  454. if (pMidRect)
  455. {
  456. if (m_dwStyle & MBS_DROPRIGHT)
  457. {
  458. //set rect to just the middle of the button part
  459. SetRect(pMidRect,
  460. lpdis->rcItem.left,
  461. lpdis->rcItem.top,
  462. lpdis->rcItem.left + widLeft + widMid,
  463. lpdis->rcItem.top + BUTTON_BITMAP_HEIGHT);
  464. }
  465. else
  466. {
  467. //set rect to whole button
  468. SetRect(pMidRect,
  469. lpdis->rcItem.left,
  470. lpdis->rcItem.top,
  471. lpdis->rcItem.right,
  472. lpdis->rcItem.bottom);
  473. }
  474. }
  475. if (hTemp == NULL)
  476. {
  477. //draw and save bumps
  478. HDC memDC = CreateCompatibleDC(lpdis->hDC);
  479. HPALETTE hpalOld = SelectPalette(memDC, hpalMain, FALSE);
  480. HBITMAP holdbmp;
  481. switch (nState)
  482. {
  483. case STATE_UP :
  484. {
  485. m_hbmpUp = CreateCompatibleBitmap(lpdis->hDC,
  486. lpdis->rcItem.right - lpdis->rcItem.left,
  487. BUTTON_BITMAP_HEIGHT);
  488. holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpUp);
  489. }
  490. break;
  491. case STATE_DN :
  492. {
  493. m_hbmpDn = CreateCompatibleBitmap(lpdis->hDC,
  494. lpdis->rcItem.right - lpdis->rcItem.left,
  495. BUTTON_BITMAP_HEIGHT);
  496. holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpDn);
  497. }
  498. break;
  499. case STATE_HI :
  500. {
  501. m_hbmpHi = CreateCompatibleBitmap(lpdis->hDC,
  502. lpdis->rcItem.right - lpdis->rcItem.left,
  503. BUTTON_BITMAP_HEIGHT);
  504. holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpHi);
  505. }
  506. break;
  507. }
  508. //draw left
  509. DibBlt(memDC,
  510. lpdis->rcItem.left,
  511. lpdis->rcItem.top,
  512. -1,
  513. -1,
  514. hbmpButtonToolkit,
  515. offLeft,0,
  516. SRCCOPY,0);
  517. if ((m_dwStyle & MBS_SYSTEMTYPE) != MBS_SYSTEMTYPE)
  518. {
  519. //draw middle
  520. StretchDibBlt(memDC,
  521. lpdis->rcItem.left + widLeft,
  522. lpdis->rcItem.top,
  523. widMid,
  524. BUTTON_BITMAP_HEIGHT,
  525. hbmpButtonToolkit,
  526. offMid,0,
  527. nButtonOffsets[BOFF_MIDDLE+1] - nButtonOffsets[BOFF_MIDDLE],
  528. BUTTON_BITMAP_HEIGHT,
  529. SRCCOPY,0);
  530. //draw right
  531. DibBlt(memDC,
  532. lpdis->rcItem.right - widRight,
  533. lpdis->rcItem.top,
  534. -1,
  535. -1,
  536. hbmpButtonToolkit,
  537. offRight,0,
  538. SRCCOPY,0);
  539. }
  540. SelectObject(memDC,holdbmp);
  541. SelectPalette(memDC, hpalOld, TRUE);
  542. DeleteDC(memDC);
  543. } //end not already drawn
  544. if (fDrawToScreen)
  545. {
  546. //should have bumps ready to go now
  547. hTemp = m_hbmpUp;
  548. if (m_fMouseInButton)
  549. {
  550. hTemp = m_hbmpHi;
  551. }
  552. if (lpdis->itemState & ODS_FOCUS)
  553. {
  554. if (fAllowFocus)
  555. {
  556. hTemp = m_hbmpHi;
  557. }
  558. }
  559. if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
  560. {
  561. hTemp = m_hbmpDn;
  562. }
  563. if (!(lpdis->itemState & ODS_SELECTED) && (m_fMenuingOff))
  564. {
  565. m_fMenu = FALSE;
  566. m_fMenuingOff = FALSE;
  567. hTemp = m_hbmpUp;
  568. }
  569. HDC memDC = CreateCompatibleDC(lpdis->hDC);
  570. HBITMAP holdbmp = (HBITMAP)SelectObject(memDC,hTemp);
  571. BitBlt(lpdis->hDC,
  572. lpdis->rcItem.left,
  573. lpdis->rcItem.top,
  574. lpdis->rcItem.right - lpdis->rcItem.left,
  575. lpdis->rcItem.bottom - lpdis->rcItem.top,
  576. memDC,
  577. 0,0,
  578. SRCCOPY);
  579. SelectObject(memDC,holdbmp);
  580. DeleteDC(memDC);
  581. }
  582. }
  583. void CMButton::Draw(LPDRAWITEMSTRUCT lpdis)
  584. {
  585. HPALETTE hpalOld = SelectPalette(lpdis->hDC,hpalMain,FALSE);
  586. RealizePalette(lpdis->hDC);
  587. SetTextColor(lpdis->hDC, MBUTTON_TEXT_COLOR);
  588. m_LastState = lpdis->itemState;
  589. if (lpdis->itemState & ODS_DISABLED)
  590. {
  591. SetTextColor(lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
  592. }
  593. RECT midRect;
  594. DrawButtonBitmap(lpdis,TRUE,&midRect);
  595. if ((m_dwStyle & MBS_SYSTEMTYPE) == MBS_SYSTEMTYPE)
  596. {
  597. SelectPalette(lpdis->hDC,hpalOld,TRUE);
  598. RealizePalette(lpdis->hDC);
  599. return;
  600. }
  601. SetBkMode(lpdis->hDC,TRANSPARENT);
  602. if (m_IconID == 0)
  603. {
  604. HFONT hOldFont = (HFONT)SelectObject(lpdis->hDC,m_hFont);
  605. TCHAR szCaption[MAX_PATH];
  606. GetWindowText(m_hwnd,szCaption,sizeof(szCaption)/sizeof(TCHAR));
  607. SIZE size;
  608. GetTextExtentPoint32( lpdis->hDC, szCaption, _tcslen(szCaption), &size );
  609. //center text
  610. int x = (((midRect.right - midRect.left) - size.cx) / 2) + midRect.left;
  611. int y = (((lpdis->rcItem.bottom - lpdis->rcItem.top) - size.cy) / 2) + lpdis->rcItem.top;
  612. //simulate a press
  613. if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
  614. {
  615. x++;
  616. y++;
  617. }
  618. ExtTextOut( lpdis->hDC, x, y, 0, NULL, szCaption, _tcslen(szCaption), NULL );
  619. SelectObject(lpdis->hDC,hOldFont);
  620. } //end if no icon
  621. else
  622. {
  623. //center icon
  624. int x = (((midRect.right - midRect.left) - 32) / 2) + midRect.left;
  625. int y = (((lpdis->rcItem.bottom - lpdis->rcItem.top) - 32) / 2) + lpdis->rcItem.top;
  626. //simulate a press
  627. if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
  628. {
  629. x++;
  630. y++;
  631. }
  632. HICON hIcon = (HICON)LoadImage(m_hInst, MAKEINTRESOURCE(m_IconID), IMAGE_ICON, 32, 32, LR_MONOCHROME);
  633. DrawIcon(lpdis->hDC,x,y,hIcon);
  634. DestroyIcon(hIcon);
  635. }
  636. SelectPalette(lpdis->hDC,hpalOld,TRUE);
  637. RealizePalette(lpdis->hDC);
  638. }
  639. void CMButton::SetMenuingState(BOOL fMenuOn)
  640. {
  641. if (fMenuOn)
  642. {
  643. m_fMenu = fMenuOn;
  644. m_fMenuingOff = FALSE;
  645. }
  646. else
  647. {
  648. m_fMenuingOff = TRUE;
  649. InvalidateRect(m_hwnd,NULL,FALSE);
  650. UpdateWindow(m_hwnd);
  651. }
  652. }