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.

864 lines
23 KiB

  1. //#define WIN32_LEAN_AND_MEAN
  2. #define OEMRESOURCE
  3. #include <windows.h>
  4. #include <windowsx.h>
  5. #include "ddbtn.h"
  6. #include "cddbtn.h"
  7. #include "dbg.h"
  8. #include "exgdiw.h"
  9. //----------------------------------------------------------------
  10. //Menu Index mask
  11. //----------------------------------------------------------------
  12. #define INDEX_MASK 0x7000
  13. //----------------------------------------------------------------
  14. //Private method definition
  15. //----------------------------------------------------------------
  16. //////////////////////////////////////////////////////////////////
  17. // Function : CDDButton::NotifyToParent
  18. // Type : INT
  19. // Purpose : Send WM_COMMAND to Parent window procedure.
  20. // Args :
  21. // : INT notify
  22. // Return :
  23. // DATE :
  24. //////////////////////////////////////////////////////////////////
  25. INT CDDButton::NotifyToParent(INT notify)
  26. {
  27. SendMessage(m_hwndParent,
  28. WM_COMMAND,
  29. MAKEWPARAM(m_wID, notify),
  30. (LPARAM)m_hwndFrame);
  31. return 0;
  32. }
  33. //////////////////////////////////////////////////////////////////
  34. // Function : CDDButton::GetButtonFromPos
  35. // Type : INT
  36. // Purpose :
  37. // Args :
  38. // : INT xPos
  39. // : INT yPos
  40. // Return :
  41. // DATE :
  42. //////////////////////////////////////////////////////////////////
  43. INT CDDButton::GetButtonFromPos(INT xPos, INT yPos)
  44. {
  45. static RECT rc, rcBtn, rcDrop;
  46. POINT pt;
  47. GetClientRect(m_hwndFrame, &rc);
  48. pt.x = xPos;
  49. pt.y = yPos;
  50. if(m_dwStyle & DDBS_NOSEPARATED) {
  51. if(PtInRect(&rc, pt)) {
  52. return BID_ALL;
  53. }
  54. }
  55. else {
  56. SplitRect(&rc, &rcBtn, &rcDrop);
  57. if(PtInRect(&rcBtn, pt)) {
  58. return BID_BUTTON;
  59. }
  60. if(PtInRect(&rcDrop, pt)) {
  61. return BID_DROPDOWN;
  62. }
  63. }
  64. return BID_UNDEF;
  65. }
  66. INT CDDButton::SplitRect(LPRECT lpRc, LPRECT lpButton, LPRECT lpDrop)
  67. {
  68. *lpButton = *lpDrop = *lpRc;
  69. if((lpRc->right - lpRc->left) <= m_cxDropDown) {
  70. lpButton->right = lpRc->left;
  71. }
  72. else {
  73. lpButton->right = lpRc->right - m_cxDropDown;
  74. lpDrop->left = lpRc->right - m_cxDropDown;
  75. }
  76. return 0;
  77. }
  78. //////////////////////////////////////////////////////////////////
  79. // Function : CDDButton::DrawButton
  80. // Type : INT
  81. // Purpose :
  82. // Args :
  83. // : HDC hDC
  84. // : LPRECT lpRc
  85. // Return :
  86. // DATE :
  87. //////////////////////////////////////////////////////////////////
  88. INT CDDButton::DrawButton(HDC hDC, LPRECT lpRc)
  89. {
  90. POINT pt;
  91. #if 0
  92. Dbg(("DrawButton START l[%d] t[%d] r[%d] b[%d]\n",
  93. lpRc->left,
  94. lpRc->top,
  95. lpRc->right,
  96. lpRc->bottom));
  97. #endif
  98. #ifndef UNDER_CE // Windows CE does not support GetCursorPos
  99. GetCursorPos(&pt);
  100. ScreenToClient(m_hwndFrame, &pt);
  101. #else // UNDER_CE
  102. pt = m_ptEventPoint;
  103. #endif // UNDER_CE
  104. INT curBID = GetButtonFromPos(pt.x, pt.y);
  105. //Dbg(("--->curBID 0x%04x\n", curBID));
  106. //Dbg(("--->m_bidDown 0x%04x\n", m_bidDown));
  107. SplitRect(lpRc, &m_tmpBtnRc, &m_tmpDropRc);
  108. IMAGESTYLE styleBtn, styleDrop;
  109. DWORD dwOldTextColor, dwOldBkColor;
  110. dwOldBkColor = ::SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
  111. dwOldTextColor = ::SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  112. #ifndef UNDER_CE
  113. ::FillRect(hDC, lpRc, (HBRUSH)(COLOR_3DFACE +1));
  114. #else // UNDER_CE
  115. ::FillRect(hDC, lpRc, GetSysColorBrush(COLOR_3DFACE));
  116. #endif // UNDER_CE
  117. switch(m_bidDown) {
  118. case BID_UNDEF: // no Button was clicked.
  119. if(m_dwStyle & DDBS_NOSEPARATED) {
  120. if(curBID == BID_ALL) {
  121. styleBtn = styleDrop = IS_POPED;
  122. }
  123. else {
  124. if(m_dwStyle & DDBS_FLAT) {
  125. styleBtn = styleDrop = IS_FLAT;
  126. }
  127. else {
  128. styleBtn = styleDrop = IS_POPED;
  129. }
  130. }
  131. }
  132. else {
  133. if(m_dwStyle & DDBS_FLAT) {
  134. if( (curBID == BID_BUTTON) || (curBID == BID_DROPDOWN) ) {
  135. styleBtn = styleDrop = IS_POPED;
  136. }
  137. else {
  138. styleBtn = styleDrop = IS_FLAT;
  139. }
  140. }
  141. else {
  142. styleBtn = styleDrop = IS_POPED;
  143. }
  144. }
  145. break;
  146. case BID_BUTTON:
  147. styleBtn = (curBID == BID_BUTTON) ? IS_PUSHED : IS_POPED;
  148. styleDrop = IS_POPED;
  149. break;
  150. case BID_DROPDOWN:
  151. styleBtn = IS_POPED;
  152. styleDrop = IS_PUSHED;
  153. break;
  154. case BID_ALL: //DDBS_NOSEPARATED style.
  155. styleBtn = styleDrop = IS_PUSHED;
  156. break;
  157. default:
  158. return 0;
  159. break;
  160. }
  161. //Dbg(("styleBtn [%d]\n", styleBtn));
  162. if(m_dwStyle & DDBS_NOSEPARATED) {
  163. if(m_dwStyle & DDBS_THINEDGE) {
  164. DrawThinEdge(hDC, lpRc, styleBtn);
  165. }
  166. else {
  167. DrawThickEdge(hDC, lpRc, styleBtn);
  168. }
  169. }
  170. else {
  171. if(m_dwStyle & DDBS_THINEDGE) {
  172. DrawThinEdge(hDC, &m_tmpBtnRc, styleBtn);
  173. DrawThinEdge(hDC, &m_tmpDropRc, styleDrop);
  174. }
  175. else {
  176. DrawThickEdge(hDC, &m_tmpBtnRc, styleBtn);
  177. DrawThickEdge(hDC, &m_tmpDropRc, styleDrop);
  178. }
  179. }
  180. if(m_dwStyle & DDBS_ICON) {
  181. DrawIcon(hDC, &m_tmpBtnRc, styleBtn);
  182. }
  183. else {
  184. DrawText(hDC, &m_tmpBtnRc, styleBtn);
  185. }
  186. DrawTriangle(hDC, &m_tmpDropRc, styleDrop);
  187. ::SetBkColor(hDC, dwOldBkColor);
  188. ::SetTextColor(hDC, dwOldTextColor);
  189. return 0;
  190. }
  191. //////////////////////////////////////////////////////////////////
  192. // Function : CDDButton::DrawThickEdge
  193. // Type : INT
  194. // Purpose :
  195. // Args :
  196. // : HDC hDC
  197. // : LPRECT lpRc
  198. // : IMAGESTYLE style
  199. // Return :
  200. // DATE :
  201. //////////////////////////////////////////////////////////////////
  202. INT CDDButton::DrawThickEdge(HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  203. {
  204. DWORD dwStyle;
  205. switch(style) {
  206. case IS_PUSHED:
  207. dwStyle = DFCS_PUSHED;
  208. break;
  209. case IS_POPED:
  210. dwStyle = 0;
  211. break;
  212. case IS_FLAT: // do not draw
  213. default:
  214. return 0;
  215. break;
  216. }
  217. ::DrawFrameControl(hDC, lpRc, DFC_BUTTON, DFCS_BUTTONPUSH | dwStyle);
  218. return 0;
  219. }
  220. //////////////////////////////////////////////////////////////////
  221. // Function : CDDButton::DrawThinEdge
  222. // Type : INT
  223. // Purpose :
  224. // Args :
  225. // : HDC hDC
  226. // : LPRECT lpRc
  227. // : IMAGESTYLE style
  228. // Return :
  229. // DATE :
  230. //////////////////////////////////////////////////////////////////
  231. INT CDDButton::DrawThinEdge(HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  232. {
  233. HPEN hPenPrev, hPenNew=0 ;
  234. HPEN hPenTopLeft = 0;
  235. HPEN hPenBottomRight = 0;
  236. switch(style) {
  237. case IS_PUSHED:
  238. hPenNew = hPenTopLeft = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  239. hPenBottomRight = (HPEN)GetStockObject(WHITE_PEN);
  240. break;
  241. case IS_POPED:
  242. hPenTopLeft = (HPEN)GetStockObject(WHITE_PEN);
  243. hPenNew = hPenBottomRight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  244. break;
  245. case IS_FLAT: // do not draw
  246. return 0;
  247. break;
  248. }
  249. hPenPrev = (HPEN)SelectObject(hDC, hPenTopLeft);
  250. #ifndef UNDER_CE // Windows CE does not support MoveToEx/LineTo. Use Polyline.
  251. MoveToEx(hDC, lpRc->left, lpRc->top, NULL);
  252. LineTo(hDC, lpRc->right, lpRc->top);
  253. MoveToEx(hDC, lpRc->left, lpRc->top, NULL);
  254. LineTo(hDC, lpRc->left, lpRc->bottom);
  255. #else // UNDER_CE
  256. {
  257. POINT pts[] = {{lpRc->left, lpRc->bottom},
  258. {lpRc->left, lpRc->top},
  259. {lpRc->right, lpRc->top}};
  260. Polyline(hDC, pts, sizeof pts / sizeof pts[0]);
  261. }
  262. #endif // UNDER_CE
  263. SelectObject(hDC, hPenBottomRight);
  264. #ifndef UNDER_CE // Windows CE does not support MoveToEx/LineTo. Use Polyline.
  265. MoveToEx(hDC, lpRc->right -1, lpRc->top - 1, NULL);
  266. LineTo(hDC, lpRc->right -1, lpRc->bottom);
  267. MoveToEx(hDC, lpRc->left + 1, lpRc->bottom -1, NULL);
  268. LineTo(hDC, lpRc->right -1, lpRc->bottom -1);
  269. #else // UNDER_CE
  270. {
  271. POINT pts[] = {{lpRc->right - 1, lpRc->top - 1},
  272. {lpRc->right - 1, lpRc->bottom - 1},
  273. {lpRc->left + 1, lpRc->bottom - 1}};
  274. Polyline(hDC, pts, sizeof pts / sizeof pts[0]);
  275. }
  276. #endif // UNDER_CE
  277. SelectObject(hDC, hPenPrev);
  278. DeleteObject(hPenNew);
  279. return 0;
  280. }
  281. //////////////////////////////////////////////////////////////////
  282. // Function : CDDButton::DrawTriangle
  283. // Type : INT
  284. // Purpose :
  285. // Args :
  286. // : HDC hDC
  287. // : LPRECT lpRc
  288. // : IMAGESTYLE style
  289. // Return :
  290. // DATE :
  291. //////////////////////////////////////////////////////////////////
  292. INT CDDButton::DrawTriangle (HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  293. {
  294. POINT pt;
  295. HPEN hPenPrev, hPen;
  296. INT sunken;
  297. if ( m_fEnable )
  298. {
  299. hPen = (HPEN)GetStockObject(BLACK_PEN);
  300. }
  301. else
  302. {
  303. hPen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_GRAYTEXT)); // dark gray color
  304. }
  305. hPenPrev = (HPEN)SelectObject(hDC, hPen);
  306. switch(style) {
  307. case IS_PUSHED:
  308. sunken = 1;
  309. break;
  310. case IS_FLAT:
  311. case IS_POPED:
  312. default:
  313. sunken = 0;
  314. break;
  315. }
  316. pt.x = lpRc->left + (lpRc->right - lpRc->left)/2 - 3 + sunken;
  317. pt.y = lpRc->top + (lpRc->bottom - lpRc->top )/2 - 2 + sunken;
  318. #ifndef UNDER_CE // Windows CE does not support MoveToEx/LineTo. Use Polyline.
  319. MoveToEx(hDC, pt.x, pt.y, NULL);
  320. LineTo(hDC, pt.x + 5, pt.y);
  321. pt.y++;
  322. MoveToEx(hDC, pt.x + 1, pt.y, NULL);
  323. LineTo(hDC, pt.x + 4, pt.y);
  324. pt.y++;
  325. MoveToEx(hDC, pt.x + 2, pt.y, NULL);
  326. LineTo(hDC, pt.x + 3, pt.y);
  327. #else // UNDER_CE
  328. {
  329. POINT pts[] = {{pt.x, pt.y}, {pt.x + 5, pt.y}};
  330. Polyline(hDC, pts, sizeof pts / sizeof pts[0]);
  331. }
  332. pt.y++;
  333. {
  334. POINT pts[] = {{pt.x + 1, pt.y}, {pt.x + 4, pt.y}};
  335. Polyline(hDC, pts, sizeof pts / sizeof pts[0]);
  336. }
  337. pt.y++;
  338. {
  339. POINT pts[] = {{pt.x + 2, pt.y}, {pt.x + 3, pt.y}};
  340. Polyline(hDC, pts, sizeof pts / sizeof pts[0]);
  341. }
  342. #endif // UNDER_CE
  343. hPen = (HPEN)SelectObject(hDC, hPenPrev);
  344. if ( !m_fEnable )
  345. {
  346. DeletePen(hPen);
  347. }
  348. return 0;
  349. }
  350. //////////////////////////////////////////////////////////////////
  351. // Function : CDDButton::DrawIcon
  352. // Type : INT
  353. // Purpose :
  354. // Args :
  355. // : HDC hDC
  356. // : LPRECT lpRc
  357. // : IMAGESTYLE style
  358. // Return :
  359. // DATE :
  360. //////////////////////////////////////////////////////////////////
  361. INT CDDButton::DrawIcon(HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  362. {
  363. if(!m_hIcon) {
  364. return -1;
  365. }
  366. INT sunken, xPos, yPos;
  367. switch(style) {
  368. case IS_PUSHED:
  369. sunken = 1;
  370. break;
  371. case IS_POPED:
  372. case IS_FLAT:
  373. default:
  374. sunken = 0;
  375. break;
  376. }
  377. //----------------------------------------------------------------
  378. //centering Icon
  379. xPos = lpRc->left + ((lpRc->right - lpRc->left) - m_cxIcon)/2;
  380. yPos = lpRc->top + ((lpRc->bottom - lpRc->top) - m_cyIcon)/2;
  381. if ( m_fEnable )
  382. {
  383. DrawIconEx(hDC, //HDC hdc,// handle to device context
  384. xPos + sunken, //int xLeft,// x-coordinate of upper left corner
  385. yPos + sunken, //int yTop,// y-coordinate of upper left corner
  386. m_hIcon, //HICON hIcon,// handle to icon to draw
  387. #ifndef UNDER_CE // CE specific
  388. m_cxIcon, //int cxWidth,// width of the icon
  389. m_cyIcon, //int cyWidth,// height of the icon
  390. #else // UNDER_CE
  391. 0,0,
  392. #endif // UNDER_CE
  393. 0, //UINT istepIfAniCur,// index of frame in animated cursor
  394. NULL, //HBRUSH hbrFlickerFreeDraw,// handle to background brush
  395. DI_NORMAL); //UINT diFlags// icon-drawing flags
  396. }
  397. else
  398. {
  399. #ifndef UNDER_CE // Windows CE does not support DrawState
  400. DrawState(hDC,NULL,NULL,(LPARAM)m_hIcon,0,
  401. xPos + sunken,
  402. yPos + sunken,
  403. m_cxIcon,
  404. m_cyIcon,
  405. DST_ICON | DSS_DISABLED);
  406. #else // UNDER_CE
  407. // needs to create or replace DrawState() !!!
  408. DBGCHK(TEXT("CDDButton::DrawIcon"), FALSE);
  409. #endif // UNDER_CE
  410. }
  411. return 0;
  412. }
  413. //////////////////////////////////////////////////////////////////
  414. // Function : CDDButton::DrawBitmap
  415. // Type : INT
  416. // Purpose :
  417. // Args :
  418. // : HDC hDC
  419. // : LPRECT lpRc
  420. // : IMAGESTYLE style
  421. // Return :
  422. // DATE :
  423. //////////////////////////////////////////////////////////////////
  424. INT CDDButton::DrawBitmap(HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  425. {
  426. return 0;
  427. UNREFERENCED_PARAMETER(hDC);
  428. UNREFERENCED_PARAMETER(lpRc);
  429. UNREFERENCED_PARAMETER(style);
  430. }
  431. //////////////////////////////////////////////////////////////////
  432. // Function : CDDButton::DrawText
  433. // Type : INT
  434. // Purpose :
  435. // Args :
  436. // : HDC hDC
  437. // : LPRECT lpRc
  438. // : IMAGESTYLE style
  439. // Return :
  440. // DATE :
  441. //////////////////////////////////////////////////////////////////
  442. inline BOOL MIN(INT a, INT b)
  443. {
  444. if(a > b) {
  445. return b;
  446. }
  447. else {
  448. return a;
  449. }
  450. }
  451. INT CDDButton::DrawText(HDC hDC, LPRECT lpRc, IMAGESTYLE style)
  452. {
  453. static POINT pt;
  454. static RECT rc;
  455. INT sunken, len;
  456. if(!m_lpwstrText) {
  457. return -1;
  458. }
  459. len = lstrlenW(m_lpwstrText);
  460. HFONT hFontPrev;
  461. if(m_hFont) {
  462. hFontPrev = (HFONT)SelectObject(hDC, m_hFont);
  463. }
  464. else {
  465. hFontPrev = (HFONT)SelectObject(hDC, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
  466. }
  467. ExGetTextExtentPoint32W(hDC,
  468. m_lpwstrText,
  469. len,
  470. &m_tmpSize);
  471. if((lpRc->right - lpRc->left) > m_tmpSize.cx) {
  472. pt.x = lpRc->left + ((lpRc->right - lpRc->left) - m_tmpSize.cx)/2;
  473. }
  474. else {
  475. pt.x = lpRc->left+2; //2 is edge space
  476. }
  477. if((lpRc->bottom - lpRc->top) > m_tmpSize.cy) {
  478. pt.y = lpRc->top + ((lpRc->bottom - lpRc->top) - m_tmpSize.cy)/2;
  479. }
  480. else {
  481. pt.y = lpRc->top+2; //2 is edge space
  482. }
  483. switch(style) {
  484. case IS_PUSHED:
  485. sunken = 1;
  486. break;
  487. case IS_POPED:
  488. case IS_FLAT:
  489. default:
  490. sunken = 0;
  491. }
  492. rc.left = pt.x;
  493. rc.right = MIN(pt.x + m_tmpSize.cx, lpRc->right-2);
  494. rc.top = pt.y;
  495. rc.bottom = MIN(pt.y + m_tmpSize.cy, lpRc->bottom-2 );
  496. ExExtTextOutW(hDC,
  497. pt.x + sunken,
  498. pt.y + sunken,
  499. ETO_CLIPPED | ETO_OPAQUE,
  500. &rc,
  501. m_lpwstrText,
  502. len,
  503. NULL);
  504. SelectObject(hDC, hFontPrev);
  505. return 0;
  506. }
  507. //////////////////////////////////////////////////////////////////
  508. // Function : CDDButton::GetDDBItemCount
  509. // Type : INT
  510. // Purpose :
  511. // Args :
  512. // : VOID
  513. // Return :
  514. // DATE :
  515. //////////////////////////////////////////////////////////////////
  516. INT CDDButton::GetDDBItemCount(VOID)
  517. {
  518. INT i;
  519. LPCDDBItem *pp;
  520. for(i = 0, pp = &m_lpCDDBItem; *pp; pp = &(*pp)->next, i++) {
  521. }
  522. return i;
  523. }
  524. //////////////////////////////////////////////////////////////////
  525. // Function : CDDButton::GetDDBItemByIndex
  526. // Type : LPCDDBItem
  527. // Purpose :
  528. // Args :
  529. // : INT index
  530. // Return :
  531. // DATE :
  532. //////////////////////////////////////////////////////////////////
  533. LPCDDBItem CDDButton::GetDDBItemByIndex(INT index)
  534. {
  535. INT i;
  536. LPCDDBItem *pp;
  537. for(i = 0, pp = &m_lpCDDBItem; *pp; pp = &(*pp)->next, i++) {
  538. if(i == index) {
  539. break;
  540. }
  541. }
  542. return *pp;
  543. }
  544. //////////////////////////////////////////////////////////////////
  545. // Function : CDDButton::InsertDDBItem
  546. // Type : LPCDDBItem
  547. // Purpose :
  548. // Args :
  549. // : LPCDDBItem lpCDDBItem
  550. // : INT index
  551. // Return :
  552. // DATE :
  553. //////////////////////////////////////////////////////////////////
  554. LPCDDBItem CDDButton::InsertDDBItem(LPCDDBItem lpCDDBItem, INT index)
  555. {
  556. INT i;
  557. LPCDDBItem *pp;
  558. for(i = 0, pp = &m_lpCDDBItem; *pp; pp = &(*pp)->next, i++) {
  559. if(i == index) {
  560. lpCDDBItem->next = (*pp)->next;
  561. *pp = lpCDDBItem;
  562. return lpCDDBItem;
  563. }
  564. }
  565. *pp = lpCDDBItem;
  566. return lpCDDBItem;
  567. }
  568. //////////////////////////////////////////////////////////////////
  569. // Function : CDDButton::DropDownItemList
  570. // Type : INT
  571. // Purpose :
  572. // Args :
  573. // : VOID
  574. // Return :
  575. // DATE :
  576. //////////////////////////////////////////////////////////////////
  577. INT CDDButton::DropDownItemList(VOID)
  578. {
  579. POINT pt;
  580. INT count;
  581. if((count = GetDDBItemCount()) <= 0) {
  582. return 0;
  583. }
  584. HMENU hMenu = ::CreatePopupMenu();
  585. INT i;
  586. for(i = 0; i < count; i++) {
  587. #ifndef UNDER_CE // Windows CE does not support InsertMenuItem
  588. ::ZeroMemory(&m_miInfo, sizeof(m_miInfo));
  589. #endif // UNDER_CE
  590. LPCDDBItem lpItem = GetDDBItemByIndex(i);
  591. if(!lpItem) {
  592. continue;
  593. }
  594. #ifndef UNDER_CE // Windows CE does not support InsertMenuItem
  595. m_miInfo.cbSize = sizeof(m_miInfo);
  596. m_miInfo.fMask = MIIM_TYPE | MIIM_ID | MIIM_DATA;
  597. m_miInfo.fType = MFT_OWNERDRAW;
  598. m_miInfo.fState = MFS_ENABLED;
  599. m_miInfo.wID = INDEX_MASK + i;
  600. m_miInfo.dwItemData = (ULONG_PTR)lpItem;
  601. ::InsertMenuItem(hMenu, i, TRUE, &m_miInfo);
  602. #else // UNDER_CE
  603. // Windows CE does not support OBM_CHECK
  604. ::InsertMenu(hMenu, i, MF_BYPOSITION | MF_STRING | MF_ENABLED |
  605. (m_curDDBItemIndex == i ? MF_CHECKED : MF_UNCHECKED),
  606. INDEX_MASK + i, lpItem->GetTextW());
  607. // ::InsertMenu(hMenu, i, MF_BYPOSITION | MF_OWNERDRAW | MF_ENABLED,
  608. // INDEX_MASK + i, (LPCTSTR)lpItem);
  609. #endif // UNDER_CE
  610. }
  611. //----------------------------------------------------------------
  612. // calc menu position
  613. //----------------------------------------------------------------
  614. ::GetWindowRect(m_hwndFrame, &m_tmpRect);
  615. pt.x = m_tmpRect.left;
  616. pt.y = m_tmpRect.bottom;
  617. m_tmpTpmParams.cbSize = sizeof(m_tmpTpmParams);
  618. m_tmpTpmParams.rcExclude = m_tmpRect;
  619. Dbg(("Before Call TrackPopupMenuEx\n"));
  620. INT newIndex = ::TrackPopupMenuEx(hMenu,
  621. TPM_VERTICAL | TPM_RETURNCMD,
  622. pt.x,
  623. pt.y,
  624. m_hwndFrame,
  625. &m_tmpTpmParams);
  626. Dbg(("After Call TrackPopupMenuEx\n"));
  627. if(newIndex == 0) { //Do NOT selected, but menu has closed.
  628. #ifdef UNDER_CE // Windows CE does not support GetCursorPos()
  629. MSG msg;
  630. if(PeekMessage(&msg, m_hwndFrame,
  631. WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){
  632. if(m_hwndFrame == msg.hwnd){
  633. POINT pt = {(SHORT)LOWORD(msg.lParam),
  634. (SHORT)HIWORD(msg.lParam)};
  635. RECT rc;
  636. GetClientRect(m_hwndFrame, &rc);
  637. if(PtInRect(&rc, pt)) {
  638. m_fExitMenuLoop = TRUE;
  639. }
  640. else {
  641. m_fExitMenuLoop = FALSE;
  642. }
  643. }
  644. }
  645. #endif // UNDER_CE
  646. return -1;
  647. }
  648. if(0 <= (newIndex - INDEX_MASK) && (newIndex - INDEX_MASK) < count) {
  649. return newIndex - INDEX_MASK;
  650. }
  651. return -1;
  652. }
  653. //////////////////////////////////////////////////////////////////
  654. // Function : CDDButton::IncrementIndex
  655. // Type : INT
  656. // Purpose : increment and circurate m_curDDBItemIndex
  657. // Args :
  658. // : VOID
  659. // Return : new Index;
  660. // DATE :
  661. //////////////////////////////////////////////////////////////////
  662. INT CDDButton::IncrementIndex(VOID)
  663. {
  664. if(m_curDDBItemIndex == -1) {
  665. return -1;
  666. }
  667. INT count = GetDDBItemCount();
  668. if(count == 0) {
  669. return -1;
  670. }
  671. m_curDDBItemIndex = (m_curDDBItemIndex+1) % count;
  672. return m_curDDBItemIndex;
  673. }
  674. INT CDDButton::MenuMeasureItem(HWND hwndOwner, LPMEASUREITEMSTRUCT lpmis)
  675. {
  676. #ifndef UNDER_CE // Windows CE does not support OBM_CHECK (OWNERDRAW)
  677. //Dbg(("MenuMeasureItem START\n"));
  678. SIZE size;
  679. HDC hDC;
  680. //INT checkW = ::GetSystemMetrics(SM_CXMENUCHECK);
  681. //INT checkH = ::GetSystemMetrics(SM_CYMENUCHECK);
  682. LPCDDBItem lpCItem = (LPCDDBItem)lpmis->itemData;
  683. if(!lpCItem) {
  684. return 0;
  685. }
  686. hDC = ::GetDC(hwndOwner);
  687. HFONT hFontPrev = NULL;
  688. HFONT hFontMenu = NULL;
  689. if(m_hFont) {
  690. hFontPrev = (HFONT)::SelectObject(hDC, m_hFont);
  691. }
  692. else {
  693. m_ncm.cbSize = sizeof(m_ncm);
  694. ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &m_ncm, 0);
  695. hFontMenu = ::CreateFontIndirect(&m_ncm.lfMenuFont);
  696. if(hFontMenu) {
  697. hFontPrev = (HFONT)::SelectObject(hDC, hFontMenu);
  698. }
  699. }
  700. ::ExGetTextExtentPoint32W(hDC,
  701. lpCItem->GetTextW(),
  702. ::lstrlenW(lpCItem->GetTextW()),
  703. &size);
  704. TEXTMETRIC tm;
  705. ::GetTextMetrics(hDC, &tm);
  706. if(hFontPrev) {
  707. ::SelectObject(hDC, hFontPrev);
  708. }
  709. if(hFontMenu) {
  710. ::DeleteObject(hFontMenu);
  711. }
  712. ::ReleaseDC(hwndOwner, hDC);
  713. //----------------------------------------------------------------
  714. //Use magic number.
  715. //----------------------------------------------------------------
  716. lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENUSIZE) - 2;
  717. lpmis->itemWidth = lpmis->itemHeight + size.cx;
  718. //Dbg(("MenuMeasureItem END\n"));
  719. #endif // UNDER_CE
  720. return TRUE;
  721. }
  722. INT CDDButton::MenuDrawItem(HWND hwndOwner, LPDRAWITEMSTRUCT lpdis)
  723. {
  724. #ifndef UNDER_CE // Windows CE does not support OBM_CHECK (OWNERDRAW)
  725. //Dbg(("MenuDrawItem START\n"));
  726. LPCDDBItem lpCItem;
  727. SIZE size;
  728. DWORD dwOldTextColor, dwOldBkColor;
  729. if(!lpdis) { DBGAssert(FALSE); return 0;}
  730. Dbg(("itemID [%d]\n", lpdis->itemID));
  731. lpCItem = (LPCDDBItem)lpdis->itemData;
  732. if(lpdis->itemState & ODS_SELECTED) {
  733. #ifndef UNDER_CE
  734. ::FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1));
  735. #else // UNDER_CE
  736. ::FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
  737. #endif // UNDER_CE
  738. dwOldBkColor = ::SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT));
  739. dwOldTextColor = ::SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  740. }
  741. else {
  742. #ifndef UNDER_CE
  743. ::FillRect(lpdis->hDC, &lpdis->rcItem, (HBRUSH)(COLOR_MENU + 1));
  744. #else // UNDER_CE
  745. ::FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_MENU));
  746. #endif // UNDER_CE
  747. dwOldBkColor = ::SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU));
  748. dwOldTextColor = ::SetTextColor(lpdis->hDC, GetSysColor(COLOR_WINDOWTEXT));
  749. }
  750. HBITMAP hBmp = NULL;
  751. INT offsetX, offsetY;
  752. TEXTMETRIC tm;
  753. HFONT hFontPrev = NULL;
  754. if(m_hFont) {
  755. hFontPrev = (HFONT)::SelectObject(lpdis->hDC, m_hFont);
  756. }
  757. ::GetTextMetrics(lpdis->hDC, &tm);
  758. INT height = tm.tmHeight + tm.tmExternalLeading;
  759. ::ExGetTextExtentPoint32W(lpdis->hDC,
  760. lpCItem->GetTextW(),
  761. ::lstrlenW(lpCItem->GetTextW()),
  762. &size);
  763. //----------------------------------------------------------------
  764. //In DropDownItemList(), item Id is command id with INDEX_MASK
  765. //To get real index, remove INDEX_MASK
  766. //----------------------------------------------------------------
  767. if(m_curDDBItemIndex == ((INT)lpdis->itemID & ~INDEX_MASK)) {
  768. //----------------------------------------------------------------
  769. //Draw checked mark
  770. //----------------------------------------------------------------
  771. hBmp = ::LoadBitmap(NULL, MAKEINTRESOURCE(OBM_CHECK));
  772. if(hBmp) {
  773. BITMAP bmp;
  774. ::GetObject(hBmp, sizeof(bmp), &bmp);
  775. offsetX = (height - bmp.bmWidth )/2;
  776. offsetY = (lpdis->rcItem.bottom - lpdis->rcItem.top - bmp.bmHeight)/2;
  777. ::DrawState(lpdis->hDC,
  778. NULL,
  779. NULL,
  780. (LPARAM)hBmp,
  781. (WPARAM)0,
  782. lpdis->rcItem.left + offsetX,
  783. lpdis->rcItem.top + offsetY,
  784. bmp.bmWidth, bmp.bmHeight,
  785. DST_BITMAP | DSS_NORMAL);
  786. ::DeleteObject(hBmp);
  787. }
  788. }
  789. offsetX = size.cy;
  790. offsetY = ((lpdis->rcItem.bottom - lpdis->rcItem.top)-size.cy)/2;
  791. ::ExExtTextOutW(lpdis->hDC,
  792. lpdis->rcItem.left + height, //offsetX,
  793. lpdis->rcItem.top +offsetY,
  794. ETO_CLIPPED,
  795. &lpdis->rcItem,
  796. lpCItem->GetTextW(),
  797. ::lstrlenW(lpCItem->GetTextW()),
  798. NULL);
  799. //----------------------------------------------------------------
  800. //Restore DC
  801. //----------------------------------------------------------------
  802. if(hFontPrev) {
  803. ::SelectObject(lpdis->hDC, hFontPrev);
  804. }
  805. ::SetBkColor(lpdis->hDC, dwOldBkColor);
  806. ::SetTextColor(lpdis->hDC, dwOldTextColor);
  807. //Dbg(("MenuDrawItem END\n"));
  808. #endif // UNDER_CE
  809. return TRUE;
  810. UNREFERENCED_PARAMETER(hwndOwner);
  811. }