SkinMenu.cpp
上传用户:weijiexitu
上传日期:2007-01-18
资源大小:54k
文件大小:17k
源码类别:

菜单

开发平台:

WINDOWS

  1. // SkinMenu.cpp: implementation of the CSkinMenu class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SkinMenu.h"
  6. #include "SkinMenuMgr.h"
  7. #include "wclassdefines.h"
  8. #include "winclasses.h"
  9. #include "skinglobals.h"
  10. #include "skinbase.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char THIS_FILE[]=__FILE__;
  14. #define new DEBUG_NEW
  15. #endif
  16. ISkinMenuRender* CSkinMenu::s_pRenderer = NULL;
  17. enum { REDRAWALL = -2 };
  18. #ifndef SPI_GETMENUANIMATION
  19. #define SPI_GETMENUANIMATION  0x1002
  20. #endif
  21. #ifndef SPI_GETMENUFADE
  22. #define SPI_GETMENUFADE  0x1012
  23. #endif
  24. //////////////////////////////////////////////////////////////////////
  25. struct colorMapping
  26. {
  27. int nSrcColor;
  28. int nDestColor;
  29. };
  30. static colorMapping colors[] = 
  31. {
  32. // { COLOR_HIGHLIGHT, COLOR_HIGHLIGHT },
  33. { COLOR_WINDOWTEXT, COLOR_WINDOWTEXT },
  34. { COLOR_GRAYTEXT, COLOR_MENU },
  35. { COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHTTEXT },
  36. { COLOR_3DHILIGHT, COLOR_MENU },
  37. // { COLOR_3DDKSHADOW, COLOR_MENU },
  38. { COLOR_3DSHADOW, COLOR_3DSHADOW },
  39. { COLOR_3DFACE, COLOR_MENU },
  40. { COLOR_MENU, COLOR_MENU },
  41. };
  42. CSkinMenu::CSkinMenu(CSkinGlobals* pGlobals, DWORD dwStyle, int nSBWidth) 
  43. : m_pGlobals(pGlobals), m_nSidebarWidth(nSBWidth), m_dwStyle(dwStyle)
  44. {
  45. m_nSelIndex = REDRAWALL; // this ensures a full repaint when we first show
  46. m_hContextWnd = NULL;
  47. m_hMenu = NULL;
  48. // fix for animated menus
  49. m_bFirstRedraw = TRUE;
  50. m_bAnimatedMenus = FALSE;
  51. SystemParametersInfo(SPI_GETMENUANIMATION, 0, &m_bAnimatedMenus, 0);
  52. }
  53. CSkinMenu::~CSkinMenu()
  54. {
  55. }
  56. BOOL CSkinMenu::IsMenuWnd(HWND hWnd)
  57. {
  58. return CWinClasses::IsClass(hWnd, WC_MENU);
  59. }
  60. BOOL CSkinMenu::AttachWindow(HWND hWnd) 
  61. if (!IsMenuWnd(hWnd))
  62. return FALSE;
  63. if (HookWindow(hWnd))
  64. {
  65. return TRUE;
  66. }
  67. // else
  68. return FALSE;
  69. }
  70. BOOL CSkinMenu::DetachWindow() 
  71. return HookWindow((HWND)NULL); 
  72. }
  73. LRESULT CSkinMenu::WindowProc(HWND hRealWnd, UINT msg, WPARAM wp, LPARAM lp)
  74. {
  75. UINT uRes = 0;
  76. LRESULT lr = 0;
  77. int nOS = CSkinBase::GetOS();
  78. switch (msg) 
  79. {
  80. case WM_NCPAINT: 
  81. // the very first WM_NCPAINT appears to be responsible for
  82. // doing any menu animation. since our std OnNcPaint does not
  83. // deal with animation we must leave it to the default handler.
  84. // fortunately, the default handler calls WM_PRINT to implement
  85. // the animation.
  86. if (!m_bAnimatedMenus || !m_bFirstRedraw)
  87. {
  88. CWindowDC dc(GetCWnd());
  89. OnNcPaint(&dc);
  90. return 0;
  91. }
  92. break; 
  93. case WM_PRINT: 
  94. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  95. {
  96. lr = CSubclassWnd::WindowProc(hRealWnd, msg, wp, lp);
  97. OnNcPaint(CDC::FromHandle((HDC)wp));
  98. return lr;
  99. }
  100. break; 
  101. case WM_PRINTCLIENT:
  102. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  103. {
  104. OnPrintClient(CDC::FromHandle((HDC)wp), lp);
  105. return 0;
  106. }
  107. break; 
  108. case WM_PAINT:
  109. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  110. {
  111. CPaintDC dc(GetCWnd());
  112. SendMessage(WM_PRINTCLIENT, (WPARAM)(HDC)dc, PRF_CLIENT | PRF_CHECKVISIBLE);
  113. return 0;
  114. }
  115. break; 
  116. // handle keyboard navigation
  117. case WM_KEYDOWN:
  118. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  119. {
  120. switch (wp)
  121. {
  122. case VK_UP:
  123. case VK_DOWN:
  124. case VK_RIGHT:
  125. // left is much trickier because if the currently selected item
  126. // has a popup menu then left will close that submenu, and if
  127. // we prevent the default redrawing then the submenu is not correctly
  128. // removed from the screen.
  129. // so we must always do the default drawing and follow it up with our own.
  130. case VK_LEFT:
  131. if (!m_hMenu)
  132. {
  133. if (wp != VK_LEFT) 
  134. SetRedraw(FALSE);
  135. lr = Default();
  136. if (wp != VK_LEFT) 
  137. SetRedraw(TRUE);
  138. // TRACE ("Invalidating entire menu in response to a cursor keypressn");
  139. m_nSelIndex = -1; // reset current selection because its too risky to 
  140. // try to figure it out for ourselves
  141. Invalidate(FALSE);
  142. UpdateWindow(GetHwnd());
  143. m_bFirstRedraw = FALSE;
  144. }
  145. else // have menu handle
  146. {
  147. int nPrevSel = GetCurSel();
  148. if (wp != VK_LEFT) 
  149. SetRedraw(FALSE);
  150. lr = Default();
  151. if (wp != VK_LEFT) 
  152. SetRedraw(TRUE);
  153. // if we have the handle of the menu then 
  154. // we can do a selective redraw else we must redraw all
  155. m_nSelIndex = GetCurSel();
  156. if (m_nSelIndex != nPrevSel)
  157. {
  158. CRect rInvalid;
  159. GetInvalidRect(m_nSelIndex, nPrevSel, rInvalid);
  160. // TRACE ("Invalidating menu items %d & %d in response to a cursor keypressn", m_nSelIndex, nPrevSel);
  161. InvalidateRect(GetHwnd(), rInvalid, FALSE);
  162. UpdateWindow(GetHwnd());
  163. m_bFirstRedraw = FALSE;
  164. }
  165. }
  166. return lr;
  167. }
  168. }
  169. break;
  170. case 0x1e5: 
  171. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  172. {
  173. if (m_nSelIndex != (int)wp)
  174. {
  175. // attempt to do a partial redraw where possible
  176. // this needs more thought
  177. CRect rInvalid;
  178. if (m_hMenu)
  179. GetInvalidRect((int)wp, m_nSelIndex, rInvalid);
  180. else
  181. GetClientRect(rInvalid);
  182. // prevent redrawing during default message processing
  183. // because otherwise the item is redrawn oven ours.
  184. SetRedraw(FALSE);
  185. lr = Default();
  186. SetRedraw(TRUE);
  187. m_nSelIndex = (int)wp;
  188. InvalidateRect(hRealWnd, rInvalid, FALSE);
  189. if (!m_bFirstRedraw)
  190. UpdateWindow(hRealWnd);
  191. }
  192. // special fix for animated menus
  193. if (m_bAnimatedMenus && m_bFirstRedraw)
  194. {
  195. CWindowDC dc(GetCWnd());
  196. OnNcPaint(&dc);
  197. }
  198. m_bFirstRedraw = FALSE;
  199. return lr;
  200. }
  201. break;
  202. case WM_NCCALCSIZE:
  203. if (Sidebar())
  204. {
  205. lr = Default();
  206. LPRECT pRect = wp ? &((LPNCCALCSIZE_PARAMS)lp)->rgrc[0] : (LPRECT)lp;
  207. pRect->left += m_nSidebarWidth;
  208. return lr;
  209. }
  210. break;
  211. case WM_WINDOWPOSCHANGING:
  212. {
  213. WINDOWPOS* pWP = (WINDOWPOS*)lp;
  214. // adjust width for sidebar
  215. if (Sidebar() && !(pWP->flags & SWP_NOSIZE))
  216. pWP->cx += m_nSidebarWidth;
  217. // if we have a parent menu we may need to adjust our
  218. // pos to avoid client repainting issues
  219. if (m_pParentMenu && !(pWP->flags & SWP_NOMOVE))
  220. {
  221. // if we are on the right side of our parent
  222. // then we need to adjust ourselves to avoid the client rect
  223. CRect rParentWindow;
  224. ::GetWindowRect(m_pParentMenu->GetHwnd(), rParentWindow);
  225. if (pWP->x > rParentWindow.left) // right
  226. {
  227. CRect rParentClient;
  228. ::GetClientRect(m_pParentMenu->GetHwnd(), rParentClient);
  229. m_pParentMenu->ClientToScreen(rParentClient);
  230. pWP->x = rParentClient.right;
  231. }
  232. }
  233. }
  234. break;
  235. case WM_ERASEBKGND: 
  236. if (nOS != SBOS_95 && nOS != SBOS_NT4)
  237. return TRUE; 
  238. break;
  239. default:
  240. break;
  241. }
  242. // We don't handle it: pass along
  243. return CSubclassWnd::WindowProc(hRealWnd, msg, wp, lp);
  244. }
  245. CDC* CSkinMenu::ReplaceSystemColors(CDC* pDCSrc, CDC* pDCDest, LPRECT pRect, LPRECT pClip)
  246. {
  247. int nOS = CSkinBase::GetOS();
  248. if (nOS == SBOS_95 || nOS == SBOS_NT4)
  249. return pDCSrc;
  250. // replace the system colors with skin colors
  251. CMap<COLORREF, COLORREF, int, int&> mapColors;
  252. // 1. replace the actual background color with COLOR_MENU
  253. const COLORREF COLORMENU = GetColor(COLOR_MENU);
  254. COLORREF crSrc, crDest = COLORMENU;
  255. if (m_nSelIndex != 0)
  256. crSrc = pDCSrc->GetPixel(pRect->right, pRect->top);
  257. else
  258. crSrc = pDCSrc->GetPixel(pRect->right, pRect->bottom);
  259. // see if user wants to render bkgnd
  260. if (crSrc != -1)
  261. {
  262. if (s_pRenderer && s_pRenderer->DrawMenuClientBkgnd(pDCDest, pRect, pClip))
  263. {
  264. // transparent blt
  265. CSkinBase::BitBlt(pDCDest, pRect->left, pRect->top, 
  266. pRect->right - pRect->left, 
  267. pRect->bottom - pRect->top, pDCSrc, 0, 0, SRCCOPY, crSrc);
  268. // swap dest and src
  269. SwapDCs(pDCSrc, pDCDest);
  270. }
  271. // else simple color replacement
  272. else if (ReplaceColor(pDCSrc, crSrc, pDCDest, crDest, pRect, pClip))
  273. {
  274. // swap dest and src
  275. SwapDCs(pDCSrc, pDCDest);
  276. }
  277. mapColors[crSrc] = 1;
  278. }
  279. // 2. replace other mapped colors 
  280. int nColor = sizeof(colors) / sizeof(colorMapping);
  281. while (nColor--)
  282. {
  283. int nTemp;
  284. int nSrcColor = colors[nColor].nSrcColor;
  285. crSrc = GetSysColor(nSrcColor);
  286. if (mapColors.Lookup(crSrc, nTemp))
  287. {
  288. // TRACE("CSkinMenu::ReplaceSystemColors - %d already replacedn", crSrc);
  289. continue;
  290. }
  291. int nDestColor = colors[nColor].nDestColor;
  292. crDest = GetColor(nDestColor);
  293. // if the dest color is COLORMENU let the user have first go
  294. if (crDest == COLORMENU && s_pRenderer && s_pRenderer->DrawMenuClientBkgnd(pDCDest, pRect, pClip))
  295. {
  296. // transparent blt
  297. CSkinBase::BitBlt(pDCDest, pRect->left, pRect->top, 
  298. pRect->right - pRect->left, 
  299. pRect->bottom - pRect->top, pDCSrc, 0, 0, SRCCOPY, crSrc);
  300. // swap dest and src
  301. SwapDCs(pDCSrc, pDCDest);
  302. }
  303. // else simple color replacement
  304. else if (ReplaceColor(pDCSrc, crSrc, pDCDest, crDest, pRect, pClip))
  305. {
  306. // swap dest and src
  307. SwapDCs(pDCSrc, pDCDest);
  308. }
  309. // else
  310. // TRACE("CSkinMenu::ReplaceSystemColors - GetSysColor(%d) == CSkinBase::GetColor(%d)n", nSrcColor, nDestColor);
  311. mapColors[crSrc] = 1;
  312. }
  313. return pDCSrc;
  314. }
  315. BOOL CSkinMenu::ReplaceColor(CDC* pDCSrc, COLORREF crSrc, CDC* pDCDest, COLORREF crDest, LPRECT pRect, LPRECT pClip)
  316. {
  317. if (crSrc == crDest)
  318. return FALSE;
  319. // else
  320. if (pClip)
  321. {
  322. pDCDest->FillSolidRect(pClip, crDest);
  323. CSkinBase::BitBlt(pDCDest, pClip->left, pClip->top, pClip->right - pClip->left, 
  324. pClip->bottom - pClip->top, pDCSrc, pClip->left, pClip->top, SRCCOPY, crSrc);
  325. }
  326. else
  327. {
  328. pDCDest->FillSolidRect(pRect, crDest);
  329. CSkinBase::BitBlt(pDCDest, pRect->left, pRect->top, pRect->right - pRect->left, 
  330. pRect->bottom - pRect->top, pDCSrc, pRect->left, pRect->top, SRCCOPY, crSrc);
  331. }
  332. return TRUE;
  333. }
  334. void CSkinMenu::OnPrintClient(CDC* pDC, DWORD dwFlags)
  335. {
  336. CRect rClient;
  337. GetClientRect(rClient);
  338. CRect rClip(rClient);
  339. // pDC->GetClipBox(rClip);
  340. // create standard back buffer and another dc on which 
  341. // to layer the background and foreground
  342. CDC dcMem, dcMem2;
  343. dcMem.CreateCompatibleDC(NULL);
  344. dcMem2.CreateCompatibleDC(NULL);
  345. // use screen dc for creating bitmaps because
  346. // menu dc's seem not to be standard.
  347. CDC* pDCScrn = CWnd::GetDesktopWindow()->GetDC();
  348. CBitmap bmMem, bmMem2;
  349. bmMem.CreateCompatibleBitmap(pDCScrn, rClient.right, rClient.bottom);
  350. bmMem2.CreateCompatibleBitmap(pDCScrn, rClient.right, rClient.bottom);
  351. // release screen dc asap
  352. CWnd::GetDesktopWindow()->ReleaseDC(pDCScrn);
  353. // prepare dc's
  354. dcMem.SetBkMode(TRANSPARENT);
  355. dcMem.SetBkColor(GetSysColor(COLOR_MENU));
  356. CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
  357. CFont* pOldFont = dcMem.SelectObject(GetFont(SBFONT_MENU));
  358. CBitmap* pOldBM2 = dcMem2.SelectObject(&bmMem2);
  359. // trim clip rgn
  360. if (rClip.top)
  361. dcMem.ExcludeClipRect(0, 0, rClient.right, rClip.top);
  362. if (rClip.bottom < rClient.bottom)
  363. dcMem.ExcludeClipRect(0, rClip.bottom, rClient.right, rClient.bottom);
  364. // draw background
  365. // dcMem.FillSolidRect(rClient, GetSysColor(COLOR_MENU));
  366. dcMem.FillSolidRect(rClip, GetSysColor(COLOR_MENU));
  367. // default draw
  368. CSubclassWnd::WindowProc(GetHwnd(), WM_PRINTCLIENT, (WPARAM)(HDC)dcMem, (LPARAM)dwFlags);
  369. // replace the system colors with skin colors
  370. CDC* pDCSrc = ReplaceSystemColors(&dcMem, &dcMem2, rClient, rClip);
  371. // blt the lot to pDC
  372. // pDC->BitBlt(0, 0, rClient.right, rClient.bottom, pDCSrc, 0, 0, SRCCOPY);
  373. pDC->BitBlt(rClip.left, rClip.top, rClip.Width(), rClip.Height(), 
  374. pDCSrc, rClip.left, rClip.top, SRCCOPY);
  375. // cleanup
  376. dcMem.SelectObject(pOldBM);
  377. dcMem.SelectObject(pOldFont);
  378. dcMem.DeleteDC();
  379. bmMem.DeleteObject();
  380. dcMem2.SelectObject(pOldBM2);
  381. dcMem2.DeleteDC();
  382. bmMem2.DeleteObject();
  383. }
  384. void CSkinMenu::OnPaint(CDC* pDC)
  385. {
  386. // construct a back buffer for the default draw
  387. CRect rClient;
  388. GetClientRect(rClient);
  389. CBitmap bmMem;
  390. bmMem.CreateCompatibleBitmap(pDC, rClient.right, rClient.bottom);
  391. CDC dcMem;
  392. dcMem.CreateCompatibleDC(NULL);
  393. dcMem.SetBkMode(TRANSPARENT);
  394. dcMem.SetBkColor(GetSysColor(COLOR_MENU));
  395. CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
  396. CFont* pOldFont = dcMem.SelectObject(GetFont(SBFONT_MENU));
  397. // draw background
  398. dcMem.FillSolidRect(rClient, GetSysColor(COLOR_MENU));
  399. // default draw
  400. CSubclassWnd::WindowProc(GetHwnd(), WM_PAINT, (WPARAM)(HDC)dcMem, 0);
  401. // create another dc on which to layer the background and foreground
  402. CDC dcMem2;
  403. dcMem2.CreateCompatibleDC(NULL);
  404. CBitmap bmMem2;
  405. bmMem2.CreateCompatibleBitmap(pDC, rClient.right, rClient.bottom);
  406. CBitmap* pOldBM2 = dcMem2.SelectObject(&bmMem2);
  407. // replace the system colors with skin colors
  408. CDC* pDCSrc = ReplaceSystemColors(&dcMem, &dcMem2, rClient, NULL);
  409. // blt the lot to pDC
  410. pDC->BitBlt(0, 0, rClient.right, rClient.bottom, pDCSrc, 0, 0, SRCCOPY);
  411. // cleanup
  412. dcMem.SelectObject(pOldBM);
  413. dcMem.SelectObject(pOldFont);
  414. dcMem.DeleteDC();
  415. bmMem.DeleteObject();
  416. dcMem2.SelectObject(pOldBM2);
  417. dcMem2.DeleteDC();
  418. bmMem2.DeleteObject();
  419. }
  420. void CSkinMenu::OnNcPaint(CDC* pDC)
  421. {
  422. int nOS = CSkinBase::GetOS();
  423. BOOL bIRender = !(nOS == SBOS_95 || nOS == SBOS_NT4);
  424. CRect rWindow, rClient;
  425. GetDrawRect(rWindow, rClient);
  426. CRect rClip;
  427. pDC->GetClipBox(rClip);
  428. // TRACE ("CSkinMenu::OnNcPaint(clip box = {%d x %d})n", rClip.Width(), rClip.Height());
  429. // back buffer
  430. CBitmap bmMem;
  431. bmMem.CreateCompatibleBitmap(pDC, rWindow.right, rWindow.bottom);
  432. CDC dcMem;
  433. dcMem.CreateCompatibleDC(NULL);
  434. CBitmap* pOldBM = dcMem.SelectObject(&bmMem);
  435. COLORREF crColorMenu = GetColor(COLOR_MENU);
  436. // draw sidebar
  437. CRect rSidebar(rWindow);
  438. rSidebar.DeflateRect(3, 3);
  439. rSidebar.right = rSidebar.left + m_nSidebarWidth;
  440. if (Sidebar() && (!s_pRenderer || !s_pRenderer->DrawMenuSidebar(&dcMem, rSidebar)))
  441. {
  442. dcMem.FillSolidRect(rSidebar, CSkinBase::VaryColor(GetColor(COLOR_3DSHADOW), 0.9f));
  443. }
  444. // then clip sidebar out
  445. dcMem.ExcludeClipRect(rSidebar);
  446. // draw nc bkgnd
  447. // note: do this ourselves under win95 to ensure continuity with client bkgnd
  448. if (!bIRender || !s_pRenderer || !s_pRenderer->DrawMenuNonClientBkgnd(&dcMem, rWindow))
  449. {
  450. dcMem.FillSolidRect(rWindow, crColorMenu);
  451. }
  452. // draw nc border
  453. if (!bIRender || !s_pRenderer || !s_pRenderer->DrawMenuBorder(&dcMem, rWindow))
  454. {
  455. COLORREF crShadow = GetColor(COLOR_3DSHADOW);
  456. if (Flat())
  457. dcMem.Draw3dRect(rWindow, crShadow, crShadow);
  458. else
  459. dcMem.Draw3dRect(rWindow, GetColor(COLOR_3DHIGHLIGHT), crShadow);
  460. }
  461. // blt to screen
  462. int nSaveDC = pDC->SaveDC(); // must restore dc to original state
  463. pDC->ExcludeClipRect(rClient);
  464. pDC->BitBlt(0, 0, rWindow.right, rWindow.bottom, &dcMem, 0, 0, SRCCOPY);
  465. pDC->RestoreDC(nSaveDC);
  466. // cleanup
  467. dcMem.SelectObject(pOldBM);
  468. }
  469. void CSkinMenu::GetDrawRect(LPRECT pWindow, LPRECT pClient)
  470. {
  471. CRect rWindow;
  472. GetWindowRect(rWindow);
  473. if (pClient)
  474. {
  475. GetClientRect(pClient);
  476. ClientToScreen(pClient);
  477. ::OffsetRect(pClient, -rWindow.left, -rWindow.top);
  478. }
  479. if (pWindow)
  480. {
  481. rWindow.OffsetRect(-rWindow.TopLeft());
  482. *pWindow = rWindow;
  483. }
  484. }
  485. COLORREF CSkinMenu::GetColor(int nColor)
  486. {
  487. return m_pGlobals ? m_pGlobals->GetColor(nColor) : CSkinGlobals::GetColorSt(nColor);
  488. }
  489. CFont* CSkinMenu::GetFont(int nFont)
  490. {
  491. return m_pGlobals ? m_pGlobals->GetFont(nFont) : CSkinGlobals::GetFontSt(nFont);
  492. }
  493. void CSkinMenu::SetContextWnd(HWND hWnd) 
  494. if (hWnd && ::IsWindow(hWnd))
  495. m_hContextWnd = hWnd;
  496. else
  497. m_hContextWnd = NULL; 
  498. }
  499. void CSkinMenu::SetMenu(HMENU hMenu, CSkinMenu* pParentMenu) 
  500. if (m_hMenu && hMenu) // already set
  501. return;
  502. // else
  503. if (hMenu && ::IsMenu(hMenu)) 
  504. m_hMenu = hMenu;
  505. else
  506. m_hMenu = NULL; 
  507. TRACE("CSkinMenu::SetMenu(hwnd = %08x, hmenu = %08x)n", m_hWndHooked, hMenu);
  508. m_pParentMenu = pParentMenu;
  509. }
  510. void CSkinMenu::GetInvalidRect(int nCurSel, int nPrevSel, LPRECT lpRect)
  511. {
  512. ASSERT (lpRect);
  513. if (!m_hMenu || nCurSel == REDRAWALL || nPrevSel == REDRAWALL)
  514. GetClientRect(lpRect);
  515. else if (m_hMenu)
  516. {
  517. ::SetRectEmpty(lpRect);
  518. if (nCurSel >= 0 || nPrevSel >= 0)
  519. {
  520. if (nCurSel >= 0)
  521. {
  522. GetMenuItemRect(NULL, m_hMenu, nCurSel, lpRect);
  523. }
  524. if (nPrevSel >= 0)
  525. {
  526. CRect rTemp;
  527. GetMenuItemRect(NULL, m_hMenu, nPrevSel, rTemp);
  528. ::UnionRect(lpRect, lpRect, rTemp);
  529. }
  530. // convert to client coords
  531. ScreenToClient(lpRect);
  532. }
  533. }
  534. }
  535. int CSkinMenu::GetCurSel()
  536. {
  537. ASSERT (m_hMenu);
  538. int nItem = GetMenuItemCount(m_hMenu);
  539. while (nItem--)
  540. {
  541. if (GetMenuState(m_hMenu, nItem, MF_BYPOSITION) & MF_HILITE)
  542. return nItem;
  543. }
  544. return -1; // nothing selected
  545. }