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.

2879 lines
75 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: inplace.cpp
  7. //
  8. // Contents: Implementation of OLE inplace editing API's
  9. //
  10. // Classes: CFrame implementation, used to store per-window info
  11. //
  12. // Functions: OleCreateMenuDescriptor
  13. // OleSetMenuDescriptor
  14. // OleDestroyMenuDescriptor
  15. // OleTranslateAccelerator
  16. // IsAccelerator
  17. // FrameWndFilterProc
  18. // MessageFilterProc
  19. //
  20. //
  21. // History: dd-mmm-yy Author Comment
  22. // 31-Mar-94 ricksa Fixed menu merge bug & added some comments
  23. // 23-Feb-94 alexgo added call tracing
  24. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  25. // 31-Dec-93 ChrisWe fixed casts in OutputDebugStrings
  26. // 07-Dec-93 alexgo merged changes with shipped 16bit 2.01a
  27. // (RC9). Also removed lots of bad inlining.
  28. // 01-Dec-93 alexgo 32bit port, made globals static
  29. // 07-Dec-92 srinik Converted frame filter implementatio
  30. // into a C++ class implementation.
  31. // So, most of the code is rewritten.
  32. // 09-Jul-92 srinik author
  33. //
  34. // Notes: REVIEW32: we need to do something about the new
  35. // focus management policy for NT (re TonyWi's mail)
  36. //
  37. //--------------------------------------------------------------------------
  38. #include <le2int.h>
  39. #pragma SEG(inplace)
  40. #include "inplace.h"
  41. NAME_SEG(InPlace)
  42. ASSERTDATA
  43. // to keep the code bases common
  44. // REVIEW32: we may want to clean this up a bit
  45. #ifdef WIN32
  46. #define FARPROC WNDPROC
  47. #endif
  48. #ifdef WIN32
  49. // we'd be faster if we used an atom instead of a string!
  50. static const OLECHAR szPropFrameFilter[] = OLESTR("pFrameFilter");
  51. #else
  52. static const OLECHAR szPropFrameFilterH[] = OLESTR("pFrameFilterH");
  53. static const OLECHAR szPropFrameFilterL[] = OLESTR("pFrameFilterL");
  54. #endif //WIN32
  55. static WORD wSignature; // = (WORD) { 'S', 'K' }
  56. static HHOOK hMsgHook = NULL;
  57. static PCFRAMEFILTER pFrameFilter = NULL;
  58. // the values for these globals are set in ole2.cpp
  59. UINT uOmPostWmCommand;
  60. UINT uOleMessage;
  61. #define OM_CLEAR_MENU_STATE 0 // lParam is NULL
  62. #define OM_COMMAND_ID 1 // LOWORD(lParam) contains
  63. // the command ID
  64. //+-------------------------------------------------------------------------
  65. //
  66. // Function: IsHmenuEqual
  67. //
  68. // Synopsis: Test whether two menu handles are equal taking into
  69. // account whether one might be a Win16 handle.
  70. //
  71. // History: dd-mmm-yy Author Comment
  72. // 31-May-94 Ricksa Created
  73. //
  74. //--------------------------------------------------------------------------
  75. inline BOOL IsHmenuEqual(HMENU hmenu1, HMENU hmenu2)
  76. {
  77. #ifdef _WIN64
  78. //
  79. // Sundown v-thief ( in accordance with Jerry Shea's feedback ):
  80. //
  81. // At this time - 07/98 - all the bits of the HMENUs have to be equal
  82. //
  83. return hmenu1 == hmenu2;
  84. #else // !_WIN64
  85. if (HIWORD(hmenu1) == 0 || HIWORD(hmenu2) == 0)
  86. {
  87. return LOWORD(hmenu1) == LOWORD(hmenu2);
  88. }
  89. else
  90. {
  91. return hmenu1 == hmenu2;
  92. }
  93. #endif // !_WIN64
  94. }
  95. //+-------------------------------------------------------------------------
  96. //
  97. // Class: CPaccel
  98. //
  99. // Purpose: Handles enumeration of ACCEL table for IsAccelerator
  100. //
  101. // Interface: InitLPACCEL - Initialize object
  102. // operator-> Get pointer to current ACCEL in enumeration
  103. // Next - bump current pointer
  104. //
  105. // History: dd-mmm-yy Author Comment
  106. // 14-Apr-94 Ricksa Created
  107. //
  108. // Notes: This class also guarantees clean up of the
  109. // allocated accelerator table & to localize the differences
  110. // between Win16 & Win32 within this class.
  111. //
  112. //--------------------------------------------------------------------------
  113. class CPaccelEnum : public CPrivAlloc
  114. {
  115. public:
  116. CPaccelEnum(void);
  117. inline ~CPaccelEnum(void);
  118. BOOL InitLPACCEL(HACCEL haccel, int cAccel);
  119. LPACCEL operator->(void);
  120. void Next(void);
  121. private:
  122. LPACCEL _lpaccel;
  123. #ifdef WIN32
  124. LPACCEL _lpaccelBase;
  125. #else // !WIN32
  126. HACCEL _haccel;
  127. #endif // WIN32
  128. };
  129. //+-------------------------------------------------------------------------
  130. //
  131. // Function: CPaccelEnum::CPaccelEnum
  132. //
  133. // Synopsis: Initialize object to zero
  134. //
  135. // History: dd-mmm-yy Author Comment
  136. // 14-Apr-94 Ricksa Created
  137. //
  138. //--------------------------------------------------------------------------
  139. inline CPaccelEnum::CPaccelEnum(void) : _lpaccel(NULL)
  140. {
  141. #ifdef WIN32
  142. // In Win32, we allocate the memory so we need to keep track of the
  143. // base of the memory that we allocated.
  144. _lpaccelBase = NULL;
  145. #else // !WIN32
  146. // In Win16, we release by unlock resource so we need to keep track of
  147. // the accelerator handle.
  148. _haccel = NULL;
  149. #endif // WIN32
  150. }
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Function: CPaccelEnum::~CPaccelEnum
  154. //
  155. // Synopsis: Free resources connected with resource table
  156. //
  157. // History: dd-mmm-yy Author Comment
  158. // 14-Apr-94 Ricksa Created
  159. //
  160. //--------------------------------------------------------------------------
  161. inline CPaccelEnum::~CPaccelEnum(void)
  162. {
  163. #ifdef WIN32
  164. PrivMemFree(_lpaccelBase);
  165. #else // !WIN32
  166. UnlockResource(hAccel);
  167. #endif // WIN32
  168. }
  169. //+-------------------------------------------------------------------------
  170. //
  171. // Function: CPaccelEnum::InitLPACCEL
  172. //
  173. // Synopsis: Initialize Accelerator table pointer
  174. //
  175. // Arguments: [haccel] - handle to accelerator table
  176. // [cAccel] - count of entries in the table
  177. //
  178. // Returns: TRUE - table was allocated successfully
  179. // FALSE - table could not be allocated
  180. //
  181. // History: dd-mmm-yy Author Comment
  182. // 14-Apr-94 Ricksa Created
  183. //
  184. //--------------------------------------------------------------------------
  185. inline BOOL CPaccelEnum::InitLPACCEL(HACCEL haccel, int cAccel)
  186. {
  187. #ifdef WIN32
  188. // Allocate the memory for the table. If that succeeds, then copy
  189. // the accelerator table. Note that if _lpaccelBase gets allocated,
  190. // but CopyAcceleratorTable fails, the memory will be cleaned up
  191. // in the destructor.
  192. if (((_lpaccelBase
  193. = (LPACCEL) PrivMemAlloc(cAccel * sizeof(ACCEL))) != NULL)
  194. && (CopyAcceleratorTable(haccel, _lpaccelBase, cAccel) == cAccel))
  195. {
  196. _lpaccel = _lpaccelBase;
  197. return TRUE;
  198. }
  199. return FALSE;
  200. #else // !WIN32
  201. // Just lock the resource
  202. return ((_lpaccel = LockResource(haccel)) != NULL);
  203. #endif // WIN32
  204. }
  205. //+-------------------------------------------------------------------------
  206. //
  207. // Function: CPaccelEnum::operator->
  208. //
  209. // Synopsis: Return pointer to accelerator table
  210. //
  211. // History: dd-mmm-yy Author Comment
  212. // 14-Apr-94 Ricksa Created
  213. //
  214. //--------------------------------------------------------------------------
  215. inline LPACCEL CPaccelEnum::operator->(void)
  216. {
  217. AssertSz((_lpaccel != NULL), "CPaccelEnum::operator-> _lpaccel NULL!");
  218. return _lpaccel;
  219. }
  220. //+-------------------------------------------------------------------------
  221. //
  222. // Function: CPaccelEnum::Next
  223. //
  224. // Synopsis: Bump enumeration pointer
  225. //
  226. // History: dd-mmm-yy Author Comment
  227. // 14-Apr-94 Ricksa Created
  228. //
  229. //--------------------------------------------------------------------------
  230. inline void CPaccelEnum::Next(void)
  231. {
  232. AssertSz((_lpaccel != NULL), "CPaccelEnum::Next _lpaccel NULL!");
  233. _lpaccel++;
  234. }
  235. //+-------------------------------------------------------------------------
  236. //
  237. // Function: OleCreateMenuDescriptor
  238. //
  239. // Synopsis: creates a descriptor from a combined menu (for use in
  240. // dispatching menu messages)
  241. //
  242. // Effects:
  243. //
  244. // Arguments: [hmenuCombined] -- handle the combined menu
  245. // [lpMenuWidths] -- an array of 6 longs with the
  246. // the number of menus in each
  247. // group
  248. //
  249. // Requires:
  250. //
  251. // Returns: handle to an OLEMENU
  252. //
  253. // Signals:
  254. //
  255. // Modifies:
  256. //
  257. // Algorithm: Allocates space for enough ole menu items (total of all the
  258. // combined menues) and then fills in each ole menu item from
  259. // the combined menu
  260. //
  261. // History: dd-mmm-yy Author Comment
  262. // 01-Dec-93 alexgo 32bit port
  263. //
  264. // Notes: if hmenuCombined is NULL, we still allocate the ole menu
  265. // descriptor handle
  266. //
  267. //--------------------------------------------------------------------------
  268. #pragma SEG(OleCreateMenuDescriptor)
  269. STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
  270. LPOLEMENUGROUPWIDTHS lplMenuWidths)
  271. {
  272. OLETRACEIN((API_OleCreateMenuDescriptor, PARAMFMT("hmenuCombined= %h, lplMenuWidths= %tw"),
  273. hmenuCombined, lplMenuWidths));
  274. VDATEHEAP();
  275. int iGroupCnt, n;
  276. int iMenuCnt;
  277. HGLOBAL hOleMenu;
  278. LPOLEMENU lpOleMenu;
  279. LPOLEMENUITEM lpMenuList;
  280. DWORD dwOleMenuItemsSize = 0;
  281. LEDebugOut((DEB_TRACE, "%p _IN OleCreateMenuDescriptor ( %lx , "
  282. "%p )\n", NULL, hmenuCombined, lplMenuWidths));
  283. if (hmenuCombined)
  284. {
  285. GEN_VDATEPTRIN_LABEL( lplMenuWidths, OLEMENUGROUPWIDTHS,
  286. (HOLEMENU)NULL, errRtn, hOleMenu );
  287. iMenuCnt = 0;
  288. for (iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
  289. {
  290. iMenuCnt += (int) lplMenuWidths->width[iGroupCnt];
  291. }
  292. if (iMenuCnt == 0)
  293. {
  294. hOleMenu = NULL;
  295. goto errRtn;
  296. }
  297. dwOleMenuItemsSize = (iMenuCnt-1) * sizeof(OLEMENUITEM);
  298. }
  299. hOleMenu = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT,
  300. sizeof(OLEMENU) + dwOleMenuItemsSize);
  301. if (!hOleMenu)
  302. {
  303. goto errRtn;
  304. }
  305. if (! (lpOleMenu = (LPOLEMENU) GlobalLock(hOleMenu)))
  306. {
  307. GlobalFree(hOleMenu);
  308. hOleMenu = NULL;
  309. goto errRtn;
  310. }
  311. lpOleMenu->wSignature = wSignature;
  312. lpOleMenu->hmenuCombined = PtrToUlong(hmenuCombined);
  313. lpOleMenu->lMenuCnt = (LONG) iMenuCnt;
  314. if (! hmenuCombined)
  315. {
  316. goto Exit;
  317. }
  318. lpMenuList = lpOleMenu->menuitem;
  319. for (iMenuCnt = 0, iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
  320. {
  321. lpOleMenu->MenuWidths.width[iGroupCnt] =
  322. lplMenuWidths->width[iGroupCnt];
  323. for (n = 0; n < lplMenuWidths->width[iGroupCnt]; n++)
  324. {
  325. lpMenuList->fObjectMenu = (iGroupCnt % 2);
  326. if (GetSubMenu(hmenuCombined, iMenuCnt) != NULL)
  327. {
  328. lpMenuList->fwPopup = MF_POPUP;
  329. lpMenuList->item = PtrToUlong(GetSubMenu(
  330. hmenuCombined, iMenuCnt));
  331. }
  332. else
  333. {
  334. lpMenuList->fwPopup = NULL;
  335. lpMenuList->item = GetMenuItemID (
  336. hmenuCombined, iMenuCnt);
  337. }
  338. lpMenuList++;
  339. iMenuCnt++;
  340. }
  341. }
  342. Exit:
  343. GlobalUnlock(hOleMenu);
  344. errRtn:
  345. LEDebugOut((DEB_TRACE, "%p OUT OleCreateMenuDescriptor ( %lx )\n",
  346. NULL, hOleMenu));
  347. OLETRACEOUTEX((API_OleCreateMenuDescriptor, RETURNFMT("%h"), hOleMenu));
  348. return (HOLEMENU) hOleMenu;
  349. }
  350. //+-------------------------------------------------------------------------
  351. //
  352. // Function: OleSetMenuDescriptor
  353. //
  354. // Synopsis: Called by the SetMenu method on the IOleInPlace frame
  355. // interface. This API adds(removes) the FrameWndFilterProc
  356. // to the Frame window of the container. And then sets and
  357. // removes the main(frame) menu bar
  358. //
  359. // Effects:
  360. //
  361. // Arguments: [holemenu] -- a handle to the composite menu descriptor
  362. // [hwndFrame] -- a handle to the container's frame window
  363. // [hwndActiveObject] -- a handle to the object's in-place
  364. // window
  365. // [lpFrame] -- pointer to the container's
  366. // IOleInPlaceFrame implementation
  367. // [lpActiveObj] -- pointer to in-place object
  368. //
  369. // Requires:
  370. //
  371. // Returns: HRESULT
  372. //
  373. // Signals:
  374. //
  375. // Modifies:
  376. //
  377. // Algorithm: check arguments, then create a new frame filter object
  378. // and attach it to the frame (replacing any that might
  379. // already be there).
  380. //
  381. // History: dd-mmm-yy Author Comment
  382. // 01-Dec-93 alexgo 32bit port
  383. //
  384. // Notes:
  385. //
  386. //--------------------------------------------------------------------------
  387. #pragma SEG(OleSetMenuDescriptor)
  388. STDAPI OleSetMenuDescriptor
  389. (
  390. HOLEMENU holemenu,
  391. HWND hwndFrame,
  392. HWND hwndObject,
  393. LPOLEINPLACEFRAME lpFrame,
  394. LPOLEINPLACEACTIVEOBJECT lpObject
  395. )
  396. {
  397. OLETRACEIN((API_OleSetMenuDescriptor,
  398. PARAMFMT("holemenu= %h, hwndFrame= %h, hwndObject= %h, lpFrame= %p, lpObject= %p"),
  399. holemenu, hwndFrame, hwndObject, lpFrame, lpObject));
  400. VDATEHEAP();
  401. PCFRAMEFILTER pFrameFilter;
  402. LPOLEMENU lpOleMenu = NULL;
  403. LPOLEMENU lpOleMenuCopy = NULL;
  404. HRESULT error = NOERROR;
  405. LEDebugOut((DEB_TRACE, "%p _IN OleSetMenuDescriptor ( %lx , %lx ,"
  406. "%lx , %p , %p )\n", NULL, holemenu, hwndFrame, hwndObject,
  407. lpFrame, lpObject));
  408. // The Frame window parameter always needs to be valid since
  409. // we use it for both hook and unhook of menus
  410. if (hwndFrame == NULL || !IsWindow(hwndFrame))
  411. {
  412. LEDebugOut((DEB_ERROR,
  413. "ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
  414. error = ResultFromScode(OLE_E_INVALIDHWND);
  415. goto errRtn;
  416. }
  417. if (holemenu != NULL)
  418. {
  419. if (hwndObject == NULL || !IsWindow(hwndObject))
  420. {
  421. LEDebugOut((DEB_ERROR,
  422. "ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
  423. error = ResultFromScode(OLE_E_INVALIDHWND);
  424. goto errRtn;
  425. }
  426. if (lpFrame && lpObject)
  427. {
  428. // the caller wants us to provide the support for
  429. // context sensitive help, let's validat the pointers
  430. VDATEIFACE_LABEL(lpFrame, errRtn, error);
  431. VDATEIFACE_LABEL(lpObject, errRtn, error);
  432. CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
  433. (IUnknown **)&lpFrame);
  434. CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceActiveObject,
  435. (IUnknown **)&lpObject);
  436. }
  437. if (!(lpOleMenu = wGetOleMenuPtr(holemenu)))
  438. {
  439. error = ResultFromScode(E_HANDLE);
  440. goto errRtn;
  441. }
  442. // OleMenuPtr gets released down below by wReleaseOleMenuPtr
  443. // Allocate memory for the copy
  444. DWORD dwSize = (DWORD) GlobalSize(holemenu);
  445. lpOleMenuCopy = (LPOLEMENU) PrivMemAlloc(dwSize);
  446. if (lpOleMenuCopy == NULL)
  447. {
  448. wReleaseOleMenuPtr(holemenu);
  449. error = E_OUTOFMEMORY;
  450. goto errRtn;
  451. }
  452. memcpy(lpOleMenuCopy, lpOleMenu, dwSize);
  453. }
  454. // if there is a frame filter get rid off it.
  455. if (pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwndFrame))
  456. {
  457. // be sure to remove our window proc hook
  458. pFrameFilter->RemoveWndProc();
  459. pFrameFilter->SafeRelease();
  460. }
  461. // Add a new frame filter
  462. if (holemenu)
  463. {
  464. error = CFrameFilter::Create (lpOleMenuCopy,
  465. (HMENU)UlongToPtr(lpOleMenu->hmenuCombined),
  466. hwndFrame,
  467. hwndObject,
  468. lpFrame,
  469. lpObject);
  470. if (FAILED(error))
  471. {
  472. PrivMemFree(lpOleMenuCopy);
  473. }
  474. wReleaseOleMenuPtr(holemenu);
  475. }
  476. errRtn:
  477. LEDebugOut((DEB_TRACE, "%p OUT OleSetMenuDescriptor ( %lx )\n",
  478. NULL, error ));
  479. OLETRACEOUT((API_OleSetMenuDescriptor, error));
  480. return error;
  481. }
  482. //+-------------------------------------------------------------------------
  483. //
  484. // Function: OleDestroyMenuDescriptor
  485. //
  486. // Synopsis: Releases the menu descriptor allocated by
  487. // OleCreateMenuDescriptor
  488. //
  489. // Effects:
  490. //
  491. // Arguments: [holemenu] -- the menu descriptor
  492. //
  493. // Requires:
  494. //
  495. // Returns: NOERROR, E_HANDLE
  496. //
  497. // Signals:
  498. //
  499. // Modifies:
  500. //
  501. // Algorithm: does a global lock and verifies that holemenu is
  502. // really a menu descriptor handle (via wGetOleMenuPtr),
  503. // then unlock's and free's.
  504. //
  505. // History: dd-mmm-yy Author Comment
  506. // 01-Dec-93 alexgo 32bit port
  507. //
  508. // Notes:
  509. //
  510. //--------------------------------------------------------------------------
  511. #pragma SEG(OleDestroyMenuDescriptor)
  512. STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu)
  513. {
  514. OLETRACEIN((API_OleDestroyMenuDescriptor, PARAMFMT("holemenu= %h"), holemenu));
  515. VDATEHEAP();
  516. LPOLEMENU lpOleMenu;
  517. HRESULT error;
  518. LEDebugOut((DEB_TRACE, "%p _IN OleDestroyMenuDescriptor ( %lx )\n",
  519. NULL, holemenu));
  520. // make sure that it is a valid handle
  521. if (! (lpOleMenu = wGetOleMenuPtr(holemenu)))
  522. {
  523. error = ResultFromScode(E_HANDLE);
  524. }
  525. else
  526. {
  527. wReleaseOleMenuPtr(holemenu);
  528. GlobalFree((HGLOBAL) holemenu);
  529. error = NOERROR;
  530. }
  531. LEDebugOut((DEB_TRACE, "%p OUT OleDestroyMenuDescriptor ( %lx )\n",
  532. NULL, error));
  533. OLETRACEOUT((API_OleDestroyMenuDescriptor, error));
  534. return error;
  535. }
  536. //+-------------------------------------------------------------------------
  537. //
  538. // Function: wSysKeyToKey (internal)
  539. //
  540. // Synopsis: Converts a message from a WM_SYSKEY to a WM_KEY message
  541. // if the alt key was not held down
  542. //
  543. // Effects:
  544. //
  545. // Arguments: [lpMsg] -- the message to convert
  546. //
  547. // Requires:
  548. //
  549. // Returns: UINT -- the new message
  550. //
  551. // Signals:
  552. //
  553. // Modifies:
  554. //
  555. // Algorithm:
  556. //
  557. // History: dd-mmm-yy Author Comment
  558. // 01-Dec-93 alexgo 32bit port
  559. // 07-Dec-93 alexgo removed inlining
  560. //
  561. // Notes: original notes:
  562. //
  563. // if the ALT key is down when a key is pressed, then the 29th bit of the
  564. // LPARAM will be set
  565. //
  566. // If the message was not made with the ALT key down, convert the message
  567. // from a WM_SYSKEY* to a WM_KEY* message.
  568. //
  569. //--------------------------------------------------------------------------
  570. static UINT wSysKeyToKey(LPMSG lpMsg)
  571. {
  572. VDATEHEAP();
  573. UINT message = lpMsg->message;
  574. if (!(HIWORD(lpMsg->lParam) & 0x2000)
  575. && (message >= WM_SYSKEYDOWN && message <= WM_SYSDEADCHAR))
  576. {
  577. message -= (WM_SYSKEYDOWN - WM_KEYDOWN);
  578. }
  579. return message;
  580. }
  581. //+-------------------------------------------------------------------------
  582. //
  583. // Function: OleTranslateAccelerator
  584. //
  585. // Synopsis: Called by an inplace object to allow a container to attempt
  586. // to handle an accelerator
  587. //
  588. // Effects:
  589. //
  590. // Arguments: [lpFrame] -- pointer to IOleInPlaceFrame where the
  591. // keystroke might be sent
  592. // [lpFrameInfo] -- pointer to and OLEINPLACEFRAMEINFO
  593. // from the container with it's accelerator
  594. // table
  595. // [lpmsg] -- the keystroke
  596. //
  597. // Requires:
  598. //
  599. // Returns: HRESULT
  600. //
  601. // Signals:
  602. //
  603. // Modifies:
  604. //
  605. // Algorithm: We call SendMessage to store the accelerator cmd
  606. // (to handle degenerate lookups on the container) and
  607. // then ask the container to handle
  608. //
  609. // History: dd-mmm-yy Author Comment
  610. // 01-Dec-93 alexgo 32bit port
  611. //
  612. // Notes:
  613. //
  614. //--------------------------------------------------------------------------
  615. #pragma SEG(OleTranslateAccelerator)
  616. STDAPI OleTranslateAccelerator(LPOLEINPLACEFRAME lpFrame,
  617. LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpMsg)
  618. {
  619. OLETRACEIN((API_OleTranslateAccelerator,
  620. PARAMFMT("lpFrame= %p, lpFrameInfo= %to, lpMsg= %tm"),
  621. lpFrame, lpFrameInfo, lpMsg));
  622. VDATEHEAP();
  623. WORD cmd;
  624. BOOL fFound;
  625. HRESULT error;
  626. LEDebugOut((DEB_TRACE, "%p _IN OleTranslateAccelerator ( %p , %p "
  627. ", %p )\n", NULL, lpFrame, lpFrameInfo, lpMsg));
  628. CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
  629. (IUnknown **)&lpFrame);
  630. // Validate parameters -- the best that we can!
  631. // Note: the macro's VDATEPTR* were not used because they return
  632. // immediately & break the tracing semantics
  633. if (!IsValidInterface(lpFrame)
  634. || !IsValidPtrIn(lpFrameInfo, sizeof(OLEINPLACEFRAMEINFO))
  635. || !IsValidPtrIn(lpMsg, sizeof(MSG)))
  636. {
  637. error = ResultFromScode(E_INVALIDARG);
  638. goto exitRtn;
  639. }
  640. // Search the (container) frame's table of accelerators. Remember that
  641. // the container may be (actually most likely) is in a separate
  642. // process.
  643. fFound = IsAccelerator(lpFrameInfo->haccel,
  644. lpFrameInfo->cAccelEntries, lpMsg, &cmd);
  645. if (!fFound && lpFrameInfo->fMDIApp)
  646. {
  647. // If no accelerator was found and the app is a MDI app,
  648. // then we see if there is a mdi accelerator found.
  649. fFound = IsMDIAccelerator(lpMsg, &cmd);
  650. }
  651. if (fFound)
  652. {
  653. // Found some kind of for the container accelerator.
  654. // uOleMessage is set in ole2.cpp -- it is a private message
  655. // between OLE applications.
  656. // This SendMessage tells the message filter that is on the
  657. // frame window what the command translated to. This will
  658. // be used in menu collision processing.
  659. SSSendMessage(lpFrameInfo->hwndFrame, uOleMessage,
  660. OM_COMMAND_ID, MAKELONG(cmd, 0));
  661. // Send the command and the message to the container. The
  662. // result tells the caller whether the container really
  663. // used the command.
  664. error = lpFrame->TranslateAccelerator(lpMsg, cmd);
  665. }
  666. else if (wSysKeyToKey(lpMsg) == WM_SYSCHAR)
  667. {
  668. // Eat the message if it is "Alt -". This is supposed
  669. // to bring the MDI system menu down. But we can not
  670. // support it. And we also don't want the message to
  671. // be Translated by the object application either.
  672. // So, we return as if it has been accepted by the
  673. // container as an accelerator.
  674. // If the container wants to support this it can
  675. // have an accelerator for this. This is not an
  676. // issue for SDI apps, because it will be thrown
  677. // away by USER anyway.
  678. // This is the original support as it appeared in
  679. // the 16-bit version of OLE and the first 32-bit
  680. // release. To fix the problem, remove the comment
  681. // tags from the else case below and comment the
  682. // code out in the _DEBUG #ifdef below. This new
  683. // code will walk back up through the objects
  684. // parent windows until a window is found that
  685. // contains a system menu, at which point the
  686. // message is sent.
  687. if (lpMsg->wParam != OLESTR('-'))
  688. {
  689. SSSendMessage(lpFrameInfo->hwndFrame,
  690. lpMsg->message,
  691. lpMsg->wParam, lpMsg->lParam);
  692. }
  693. // else
  694. // {
  695. // HWND hWndCurrent = lpMsg->hwnd;
  696. //
  697. // while ( hWndCurrent &&
  698. // !(GetWindowLong(hWndCurrent, GWL_STYLE) & WS_SYSMENU))
  699. // {
  700. // hWndCurrent = GetParent(hWndCurrent);
  701. // }
  702. //
  703. // if (hWndCurrent)
  704. // {
  705. // SSSendMessage(hWndCurrent,
  706. // lpMsg->message,
  707. // lpMsg->wParam, lpMsg->lParam);
  708. // }
  709. // }
  710. #ifdef _DEBUG
  711. else
  712. {
  713. OutputDebugString(
  714. TEXT("OleTranslateAccelerator: Alt+ - key is discarded\r\n"));
  715. }
  716. #endif
  717. error = NOERROR;
  718. }
  719. else
  720. {
  721. error = ResultFromScode(S_FALSE);
  722. }
  723. exitRtn:
  724. LEDebugOut((DEB_TRACE, "%p OUT OleTranslateAccelerator ( %lx )\n",
  725. NULL, error));
  726. OLETRACEOUT((API_OleTranslateAccelerator, error));
  727. return error;
  728. }
  729. //+-------------------------------------------------------------------------
  730. //
  731. // Function: IsAccelerator
  732. //
  733. // Synopsis: determines whether [lpMsg] is an accelerator in the [hAccel]
  734. //
  735. // Effects:
  736. //
  737. // Arguments: [hAccel] -- the accelerator table
  738. // [cAccelEntries] -- the number of entries in the accelerator
  739. // table
  740. // [lpMsg] -- the keystroke message that we should
  741. // see if it's an accelerator
  742. // [lpCmd] -- where to return the corresponding command
  743. // ID if an accelerator is found (may be NULL)
  744. //
  745. // Requires:
  746. //
  747. // Returns: TRUE if accelerator is found, FALSE otherwise or on error
  748. //
  749. // Signals:
  750. //
  751. // Modifies:
  752. //
  753. // Algorithm:
  754. //
  755. // History: dd-mmm-yy Author Comment
  756. // 01-Dec-93 alexgo 32bit port
  757. //
  758. // Notes:
  759. //
  760. //--------------------------------------------------------------------------
  761. STDAPI_(BOOL) IsAccelerator
  762. (HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD FAR* lpwCmd)
  763. {
  764. OLETRACEIN((API_IsAccelerator,
  765. PARAMFMT("hAccel= %h, cAccelEntries= %d, lpMsg= %tm, lpwCmd= %p"),
  766. hAccel, cAccelEntries, lpMsg, lpwCmd));
  767. VDATEHEAP();
  768. WORD cmd = NULL;
  769. WORD flags;
  770. BOOL fFound = FALSE;
  771. BOOL fVirt;
  772. UINT message;
  773. // Safe place for pointer to accelerator table
  774. CPaccelEnum cpaccelenum;
  775. LEDebugOut((DEB_TRACE, "%p _IN IsAccelerator ( %lx , %d , %p , %p )\n",
  776. NULL, hAccel, cAccelEntries, lpMsg, lpwCmd));
  777. if (! cAccelEntries)
  778. {
  779. // no accelerators so we can stop here.
  780. goto errRtn;
  781. }
  782. // Change message type from WM_SYS type to WM_KEY type if the ALT
  783. // key is not pressed.
  784. message = wSysKeyToKey(lpMsg);
  785. // Figure out whether this message is one that can possibly contain
  786. // an accelerator.
  787. switch (message)
  788. {
  789. case WM_KEYDOWN:
  790. case WM_SYSKEYDOWN:
  791. // wParam in this message is virtual key code
  792. fVirt = TRUE;
  793. break;
  794. case WM_CHAR:
  795. case WM_SYSCHAR:
  796. // wParam is the character
  797. fVirt = FALSE;
  798. break;
  799. default:
  800. goto errRtn;
  801. }
  802. // Get a pointer to the accerator table
  803. if ((hAccel == NULL)
  804. || !cpaccelenum.InitLPACCEL(hAccel, cAccelEntries))
  805. {
  806. // Handle is NULL or we could not lock the resource so exit.
  807. goto errRtn;
  808. }
  809. do
  810. {
  811. // Get the flags from the accelerator table entry to save
  812. // a pointer dereference.
  813. flags = cpaccelenum->fVirt;
  814. // if the key in the message and the table aren't the same,
  815. // or if the key is virtual and the accel table entry is not or
  816. // vice versa (if key is not virtual & accel table entry is
  817. // not), we can skip checking the accel entry immediately.
  818. if ((cpaccelenum->key != (WORD) lpMsg->wParam) ||
  819. ((fVirt != 0) != ((flags & FVIRTKEY) != 0)))
  820. {
  821. goto Next;
  822. }
  823. if (fVirt)
  824. {
  825. // If shift down & shift not requested in accelerator
  826. // table or if shift not down and shift not set,
  827. // we skip this table entry.
  828. if ((GetKeyState(VK_SHIFT) < 0) != ((flags & FSHIFT)
  829. != 0))
  830. {
  831. goto Next;
  832. }
  833. // Likewise if control key down & control key not
  834. // set in accelerator table or if control not down
  835. // and it was set in the accelerator table, we skip
  836. // skip this entry in the table.
  837. if ((GetKeyState(VK_CONTROL) < 0) !=
  838. ((flags & FCONTROL) != 0))
  839. {
  840. goto Next;
  841. }
  842. }
  843. // If the ALT key is down and the accel table flags do not
  844. // request the ALT flags or if the alt key is not down and
  845. // the ALT is requested, this item does not match.
  846. if ((GetKeyState(VK_MENU) < 0) != ((flags & FALT) != 0))
  847. {
  848. goto Next;
  849. }
  850. // We have gotten a match in the table.
  851. // we get the command out of the table and record that we found
  852. // something.
  853. cmd = cpaccelenum->cmd;
  854. fFound = TRUE;
  855. goto errRtn;
  856. Next:
  857. cpaccelenum.Next();
  858. } while (--cAccelEntries);
  859. errRtn:
  860. // Common exit
  861. if (lpwCmd)
  862. {
  863. // If caller wants to get back the command that they
  864. // requested, we assign it at this point.
  865. *lpwCmd = cmd;
  866. }
  867. LEDebugOut((DEB_TRACE, "%p OUT IsAccelerator ( %lu )\n", NULL,
  868. fFound));
  869. OLETRACEOUTEX((API_IsAccelerator, RETURNFMT("%B"), fFound));
  870. // Return the result of the search.
  871. return fFound;
  872. }
  873. //+-------------------------------------------------------------------------
  874. //
  875. // Function: IsMDIAccelerator
  876. //
  877. // Synopsis: determines wither [lpMsg] is an accelerator for MDI window
  878. // commands
  879. //
  880. // Effects:
  881. //
  882. // Arguments: [lpMsg] -- the keystroke to look at
  883. // [lpCmd] -- where to put the command ID
  884. //
  885. // Requires:
  886. //
  887. // Returns: BOOL
  888. //
  889. // Signals:
  890. //
  891. // Modifies:
  892. //
  893. // Algorithm: Make sure message is a key down message. Then make sure
  894. // that the control key is up or toggled and the ALT key is
  895. // down. Then if F4 is pressed set the system command to
  896. // close or if the F6 or tab keys are pressed send the
  897. // appropriate window switch message.
  898. //
  899. // History: dd-mmm-yy Author Comment
  900. // 01-Dec-93 alexgo 32bit port, fixed fall-through bug
  901. //
  902. // Notes:
  903. //
  904. //--------------------------------------------------------------------------
  905. #pragma SEG(IsMDIAccelerator)
  906. BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* lpCmd)
  907. {
  908. VDATEHEAP();
  909. BOOL fResult = FALSE;
  910. LEDebugOut((DEB_TRACE, "%p _IN IsMDIAccelerator ( %p , %p )\n",
  911. NULL, lpMsg, lpCmd));
  912. // This can be an accelerator only if this is some kind of key down.
  913. if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
  914. {
  915. goto IsMDIAccelerator_exit;
  916. }
  917. if (GetKeyState(VK_CONTROL) >= 0)
  918. {
  919. // All MIDI accelerators have the control key up (or toggled),
  920. // so we can exit here if it isn't down.
  921. goto IsMDIAccelerator_exit;
  922. }
  923. switch ((WORD)lpMsg->wParam)
  924. {
  925. case VK_F4:
  926. *lpCmd = SC_CLOSE;
  927. fResult = TRUE;
  928. break; // this break was not in the 16bit code, but
  929. // it looks like it must be there (otherwise
  930. // this info is lost)
  931. case VK_F6:
  932. case VK_TAB:
  933. fResult = TRUE;
  934. *lpCmd = (GetKeyState(VK_SHIFT) < 0)
  935. ? SC_PREVWINDOW : SC_NEXTWINDOW;
  936. break;
  937. }
  938. IsMDIAccelerator_exit:
  939. LEDebugOut((DEB_TRACE, "%p OUT IsMDIAccelerator ( %lu ) [ %lu ] \n",
  940. NULL, fResult, *lpCmd));
  941. return fResult;
  942. }
  943. //+-------------------------------------------------------------------------
  944. //
  945. // Function: FrameWndFilterProc
  946. //
  947. // Synopsis: The callback proc for the container's frame window
  948. //
  949. // Effects:
  950. //
  951. // Arguments: [hwnd] -- the window handle
  952. // [msg] -- the msg causing the notification
  953. // [uParam] -- first param
  954. // [lParam] -- second param
  955. //
  956. // Requires:
  957. //
  958. // Returns: LRESULT
  959. //
  960. // Signals:
  961. //
  962. // Modifies:
  963. //
  964. // Algorithm: Gets the CFrame object (if available) and asks it
  965. // to deal with the window message
  966. //
  967. // History: dd-mmm-yy Author Comment
  968. // 01-Dec-93 alexgo 32bit port
  969. //
  970. // Notes:
  971. //
  972. //--------------------------------------------------------------------------
  973. #pragma SEG(FrameWndFilterProc)
  974. STDAPI_(LRESULT) FrameWndFilterProc(HWND hwnd, UINT msg, WPARAM uParam, LPARAM lParam)
  975. {
  976. VDATEHEAP();
  977. PCFRAMEFILTER pFrameFilter;
  978. LRESULT lresult;
  979. LEDebugOut((DEB_TRACE, "%p _IN FrameWndFilterProc ( 0x%p , %u ,"
  980. " %u , %ld )\n", NULL, hwnd, msg, PtrToUlong((void*)uParam), PtrToLong((void*)lParam)));
  981. if (!(pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwnd)))
  982. {
  983. lresult = SSDefWindowProc(hwnd, msg, uParam, lParam);
  984. }
  985. else
  986. {
  987. // stabilize the frame filter
  988. CStabilize FFstabilize((CSafeRefCount *)pFrameFilter);
  989. if (msg == WM_SYSCOMMAND)
  990. {
  991. lresult = pFrameFilter->OnSysCommand(uParam,
  992. lParam);
  993. }
  994. else
  995. {
  996. lresult = pFrameFilter->OnMessage(msg, uParam,
  997. lParam);
  998. }
  999. }
  1000. LEDebugOut((DEB_TRACE, "%p OUT FrameWndFilterProc ( %lu )\n",
  1001. NULL, PtrToUlong((void*)lresult)));
  1002. return lresult;
  1003. }
  1004. //+-------------------------------------------------------------------------
  1005. //
  1006. // Function: CFrameFilter::Create
  1007. //
  1008. // Synopsis: Allocates and initializes a CFrame object (which handles
  1009. // all of the real processing work for event callbacks)
  1010. //
  1011. // Effects:
  1012. //
  1013. // Arguments: [lpOleMenu] -- pointer to the ole menu descriptor
  1014. // [hmenuCombined] -- the combined menu handle
  1015. // [hwndFrame] -- handle to the container's frame
  1016. // (where the CFrame should be installed)
  1017. // [hwndActiveObj] -- handle to the in-place object's window
  1018. // [lpFrame] -- pointer to the container's
  1019. // IOleInPlaceFrame implementation
  1020. //
  1021. // Requires:
  1022. //
  1023. // Returns: HRESULT
  1024. //
  1025. // Signals:
  1026. //
  1027. // Modifies:
  1028. //
  1029. // Algorithm: Allocates the object and installs a pointer to it as
  1030. // a property on the window
  1031. //
  1032. // History: dd-mmm-yy Author Comment
  1033. // 01-Dec-93 alexgo 32bit port
  1034. //
  1035. // Notes:
  1036. //
  1037. //--------------------------------------------------------------------------
  1038. #pragma SEG(CFrameFilter_Create)
  1039. HRESULT CFrameFilter::Create(LPOLEMENU lpOleMenu, HMENU hmenuCombined,
  1040. HWND hwndFrame, HWND hwndActiveObj,
  1041. LPOLEINPLACEFRAME lpFrame, LPOLEINPLACEACTIVEOBJECT lpActiveObj)
  1042. {
  1043. VDATEHEAP();
  1044. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::Create ( %lx , %p ,"
  1045. " %lx , %lx , %p , %p )\n", NULL, lpOleMenu,
  1046. hmenuCombined, hwndFrame, hwndActiveObj,
  1047. lpFrame, lpActiveObj));
  1048. CFrameFilter * pFF = new CFrameFilter(hwndFrame, hwndActiveObj);
  1049. if (!pFF)
  1050. {
  1051. goto errRtn;
  1052. }
  1053. pFF->SafeAddRef();
  1054. pFF->m_lpOleMenu = lpOleMenu;
  1055. pFF->m_hmenuCombined = hmenuCombined;
  1056. // If the following pointers are NON-NULL, it means that the container
  1057. // wants us to use our message filter to deal with the F1 key. So,
  1058. // remember the pointers.
  1059. if (lpFrame && lpActiveObj)
  1060. {
  1061. // these addref's should not be outgoing calls, so
  1062. // no need to stabilize around them. (unless, of
  1063. // course, the container made an outgoing call for
  1064. // frame->AddRef, but that would be really weird).
  1065. (pFF->m_lpFrame = lpFrame)->AddRef();
  1066. (pFF->m_lpObject = lpActiveObj)->AddRef();
  1067. }
  1068. // Hook the frame wnd proc
  1069. if (!(pFF->m_lpfnPrevWndProc = (WNDPROC) SetWindowLongPtr (hwndFrame,
  1070. GWLP_WNDPROC, (LONG_PTR) FrameWndFilterProc)))
  1071. {
  1072. goto errRtn;
  1073. }
  1074. #ifdef WIN32
  1075. if (!SetProp (hwndFrame, szPropFrameFilter, (HANDLE) pFF))
  1076. {
  1077. goto errRtn;
  1078. }
  1079. #else
  1080. if (!SetProp (hwndFrame, szPropFrameFilterH, HIWORD(pFF)))
  1081. {
  1082. goto errRtn;
  1083. }
  1084. if (!SetProp (hwndFrame, szPropFrameFilterL, LOWORD(pFF)))
  1085. {
  1086. goto errRtn;
  1087. }
  1088. #endif
  1089. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
  1090. NULL, NOERROR ));
  1091. return NOERROR;
  1092. errRtn:
  1093. if (pFF)
  1094. {
  1095. pFF->SafeRelease();
  1096. }
  1097. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
  1098. NULL, ResultFromScode(E_OUTOFMEMORY)));
  1099. return ResultFromScode(E_OUTOFMEMORY);
  1100. }
  1101. //+-------------------------------------------------------------------------
  1102. //
  1103. // Member: CFrameFilter::CFrameFilter
  1104. //
  1105. // Synopsis: Constructor for the frame filter object
  1106. //
  1107. // Effects:
  1108. //
  1109. // Arguments: [hwndFrame] -- the container's frame
  1110. // [hwndActiveObj] -- the inplace object's window
  1111. //
  1112. // Requires:
  1113. //
  1114. // Returns:
  1115. //
  1116. // Signals:
  1117. //
  1118. // Modifies:
  1119. //
  1120. // Derivation:
  1121. //
  1122. // Algorithm:
  1123. //
  1124. // History: dd-mmm-yy Author Comment
  1125. // 01-Dec-93 alexgo 32bit port
  1126. //
  1127. // Notes:
  1128. //
  1129. //--------------------------------------------------------------------------
  1130. #pragma SEG(CFrameFilter_ctor)
  1131. CFrameFilter::CFrameFilter (HWND hwndFrame, HWND hwndActiveObj) :
  1132. CSafeRefCount(NULL)
  1133. {
  1134. VDATEHEAP();
  1135. m_hwndFrame = hwndFrame;
  1136. m_hwndObject = hwndActiveObj;
  1137. m_lpFrame = NULL;
  1138. m_lpObject = NULL;
  1139. m_lpfnPrevWndProc = NULL;
  1140. m_fObjectMenu = FALSE;
  1141. m_fCurItemPopup = FALSE;
  1142. m_fInMenuMode = FALSE;
  1143. m_fGotMenuCloseEvent = FALSE;
  1144. m_uCurItemID = NULL;
  1145. m_cAltTab = NULL;
  1146. m_hwndFocusOnEnter = NULL;
  1147. m_fDiscardWmCommand = FALSE;
  1148. m_cmdId = NULL;
  1149. m_fRemovedWndProc = FALSE;
  1150. #ifdef _CHICAGO_
  1151. m_fInNCACTIVATE = FALSE;
  1152. #endif
  1153. }
  1154. //+-------------------------------------------------------------------------
  1155. //
  1156. // Member: CFrameFileter::~CFrameFilter
  1157. //
  1158. // Synopsis: destroys the object
  1159. //
  1160. // Effects:
  1161. //
  1162. // Arguments: void
  1163. //
  1164. // Requires:
  1165. //
  1166. // Returns:
  1167. //
  1168. // Signals:
  1169. //
  1170. // Modifies:
  1171. //
  1172. // Derivation:
  1173. //
  1174. // Algorithm:
  1175. //
  1176. // History: dd-mmm-yy Author Comment
  1177. // 01-Dec-93 alexgo 32bit port
  1178. //
  1179. // Notes:
  1180. //
  1181. //--------------------------------------------------------------------------
  1182. #pragma SEG(CFrameFilter_dtor)
  1183. CFrameFilter::~CFrameFilter(void)
  1184. {
  1185. VDATEHEAP();
  1186. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::~CFrameFilter ( )\n",
  1187. this));
  1188. PrivMemFree(m_lpOleMenu);
  1189. // remove the FrameWndFilterProc hook. We do this *before*
  1190. // the Releases since those releases may make outgoing calls
  1191. // (we'd like to be in a 'safe' state).
  1192. // REVIEW32: We may want to check to see if we're the current
  1193. // window proc before blowing it away. Some apps (like Word)
  1194. // go ahead and blow away the wndproc by theselves without calling
  1195. // OleSetMenuDescriptor(NULL);
  1196. RemoveWndProc();
  1197. if (m_lpFrame != NULL)
  1198. {
  1199. // OleUnInitialize could have been called.
  1200. // In such case we do not want to call releas
  1201. // on OLeObject.
  1202. COleTls tls;
  1203. if(tls->cOleInits > 0)
  1204. {
  1205. SafeReleaseAndNULL((IUnknown **)&m_lpFrame);
  1206. SafeReleaseAndNULL((IUnknown **)&m_lpObject);
  1207. }
  1208. else
  1209. {
  1210. m_lpObject = NULL;
  1211. m_lpFrame = NULL;
  1212. }
  1213. }
  1214. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::~CFrameFilter ( )\n",
  1215. this));
  1216. }
  1217. //+-------------------------------------------------------------------------
  1218. //
  1219. // Member: CFrameFilter::RemoveWndProc
  1220. //
  1221. // Synopsis: un-installs our window proc for inplace-processing
  1222. //
  1223. // Effects:
  1224. //
  1225. // Arguments:
  1226. //
  1227. // Requires: none
  1228. //
  1229. // Returns: void
  1230. //
  1231. // Signals:
  1232. //
  1233. // Modifies:
  1234. //
  1235. // Derivation:
  1236. //
  1237. // Algorithm:
  1238. //
  1239. // History: dd-mmm-yy Author Comment
  1240. // 04-Aug-94 alexgo author
  1241. //
  1242. // Notes:
  1243. //
  1244. //--------------------------------------------------------------------------
  1245. void CFrameFilter::RemoveWndProc()
  1246. {
  1247. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::RemoveWndProc ( )\n",
  1248. this));
  1249. if( m_fRemovedWndProc == FALSE)
  1250. {
  1251. m_fRemovedWndProc = TRUE;
  1252. if (m_lpfnPrevWndProc)
  1253. {
  1254. // If the sub-classing has already been removed, then
  1255. // don't bother to remove it again. This happens
  1256. // to be the case with Word 6 and inplace embeddings.
  1257. // and Word95 with SnapGraphics.
  1258. // if somebody comes along later (after us) and
  1259. // sub-classes the window, we won't be able to remove
  1260. // ourselves so we just avoid it.
  1261. if (GetWindowLongPtr(m_hwndFrame, GWLP_WNDPROC) ==
  1262. (LONG_PTR)FrameWndFilterProc)
  1263. {
  1264. SetWindowLongPtr (m_hwndFrame, GWLP_WNDPROC,
  1265. (LONG_PTR) m_lpfnPrevWndProc);
  1266. }
  1267. // We remove the window property at the
  1268. // same time as the sub-classing since
  1269. // the window property is the flag as to
  1270. // whether we are doing sub-classing. The
  1271. // problem this solves is that what if
  1272. // OleSetMenuDescriptor is called while we
  1273. // have the menu subclassed? We won't remove
  1274. // this property until the outer most sub
  1275. // classing is exited which if we are setting
  1276. // a new sub-class will remove the new
  1277. // sub-class' window property. Therefore, it
  1278. // will look like the window is not sub-classed
  1279. // at all.
  1280. #ifdef WIN32
  1281. HANDLE h = RemoveProp (m_hwndFrame, szPropFrameFilter);
  1282. // We must not free 'h'. It's not a real handle.
  1283. #else
  1284. RemoveProp (m_hwndFrame, szPropFrameFilterH);
  1285. RemoveProp (m_hwndFrame, szPropFrameFilterL);
  1286. #endif
  1287. }
  1288. }
  1289. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::RemoveWndProc ( )\n",
  1290. this));
  1291. }
  1292. //+-------------------------------------------------------------------------
  1293. //
  1294. // Member: CFrameFilter::OnSysCommand
  1295. //
  1296. // Synopsis: Process system messages
  1297. //
  1298. // Effects:
  1299. //
  1300. // Arguments: [uParam] -- the first message argument
  1301. // [lParam] -- the second message argument
  1302. //
  1303. // Requires: the 'this' pointer must have been stabilized before
  1304. // calling this function.
  1305. //
  1306. // Returns: LRESULT
  1307. //
  1308. // Signals:
  1309. //
  1310. // Modifies:
  1311. //
  1312. // Derivation:
  1313. //
  1314. // Algorithm: big switch to deal with the different types of messages
  1315. // see comments below
  1316. //
  1317. // History: dd-mmm-yy Author Comment
  1318. // 01-Dec-93 alexgo 32bit port
  1319. // 07-Dec-93 alexgo removed inlining
  1320. //
  1321. // Notes: FrameWndFilterProc currently does the work of stabilizing
  1322. // the framefilter's 'this' pointer.
  1323. //
  1324. //--------------------------------------------------------------------------
  1325. #pragma SEG(CFrameFilter_OnSysCommand)
  1326. LRESULT CFrameFilter::OnSysCommand(WPARAM uParam, LPARAM lParam)
  1327. {
  1328. VDATEHEAP();
  1329. UINT uParamTmp = ((UINT)uParam & 0xFFF0);
  1330. LRESULT lresult;
  1331. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnSysCommand ( %lu ,"
  1332. " %ld )\n", this, PtrToUlong((void*)uParam), PtrToLong((void*)lParam)));
  1333. // this lets the sending app continue processing
  1334. if (SSInSendMessage())
  1335. {
  1336. SSReplyMessage(NULL);
  1337. }
  1338. switch (uParamTmp)
  1339. {
  1340. case SC_KEYMENU:
  1341. case SC_MOUSEMENU:
  1342. OnEnterMenuMode();
  1343. SSCallWindowProc((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
  1344. WM_SYSCOMMAND, uParam, lParam);
  1345. // By this time menu processing would've been completed.
  1346. if (! m_fGotMenuCloseEvent)
  1347. {
  1348. // Can happen if user cancelled menu mode when MDI
  1349. // window's system menu is down. Hence generate
  1350. // the message here
  1351. SSSendMessage(m_hwndFrame, WM_MENUSELECT, 0,
  1352. MAKELONG(-1,0));
  1353. }
  1354. // We can not set m_fObjectMenu to FALSE yet, 'cause we
  1355. // could be recieving the WM_COMMAND (if a menu item is
  1356. // selected), which gets posted by the windows' menu
  1357. // processing code.
  1358. // We will clear the flag when we get OM_CLEAR_MENU_STATE
  1359. // message. Even if WM_COMMAND got generated, this message
  1360. // will come after that
  1361. PostMessage (m_hwndFrame, uOleMessage, OM_CLEAR_MENU_STATE,
  1362. 0L);
  1363. OnExitMenuMode();
  1364. lresult = 0L;
  1365. goto errRtn;
  1366. case SC_NEXTWINDOW:
  1367. case SC_PREVWINDOW:
  1368. OnEnterAltTabMode();
  1369. lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc,
  1370. m_hwndFrame, WM_SYSCOMMAND, uParam, lParam);
  1371. OnExitAltTabMode();
  1372. goto errRtn;
  1373. default:
  1374. break;
  1375. }
  1376. lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc, m_hwndFrame,
  1377. WM_SYSCOMMAND, uParam, lParam);
  1378. errRtn:
  1379. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnSysCommand ( %lx )\n",
  1380. this, PtrToLong((void*)lresult)));
  1381. return lresult;
  1382. }
  1383. //+-------------------------------------------------------------------------
  1384. //
  1385. // Member: CFrameFilter::OnEnterMenuMode
  1386. //
  1387. // Synopsis: called by the SysCommand processing, puts us into in
  1388. // InMenuMode, sets the focus and installs our message filter
  1389. // hook.
  1390. //
  1391. // Effects:
  1392. //
  1393. // Arguments: void
  1394. //
  1395. // Requires:
  1396. //
  1397. // Returns: void
  1398. //
  1399. // Signals:
  1400. //
  1401. // Modifies:
  1402. //
  1403. // Derivation:
  1404. //
  1405. // Algorithm:
  1406. //
  1407. // History: dd-mmm-yy Author Comment
  1408. // 23-Feb-94 alexgo restored OLE32 in GetModuleHandle
  1409. // 31-Dec-93 erikgav removed hardcoded "OLE2" in GetModuleHandle
  1410. // 07-Dec-93 alexgo removed inlining
  1411. // 01-Dec-93 alexgo 32bit port
  1412. //
  1413. // Notes: REVIEW32: We may need to update this to reflect new
  1414. // focus management policies.
  1415. //
  1416. //--------------------------------------------------------------------------
  1417. #pragma SEG(CFrameFilter_OnEnterMenuMode)
  1418. void CFrameFilter::OnEnterMenuMode()
  1419. {
  1420. VDATEHEAP();
  1421. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterMenuMode ( )\n",
  1422. this ));
  1423. if (m_fInMenuMode)
  1424. {
  1425. goto errRtn;
  1426. }
  1427. m_fInMenuMode = TRUE;
  1428. m_fGotMenuCloseEvent = FALSE;
  1429. m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
  1430. if (!m_lpFrame)
  1431. {
  1432. goto errRtn;
  1433. }
  1434. // REVIEW32: hMsgHook is a static (formerly global) variable for
  1435. // the whole dll. This may cause problems on NT (with threads, etc)
  1436. // (what happens if we haven't yet unhooked a previous call and
  1437. // we get here again????)
  1438. if (hMsgHook = (HHOOK) SetWindowsHookEx (WH_MSGFILTER,
  1439. (HOOKPROC) MessageFilterProc,
  1440. //GetModuleHandle(NULL),
  1441. GetModuleHandle(TEXT("OLE32")),
  1442. GetCurrentThreadId()))
  1443. {
  1444. pFrameFilter = this;
  1445. }
  1446. errRtn:
  1447. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterMenuMode ( )\n",
  1448. this ));
  1449. }
  1450. //+-------------------------------------------------------------------------
  1451. //
  1452. // Member: CFrameFilter::OnExitMenuMode
  1453. //
  1454. // Synopsis: takes us out of InMenuMode
  1455. //
  1456. // Effects:
  1457. //
  1458. // Arguments: void
  1459. //
  1460. // Requires:
  1461. //
  1462. // Returns: void
  1463. //
  1464. // Signals:
  1465. //
  1466. // Modifies:
  1467. //
  1468. // Derivation:
  1469. //
  1470. // Algorithm: Resets the focus and unhooks our callback function
  1471. //
  1472. // History: dd-mmm-yy Author Comment
  1473. // 01-Dec-93 alexgo 32bit port
  1474. // 07-Dec-93 alexgo removed inlining
  1475. //
  1476. // Notes: REVIEW32:: see OnEnterMenuMode
  1477. //
  1478. //--------------------------------------------------------------------------
  1479. #pragma SEG(CFrameFilter_OnExitMenuMode)
  1480. void CFrameFilter::OnExitMenuMode()
  1481. {
  1482. VDATEHEAP();
  1483. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitMenuMode ( )\n",
  1484. this));
  1485. if (m_fInMenuMode)
  1486. {
  1487. m_fInMenuMode = FALSE;
  1488. m_fGotMenuCloseEvent = TRUE;
  1489. m_uCurItemID = NULL;
  1490. if (hMsgHook)
  1491. {
  1492. UnhookWindowsHookEx(hMsgHook);
  1493. hMsgHook = NULL;
  1494. pFrameFilter = NULL;
  1495. }
  1496. SetFocus(m_hwndFocusOnEnter);
  1497. m_hwndFocusOnEnter = NULL;
  1498. }
  1499. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitMenuMode ( )\n",
  1500. this));
  1501. }
  1502. //+-------------------------------------------------------------------------
  1503. //
  1504. // Member: CFrameFileter::OnEnterAltTabMode
  1505. //
  1506. // Synopsis: enters AltTab mode and sets the focus
  1507. //
  1508. // Effects:
  1509. //
  1510. // Arguments: void
  1511. //
  1512. // Requires:
  1513. //
  1514. // Returns:
  1515. //
  1516. // Signals:
  1517. //
  1518. // Modifies:
  1519. //
  1520. // Derivation:
  1521. //
  1522. // Algorithm:
  1523. //
  1524. // History: dd-mmm-yy Author Comment
  1525. // 01-Dec-93 alexgo 32bit port
  1526. // 07-Dec-93 alexgo removed inlining
  1527. //
  1528. // Notes: REVIEW32: we may need to modify to implement new
  1529. // focus management policy
  1530. //
  1531. //--------------------------------------------------------------------------
  1532. void CFrameFilter::OnEnterAltTabMode(void)
  1533. {
  1534. VDATEHEAP();
  1535. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterAltTabMode ( )\n",
  1536. this ));
  1537. if (m_cAltTab == NULL)
  1538. {
  1539. m_fInMenuMode = TRUE;
  1540. // this will prevent SetFocus from getting
  1541. // delegated to the object
  1542. m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
  1543. m_fInMenuMode = FALSE;
  1544. }
  1545. m_cAltTab++;
  1546. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterAltTabMode ( )\n",
  1547. this ));
  1548. }
  1549. //+-------------------------------------------------------------------------
  1550. //
  1551. // Member: CFrameFilter::OnExitAltTabMode
  1552. //
  1553. // Synopsis: exits alt-tab mode and sets the focus
  1554. //
  1555. // Effects:
  1556. //
  1557. // Arguments: void
  1558. //
  1559. // Requires:
  1560. //
  1561. // Returns: void
  1562. //
  1563. // Signals:
  1564. //
  1565. // Modifies:
  1566. //
  1567. // Derivation:
  1568. //
  1569. // Algorithm:
  1570. //
  1571. // History: dd-mmm-yy Author Comment
  1572. // 01-Dec-93 alexgo 32bit port
  1573. // 07-Dec-93 alexgo removed inlining
  1574. //
  1575. // Notes:
  1576. //
  1577. //--------------------------------------------------------------------------
  1578. void CFrameFilter::OnExitAltTabMode()
  1579. {
  1580. VDATEHEAP();
  1581. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitAltTabMode ( )\n",
  1582. this ));
  1583. Assert(m_cAltTab != NULL);
  1584. if (--m_cAltTab == 0)
  1585. {
  1586. // The m_hwndFocusOnEnter would've been set to NULL if we are
  1587. // going to ALT-TAB out into some other process. In that case
  1588. // we would have got WM_ACTIVATEAPP and/or WM_KILLFOCUS.
  1589. if (m_hwndFocusOnEnter)
  1590. {
  1591. SetFocus(m_hwndFocusOnEnter);
  1592. m_hwndFocusOnEnter = NULL;
  1593. }
  1594. }
  1595. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitAltTabMode ( )\n",
  1596. this ));
  1597. }
  1598. //+-------------------------------------------------------------------------
  1599. //
  1600. // Member: CFrameFilter::OnMessage
  1601. //
  1602. // Synopsis: Handles window message processing
  1603. //
  1604. // Effects:
  1605. //
  1606. // Arguments: [msg] -- the window message
  1607. // [uParam] -- the first argument
  1608. // [lParam] -- the second argument
  1609. //
  1610. // Requires:
  1611. //
  1612. // Returns: LRESULT
  1613. //
  1614. // Signals:
  1615. //
  1616. // Modifies:
  1617. //
  1618. // Derivation:
  1619. //
  1620. // Algorithm: a big switch to deal with the different commands
  1621. // see comments below
  1622. //
  1623. // History: dd-mmm-yy Author Comment
  1624. // 01-Dec-93 alexgo 32bit port
  1625. // 07-Dec-93 alexgo removed inlining
  1626. //
  1627. // Notes:
  1628. //
  1629. //--------------------------------------------------------------------------
  1630. #pragma SEG(CFrameFilter_OnMessage)
  1631. LRESULT CFrameFilter::OnMessage(UINT msg, WPARAM uParam, LPARAM lParam)
  1632. {
  1633. VDATEHEAP();
  1634. LRESULT lresult;
  1635. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnMessage ( %u , %u ,"
  1636. " %ld )\n", this, msg, PtrToUlong((void*)uParam),
  1637. PtrToLong((void*)lParam)));
  1638. // We come to this routine only if the message is not WM_SYSCOMMAND
  1639. switch (msg)
  1640. {
  1641. case WM_SETFOCUS:
  1642. if (m_fInMenuMode)
  1643. {
  1644. lresult = SSDefWindowProc (m_hwndFrame, msg, uParam, lParam);
  1645. goto errRtn;
  1646. }
  1647. break;
  1648. case WM_MENUSELECT:
  1649. if (m_fInMenuMode)
  1650. {
  1651. #ifdef WIN32
  1652. HMENU hmenu = (HMENU) lParam;
  1653. UINT fwMenu = HIWORD(uParam);
  1654. UINT uItem = 0;
  1655. // There is a subtle difference in the message between
  1656. // Win16 & Win32 here. In Win16, the item is either
  1657. // an item id or a menu handle for a pop up menu.
  1658. // In Win32, the item is an item id or an offset
  1659. // in a menu if it is a popup menu handle. To minimize
  1660. // changes, we map this field as was appropriate for
  1661. // Win16.
  1662. if ( (fwMenu & MF_POPUP) &&
  1663. (hmenu != 0) )
  1664. {
  1665. uItem = (UINT) PtrToUlong(GetSubMenu(hmenu, (int) LOWORD(uParam)));
  1666. }
  1667. else {
  1668. uItem = LOWORD(uParam);
  1669. }
  1670. #ifdef _CHICAGO_
  1671. if (!uItem) {
  1672. uItem = LOWORD(uParam);
  1673. }
  1674. #endif // _CHICAGO_
  1675. #else // !WIN32
  1676. HMENU hmenu = (HMENU)HIWORD(lParam);
  1677. UINT fwMenu = LOWORD(lParam);
  1678. UINT uItem = uParam;
  1679. #endif // else !WIN32
  1680. m_uCurItemID = uItem;
  1681. m_fCurItemPopup = fwMenu & MF_POPUP;
  1682. if (hmenu == 0 && fwMenu == 0xFFFF)
  1683. {
  1684. // end of menu processing
  1685. // We can not set m_fObjectMenu to FALSE yet,
  1686. // because we could be recieving the
  1687. // WM_COMMAND (if a menu item is selected),
  1688. // which is posted by the windows' menu
  1689. // processing code, and will be recieved at
  1690. // a later time.
  1691. // There is no way to figure whether the user
  1692. // has selected a menu (which implies that
  1693. // WM_COMMAND is posted), or ESCaped out of
  1694. // menu selection.
  1695. // This problem is handled by posting a
  1696. // message to ourselves to clear the flag.
  1697. // See CFrameFilter::OnSysCommand() for
  1698. // more details...
  1699. m_fGotMenuCloseEvent = TRUE;
  1700. SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1701. }
  1702. else
  1703. {
  1704. if (fwMenu & MF_SYSMENU)
  1705. {
  1706. m_fObjectMenu = FALSE;
  1707. // if it is top level menu, see whose
  1708. // menu it is
  1709. }
  1710. else if (IsHmenuEqual(hmenu, m_hmenuCombined))
  1711. {
  1712. // set m_fObjectMenu
  1713. IsObjectMenu (uItem, fwMenu);
  1714. // this flag must not be modified
  1715. // when nested menus are selected.
  1716. }
  1717. if (m_fObjectMenu)
  1718. {
  1719. lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1720. goto errRtn;
  1721. }
  1722. } // else
  1723. } // if (m_fInMenuMode)
  1724. break; // WM_MENUSELECT
  1725. case WM_MEASUREITEM:
  1726. case WM_DRAWITEM:
  1727. if (m_fInMenuMode && m_fObjectMenu)
  1728. {
  1729. lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1730. goto errRtn;
  1731. }
  1732. break;
  1733. case WM_ENTERIDLE:
  1734. {
  1735. WCHAR wstr[10];
  1736. // We need to post this message if the server is
  1737. // SnapGraphics. See bug #18576.
  1738. GetClassName(m_hwndObject, wstr, 10);
  1739. if (0 == lstrcmpW(OLESTR("MGX:SNAP2"), wstr))
  1740. {
  1741. PostMessage(m_hwndObject, msg, uParam, lParam);
  1742. }
  1743. else
  1744. {
  1745. SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1746. }
  1747. }
  1748. break;
  1749. case WM_INITMENU:
  1750. m_fObjectMenu = FALSE;
  1751. if (m_fInMenuMode && IsHmenuEqual(m_hmenuCombined, (HMENU)uParam))
  1752. {
  1753. SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1754. }
  1755. break;
  1756. case WM_INITMENUPOPUP:
  1757. if (!m_fInMenuMode)
  1758. {
  1759. // Accelarator translation....
  1760. if (! ((BOOL) HIWORD(lParam)))
  1761. {
  1762. // if not a system menu, see whether windows
  1763. // generated WM_INITMENUPOPUP for object's
  1764. // menu because of menu collision. If so
  1765. // fix it and route it to container
  1766. // menu collisions can occur with combined
  1767. // menus (from object and container)
  1768. if (IsMenuCollision(uParam, lParam))
  1769. {
  1770. lresult = 0L;
  1771. goto errRtn;
  1772. }
  1773. }
  1774. }
  1775. if (m_fObjectMenu)
  1776. {
  1777. lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
  1778. goto errRtn;
  1779. }
  1780. break;
  1781. case WM_SYSCHAR:
  1782. if (SSInSendMessage())
  1783. {
  1784. SSReplyMessage(NULL);
  1785. }
  1786. break;
  1787. #ifdef _CHICAGO_
  1788. case WM_NCACTIVATE:
  1789. //Note: On chicago with new rpc WM_NCACTIVATE gets dispatched
  1790. // recursively until stack overflow.
  1791. // Needs to be reviewed. (OS problem)
  1792. // See bug 25313, 25490, 25549
  1793. if (m_fInNCACTIVATE)
  1794. {
  1795. goto errRtn;
  1796. }
  1797. m_fInNCACTIVATE = TRUE;
  1798. break;
  1799. #endif // _CHICAGO_
  1800. case WM_COMMAND:
  1801. // End of menu processing or accelartor translation.
  1802. // Check whether we should give the message to the object
  1803. // or not.
  1804. // If the LOWORD of lParam is NON-NULL, then the message
  1805. // must be from a control, and the control must belong to
  1806. // the container app.
  1807. // REVIEW32: what about app-specific commands with NULL
  1808. // lParams???
  1809. if (LOWORD(lParam) == 0)
  1810. {
  1811. m_cmdId = 0;
  1812. if (m_fDiscardWmCommand)
  1813. {
  1814. m_fDiscardWmCommand = FALSE;
  1815. lresult = 0L;
  1816. goto errRtn;
  1817. }
  1818. if (m_fObjectMenu)
  1819. {
  1820. m_fObjectMenu = FALSE;
  1821. lresult = PostMessage(m_hwndObject, msg, uParam,lParam);
  1822. goto errRtn;
  1823. }
  1824. }
  1825. break;
  1826. case WM_ACTIVATEAPP:
  1827. case WM_KILLFOCUS:
  1828. // If in ALT-TAB mode, we get these messages only if we are
  1829. // going to ALT-TAB out in to some other task. In this case,
  1830. // on exit from ALT-TAB mode we wouldn't want to set
  1831. // focus back to the window that had the focus on
  1832. // entering the ALT-TAB mode.
  1833. if (m_cAltTab)
  1834. {
  1835. m_hwndFocusOnEnter = NULL;
  1836. }
  1837. break;
  1838. default:
  1839. if (msg == uOleMessage)
  1840. {
  1841. switch(uParam)
  1842. {
  1843. case OM_CLEAR_MENU_STATE:
  1844. m_fObjectMenu = FALSE;
  1845. break;
  1846. case OM_COMMAND_ID:
  1847. // this message is sent by
  1848. // OleTranslateAccelerator, before it actually
  1849. // calls the lpFrame->TranslateAccelerator
  1850. // method.
  1851. // We remember the command id here, later it
  1852. // gets used if the container's calling of
  1853. // TranslateAccelerator results in a
  1854. // WM_INITMENUPOPUP for the object because
  1855. // of command id collision. In that case we
  1856. // scan the menu list to see whether there is
  1857. // any container menu which has the same
  1858. // command id, if so we generate
  1859. // WM_INITMENUPOPUP for that menu.
  1860. m_cmdId = LOWORD(lParam);
  1861. break;
  1862. default:
  1863. AssertSz(FALSE, "Unexpected OLE private message");
  1864. break;
  1865. } // switch
  1866. lresult = 0L;
  1867. goto errRtn;
  1868. } // if (msg == uOleMessage)
  1869. else if (m_fInMenuMode && (msg == uOmPostWmCommand))
  1870. {
  1871. // if the current selection is a popup menu then
  1872. // return its menu handle else post the command
  1873. // and return NULL.
  1874. if (m_fCurItemPopup)
  1875. {
  1876. lresult = m_uCurItemID;
  1877. goto errRtn;
  1878. }
  1879. HWND hwnd;
  1880. hwnd = m_hwndFrame;
  1881. if (m_fObjectMenu)
  1882. {
  1883. hwnd = m_hwndObject;
  1884. }
  1885. PostMessage (hwnd, WM_COMMAND, m_uCurItemID, 0L);
  1886. m_fObjectMenu = FALSE;
  1887. lresult = 0L;
  1888. goto errRtn;
  1889. } // else if
  1890. break; // default
  1891. } // switch
  1892. lresult = SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
  1893. msg, uParam, lParam);
  1894. errRtn:
  1895. #ifdef _CHICAGO_
  1896. m_fInNCACTIVATE = FALSE;
  1897. #endif
  1898. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnMessage ( %lu )\n",
  1899. this, lresult));
  1900. return lresult;
  1901. }
  1902. //+-------------------------------------------------------------------------
  1903. //
  1904. // Member: CFrameFilter::IsObjectMenu
  1905. //
  1906. // Synopsis: This gets called when WM_MENUSELECT is sent for a
  1907. // top level (either POPUP or normal) menu item. Figures
  1908. // out whether [uMenuItem] really belongs to the in-place object
  1909. //
  1910. // Effects:
  1911. //
  1912. // Arguments: [uMenuItem] -- the menu in question
  1913. // [fwMenu] -- the menu type
  1914. //
  1915. // Requires:
  1916. //
  1917. // Returns: void
  1918. //
  1919. // Signals:
  1920. //
  1921. // Modifies:
  1922. //
  1923. // Derivation:
  1924. //
  1925. // Algorithm: Searchs through our ole menu descriptor to find a match
  1926. //
  1927. // History: dd-mmm-yy Author Comment
  1928. // 01-Dec-93 alexgo 32bit port
  1929. // 07-Dec-93 alexgo removed inlining
  1930. //
  1931. // Notes:
  1932. //
  1933. //--------------------------------------------------------------------------
  1934. #pragma SEG(CFrameFilter_IsObjectMenu)
  1935. void CFrameFilter::IsObjectMenu(UINT uMenuItem, UINT fwMenu)
  1936. {
  1937. VDATEHEAP();
  1938. int i,
  1939. iMenuCnt;
  1940. LPOLEMENUITEM lpMenuList;
  1941. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsObjectMenu ( %u , "
  1942. "%u )\n", this, uMenuItem, fwMenu));
  1943. if (m_hmenuCombined == NULL)
  1944. {
  1945. goto errRtn;
  1946. }
  1947. m_fObjectMenu = FALSE;
  1948. lpMenuList = m_lpOleMenu->menuitem;
  1949. iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
  1950. for (i = 0; i < iMenuCnt; i++)
  1951. {
  1952. // Are the types of the menus the same?
  1953. if ((fwMenu & MF_POPUP) == lpMenuList[i].fwPopup)
  1954. {
  1955. HMENU hmenuMenuListItem = (HMENU)UlongToPtr(lpMenuList[i].item);
  1956. // Are we dealing with a menu handle?
  1957. if (fwMenu & MF_POPUP)
  1958. {
  1959. // See if windows handles are equal
  1960. if (IsHmenuEqual((HMENU)IntToPtr(uMenuItem),
  1961. hmenuMenuListItem))
  1962. {
  1963. m_fObjectMenu = lpMenuList[i].fObjectMenu;
  1964. break;
  1965. }
  1966. }
  1967. // Are item handles equal?
  1968. else if (uMenuItem == lpMenuList[i].item)
  1969. {
  1970. m_fObjectMenu = lpMenuList[i].fObjectMenu;
  1971. // If the menu isn't hilited, another menu with a duplicate
  1972. // menu ID must have been selected. The duplicate menu was
  1973. // probably created by the other application.
  1974. if (!(GetMenuState(m_hmenuCombined, uMenuItem, MF_BYCOMMAND)
  1975. & MF_HILITE))
  1976. {
  1977. m_fObjectMenu = !m_fObjectMenu;
  1978. }
  1979. break;
  1980. }
  1981. }
  1982. }
  1983. errRtn:
  1984. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsObjectMenu ( )\n",
  1985. this ));
  1986. }
  1987. //+-------------------------------------------------------------------------
  1988. //
  1989. // Member: CFrameFilter::IsMenuCollision
  1990. //
  1991. // Synopsis: Determines if we've had a menu collission. This gets called
  1992. // as a result of WM_INITMENUPOPUP during accelerator translation
  1993. //
  1994. // Effects:
  1995. //
  1996. // Arguments: [uParam] -- the first window message argument
  1997. // [lParam] -- the second argument
  1998. //
  1999. // Requires:
  2000. //
  2001. // Returns: BOOL
  2002. //
  2003. // Signals:
  2004. //
  2005. // Modifies:
  2006. //
  2007. // Derivation:
  2008. //
  2009. // Algorithm:
  2010. //
  2011. // History: dd-mmm-yy Author Comment
  2012. // 01-Dec-93 alexgo 32bit port
  2013. // 07-Dec-93 alexgo changed Assert(hmenuPopup) to an if
  2014. // in merging with 16bit RC9 sources
  2015. // 07-Dec-93 alexgo removed inlining
  2016. //
  2017. // Notes:
  2018. //
  2019. //--------------------------------------------------------------------------
  2020. BOOL CFrameFilter::IsMenuCollision(WPARAM uParam, LPARAM lParam)
  2021. {
  2022. BOOL fRet;
  2023. int iCntrMenu, iObjMenu, iMenuCnt;
  2024. BOOL fGenerateWmCommand;
  2025. HMENU hmenuPopup;
  2026. LPOLEMENUITEM lpMenuList;
  2027. VDATEHEAP();
  2028. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsMenuCollision ( %u ,"
  2029. " %ld )\n", this, uParam, lParam ));
  2030. if (m_hmenuCombined == NULL)
  2031. {
  2032. fRet = FALSE;
  2033. goto errRtn;
  2034. }
  2035. if (m_lpOleMenu == NULL)
  2036. {
  2037. fRet = FALSE;
  2038. goto errRtn;
  2039. }
  2040. hmenuPopup = (HMENU) uParam;
  2041. iObjMenu = (int) LOWORD(lParam);
  2042. lpMenuList = m_lpOleMenu->menuitem;
  2043. iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
  2044. if (iObjMenu >= iMenuCnt)
  2045. {
  2046. fRet = FALSE;
  2047. goto errRtn;
  2048. }
  2049. if( hmenuPopup != (HMENU)UlongToPtr(lpMenuList[iObjMenu].item) )
  2050. {
  2051. // this could be the container's popmenu, not associated
  2052. // with the frame
  2053. fRet = FALSE;
  2054. goto errRtn;
  2055. }
  2056. Assert(lpMenuList[iObjMenu].fwPopup);
  2057. if (! lpMenuList[iObjMenu].fObjectMenu)
  2058. {
  2059. fRet = FALSE; // container's pop-up menu
  2060. goto errRtn;
  2061. }
  2062. // Otherwise the popup menu belongs to the object. This can only
  2063. // happen because of id collision. Start scanning the menus starting
  2064. // from the next top level menu item to look for a match in
  2065. // container's menus (while scanning skip object's menus)
  2066. // It is possible that the colliding command id may not be associated
  2067. // with any of the container's menus. In that case we must send
  2068. // WM_COMMAND to the container.
  2069. fGenerateWmCommand = TRUE;
  2070. m_fDiscardWmCommand = FALSE;
  2071. iCntrMenu = iObjMenu + 1;
  2072. while (iCntrMenu < iMenuCnt)
  2073. {
  2074. if (! lpMenuList[iCntrMenu].fObjectMenu)
  2075. {
  2076. if (lpMenuList[iCntrMenu].fwPopup & MF_POPUP)
  2077. {
  2078. HMENU hmenuListItem = (HMENU)UlongToPtr(lpMenuList[iCntrMenu].item);
  2079. if (GetMenuState(hmenuListItem, m_cmdId, MF_BYCOMMAND) != -1)
  2080. {
  2081. // We found match in the container's
  2082. // menu list Generate WM_INITMENUPOPUP
  2083. // for the corresponding popup
  2084. SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc,
  2085. m_hwndFrame,
  2086. WM_INITMENUPOPUP,
  2087. lpMenuList[iCntrMenu].item /*uParam*/,
  2088. MAKELONG(iCntrMenu, HIWORD(lParam)));
  2089. // We have sent WM_INITMENUPOPUP to
  2090. // the container.
  2091. // Now rechek the menu state. If
  2092. // disabled or grayed then
  2093. // don't generate WM_COMMAND
  2094. if (GetMenuState(hmenuListItem, m_cmdId, MF_BYCOMMAND) &
  2095. (MF_DISABLED | MF_GRAYED))
  2096. {
  2097. fGenerateWmCommand = FALSE;
  2098. }
  2099. break;
  2100. }
  2101. }
  2102. else
  2103. {
  2104. // top-level, non-popup container menu
  2105. HMENU hmenuCombined = (HMENU)UlongToPtr(m_lpOleMenu->hmenuCombined);
  2106. if (GetMenuItemID(hmenuCombined, iCntrMenu) == m_cmdId)
  2107. {
  2108. // No need to generate
  2109. // WM_INITMENUPOPUP
  2110. // Chek the menu state. If disabled or
  2111. // grayed then don't generate
  2112. // WM_COMMAND
  2113. if (GetMenuState(hmenuCombined, m_cmdId, MF_BYCOMMAND) &
  2114. (MF_DISABLED | MF_GRAYED))
  2115. {
  2116. fGenerateWmCommand = FALSE;
  2117. }
  2118. break;
  2119. }
  2120. }
  2121. }
  2122. iCntrMenu++;
  2123. }
  2124. // Check the object's colliding menu's status
  2125. if (GetMenuState((HMENU)UlongToPtr(lpMenuList[iObjMenu].item), m_cmdId,
  2126. MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED))
  2127. {
  2128. // Then windows is not going to genearte WM_COMMAND for the
  2129. // object's menu, so we will generate
  2130. // the command and send it to the container
  2131. if (fGenerateWmCommand)
  2132. {
  2133. SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc,
  2134. m_hwndFrame, WM_COMMAND, m_cmdId,
  2135. MAKELONG(0, 1)); /* not from control */
  2136. // & and as result of
  2137. // accelerator
  2138. m_cmdId = NULL;
  2139. }
  2140. }
  2141. else
  2142. {
  2143. // Wait for WM_COMMAND generated by windows to come to our
  2144. // frame filter wndproc which would have been sent to the
  2145. // container anyway because we have not set the m_fObjectMenu
  2146. // flag.
  2147. //
  2148. // But we need to throw it away if the container's menu
  2149. // associated with the command is disabled or grayed
  2150. if (! fGenerateWmCommand)
  2151. {
  2152. m_fDiscardWmCommand = TRUE;
  2153. }
  2154. }
  2155. fRet = TRUE;
  2156. errRtn:
  2157. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsMenuCollision "
  2158. "( %lu )\n", this, fRet));
  2159. return fRet;
  2160. }
  2161. //+-------------------------------------------------------------------------
  2162. //
  2163. // Member: CFrameFilter::DoContextSensitiveHelp
  2164. //
  2165. // Synopsis: Calls IOIPF->ContextSensitive help on both the container
  2166. // and the object.
  2167. //
  2168. // Effects:
  2169. //
  2170. // Arguments: void
  2171. //
  2172. // Requires:
  2173. //
  2174. // Returns: FALSE if we're in popup menu mode, TRUE otherwise
  2175. //
  2176. // Signals:
  2177. //
  2178. // Modifies:
  2179. //
  2180. // Derivation:
  2181. //
  2182. // Algorithm:
  2183. //
  2184. // History: dd-mmm-yy Author Comment
  2185. // 01-Dec-93 alexgo 32bit port
  2186. // 07-Dec-93 alexgo removed inlining
  2187. //
  2188. // Notes:
  2189. //
  2190. //--------------------------------------------------------------------------
  2191. #pragma SEG(CFrameFilter_DoContextSensitiveHelp)
  2192. BOOL CFrameFilter::DoContextSensitiveHelp(void)
  2193. {
  2194. VDATEHEAP();
  2195. BOOL fRet;
  2196. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::DoContextSensitiveHelp"
  2197. " ( )\n", this ));
  2198. if (m_fCurItemPopup)
  2199. {
  2200. fRet = FALSE;
  2201. }
  2202. else
  2203. {
  2204. m_lpFrame->ContextSensitiveHelp(TRUE);
  2205. m_lpObject->ContextSensitiveHelp (TRUE);
  2206. PostMessage (m_hwndFrame, WM_COMMAND, m_uCurItemID, 0L);
  2207. fRet = TRUE;
  2208. }
  2209. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::DoContextSensitiveHelp"
  2210. " ( %lu )\n", this, fRet));
  2211. return fRet;
  2212. }
  2213. //+-------------------------------------------------------------------------
  2214. //
  2215. // Member: CFrameFilter::GetActiveObject
  2216. //
  2217. // Synopsis: Returns the IOleInplaceActiveObject interface pointer
  2218. //
  2219. // Effects:
  2220. //
  2221. // Arguments: lplpOIAO
  2222. //
  2223. // Requires:
  2224. //
  2225. // Returns: NOERROR or E_INVALIDARG
  2226. //
  2227. // Signals:
  2228. //
  2229. // Modifies:
  2230. //
  2231. // Derivation:
  2232. //
  2233. // Algorithm:
  2234. //
  2235. // History: dd-mmm-yy Author Comment
  2236. // 28-Jul-94 bobday created for WinWord hack
  2237. //
  2238. // Notes:
  2239. //
  2240. //--------------------------------------------------------------------------
  2241. #pragma SEG(CFrameFilter_GetActiveObject)
  2242. STDMETHODIMP CFrameFilter::GetActiveObject( LPOLEINPLACEACTIVEOBJECT *lplpOIAO)
  2243. {
  2244. VDATEHEAP();
  2245. LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::GetActiveObject"
  2246. " ( %p )\n", this, lplpOIAO ));
  2247. VDATEPTROUT( lplpOIAO, LPOLEINPLACEACTIVEOBJECT);
  2248. *lplpOIAO = m_lpObject;
  2249. if ( m_lpObject )
  2250. {
  2251. m_lpObject->AddRef();
  2252. }
  2253. LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::GetActiveObject"
  2254. " ( %lx ) [ %p ]\n", this, NOERROR , *lplpOIAO ));
  2255. return NOERROR;
  2256. }
  2257. //+-------------------------------------------------------------------------
  2258. //
  2259. // Function: wGetFrameFilterPtr
  2260. //
  2261. // Synopsis: Gets the CFrame object from the window
  2262. //
  2263. // Effects:
  2264. //
  2265. // Arguments: [hwndFrame] -- the window to get the CFrame object from
  2266. //
  2267. // Requires:
  2268. //
  2269. // Returns: pointer to the frame filter
  2270. //
  2271. // Signals:
  2272. //
  2273. // Modifies:
  2274. //
  2275. // Algorithm:
  2276. //
  2277. // History: dd-mmm-yy Author Comment
  2278. // 01-Dec-93 alexgo 32bit port
  2279. //
  2280. // Notes:
  2281. //
  2282. //--------------------------------------------------------------------------
  2283. inline PCFRAMEFILTER wGetFrameFilterPtr(HWND hwndFrame)
  2284. {
  2285. VDATEHEAP();
  2286. #ifdef WIN32
  2287. return (PCFRAMEFILTER) GetProp (hwndFrame, szPropFrameFilter);
  2288. #else
  2289. WORD hiword;
  2290. WORD loword;
  2291. if (!(hiword = GetProp (hwndFrame, szPropFrameFilterH)))
  2292. {
  2293. return NULL;
  2294. }
  2295. loword = GetProp (hwndFrame, szPropFrameFilterL);
  2296. return (PCFRAMEFILTER) (MAKELONG(loword, hiword));
  2297. #endif
  2298. }
  2299. //+-------------------------------------------------------------------------
  2300. //
  2301. // Function: wGetOleMenuPtr
  2302. //
  2303. // Synopsis: Locks a handle to an ole menu and returns the pointer
  2304. // (after some error checking)
  2305. //
  2306. // Effects:
  2307. //
  2308. // Arguments: [holemenu]
  2309. //
  2310. // Requires:
  2311. //
  2312. // Returns: pointer to the ole menu
  2313. //
  2314. // Signals:
  2315. //
  2316. // Modifies:
  2317. //
  2318. // Algorithm:
  2319. //
  2320. // History: dd-mmm-yy Author Comment
  2321. // 01-Dec-93 alexgo 32bit port
  2322. //
  2323. // Notes:
  2324. //
  2325. //--------------------------------------------------------------------------
  2326. LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu)
  2327. {
  2328. VDATEHEAP();
  2329. LPOLEMENU lpOleMenu;
  2330. if (! (holemenu &&
  2331. (lpOleMenu = (LPOLEMENU) GlobalLock((HGLOBAL) holemenu))))
  2332. {
  2333. return NULL;
  2334. }
  2335. if (lpOleMenu->wSignature != wSignature)
  2336. {
  2337. AssertSz(FALSE, "Error - handle is not a HOLEMENU");
  2338. GlobalUnlock((HGLOBAL) holemenu);
  2339. return NULL;
  2340. }
  2341. return lpOleMenu;
  2342. }
  2343. //+-------------------------------------------------------------------------
  2344. //
  2345. // Function: wReleaseOleMenuPtr
  2346. //
  2347. // Synopsis: calls GlobalUnlock
  2348. //
  2349. // Effects:
  2350. //
  2351. // Arguments: [holemenu] -- handle to the ole menu
  2352. //
  2353. // Requires:
  2354. //
  2355. // Returns: void
  2356. //
  2357. // Signals:
  2358. //
  2359. // Modifies:
  2360. //
  2361. // Algorithm:
  2362. //
  2363. // History: dd-mmm-yy Author Comment
  2364. // 01-Dec-93 alexgo 32bit port
  2365. //
  2366. // Notes:
  2367. //
  2368. //--------------------------------------------------------------------------
  2369. inline void wReleaseOleMenuPtr(HOLEMENU holemenu)
  2370. {
  2371. VDATEHEAP();
  2372. GlobalUnlock((HGLOBAL) holemenu);
  2373. }
  2374. //+-------------------------------------------------------------------------
  2375. //
  2376. // Function: MessageFilterProc
  2377. //
  2378. // Synopsis: The message filter installed when entering menu mode;
  2379. // handles context sensitive help
  2380. //
  2381. // Effects:
  2382. //
  2383. // Arguments: [nCode] -- hook code
  2384. // [wParam] -- first arg
  2385. // [lParam] -- second arg
  2386. //
  2387. // Requires:
  2388. //
  2389. // Returns: LRESULT
  2390. //
  2391. // Signals:
  2392. //
  2393. // Modifies:
  2394. //
  2395. // Algorithm:
  2396. //
  2397. // History: dd-mmm-yy Author Comment
  2398. // 01-Dec-93 alexgo 32bit port
  2399. //
  2400. // Notes:
  2401. //
  2402. //--------------------------------------------------------------------------
  2403. #pragma SEG(MessageFilterProc)
  2404. STDAPI_(LRESULT) MessageFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
  2405. {
  2406. VDATEHEAP();
  2407. LRESULT lresult;
  2408. LPMSG lpMsg = (LPMSG) lParam;
  2409. LEDebugOut((DEB_TRACE, "%p _IN MessageFilterProc ( %d , %ld , %lu )\n",
  2410. NULL, nCode, (LONG)wParam, lParam));
  2411. // If it is not the F1 key then let the message (wihtout modification)
  2412. // go to the next proc in the hook/filter chain.
  2413. if (lpMsg && lpMsg->message == WM_KEYDOWN
  2414. && lpMsg->wParam == VK_F1 && pFrameFilter)
  2415. {
  2416. if (pFrameFilter->DoContextSensitiveHelp())
  2417. {
  2418. // Change message value to be WM_CANCELMODE and then
  2419. // call the next hook. When the windows USER.EXE's
  2420. // menu processing code sees this message it will
  2421. // bring down menu state and come out of its
  2422. // menu processing loop.
  2423. lpMsg->message = WM_CANCELMODE;
  2424. lpMsg->wParam = NULL;
  2425. lpMsg->lParam = NULL;
  2426. }
  2427. else
  2428. {
  2429. lresult = TRUE; // otherwise throw away this message.
  2430. goto errRtn;
  2431. }
  2432. }
  2433. lresult = CallNextHookEx (hMsgHook, nCode, wParam, lParam);
  2434. errRtn:
  2435. LEDebugOut((DEB_TRACE, "%p OUT MessageFilterProc ( %ld )\n", NULL,
  2436. lresult));
  2437. return lresult;
  2438. }