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.

679 lines
16 KiB

  1. //
  2. // lbmenu.cpp
  3. //
  4. #include "private.h"
  5. #include "candmenu.h"
  6. #include "cuimenu.h"
  7. #include "globals.h"
  8. #include "candutil.h"
  9. #include "wcand.h"
  10. //
  11. //
  12. //
  13. #define g_dwMenuStyle UIWINDOW_TOPMOST | UIWINDOW_TOOLWINDOW | UIWINDOW_OFC10MENU | UIWINDOW_HASSHADOW
  14. //////////////////////////////////////////////////////////////////////////////
  15. //
  16. // CCandMenuItem
  17. //
  18. //////////////////////////////////////////////////////////////////////////////
  19. /* C C A N D M E N U I T E M */
  20. /*------------------------------------------------------------------------------
  21. ------------------------------------------------------------------------------*/
  22. CCandMenuItem::CCandMenuItem( CCandMenu *pCandMenu )
  23. {
  24. m_pCandMenu = pCandMenu;
  25. }
  26. /* ~ C C A N D M E N U I T E M */
  27. /*------------------------------------------------------------------------------
  28. ------------------------------------------------------------------------------*/
  29. CCandMenuItem::~CCandMenuItem( void )
  30. {
  31. }
  32. /* I N S E R T T O U I */
  33. /*------------------------------------------------------------------------------
  34. ------------------------------------------------------------------------------*/
  35. BOOL CCandMenuItem::InsertToUI( CUIFMenu *pCuiMenu )
  36. {
  37. UINT uFlags = MF_BYPOSITION;
  38. if (_dwFlags & TF_LBMENUF_SEPARATOR) {
  39. uFlags |= MF_SEPARATOR;
  40. pCuiMenu->InsertSeparator();
  41. return TRUE;
  42. }
  43. if (_dwFlags & TF_LBMENUF_SUBMENU) {
  44. Assert(m_pCandMenu);
  45. CUIFMenu *pCuiMenuSub = ((CCandMenu *)_pSubMenu)->CreateMenuUI( TRUE /* sub menu */ );
  46. CUIFMenuItem *pCuiItem = new CUIFMenuItem(pCuiMenu);
  47. if (!pCuiItem) {
  48. return FALSE;
  49. }
  50. pCuiItem->Initialize();
  51. pCuiItem->Init((UINT)-1, _bstr);
  52. pCuiItem->SetSub(pCuiMenuSub);
  53. if (_hbmp) {
  54. pCuiItem->SetBitmap(_hbmp);
  55. }
  56. if (_hbmpMask) {
  57. pCuiItem->SetBitmapMask(_hbmpMask);
  58. }
  59. pCuiMenu->InsertItem(pCuiItem);
  60. return TRUE;
  61. }
  62. CUIFMenuItem *pCuiItem = new CUIFMenuItem(pCuiMenu);
  63. if (!pCuiItem) {
  64. return FALSE;
  65. }
  66. pCuiItem->Initialize();
  67. pCuiItem->Init(_uId, _bstr);
  68. if (_dwFlags & TF_LBMENUF_GRAYED) {
  69. pCuiItem->Gray(TRUE);
  70. }
  71. if (_dwFlags & TF_LBMENUF_CHECKED) {
  72. pCuiItem->Check(TRUE);
  73. }
  74. else if (_dwFlags & TF_LBMENUF_RADIOCHECKED) {
  75. pCuiItem->RadioCheck(TRUE);
  76. }
  77. if (_hbmp) {
  78. pCuiItem->SetBitmap(_hbmp);
  79. }
  80. if (_hbmpMask) {
  81. pCuiItem->SetBitmapMask(_hbmpMask);
  82. }
  83. pCuiMenu->InsertItem(pCuiItem);
  84. return TRUE;
  85. }
  86. //////////////////////////////////////////////////////////////////////////////
  87. //
  88. // CCandMenu
  89. //
  90. //////////////////////////////////////////////////////////////////////////////
  91. /* C C A N D M E N U */
  92. /*------------------------------------------------------------------------------
  93. ------------------------------------------------------------------------------*/
  94. CCandMenu::CCandMenu( HINSTANCE hInst )
  95. {
  96. NONCLIENTMETRICS ncm;
  97. m_hInst = hInst;
  98. m_pCUIMenu = NULL;
  99. memset( &m_lf, 0, sizeof(m_lf) );
  100. m_pCandWnd = NULL;
  101. ncm.cbSize = sizeof(ncm);
  102. if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, FALSE)) {
  103. ConvertLogFontAtoW( &ncm.lfMenuFont, &m_lf );
  104. }
  105. }
  106. /* ~ C C A N D M E N U */
  107. /*------------------------------------------------------------------------------
  108. ------------------------------------------------------------------------------*/
  109. CCandMenu::~CCandMenu()
  110. {
  111. }
  112. /* A D D R E F */
  113. /*------------------------------------------------------------------------------
  114. ------------------------------------------------------------------------------*/
  115. STDAPI_(ULONG) CCandMenu::AddRef(void)
  116. {
  117. return CCicLibMenu::AddRef();
  118. }
  119. /* R E L E A S E */
  120. /*------------------------------------------------------------------------------
  121. ------------------------------------------------------------------------------*/
  122. STDAPI_(ULONG) CCandMenu::Release(void)
  123. {
  124. return CCicLibMenu::Release();
  125. }
  126. /* Q U E R Y I N T E R F A C E */
  127. /*------------------------------------------------------------------------------
  128. ------------------------------------------------------------------------------*/
  129. STDAPI CCandMenu::QueryInterface(REFIID riid, void **ppvObj)
  130. {
  131. if (IsEqualIID( riid, IID_ITfCandUIMenuExtension )) {
  132. if (ppvObj == NULL) {
  133. return E_POINTER;
  134. }
  135. *ppvObj = SAFECAST( this, ITfCandUIMenuExtension* );
  136. AddRef();
  137. return S_OK;
  138. }
  139. return CCicLibMenu::QueryInterface( riid, ppvObj );
  140. }
  141. /* S E T F O N T */
  142. /*------------------------------------------------------------------------------
  143. ------------------------------------------------------------------------------*/
  144. STDAPI CCandMenu::SetFont( LOGFONTW *plf )
  145. {
  146. if (plf == NULL) {
  147. return E_INVALIDARG;
  148. }
  149. m_lf = *plf;
  150. return S_OK;
  151. }
  152. /* G E T F O N T */
  153. /*------------------------------------------------------------------------------
  154. ------------------------------------------------------------------------------*/
  155. STDAPI CCandMenu::GetFont( LOGFONTW *plf )
  156. {
  157. if (plf == NULL) {
  158. return E_INVALIDARG;
  159. }
  160. *plf = m_lf;
  161. return S_OK;
  162. }
  163. /* S H O W P O P U P */
  164. /*------------------------------------------------------------------------------
  165. ------------------------------------------------------------------------------*/
  166. UINT CCandMenu::ShowPopup( CCandWindowBase *pCandWnd, const POINT pt, const RECT *prcArea )
  167. {
  168. if (m_pCUIMenu) {
  169. return 0;
  170. }
  171. m_pCandWnd = pCandWnd;
  172. UINT uRet = 0;
  173. if (m_pCUIMenu = CreateMenuUI( FALSE /* not sub menu */)) {
  174. uRet = m_pCUIMenu->ShowModalPopup( m_pCandWnd, prcArea, TRUE );
  175. delete m_pCUIMenu;
  176. m_pCUIMenu = NULL;
  177. }
  178. m_pCandWnd = NULL;
  179. return uRet;
  180. }
  181. /* C L O S E P O P U P */
  182. /*------------------------------------------------------------------------------
  183. ------------------------------------------------------------------------------*/
  184. void CCandMenu::ClosePopup( void )
  185. {
  186. if (m_pCUIMenu != NULL) {
  187. PostThreadMessage( GetCurrentThreadId(), WM_NULL, 0, 0 );
  188. }
  189. }
  190. /* C R E A T E M E N U U I */
  191. /*------------------------------------------------------------------------------
  192. ------------------------------------------------------------------------------*/
  193. CUIFMenu *CCandMenu::CreateMenuUI( BOOL fSubMenu )
  194. {
  195. CUIFCandMenu *pCuiMenu;
  196. int i;
  197. if (fSubMenu) {
  198. pCuiMenu = new CUIFCandMenu( m_hInst, g_dwMenuStyle, 0 );
  199. }
  200. else {
  201. pCuiMenu = new CUIFCandMenuParent( m_hInst, g_dwMenuStyle, 0, m_pCandWnd );
  202. }
  203. pCuiMenu->Initialize();
  204. pCuiMenu->ResetMenuFont( &m_lf );
  205. for (i = 0; i < _rgItem.Count(); i++) {
  206. CCandMenuItem *pItem = (CCandMenuItem *)_rgItem.Get(i);
  207. pItem->InsertToUI( pCuiMenu );
  208. }
  209. return pCuiMenu;
  210. }
  211. /* G E T M E N U U I */
  212. /*------------------------------------------------------------------------------
  213. ------------------------------------------------------------------------------*/
  214. CUIFMenu *CCandMenu::GetMenuUI( void )
  215. {
  216. return m_pCUIMenu;
  217. }
  218. //
  219. //
  220. //
  221. /* C U I F C A N D M E N U */
  222. /*------------------------------------------------------------------------------
  223. ------------------------------------------------------------------------------*/
  224. CUIFCandMenu::CUIFCandMenu( HINSTANCE hInst, DWORD dwWndStyle, DWORD dwMenuStyle ) : CUIFMenu( hInst, dwWndStyle, dwMenuStyle )
  225. {
  226. }
  227. /* ~ C U I F C A N D M E N U */
  228. /*------------------------------------------------------------------------------
  229. ------------------------------------------------------------------------------*/
  230. CUIFCandMenu::~CUIFCandMenu( void )
  231. {
  232. }
  233. /* R E S E T M E N U F O N T */
  234. /*------------------------------------------------------------------------------
  235. ------------------------------------------------------------------------------*/
  236. void CUIFCandMenu::ResetMenuFont( LOGFONTW *plf )
  237. {
  238. ClearMenuFont();
  239. SetFont( OurCreateFontIndirectW( plf ) );
  240. }
  241. //
  242. //
  243. //
  244. /* C U I F C A N D M E N U P A R E N T */
  245. /*------------------------------------------------------------------------------
  246. ------------------------------------------------------------------------------*/
  247. CUIFCandMenuParent::CUIFCandMenuParent( HINSTANCE hInst, DWORD dwWndStyle, DWORD dwMenuStyle, CCandWindowBase *pCandWnd ) : CUIFCandMenu( hInst, dwWndStyle, dwMenuStyle )
  248. {
  249. m_pCandWnd = pCandWnd;
  250. }
  251. /* ~ C U I F C A N D M E N U P A R E N T */
  252. /*------------------------------------------------------------------------------
  253. ------------------------------------------------------------------------------*/
  254. CUIFCandMenuParent::~CUIFCandMenuParent( void )
  255. {
  256. UninstallHook();
  257. }
  258. /* I N I T S H O W */
  259. /*------------------------------------------------------------------------------
  260. ------------------------------------------------------------------------------*/
  261. BOOL CUIFCandMenuParent::InitShow( CUIFWindow *pcuiWndParent, const RECT *prc, BOOL fVertical, BOOL fAnimate )
  262. {
  263. BOOL fSucceed = TRUE;
  264. if (!CUIFMenu::InitShow( pcuiWndParent, prc, fVertical, fAnimate )) {
  265. fSucceed = FALSE;
  266. }
  267. if (!InstallHook()) {
  268. fSucceed = FALSE;
  269. }
  270. if (m_pCandWnd != NULL) {
  271. m_pCandWnd->OnMenuOpened();
  272. }
  273. return fSucceed;
  274. }
  275. /* U N I N I T S H O W */
  276. /*------------------------------------------------------------------------------
  277. ------------------------------------------------------------------------------*/
  278. BOOL CUIFCandMenuParent::UninitShow()
  279. {
  280. BOOL fSucceed = TRUE;
  281. if (!CUIFMenu::UninitShow()) {
  282. fSucceed = FALSE;
  283. }
  284. if (!UninstallHook()) {
  285. fSucceed = FALSE;
  286. }
  287. if (m_pCandWnd != NULL) {
  288. m_pCandWnd->OnMenuClosed();
  289. }
  290. return fSucceed;
  291. }
  292. /* M O D A L M E S S A G E L O O P */
  293. /*------------------------------------------------------------------------------
  294. NOTE: we need to use PeekMessage to cancel candidate menu
  295. in unknown mouse message (w/o eating...)
  296. ------------------------------------------------------------------------------*/
  297. void CUIFCandMenuParent::ModalMessageLoop( void )
  298. {
  299. MSG msg;
  300. while (TRUE) {
  301. while (!PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
  302. WaitMessage();
  303. }
  304. if (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) {
  305. if (msg.message == WM_NULL) {
  306. break;
  307. }
  308. else if (msg.message == WM_QUIT) {
  309. PostQuitMessage( (int)msg.wParam );
  310. break;
  311. }
  312. // check hooked mouse message (messages sent to another window)
  313. else if (msg.message == g_msgHookedMouse) {
  314. if (((msg.wParam != WM_MOUSEMOVE) && (msg.wParam != WM_NCMOUSEMOVE))) {
  315. CancelMenu();
  316. break;
  317. }
  318. msg.hwnd = GetWnd();
  319. msg.message = (UINT)msg.wParam;
  320. msg.wParam = 0;
  321. }
  322. // check hooked keyboard messages (all keyboard messages)
  323. else if (msg.message == g_msgHookedKey) {
  324. UINT message;
  325. CUIFMenu *pMenuObj = GetTopSubMenu();
  326. if (HIWORD(msg.lParam) & KF_ALTDOWN) {
  327. message = (HIWORD(msg.lParam) & KF_UP) ? WM_SYSKEYUP : WM_SYSKEYDOWN;
  328. }
  329. else {
  330. message = (HIWORD(msg.lParam) & KF_UP) ? WM_KEYUP : WM_KEYDOWN;
  331. }
  332. if (message == WM_SYSKEYDOWN) {
  333. CancelMenu();
  334. }
  335. msg.hwnd = (pMenuObj != NULL) ? pMenuObj->GetWnd() : NULL;
  336. msg.message = message;
  337. }
  338. TranslateMessage(&msg);
  339. DispatchMessage(&msg);
  340. }
  341. }
  342. }
  343. /* I N S T A L L H O O K */
  344. /*------------------------------------------------------------------------------
  345. ------------------------------------------------------------------------------*/
  346. BOOL CUIFCandMenuParent::InstallHook( void )
  347. {
  348. HHOOK hHookKeyboard;
  349. HHOOK hHookMouse;
  350. if (!g_ShareMem.Create()) {
  351. return FALSE;
  352. }
  353. if (!g_ShareMem.LockData()) {
  354. return FALSE;
  355. }
  356. hHookKeyboard = SetWindowsHookEx( WH_KEYBOARD, KeyboardProc, m_hInstance, NULL );
  357. hHookMouse = SetWindowsHookEx( WH_MOUSE, MouseProc, m_hInstance, NULL );
  358. g_ShareMem.GetData()->dwThreadId = GetCurrentThreadId();
  359. g_ShareMem.GetData()->hHookKeyboard = hHookKeyboard;
  360. g_ShareMem.GetData()->hHookMouse = hHookMouse;
  361. g_ShareMem.GetData()->hWndMenu = GetWnd();
  362. g_ShareMem.UnlockData();
  363. return (hHookKeyboard != NULL) && (hHookMouse != NULL);
  364. }
  365. /* U N I N S T A L L H O O K */
  366. /*------------------------------------------------------------------------------
  367. ------------------------------------------------------------------------------*/
  368. BOOL CUIFCandMenuParent::UninstallHook( void )
  369. {
  370. HHOOK hHook;
  371. if (!g_ShareMem.LockData()) {
  372. return FALSE;
  373. }
  374. if (g_ShareMem.GetData()->dwThreadId != GetCurrentThreadId()) {
  375. g_ShareMem.UnlockData();
  376. return FALSE;
  377. }
  378. hHook = g_ShareMem.GetData()->hHookKeyboard;
  379. if (hHook != NULL) {
  380. UnhookWindowsHookEx( hHook );
  381. }
  382. hHook = g_ShareMem.GetData()->hHookMouse;
  383. if (hHook != NULL) {
  384. UnhookWindowsHookEx( hHook );
  385. }
  386. g_ShareMem.GetData()->dwThreadId = 0;
  387. g_ShareMem.GetData()->hHookKeyboard = NULL;
  388. g_ShareMem.GetData()->hHookMouse = NULL;
  389. g_ShareMem.GetData()->hWndMenu = NULL;
  390. g_ShareMem.UnlockData();
  391. g_ShareMem.Close();
  392. return TRUE;
  393. }
  394. /* K E Y B O A R D P R O C */
  395. /*------------------------------------------------------------------------------
  396. Hook function for keyboard message
  397. Forward all keyboard message as g_msgHookedKey to the manu window thread
  398. ------------------------------------------------------------------------------*/
  399. LRESULT CALLBACK CUIFCandMenuParent::KeyboardProc( int code, WPARAM wParam, LPARAM lParam )
  400. {
  401. LRESULT lResult = 0;
  402. BOOL fEatMessage = FALSE;
  403. if (!g_ShareMem.LockData()) {
  404. return 0;
  405. }
  406. if (code == HC_ACTION || code == HC_NOREMOVE) {
  407. PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedKey, wParam, lParam );
  408. fEatMessage = TRUE;
  409. }
  410. if ((code < 0) || !fEatMessage) {
  411. lResult = CallNextHookEx( g_ShareMem.GetData()->hHookKeyboard, code, wParam, lParam );
  412. }
  413. else {
  414. lResult = (LRESULT)TRUE;
  415. }
  416. g_ShareMem.UnlockData();
  417. return lResult;
  418. }
  419. /* M O U S E P R O C */
  420. /*------------------------------------------------------------------------------
  421. Hook function for mouse message
  422. Forward mouse message sent to non-menu window (excluding mouse movement)
  423. as g_msgHookedMouse to the manu window thread
  424. ------------------------------------------------------------------------------*/
  425. LRESULT CALLBACK CUIFCandMenuParent::MouseProc( int code, WPARAM wParam, LPARAM lParam )
  426. {
  427. LRESULT lResult = 0;
  428. BOOL fEatMessage = FALSE;
  429. if (!g_ShareMem.LockData()) {
  430. return 0;
  431. }
  432. if (code == HC_ACTION || code == HC_NOREMOVE) {
  433. MOUSEHOOKSTRUCT *pmhs = (MOUSEHOOKSTRUCT *)lParam;
  434. UINT message = (UINT)wParam;
  435. if (GetCurrentThreadId() == g_ShareMem.GetData()->dwThreadId) {
  436. HWND hWndTemp = pmhs->hwnd;
  437. HWND hWndMenu = g_ShareMem.GetData()->hWndMenu;
  438. while ((hWndTemp != NULL) && (hWndTemp != hWndMenu)) {
  439. hWndTemp = GetParent( hWndTemp );
  440. }
  441. if (hWndTemp == NULL /* not menu window */) {
  442. if ((message != WM_NCMOUSEMOVE) && (message != WM_MOUSEMOVE)) {
  443. PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedMouse, wParam, MAKELPARAM(pmhs->pt.x, pmhs->pt.y) );
  444. }
  445. else {
  446. fEatMessage = (message == WM_NCMOUSEMOVE);
  447. }
  448. }
  449. }
  450. else {
  451. if ((message != WM_NCMOUSEMOVE) && (message != WM_MOUSEMOVE)) {
  452. PostThreadMessage( g_ShareMem.GetData()->dwThreadId, g_msgHookedMouse, wParam, MAKELPARAM(pmhs->pt.x, pmhs->pt.y) );
  453. }
  454. }
  455. }
  456. if ((code < 0) || !fEatMessage) {
  457. lResult = CallNextHookEx( g_ShareMem.GetData()->hHookMouse, code, wParam, lParam );
  458. }
  459. else {
  460. lResult = (LRESULT)TRUE;
  461. }
  462. g_ShareMem.UnlockData();
  463. return lResult;
  464. }