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

菜单

开发平台:

WINDOWS

  1. // SkinMenuMgr.cpp: implementation of the CSkinMenuMgr class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "SkinMenuMgr.h"
  6. #include "skinmenu.h"
  7. #include "wclassdefines.h"
  8. #include "skinbase.h"
  9. #include "winclasses.h"
  10. #ifndef NO_SKIN_INI
  11. #include "skininifile.h"
  12. #endif
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char THIS_FILE[]=__FILE__;
  16. #define new DEBUG_NEW
  17. #endif
  18. //////////////////////////////////////////////////////////////////////
  19. // Construction/Destruction
  20. //////////////////////////////////////////////////////////////////////
  21. CSkinMenuMgr::CSkinMenuMgr()
  22. {
  23. m_dwMenuStyle = SKMS_SIDEBAR;
  24. m_nSidebarWidth = 10;
  25. m_pCurSkinMenu = NULL;
  26. m_hCurContextWnd = NULL;
  27. m_hCurMenu = NULL;
  28. }
  29. CSkinMenuMgr::~CSkinMenuMgr()
  30. {
  31. // cleanup any remaining windows
  32. ASSERT (!m_mapMenus.GetCount());
  33. if (m_mapMenus.GetCount() != 0)
  34. {
  35. HWND hwnd;
  36. CSkinMenu* pSkin;
  37. POSITION pos = m_mapMenus.GetStartPosition();
  38. while (pos)
  39. {
  40. m_mapMenus.GetNextAssoc(pos, hwnd, pSkin);
  41. if (pSkin)
  42. delete pSkin;
  43. }
  44. m_mapMenus.RemoveAll();
  45. }
  46. m_skGlobals.Reset();
  47. }
  48. /////////////////////////////////////////////////////////////////////////////////
  49. // static methods start
  50. BOOL CSkinMenuMgr::Initialize(DWORD dwMenuStyle, int nSBWidth, BOOL bNotXP)
  51. {
  52. if (bNotXP && CSkinBase::GetOS() >= SBOS_XP)
  53. {
  54. return FALSE;
  55. }
  56. // only initialize once
  57. VERIFY(GetInstance().InitHooks(HM_CALLWNDPROC | HM_CBT));
  58. GetInstance().m_dwMenuStyle = dwMenuStyle;
  59. GetInstance().m_nSidebarWidth = nSBWidth;
  60. return TRUE;
  61. }
  62. #ifndef NO_SKIN_INI
  63. void CSkinMenuMgr::UnloadSkin()
  64. {
  65. GetInstance().m_skGlobals.UnloadSkin();
  66. }
  67. BOOL CSkinMenuMgr::LoadSkin(const CSkinIniGlobalsFile* pIniFile)
  68. {
  69. if (!pIniFile)
  70. return FALSE;
  71. GetInstance().m_skGlobals.LoadSkin(pIniFile);
  72. return TRUE;
  73. }
  74. #endif
  75. void CSkinMenuMgr::SetColor(int nColor, COLORREF color)
  76. {
  77. int nOS = CSkinBase::GetOS();
  78. if (nOS == SBOS_95 || nOS == SBOS_NT4)
  79. return;
  80. GetInstance().m_skGlobals.SetColor(nColor, color);
  81. }
  82. COLORREF CSkinMenuMgr::GetColor(int nColor)
  83. {
  84. return GetInstance().m_skGlobals.GetColor(nColor);
  85. }
  86. void CSkinMenuMgr::ClearColors()
  87. {
  88. GetInstance().m_skGlobals.Reset();
  89. }
  90. // static methods end
  91. ///////////////////////////////////////////////////////////////////////////////////
  92. //#define NO_SKINNING
  93. void CSkinMenuMgr::OnCallWndProc(const MSG& msg)
  94. {   
  95. static BOOL bSkinning = FALSE; // initialized first time only but persistent
  96. if (!bSkinning)
  97. {
  98. bSkinning = TRUE;
  99. #ifndef NO_SKINNING
  100. // skin/unskin menus at each and every opportunity 
  101. switch (msg.message)
  102. {
  103. case WM_CREATE:
  104. if (CSkinMenu::IsMenuWnd(msg.hwnd))
  105. {
  106. BOOL bRes = Skin(msg.hwnd);
  107. }
  108. break;
  109. case WM_WINDOWPOSCHANGING: 
  110. if (CSkinMenu::IsMenuWnd(msg.hwnd) && msg.lParam)
  111. {
  112. WINDOWPOS* pWPos = (WINDOWPOS*)msg.lParam;
  113. if (pWPos->flags & SWP_SHOWWINDOW)
  114. {
  115. BOOL bRes = Skin(msg.hwnd);
  116. }
  117. else if (pWPos->flags & SWP_HIDEWINDOW)
  118. {
  119. BOOL bRes = Unskin(msg.hwnd);
  120. }
  121. }
  122. break;
  123. case 0x1e2:
  124. if (CSkinMenu::IsMenuWnd(msg.hwnd) && msg.wParam)
  125. {
  126. BOOL bRes = Skin(msg.hwnd);
  127. if (!bRes)
  128. TRACE("Skin failed on 0x1e2");
  129. }
  130. break;
  131. case WM_SHOWWINDOW: 
  132. if (CSkinMenu::IsMenuWnd(msg.hwnd))
  133. {
  134. if (msg.wParam)
  135. {
  136. BOOL bRes = Skin(msg.hwnd);
  137. }
  138. else // if (!msg.wParam)
  139. {
  140. BOOL bRes = Unskin(msg.hwnd);
  141. }
  142. }
  143. break;
  144. case WM_DESTROY:
  145. case WM_NCDESTROY:
  146. if (CSkinMenu::IsMenuWnd(msg.hwnd))
  147. {
  148. BOOL bRes = Unskin(msg.hwnd);
  149. }
  150. break;
  151. // grab the menu handle at each and every opportunity
  152. //
  153. // notes:
  154. //
  155. // 1. menu bars generate a WM_INITMENUPOPUP prior to showing their menus
  156. //
  157. // 2. edit windows do not generate WM_INITMENUPOPUP prior to showing
  158. //    their context menu so the best we can do is grab their window handle
  159. //
  160. // 3. other controls display their context menus prior to generating
  161. //    a WM_INITMENUPOPUP
  162. case WM_CONTEXTMENU: // means a menu may be about to appear
  163. {
  164. m_pCurSkinMenu = NULL;
  165. m_hCurContextWnd = msg.hwnd;
  166. TRACE ("WM_CONTEXTMENU sent to window of type '%s'n", CWinClasses::GetClass(msg.hwnd));
  167. }
  168. break;
  169. case WM_INITMENUPOPUP:
  170. if (m_pCurSkinMenu && !m_pCurSkinMenu->GetMenu())
  171. {
  172. m_pCurSkinMenu->SetContextWnd(NULL);
  173. m_pCurSkinMenu->SetMenu((HMENU)msg.wParam, GetParentSkinMenu((HMENU)msg.wParam));
  174. m_hCurMenu = NULL;
  175. m_pCurSkinMenu = NULL;
  176. m_hCurContextWnd = NULL;
  177. }
  178. else // save for menu skinning
  179. m_hCurMenu = (HMENU)msg.wParam;
  180. }
  181. #endif
  182. bSkinning = FALSE;
  183. }
  184. }
  185. BOOL CSkinMenuMgr::OnCbt(int nCode, WPARAM wParam, LPARAM lParam)
  186. {   
  187. if (nCode == HCBT_SYSCOMMAND)
  188. {
  189. switch (wParam)
  190. {
  191. case SC_MOUSEMENU:
  192. if (lParam)
  193. {
  194. int xPos = GET_X_LPARAM(lParam);
  195. int yPos = GET_Y_LPARAM(lParam);
  196. HWND hwnd = WindowFromPoint(CPoint(xPos, yPos));
  197. if (hwnd && (GetWindowLong(hwnd, GWL_STYLE) & WS_SYSMENU))
  198. {
  199. // convert to window coords
  200. CRect rWindow;
  201. GetWindowRect(hwnd, rWindow);
  202. CPoint ptScreen(xPos, yPos);
  203. xPos -= rWindow.left;
  204. yPos -= rWindow.top;
  205. if (xPos > 0 && xPos < 16 && yPos > 0 && yPos < 16)
  206. {
  207. CSkinBase::DoSysMenu(CWnd::FromHandle(hwnd), ptScreen, NULL, TRUE);
  208. return TRUE; // handled
  209. }
  210. }
  211. }
  212. break;
  213. }
  214. }
  215. return FALSE;
  216. }
  217. CSkinMenu* CSkinMenuMgr::GetSkinMenu(HWND hWnd)
  218. {
  219. CSkinMenu* pSkin = NULL;
  220. m_mapMenus.Lookup(hWnd, pSkin);
  221. return pSkin;
  222. }
  223. BOOL CSkinMenuMgr::Unskin(HWND hWnd)
  224. {
  225. m_pCurSkinMenu = NULL;
  226. m_hCurContextWnd = NULL;
  227. m_hCurMenu = NULL;
  228. ASSERT (CSkinMenu::IsMenuWnd(hWnd));
  229. CSkinMenu* pSkinMenu = GetSkinMenu(hWnd);
  230. if (!pSkinMenu)
  231. return TRUE; // already done
  232. TRACE ("menu unskinned (%08X)n", (UINT)hWnd);
  233. m_mapMenus.RemoveKey(hWnd);
  234. pSkinMenu->DetachWindow();
  235. delete pSkinMenu;
  236. return TRUE;
  237. }
  238. BOOL CSkinMenuMgr::Skin(HWND hWnd)
  239. {
  240. ASSERT (CSkinMenu::IsMenuWnd(hWnd));
  241. CSkinMenu* pSkinMenu = GetSkinMenu(hWnd);
  242. if (pSkinMenu)
  243. return TRUE; // already done
  244. pSkinMenu = new CSkinMenu(&m_skGlobals, m_dwMenuStyle, m_nSidebarWidth);
  245. if (pSkinMenu && pSkinMenu->AttachWindow(hWnd))
  246. {
  247. TRACE ("menu skinned (%08X)n", (UINT)hWnd);
  248. m_pCurSkinMenu = pSkinMenu;
  249. m_pCurSkinMenu->SetContextWnd(m_hCurContextWnd);
  250. m_pCurSkinMenu->SetMenu(m_hCurMenu, GetParentSkinMenu(m_hCurMenu));
  251. m_mapMenus[hWnd] = pSkinMenu;
  252. return TRUE;
  253. }
  254. // else
  255. delete pSkinMenu;
  256. return FALSE;
  257. }
  258. CSkinMenu* CSkinMenuMgr::GetParentSkinMenu(HMENU hMenu)
  259. {
  260. if (!hMenu)
  261. return NULL;
  262. // search the map if CSkinMenus looking for a menu
  263. // having this menu as a popup
  264. HWND hwnd;
  265. CSkinMenu* pSkin;
  266. POSITION pos = m_mapMenus.GetStartPosition();
  267. while (pos)
  268. {
  269. m_mapMenus.GetNextAssoc(pos, hwnd, pSkin);
  270. const HMENU hOther = pSkin->GetMenu();
  271. if (hOther && hOther != hMenu)
  272. {
  273. // iterate the items looking for submenus
  274. int nMenu = GetMenuItemCount(hOther);
  275. while (nMenu--)
  276. {
  277. if (GetSubMenu(hOther, nMenu) == hMenu) // submenu
  278. return pSkin;
  279. }
  280. }
  281. }
  282. return NULL;
  283. }