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.

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