2880 lines
75 KiB
C++
2880 lines
75 KiB
C++
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
||
|
//
|
||
|
// File: inplace.cpp
|
||
|
//
|
||
|
// Contents: Implementation of OLE inplace editing API's
|
||
|
//
|
||
|
// Classes: CFrame implementation, used to store per-window info
|
||
|
//
|
||
|
// Functions: OleCreateMenuDescriptor
|
||
|
// OleSetMenuDescriptor
|
||
|
// OleDestroyMenuDescriptor
|
||
|
// OleTranslateAccelerator
|
||
|
// IsAccelerator
|
||
|
// FrameWndFilterProc
|
||
|
// MessageFilterProc
|
||
|
//
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 31-Mar-94 ricksa Fixed menu merge bug & added some comments
|
||
|
// 23-Feb-94 alexgo added call tracing
|
||
|
// 11-Jan-94 alexgo added VDATEHEAP macros to every function
|
||
|
// 31-Dec-93 ChrisWe fixed casts in OutputDebugStrings
|
||
|
// 07-Dec-93 alexgo merged changes with shipped 16bit 2.01a
|
||
|
// (RC9). Also removed lots of bad inlining.
|
||
|
// 01-Dec-93 alexgo 32bit port, made globals static
|
||
|
// 07-Dec-92 srinik Converted frame filter implementatio
|
||
|
// into a C++ class implementation.
|
||
|
// So, most of the code is rewritten.
|
||
|
// 09-Jul-92 srinik author
|
||
|
//
|
||
|
// Notes: REVIEW32: we need to do something about the new
|
||
|
// focus management policy for NT (re TonyWi's mail)
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include <le2int.h>
|
||
|
#pragma SEG(inplace)
|
||
|
|
||
|
#include "inplace.h"
|
||
|
|
||
|
NAME_SEG(InPlace)
|
||
|
ASSERTDATA
|
||
|
|
||
|
// to keep the code bases common
|
||
|
// REVIEW32: we may want to clean this up a bit
|
||
|
#ifdef WIN32
|
||
|
#define FARPROC WNDPROC
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#ifdef WIN32
|
||
|
// we'd be faster if we used an atom instead of a string!
|
||
|
static const OLECHAR szPropFrameFilter[] = OLESTR("pFrameFilter");
|
||
|
#else
|
||
|
static const OLECHAR szPropFrameFilterH[] = OLESTR("pFrameFilterH");
|
||
|
static const OLECHAR szPropFrameFilterL[] = OLESTR("pFrameFilterL");
|
||
|
#endif //WIN32
|
||
|
|
||
|
static WORD wSignature; // = (WORD) { 'S', 'K' }
|
||
|
|
||
|
static HHOOK hMsgHook = NULL;
|
||
|
static PCFRAMEFILTER pFrameFilter = NULL;
|
||
|
|
||
|
// the values for these globals are set in ole2.cpp
|
||
|
UINT uOmPostWmCommand;
|
||
|
UINT uOleMessage;
|
||
|
|
||
|
#define OM_CLEAR_MENU_STATE 0 // lParam is NULL
|
||
|
#define OM_COMMAND_ID 1 // LOWORD(lParam) contains
|
||
|
// the command ID
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsHmenuEqual
|
||
|
//
|
||
|
// Synopsis: Test whether two menu handles are equal taking into
|
||
|
// account whether one might be a Win16 handle.
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 31-May-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline BOOL IsHmenuEqual(HMENU hmenu1, HMENU hmenu2)
|
||
|
{
|
||
|
|
||
|
#ifdef _WIN64
|
||
|
|
||
|
//
|
||
|
// Sundown v-thief ( in accordance with Jerry Shea's feedback ):
|
||
|
//
|
||
|
// At this time - 07/98 - all the bits of the HMENUs have to be equal
|
||
|
//
|
||
|
|
||
|
return hmenu1 == hmenu2;
|
||
|
|
||
|
#else // !_WIN64
|
||
|
|
||
|
if (HIWORD(hmenu1) == 0 || HIWORD(hmenu2) == 0)
|
||
|
{
|
||
|
|
||
|
return LOWORD(hmenu1) == LOWORD(hmenu2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
return hmenu1 == hmenu2;
|
||
|
}
|
||
|
|
||
|
#endif // !_WIN64
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Class: CPaccel
|
||
|
//
|
||
|
// Purpose: Handles enumeration of ACCEL table for IsAccelerator
|
||
|
//
|
||
|
// Interface: InitLPACCEL - Initialize object
|
||
|
// operator-> Get pointer to current ACCEL in enumeration
|
||
|
// Next - bump current pointer
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
// Notes: This class also guarantees clean up of the
|
||
|
// allocated accelerator table & to localize the differences
|
||
|
// between Win16 & Win32 within this class.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
class CPaccelEnum : public CPrivAlloc
|
||
|
{
|
||
|
public:
|
||
|
CPaccelEnum(void);
|
||
|
|
||
|
inline ~CPaccelEnum(void);
|
||
|
|
||
|
BOOL InitLPACCEL(HACCEL haccel, int cAccel);
|
||
|
|
||
|
LPACCEL operator->(void);
|
||
|
|
||
|
void Next(void);
|
||
|
|
||
|
private:
|
||
|
|
||
|
LPACCEL _lpaccel;
|
||
|
|
||
|
#ifdef WIN32
|
||
|
|
||
|
LPACCEL _lpaccelBase;
|
||
|
|
||
|
#else // !WIN32
|
||
|
|
||
|
HACCEL _haccel;
|
||
|
|
||
|
#endif // WIN32
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CPaccelEnum::CPaccelEnum
|
||
|
//
|
||
|
// Synopsis: Initialize object to zero
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline CPaccelEnum::CPaccelEnum(void) : _lpaccel(NULL)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
|
||
|
// In Win32, we allocate the memory so we need to keep track of the
|
||
|
// base of the memory that we allocated.
|
||
|
_lpaccelBase = NULL;
|
||
|
|
||
|
#else // !WIN32
|
||
|
|
||
|
// In Win16, we release by unlock resource so we need to keep track of
|
||
|
// the accelerator handle.
|
||
|
_haccel = NULL;
|
||
|
|
||
|
#endif // WIN32
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CPaccelEnum::~CPaccelEnum
|
||
|
//
|
||
|
// Synopsis: Free resources connected with resource table
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline CPaccelEnum::~CPaccelEnum(void)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
|
||
|
PrivMemFree(_lpaccelBase);
|
||
|
|
||
|
#else // !WIN32
|
||
|
|
||
|
UnlockResource(hAccel);
|
||
|
|
||
|
#endif // WIN32
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CPaccelEnum::InitLPACCEL
|
||
|
//
|
||
|
// Synopsis: Initialize Accelerator table pointer
|
||
|
//
|
||
|
// Arguments: [haccel] - handle to accelerator table
|
||
|
// [cAccel] - count of entries in the table
|
||
|
//
|
||
|
// Returns: TRUE - table was allocated successfully
|
||
|
// FALSE - table could not be allocated
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline BOOL CPaccelEnum::InitLPACCEL(HACCEL haccel, int cAccel)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
|
||
|
// Allocate the memory for the table. If that succeeds, then copy
|
||
|
// the accelerator table. Note that if _lpaccelBase gets allocated,
|
||
|
// but CopyAcceleratorTable fails, the memory will be cleaned up
|
||
|
// in the destructor.
|
||
|
if (((_lpaccelBase
|
||
|
= (LPACCEL) PrivMemAlloc(cAccel * sizeof(ACCEL))) != NULL)
|
||
|
&& (CopyAcceleratorTable(haccel, _lpaccelBase, cAccel) == cAccel))
|
||
|
{
|
||
|
_lpaccel = _lpaccelBase;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
|
||
|
#else // !WIN32
|
||
|
|
||
|
// Just lock the resource
|
||
|
return ((_lpaccel = LockResource(haccel)) != NULL);
|
||
|
|
||
|
#endif // WIN32
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CPaccelEnum::operator->
|
||
|
//
|
||
|
// Synopsis: Return pointer to accelerator table
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline LPACCEL CPaccelEnum::operator->(void)
|
||
|
{
|
||
|
AssertSz((_lpaccel != NULL), "CPaccelEnum::operator-> _lpaccel NULL!");
|
||
|
return _lpaccel;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CPaccelEnum::Next
|
||
|
//
|
||
|
// Synopsis: Bump enumeration pointer
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 14-Apr-94 Ricksa Created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
inline void CPaccelEnum::Next(void)
|
||
|
{
|
||
|
AssertSz((_lpaccel != NULL), "CPaccelEnum::Next _lpaccel NULL!");
|
||
|
_lpaccel++;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OleCreateMenuDescriptor
|
||
|
//
|
||
|
// Synopsis: creates a descriptor from a combined menu (for use in
|
||
|
// dispatching menu messages)
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [hmenuCombined] -- handle the combined menu
|
||
|
// [lpMenuWidths] -- an array of 6 longs with the
|
||
|
// the number of menus in each
|
||
|
// group
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: handle to an OLEMENU
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: Allocates space for enough ole menu items (total of all the
|
||
|
// combined menues) and then fills in each ole menu item from
|
||
|
// the combined menu
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes: if hmenuCombined is NULL, we still allocate the ole menu
|
||
|
// descriptor handle
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(OleCreateMenuDescriptor)
|
||
|
STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
|
||
|
LPOLEMENUGROUPWIDTHS lplMenuWidths)
|
||
|
{
|
||
|
OLETRACEIN((API_OleCreateMenuDescriptor, PARAMFMT("hmenuCombined= %h, lplMenuWidths= %tw"),
|
||
|
hmenuCombined, lplMenuWidths));
|
||
|
VDATEHEAP();
|
||
|
|
||
|
int iGroupCnt, n;
|
||
|
int iMenuCnt;
|
||
|
HGLOBAL hOleMenu;
|
||
|
LPOLEMENU lpOleMenu;
|
||
|
LPOLEMENUITEM lpMenuList;
|
||
|
DWORD dwOleMenuItemsSize = 0;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN OleCreateMenuDescriptor ( %lx , "
|
||
|
"%p )\n", NULL, hmenuCombined, lplMenuWidths));
|
||
|
|
||
|
if (hmenuCombined)
|
||
|
{
|
||
|
GEN_VDATEPTRIN_LABEL( lplMenuWidths, OLEMENUGROUPWIDTHS,
|
||
|
(HOLEMENU)NULL, errRtn, hOleMenu );
|
||
|
|
||
|
iMenuCnt = 0;
|
||
|
for (iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
|
||
|
{
|
||
|
iMenuCnt += (int) lplMenuWidths->width[iGroupCnt];
|
||
|
}
|
||
|
|
||
|
if (iMenuCnt == 0)
|
||
|
{
|
||
|
hOleMenu = NULL;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
dwOleMenuItemsSize = (iMenuCnt-1) * sizeof(OLEMENUITEM);
|
||
|
}
|
||
|
|
||
|
hOleMenu = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT,
|
||
|
sizeof(OLEMENU) + dwOleMenuItemsSize);
|
||
|
|
||
|
if (!hOleMenu)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (! (lpOleMenu = (LPOLEMENU) GlobalLock(hOleMenu)))
|
||
|
{
|
||
|
GlobalFree(hOleMenu);
|
||
|
hOleMenu = NULL;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
lpOleMenu->wSignature = wSignature;
|
||
|
lpOleMenu->hmenuCombined = PtrToUlong(hmenuCombined);
|
||
|
lpOleMenu->lMenuCnt = (LONG) iMenuCnt;
|
||
|
|
||
|
if (! hmenuCombined)
|
||
|
{
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
lpMenuList = lpOleMenu->menuitem;
|
||
|
|
||
|
for (iMenuCnt = 0, iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
|
||
|
{
|
||
|
lpOleMenu->MenuWidths.width[iGroupCnt] =
|
||
|
lplMenuWidths->width[iGroupCnt];
|
||
|
for (n = 0; n < lplMenuWidths->width[iGroupCnt]; n++)
|
||
|
{
|
||
|
lpMenuList->fObjectMenu = (iGroupCnt % 2);
|
||
|
if (GetSubMenu(hmenuCombined, iMenuCnt) != NULL)
|
||
|
{
|
||
|
lpMenuList->fwPopup = MF_POPUP;
|
||
|
lpMenuList->item = PtrToUlong(GetSubMenu(
|
||
|
hmenuCombined, iMenuCnt));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lpMenuList->fwPopup = NULL;
|
||
|
lpMenuList->item = GetMenuItemID (
|
||
|
hmenuCombined, iMenuCnt);
|
||
|
}
|
||
|
|
||
|
lpMenuList++;
|
||
|
iMenuCnt++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Exit:
|
||
|
GlobalUnlock(hOleMenu);
|
||
|
|
||
|
errRtn:
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT OleCreateMenuDescriptor ( %lx )\n",
|
||
|
NULL, hOleMenu));
|
||
|
|
||
|
OLETRACEOUTEX((API_OleCreateMenuDescriptor, RETURNFMT("%h"), hOleMenu));
|
||
|
|
||
|
return (HOLEMENU) hOleMenu;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OleSetMenuDescriptor
|
||
|
//
|
||
|
// Synopsis: Called by the SetMenu method on the IOleInPlace frame
|
||
|
// interface. This API adds(removes) the FrameWndFilterProc
|
||
|
// to the Frame window of the container. And then sets and
|
||
|
// removes the main(frame) menu bar
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [holemenu] -- a handle to the composite menu descriptor
|
||
|
// [hwndFrame] -- a handle to the container's frame window
|
||
|
// [hwndActiveObject] -- a handle to the object's in-place
|
||
|
// window
|
||
|
// [lpFrame] -- pointer to the container's
|
||
|
// IOleInPlaceFrame implementation
|
||
|
// [lpActiveObj] -- pointer to in-place object
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: check arguments, then create a new frame filter object
|
||
|
// and attach it to the frame (replacing any that might
|
||
|
// already be there).
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#pragma SEG(OleSetMenuDescriptor)
|
||
|
STDAPI OleSetMenuDescriptor
|
||
|
(
|
||
|
HOLEMENU holemenu,
|
||
|
HWND hwndFrame,
|
||
|
HWND hwndObject,
|
||
|
LPOLEINPLACEFRAME lpFrame,
|
||
|
LPOLEINPLACEACTIVEOBJECT lpObject
|
||
|
)
|
||
|
{
|
||
|
OLETRACEIN((API_OleSetMenuDescriptor,
|
||
|
PARAMFMT("holemenu= %h, hwndFrame= %h, hwndObject= %h, lpFrame= %p, lpObject= %p"),
|
||
|
holemenu, hwndFrame, hwndObject, lpFrame, lpObject));
|
||
|
|
||
|
VDATEHEAP();
|
||
|
|
||
|
PCFRAMEFILTER pFrameFilter;
|
||
|
LPOLEMENU lpOleMenu = NULL;
|
||
|
LPOLEMENU lpOleMenuCopy = NULL;
|
||
|
HRESULT error = NOERROR;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN OleSetMenuDescriptor ( %lx , %lx ,"
|
||
|
"%lx , %p , %p )\n", NULL, holemenu, hwndFrame, hwndObject,
|
||
|
lpFrame, lpObject));
|
||
|
|
||
|
// The Frame window parameter always needs to be valid since
|
||
|
// we use it for both hook and unhook of menus
|
||
|
if (hwndFrame == NULL || !IsWindow(hwndFrame))
|
||
|
{
|
||
|
LEDebugOut((DEB_ERROR,
|
||
|
"ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
|
||
|
error = ResultFromScode(OLE_E_INVALIDHWND);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (holemenu != NULL)
|
||
|
{
|
||
|
if (hwndObject == NULL || !IsWindow(hwndObject))
|
||
|
{
|
||
|
LEDebugOut((DEB_ERROR,
|
||
|
"ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
|
||
|
error = ResultFromScode(OLE_E_INVALIDHWND);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (lpFrame && lpObject)
|
||
|
{
|
||
|
// the caller wants us to provide the support for
|
||
|
// context sensitive help, let's validat the pointers
|
||
|
VDATEIFACE_LABEL(lpFrame, errRtn, error);
|
||
|
VDATEIFACE_LABEL(lpObject, errRtn, error);
|
||
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
|
||
|
(IUnknown **)&lpFrame);
|
||
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceActiveObject,
|
||
|
(IUnknown **)&lpObject);
|
||
|
}
|
||
|
|
||
|
if (!(lpOleMenu = wGetOleMenuPtr(holemenu)))
|
||
|
{
|
||
|
error = ResultFromScode(E_HANDLE);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
|
||
|
// OleMenuPtr gets released down below by wReleaseOleMenuPtr
|
||
|
|
||
|
// Allocate memory for the copy
|
||
|
DWORD dwSize = (DWORD) GlobalSize(holemenu);
|
||
|
|
||
|
lpOleMenuCopy = (LPOLEMENU) PrivMemAlloc(dwSize);
|
||
|
|
||
|
if (lpOleMenuCopy == NULL)
|
||
|
{
|
||
|
wReleaseOleMenuPtr(holemenu);
|
||
|
error = E_OUTOFMEMORY;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
memcpy(lpOleMenuCopy, lpOleMenu, dwSize);
|
||
|
}
|
||
|
|
||
|
// if there is a frame filter get rid off it.
|
||
|
if (pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwndFrame))
|
||
|
{
|
||
|
// be sure to remove our window proc hook
|
||
|
|
||
|
pFrameFilter->RemoveWndProc();
|
||
|
|
||
|
pFrameFilter->SafeRelease();
|
||
|
}
|
||
|
|
||
|
// Add a new frame filter
|
||
|
if (holemenu)
|
||
|
{
|
||
|
error = CFrameFilter::Create (lpOleMenuCopy,
|
||
|
(HMENU)UlongToPtr(lpOleMenu->hmenuCombined),
|
||
|
hwndFrame,
|
||
|
hwndObject,
|
||
|
lpFrame,
|
||
|
lpObject);
|
||
|
|
||
|
if (FAILED(error))
|
||
|
{
|
||
|
PrivMemFree(lpOleMenuCopy);
|
||
|
}
|
||
|
|
||
|
wReleaseOleMenuPtr(holemenu);
|
||
|
}
|
||
|
|
||
|
errRtn:
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT OleSetMenuDescriptor ( %lx )\n",
|
||
|
NULL, error ));
|
||
|
|
||
|
OLETRACEOUT((API_OleSetMenuDescriptor, error));
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OleDestroyMenuDescriptor
|
||
|
//
|
||
|
// Synopsis: Releases the menu descriptor allocated by
|
||
|
// OleCreateMenuDescriptor
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [holemenu] -- the menu descriptor
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: NOERROR, E_HANDLE
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: does a global lock and verifies that holemenu is
|
||
|
// really a menu descriptor handle (via wGetOleMenuPtr),
|
||
|
// then unlock's and free's.
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(OleDestroyMenuDescriptor)
|
||
|
STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu)
|
||
|
{
|
||
|
OLETRACEIN((API_OleDestroyMenuDescriptor, PARAMFMT("holemenu= %h"), holemenu));
|
||
|
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LPOLEMENU lpOleMenu;
|
||
|
HRESULT error;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN OleDestroyMenuDescriptor ( %lx )\n",
|
||
|
NULL, holemenu));
|
||
|
|
||
|
// make sure that it is a valid handle
|
||
|
if (! (lpOleMenu = wGetOleMenuPtr(holemenu)))
|
||
|
{
|
||
|
error = ResultFromScode(E_HANDLE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wReleaseOleMenuPtr(holemenu);
|
||
|
GlobalFree((HGLOBAL) holemenu);
|
||
|
error = NOERROR;
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT OleDestroyMenuDescriptor ( %lx )\n",
|
||
|
NULL, error));
|
||
|
|
||
|
OLETRACEOUT((API_OleDestroyMenuDescriptor, error));
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: wSysKeyToKey (internal)
|
||
|
//
|
||
|
// Synopsis: Converts a message from a WM_SYSKEY to a WM_KEY message
|
||
|
// if the alt key was not held down
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [lpMsg] -- the message to convert
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: UINT -- the new message
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes: original notes:
|
||
|
//
|
||
|
// if the ALT key is down when a key is pressed, then the 29th bit of the
|
||
|
// LPARAM will be set
|
||
|
//
|
||
|
// If the message was not made with the ALT key down, convert the message
|
||
|
// from a WM_SYSKEY* to a WM_KEY* message.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
static UINT wSysKeyToKey(LPMSG lpMsg)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
UINT message = lpMsg->message;
|
||
|
|
||
|
if (!(HIWORD(lpMsg->lParam) & 0x2000)
|
||
|
&& (message >= WM_SYSKEYDOWN && message <= WM_SYSDEADCHAR))
|
||
|
{
|
||
|
message -= (WM_SYSKEYDOWN - WM_KEYDOWN);
|
||
|
}
|
||
|
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: OleTranslateAccelerator
|
||
|
//
|
||
|
// Synopsis: Called by an inplace object to allow a container to attempt
|
||
|
// to handle an accelerator
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [lpFrame] -- pointer to IOleInPlaceFrame where the
|
||
|
// keystroke might be sent
|
||
|
// [lpFrameInfo] -- pointer to and OLEINPLACEFRAMEINFO
|
||
|
// from the container with it's accelerator
|
||
|
// table
|
||
|
// [lpmsg] -- the keystroke
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: We call SendMessage to store the accelerator cmd
|
||
|
// (to handle degenerate lookups on the container) and
|
||
|
// then ask the container to handle
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(OleTranslateAccelerator)
|
||
|
STDAPI OleTranslateAccelerator(LPOLEINPLACEFRAME lpFrame,
|
||
|
LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpMsg)
|
||
|
{
|
||
|
OLETRACEIN((API_OleTranslateAccelerator,
|
||
|
PARAMFMT("lpFrame= %p, lpFrameInfo= %to, lpMsg= %tm"),
|
||
|
lpFrame, lpFrameInfo, lpMsg));
|
||
|
|
||
|
VDATEHEAP();
|
||
|
|
||
|
WORD cmd;
|
||
|
BOOL fFound;
|
||
|
HRESULT error;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN OleTranslateAccelerator ( %p , %p "
|
||
|
", %p )\n", NULL, lpFrame, lpFrameInfo, lpMsg));
|
||
|
CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
|
||
|
(IUnknown **)&lpFrame);
|
||
|
|
||
|
// Validate parameters -- the best that we can!
|
||
|
// Note: the macro's VDATEPTR* were not used because they return
|
||
|
// immediately & break the tracing semantics
|
||
|
if (!IsValidInterface(lpFrame)
|
||
|
|| !IsValidPtrIn(lpFrameInfo, sizeof(OLEINPLACEFRAMEINFO))
|
||
|
|| !IsValidPtrIn(lpMsg, sizeof(MSG)))
|
||
|
{
|
||
|
error = ResultFromScode(E_INVALIDARG);
|
||
|
goto exitRtn;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Search the (container) frame's table of accelerators. Remember that
|
||
|
// the container may be (actually most likely) is in a separate
|
||
|
// process.
|
||
|
fFound = IsAccelerator(lpFrameInfo->haccel,
|
||
|
lpFrameInfo->cAccelEntries, lpMsg, &cmd);
|
||
|
|
||
|
if (!fFound && lpFrameInfo->fMDIApp)
|
||
|
{
|
||
|
// If no accelerator was found and the app is a MDI app,
|
||
|
// then we see if there is a mdi accelerator found.
|
||
|
fFound = IsMDIAccelerator(lpMsg, &cmd);
|
||
|
}
|
||
|
|
||
|
if (fFound)
|
||
|
{
|
||
|
// Found some kind of for the container accelerator.
|
||
|
|
||
|
// uOleMessage is set in ole2.cpp -- it is a private message
|
||
|
// between OLE applications.
|
||
|
|
||
|
// This SendMessage tells the message filter that is on the
|
||
|
// frame window what the command translated to. This will
|
||
|
// be used in menu collision processing.
|
||
|
SSSendMessage(lpFrameInfo->hwndFrame, uOleMessage,
|
||
|
OM_COMMAND_ID, MAKELONG(cmd, 0));
|
||
|
|
||
|
// Send the command and the message to the container. The
|
||
|
// result tells the caller whether the container really
|
||
|
// used the command.
|
||
|
|
||
|
error = lpFrame->TranslateAccelerator(lpMsg, cmd);
|
||
|
|
||
|
}
|
||
|
else if (wSysKeyToKey(lpMsg) == WM_SYSCHAR)
|
||
|
{
|
||
|
// Eat the message if it is "Alt -". This is supposed
|
||
|
// to bring the MDI system menu down. But we can not
|
||
|
// support it. And we also don't want the message to
|
||
|
// be Translated by the object application either.
|
||
|
// So, we return as if it has been accepted by the
|
||
|
// container as an accelerator.
|
||
|
|
||
|
// If the container wants to support this it can
|
||
|
// have an accelerator for this. This is not an
|
||
|
// issue for SDI apps, because it will be thrown
|
||
|
// away by USER anyway.
|
||
|
|
||
|
// This is the original support as it appeared in
|
||
|
// the 16-bit version of OLE and the first 32-bit
|
||
|
// release. To fix the problem, remove the comment
|
||
|
// tags from the else case below and comment the
|
||
|
// code out in the _DEBUG #ifdef below. This new
|
||
|
// code will walk back up through the objects
|
||
|
// parent windows until a window is found that
|
||
|
// contains a system menu, at which point the
|
||
|
// message is sent.
|
||
|
|
||
|
if (lpMsg->wParam != OLESTR('-'))
|
||
|
{
|
||
|
SSSendMessage(lpFrameInfo->hwndFrame,
|
||
|
lpMsg->message,
|
||
|
lpMsg->wParam, lpMsg->lParam);
|
||
|
}
|
||
|
// else
|
||
|
// {
|
||
|
// HWND hWndCurrent = lpMsg->hwnd;
|
||
|
//
|
||
|
// while ( hWndCurrent &&
|
||
|
// !(GetWindowLong(hWndCurrent, GWL_STYLE) & WS_SYSMENU))
|
||
|
// {
|
||
|
// hWndCurrent = GetParent(hWndCurrent);
|
||
|
// }
|
||
|
//
|
||
|
// if (hWndCurrent)
|
||
|
// {
|
||
|
// SSSendMessage(hWndCurrent,
|
||
|
// lpMsg->message,
|
||
|
// lpMsg->wParam, lpMsg->lParam);
|
||
|
// }
|
||
|
// }
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
else
|
||
|
{
|
||
|
OutputDebugString(
|
||
|
TEXT("OleTranslateAccelerator: Alt+ - key is discarded\r\n"));
|
||
|
}
|
||
|
#endif
|
||
|
error = NOERROR;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
error = ResultFromScode(S_FALSE);
|
||
|
}
|
||
|
|
||
|
exitRtn:
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT OleTranslateAccelerator ( %lx )\n",
|
||
|
NULL, error));
|
||
|
|
||
|
OLETRACEOUT((API_OleTranslateAccelerator, error));
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsAccelerator
|
||
|
//
|
||
|
// Synopsis: determines whether [lpMsg] is an accelerator in the [hAccel]
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [hAccel] -- the accelerator table
|
||
|
// [cAccelEntries] -- the number of entries in the accelerator
|
||
|
// table
|
||
|
// [lpMsg] -- the keystroke message that we should
|
||
|
// see if it's an accelerator
|
||
|
// [lpCmd] -- where to return the corresponding command
|
||
|
// ID if an accelerator is found (may be NULL)
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: TRUE if accelerator is found, FALSE otherwise or on error
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
STDAPI_(BOOL) IsAccelerator
|
||
|
(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD FAR* lpwCmd)
|
||
|
{
|
||
|
OLETRACEIN((API_IsAccelerator,
|
||
|
PARAMFMT("hAccel= %h, cAccelEntries= %d, lpMsg= %tm, lpwCmd= %p"),
|
||
|
hAccel, cAccelEntries, lpMsg, lpwCmd));
|
||
|
|
||
|
VDATEHEAP();
|
||
|
|
||
|
WORD cmd = NULL;
|
||
|
WORD flags;
|
||
|
BOOL fFound = FALSE;
|
||
|
BOOL fVirt;
|
||
|
UINT message;
|
||
|
|
||
|
// Safe place for pointer to accelerator table
|
||
|
CPaccelEnum cpaccelenum;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN IsAccelerator ( %lx , %d , %p , %p )\n",
|
||
|
NULL, hAccel, cAccelEntries, lpMsg, lpwCmd));
|
||
|
|
||
|
if (! cAccelEntries)
|
||
|
{
|
||
|
// no accelerators so we can stop here.
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
// Change message type from WM_SYS type to WM_KEY type if the ALT
|
||
|
// key is not pressed.
|
||
|
message = wSysKeyToKey(lpMsg);
|
||
|
|
||
|
// Figure out whether this message is one that can possibly contain
|
||
|
// an accelerator.
|
||
|
switch (message)
|
||
|
{
|
||
|
case WM_KEYDOWN:
|
||
|
case WM_SYSKEYDOWN:
|
||
|
// wParam in this message is virtual key code
|
||
|
fVirt = TRUE;
|
||
|
break;
|
||
|
|
||
|
case WM_CHAR:
|
||
|
case WM_SYSCHAR:
|
||
|
// wParam is the character
|
||
|
fVirt = FALSE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
// Get a pointer to the accerator table
|
||
|
if ((hAccel == NULL)
|
||
|
|| !cpaccelenum.InitLPACCEL(hAccel, cAccelEntries))
|
||
|
{
|
||
|
// Handle is NULL or we could not lock the resource so exit.
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
// Get the flags from the accelerator table entry to save
|
||
|
// a pointer dereference.
|
||
|
flags = cpaccelenum->fVirt;
|
||
|
|
||
|
// if the key in the message and the table aren't the same,
|
||
|
// or if the key is virtual and the accel table entry is not or
|
||
|
// vice versa (if key is not virtual & accel table entry is
|
||
|
// not), we can skip checking the accel entry immediately.
|
||
|
if ((cpaccelenum->key != (WORD) lpMsg->wParam) ||
|
||
|
((fVirt != 0) != ((flags & FVIRTKEY) != 0)))
|
||
|
{
|
||
|
goto Next;
|
||
|
}
|
||
|
|
||
|
if (fVirt)
|
||
|
{
|
||
|
// If shift down & shift not requested in accelerator
|
||
|
// table or if shift not down and shift not set,
|
||
|
// we skip this table entry.
|
||
|
if ((GetKeyState(VK_SHIFT) < 0) != ((flags & FSHIFT)
|
||
|
!= 0))
|
||
|
{
|
||
|
goto Next;
|
||
|
}
|
||
|
|
||
|
// Likewise if control key down & control key not
|
||
|
// set in accelerator table or if control not down
|
||
|
// and it was set in the accelerator table, we skip
|
||
|
// skip this entry in the table.
|
||
|
if ((GetKeyState(VK_CONTROL) < 0) !=
|
||
|
((flags & FCONTROL) != 0))
|
||
|
{
|
||
|
goto Next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If the ALT key is down and the accel table flags do not
|
||
|
// request the ALT flags or if the alt key is not down and
|
||
|
// the ALT is requested, this item does not match.
|
||
|
if ((GetKeyState(VK_MENU) < 0) != ((flags & FALT) != 0))
|
||
|
{
|
||
|
goto Next;
|
||
|
}
|
||
|
|
||
|
// We have gotten a match in the table.
|
||
|
// we get the command out of the table and record that we found
|
||
|
// something.
|
||
|
cmd = cpaccelenum->cmd;
|
||
|
fFound = TRUE;
|
||
|
|
||
|
goto errRtn;
|
||
|
|
||
|
Next:
|
||
|
cpaccelenum.Next();
|
||
|
|
||
|
} while (--cAccelEntries);
|
||
|
|
||
|
|
||
|
errRtn:
|
||
|
// Common exit
|
||
|
|
||
|
if (lpwCmd)
|
||
|
{
|
||
|
// If caller wants to get back the command that they
|
||
|
// requested, we assign it at this point.
|
||
|
*lpwCmd = cmd;
|
||
|
}
|
||
|
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT IsAccelerator ( %lu )\n", NULL,
|
||
|
fFound));
|
||
|
|
||
|
OLETRACEOUTEX((API_IsAccelerator, RETURNFMT("%B"), fFound));
|
||
|
|
||
|
// Return the result of the search.
|
||
|
return fFound;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsMDIAccelerator
|
||
|
//
|
||
|
// Synopsis: determines wither [lpMsg] is an accelerator for MDI window
|
||
|
// commands
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [lpMsg] -- the keystroke to look at
|
||
|
// [lpCmd] -- where to put the command ID
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: BOOL
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: Make sure message is a key down message. Then make sure
|
||
|
// that the control key is up or toggled and the ALT key is
|
||
|
// down. Then if F4 is pressed set the system command to
|
||
|
// close or if the F6 or tab keys are pressed send the
|
||
|
// appropriate window switch message.
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port, fixed fall-through bug
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(IsMDIAccelerator)
|
||
|
BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* lpCmd)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
BOOL fResult = FALSE;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN IsMDIAccelerator ( %p , %p )\n",
|
||
|
NULL, lpMsg, lpCmd));
|
||
|
|
||
|
// This can be an accelerator only if this is some kind of key down.
|
||
|
if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
|
||
|
{
|
||
|
goto IsMDIAccelerator_exit;
|
||
|
}
|
||
|
|
||
|
if (GetKeyState(VK_CONTROL) >= 0)
|
||
|
{
|
||
|
// All MIDI accelerators have the control key up (or toggled),
|
||
|
// so we can exit here if it isn't down.
|
||
|
goto IsMDIAccelerator_exit;
|
||
|
}
|
||
|
|
||
|
switch ((WORD)lpMsg->wParam)
|
||
|
{
|
||
|
case VK_F4:
|
||
|
*lpCmd = SC_CLOSE;
|
||
|
fResult = TRUE;
|
||
|
break; // this break was not in the 16bit code, but
|
||
|
// it looks like it must be there (otherwise
|
||
|
// this info is lost)
|
||
|
case VK_F6:
|
||
|
case VK_TAB:
|
||
|
fResult = TRUE;
|
||
|
|
||
|
*lpCmd = (GetKeyState(VK_SHIFT) < 0)
|
||
|
? SC_PREVWINDOW : SC_NEXTWINDOW;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
IsMDIAccelerator_exit:
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT IsMDIAccelerator ( %lu ) [ %lu ] \n",
|
||
|
NULL, fResult, *lpCmd));
|
||
|
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: FrameWndFilterProc
|
||
|
//
|
||
|
// Synopsis: The callback proc for the container's frame window
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [hwnd] -- the window handle
|
||
|
// [msg] -- the msg causing the notification
|
||
|
// [uParam] -- first param
|
||
|
// [lParam] -- second param
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: LRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: Gets the CFrame object (if available) and asks it
|
||
|
// to deal with the window message
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(FrameWndFilterProc)
|
||
|
STDAPI_(LRESULT) FrameWndFilterProc(HWND hwnd, UINT msg, WPARAM uParam, LPARAM lParam)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
PCFRAMEFILTER pFrameFilter;
|
||
|
LRESULT lresult;
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN FrameWndFilterProc ( 0x%p , %u ,"
|
||
|
" %u , %ld )\n", NULL, hwnd, msg, PtrToUlong((void*)uParam), PtrToLong((void*)lParam)));
|
||
|
|
||
|
if (!(pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwnd)))
|
||
|
{
|
||
|
lresult = SSDefWindowProc(hwnd, msg, uParam, lParam);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// stabilize the frame filter
|
||
|
CStabilize FFstabilize((CSafeRefCount *)pFrameFilter);
|
||
|
|
||
|
if (msg == WM_SYSCOMMAND)
|
||
|
{
|
||
|
lresult = pFrameFilter->OnSysCommand(uParam,
|
||
|
lParam);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lresult = pFrameFilter->OnMessage(msg, uParam,
|
||
|
lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT FrameWndFilterProc ( %lu )\n",
|
||
|
NULL, PtrToUlong((void*)lresult)));
|
||
|
|
||
|
return lresult;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: CFrameFilter::Create
|
||
|
//
|
||
|
// Synopsis: Allocates and initializes a CFrame object (which handles
|
||
|
// all of the real processing work for event callbacks)
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [lpOleMenu] -- pointer to the ole menu descriptor
|
||
|
// [hmenuCombined] -- the combined menu handle
|
||
|
// [hwndFrame] -- handle to the container's frame
|
||
|
// (where the CFrame should be installed)
|
||
|
// [hwndActiveObj] -- handle to the in-place object's window
|
||
|
// [lpFrame] -- pointer to the container's
|
||
|
// IOleInPlaceFrame implementation
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm: Allocates the object and installs a pointer to it as
|
||
|
// a property on the window
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_Create)
|
||
|
HRESULT CFrameFilter::Create(LPOLEMENU lpOleMenu, HMENU hmenuCombined,
|
||
|
HWND hwndFrame, HWND hwndActiveObj,
|
||
|
LPOLEINPLACEFRAME lpFrame, LPOLEINPLACEACTIVEOBJECT lpActiveObj)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::Create ( %lx , %p ,"
|
||
|
" %lx , %lx , %p , %p )\n", NULL, lpOleMenu,
|
||
|
hmenuCombined, hwndFrame, hwndActiveObj,
|
||
|
lpFrame, lpActiveObj));
|
||
|
|
||
|
CFrameFilter * pFF = new CFrameFilter(hwndFrame, hwndActiveObj);
|
||
|
|
||
|
if (!pFF)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
pFF->SafeAddRef();
|
||
|
|
||
|
pFF->m_lpOleMenu = lpOleMenu;
|
||
|
pFF->m_hmenuCombined = hmenuCombined;
|
||
|
|
||
|
// If the following pointers are NON-NULL, it means that the container
|
||
|
// wants us to use our message filter to deal with the F1 key. So,
|
||
|
// remember the pointers.
|
||
|
|
||
|
if (lpFrame && lpActiveObj)
|
||
|
{
|
||
|
// these addref's should not be outgoing calls, so
|
||
|
// no need to stabilize around them. (unless, of
|
||
|
// course, the container made an outgoing call for
|
||
|
// frame->AddRef, but that would be really weird).
|
||
|
|
||
|
(pFF->m_lpFrame = lpFrame)->AddRef();
|
||
|
(pFF->m_lpObject = lpActiveObj)->AddRef();
|
||
|
}
|
||
|
|
||
|
// Hook the frame wnd proc
|
||
|
if (!(pFF->m_lpfnPrevWndProc = (WNDPROC) SetWindowLongPtr (hwndFrame,
|
||
|
GWLP_WNDPROC, (LONG_PTR) FrameWndFilterProc)))
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32
|
||
|
if (!SetProp (hwndFrame, szPropFrameFilter, (HANDLE) pFF))
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
#else
|
||
|
if (!SetProp (hwndFrame, szPropFrameFilterH, HIWORD(pFF)))
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (!SetProp (hwndFrame, szPropFrameFilterL, LOWORD(pFF)))
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
|
||
|
NULL, NOERROR ));
|
||
|
return NOERROR;
|
||
|
|
||
|
errRtn:
|
||
|
if (pFF)
|
||
|
{
|
||
|
pFF->SafeRelease();
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
|
||
|
NULL, ResultFromScode(E_OUTOFMEMORY)));
|
||
|
|
||
|
return ResultFromScode(E_OUTOFMEMORY);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::CFrameFilter
|
||
|
//
|
||
|
// Synopsis: Constructor for the frame filter object
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [hwndFrame] -- the container's frame
|
||
|
// [hwndActiveObj] -- the inplace object's window
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_ctor)
|
||
|
CFrameFilter::CFrameFilter (HWND hwndFrame, HWND hwndActiveObj) :
|
||
|
CSafeRefCount(NULL)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
m_hwndFrame = hwndFrame;
|
||
|
m_hwndObject = hwndActiveObj;
|
||
|
m_lpFrame = NULL;
|
||
|
m_lpObject = NULL;
|
||
|
m_lpfnPrevWndProc = NULL;
|
||
|
m_fObjectMenu = FALSE;
|
||
|
m_fCurItemPopup = FALSE;
|
||
|
m_fInMenuMode = FALSE;
|
||
|
m_fGotMenuCloseEvent = FALSE;
|
||
|
m_uCurItemID = NULL;
|
||
|
m_cAltTab = NULL;
|
||
|
m_hwndFocusOnEnter = NULL;
|
||
|
m_fDiscardWmCommand = FALSE;
|
||
|
m_cmdId = NULL;
|
||
|
m_fRemovedWndProc = FALSE;
|
||
|
#ifdef _CHICAGO_
|
||
|
m_fInNCACTIVATE = FALSE;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFileter::~CFrameFilter
|
||
|
//
|
||
|
// Synopsis: destroys the object
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_dtor)
|
||
|
CFrameFilter::~CFrameFilter(void)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::~CFrameFilter ( )\n",
|
||
|
this));
|
||
|
|
||
|
PrivMemFree(m_lpOleMenu);
|
||
|
|
||
|
// remove the FrameWndFilterProc hook. We do this *before*
|
||
|
// the Releases since those releases may make outgoing calls
|
||
|
// (we'd like to be in a 'safe' state).
|
||
|
|
||
|
// REVIEW32: We may want to check to see if we're the current
|
||
|
// window proc before blowing it away. Some apps (like Word)
|
||
|
// go ahead and blow away the wndproc by theselves without calling
|
||
|
// OleSetMenuDescriptor(NULL);
|
||
|
|
||
|
RemoveWndProc();
|
||
|
|
||
|
if (m_lpFrame != NULL)
|
||
|
{
|
||
|
// OleUnInitialize could have been called.
|
||
|
// In such case we do not want to call releas
|
||
|
// on OLeObject.
|
||
|
COleTls tls;
|
||
|
if(tls->cOleInits > 0)
|
||
|
{
|
||
|
SafeReleaseAndNULL((IUnknown **)&m_lpFrame);
|
||
|
SafeReleaseAndNULL((IUnknown **)&m_lpObject);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_lpObject = NULL;
|
||
|
m_lpFrame = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::~CFrameFilter ( )\n",
|
||
|
this));
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::RemoveWndProc
|
||
|
//
|
||
|
// Synopsis: un-installs our window proc for inplace-processing
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Requires: none
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 04-Aug-94 alexgo author
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void CFrameFilter::RemoveWndProc()
|
||
|
{
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::RemoveWndProc ( )\n",
|
||
|
this));
|
||
|
|
||
|
if( m_fRemovedWndProc == FALSE)
|
||
|
{
|
||
|
m_fRemovedWndProc = TRUE;
|
||
|
|
||
|
if (m_lpfnPrevWndProc)
|
||
|
{
|
||
|
// If the sub-classing has already been removed, then
|
||
|
// don't bother to remove it again. This happens
|
||
|
// to be the case with Word 6 and inplace embeddings.
|
||
|
// and Word95 with SnapGraphics.
|
||
|
|
||
|
// if somebody comes along later (after us) and
|
||
|
// sub-classes the window, we won't be able to remove
|
||
|
// ourselves so we just avoid it.
|
||
|
|
||
|
if (GetWindowLongPtr(m_hwndFrame, GWLP_WNDPROC) ==
|
||
|
(LONG_PTR)FrameWndFilterProc)
|
||
|
{
|
||
|
|
||
|
SetWindowLongPtr (m_hwndFrame, GWLP_WNDPROC,
|
||
|
(LONG_PTR) m_lpfnPrevWndProc);
|
||
|
|
||
|
}
|
||
|
|
||
|
// We remove the window property at the
|
||
|
// same time as the sub-classing since
|
||
|
// the window property is the flag as to
|
||
|
// whether we are doing sub-classing. The
|
||
|
// problem this solves is that what if
|
||
|
// OleSetMenuDescriptor is called while we
|
||
|
// have the menu subclassed? We won't remove
|
||
|
// this property until the outer most sub
|
||
|
// classing is exited which if we are setting
|
||
|
// a new sub-class will remove the new
|
||
|
// sub-class' window property. Therefore, it
|
||
|
// will look like the window is not sub-classed
|
||
|
// at all.
|
||
|
#ifdef WIN32
|
||
|
HANDLE h = RemoveProp (m_hwndFrame, szPropFrameFilter);
|
||
|
// We must not free 'h'. It's not a real handle.
|
||
|
#else
|
||
|
RemoveProp (m_hwndFrame, szPropFrameFilterH);
|
||
|
RemoveProp (m_hwndFrame, szPropFrameFilterL);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::RemoveWndProc ( )\n",
|
||
|
this));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::OnSysCommand
|
||
|
//
|
||
|
// Synopsis: Process system messages
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [uParam] -- the first message argument
|
||
|
// [lParam] -- the second message argument
|
||
|
//
|
||
|
// Requires: the 'this' pointer must have been stabilized before
|
||
|
// calling this function.
|
||
|
//
|
||
|
// Returns: LRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm: big switch to deal with the different types of messages
|
||
|
// see comments below
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes: FrameWndFilterProc currently does the work of stabilizing
|
||
|
// the framefilter's 'this' pointer.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_OnSysCommand)
|
||
|
LRESULT CFrameFilter::OnSysCommand(WPARAM uParam, LPARAM lParam)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
UINT uParamTmp = ((UINT)uParam & 0xFFF0);
|
||
|
LRESULT lresult;
|
||
|
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnSysCommand ( %lu ,"
|
||
|
" %ld )\n", this, PtrToUlong((void*)uParam), PtrToLong((void*)lParam)));
|
||
|
|
||
|
// this lets the sending app continue processing
|
||
|
if (SSInSendMessage())
|
||
|
{
|
||
|
|
||
|
SSReplyMessage(NULL);
|
||
|
}
|
||
|
|
||
|
switch (uParamTmp)
|
||
|
{
|
||
|
case SC_KEYMENU:
|
||
|
case SC_MOUSEMENU:
|
||
|
OnEnterMenuMode();
|
||
|
SSCallWindowProc((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
|
||
|
WM_SYSCOMMAND, uParam, lParam);
|
||
|
|
||
|
// By this time menu processing would've been completed.
|
||
|
|
||
|
if (! m_fGotMenuCloseEvent)
|
||
|
{
|
||
|
// Can happen if user cancelled menu mode when MDI
|
||
|
// window's system menu is down. Hence generate
|
||
|
// the message here
|
||
|
|
||
|
SSSendMessage(m_hwndFrame, WM_MENUSELECT, 0,
|
||
|
MAKELONG(-1,0));
|
||
|
}
|
||
|
|
||
|
// We can not set m_fObjectMenu to FALSE yet, 'cause we
|
||
|
// could be recieving the WM_COMMAND (if a menu item is
|
||
|
// selected), which gets posted by the windows' menu
|
||
|
// processing code.
|
||
|
// We will clear the flag when we get OM_CLEAR_MENU_STATE
|
||
|
// message. Even if WM_COMMAND got generated, this message
|
||
|
// will come after that
|
||
|
PostMessage (m_hwndFrame, uOleMessage, OM_CLEAR_MENU_STATE,
|
||
|
0L);
|
||
|
OnExitMenuMode();
|
||
|
lresult = 0L;
|
||
|
goto errRtn;
|
||
|
|
||
|
case SC_NEXTWINDOW:
|
||
|
case SC_PREVWINDOW:
|
||
|
|
||
|
OnEnterAltTabMode();
|
||
|
lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc,
|
||
|
m_hwndFrame, WM_SYSCOMMAND, uParam, lParam);
|
||
|
OnExitAltTabMode();
|
||
|
|
||
|
goto errRtn;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc, m_hwndFrame,
|
||
|
WM_SYSCOMMAND, uParam, lParam);
|
||
|
|
||
|
errRtn:
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnSysCommand ( %lx )\n",
|
||
|
this, PtrToLong((void*)lresult)));
|
||
|
|
||
|
return lresult;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::OnEnterMenuMode
|
||
|
//
|
||
|
// Synopsis: called by the SysCommand processing, puts us into in
|
||
|
// InMenuMode, sets the focus and installs our message filter
|
||
|
// hook.
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 23-Feb-94 alexgo restored OLE32 in GetModuleHandle
|
||
|
// 31-Dec-93 erikgav removed hardcoded "OLE2" in GetModuleHandle
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes: REVIEW32: We may need to update this to reflect new
|
||
|
// focus management policies.
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_OnEnterMenuMode)
|
||
|
void CFrameFilter::OnEnterMenuMode()
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterMenuMode ( )\n",
|
||
|
this ));
|
||
|
|
||
|
if (m_fInMenuMode)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
m_fInMenuMode = TRUE;
|
||
|
m_fGotMenuCloseEvent = FALSE;
|
||
|
m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
|
||
|
|
||
|
if (!m_lpFrame)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
// REVIEW32: hMsgHook is a static (formerly global) variable for
|
||
|
// the whole dll. This may cause problems on NT (with threads, etc)
|
||
|
// (what happens if we haven't yet unhooked a previous call and
|
||
|
// we get here again????)
|
||
|
|
||
|
if (hMsgHook = (HHOOK) SetWindowsHookEx (WH_MSGFILTER,
|
||
|
(HOOKPROC) MessageFilterProc,
|
||
|
//GetModuleHandle(NULL),
|
||
|
GetModuleHandle(TEXT("OLE32")),
|
||
|
GetCurrentThreadId()))
|
||
|
{
|
||
|
pFrameFilter = this;
|
||
|
}
|
||
|
|
||
|
errRtn:
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterMenuMode ( )\n",
|
||
|
this ));
|
||
|
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::OnExitMenuMode
|
||
|
//
|
||
|
// Synopsis: takes us out of InMenuMode
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm: Resets the focus and unhooks our callback function
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes: REVIEW32:: see OnEnterMenuMode
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_OnExitMenuMode)
|
||
|
void CFrameFilter::OnExitMenuMode()
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitMenuMode ( )\n",
|
||
|
this));
|
||
|
|
||
|
if (m_fInMenuMode)
|
||
|
{
|
||
|
|
||
|
m_fInMenuMode = FALSE;
|
||
|
m_fGotMenuCloseEvent = TRUE;
|
||
|
m_uCurItemID = NULL;
|
||
|
|
||
|
if (hMsgHook)
|
||
|
{
|
||
|
UnhookWindowsHookEx(hMsgHook);
|
||
|
hMsgHook = NULL;
|
||
|
pFrameFilter = NULL;
|
||
|
}
|
||
|
|
||
|
SetFocus(m_hwndFocusOnEnter);
|
||
|
m_hwndFocusOnEnter = NULL;
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitMenuMode ( )\n",
|
||
|
this));
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFileter::OnEnterAltTabMode
|
||
|
//
|
||
|
// Synopsis: enters AltTab mode and sets the focus
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes: REVIEW32: we may need to modify to implement new
|
||
|
// focus management policy
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void CFrameFilter::OnEnterAltTabMode(void)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterAltTabMode ( )\n",
|
||
|
this ));
|
||
|
|
||
|
if (m_cAltTab == NULL)
|
||
|
{
|
||
|
|
||
|
m_fInMenuMode = TRUE;
|
||
|
// this will prevent SetFocus from getting
|
||
|
// delegated to the object
|
||
|
m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
|
||
|
m_fInMenuMode = FALSE;
|
||
|
}
|
||
|
|
||
|
m_cAltTab++;
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterAltTabMode ( )\n",
|
||
|
this ));
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::OnExitAltTabMode
|
||
|
//
|
||
|
// Synopsis: exits alt-tab mode and sets the focus
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
void CFrameFilter::OnExitAltTabMode()
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitAltTabMode ( )\n",
|
||
|
this ));
|
||
|
|
||
|
Assert(m_cAltTab != NULL);
|
||
|
|
||
|
if (--m_cAltTab == 0)
|
||
|
{
|
||
|
// The m_hwndFocusOnEnter would've been set to NULL if we are
|
||
|
// going to ALT-TAB out into some other process. In that case
|
||
|
// we would have got WM_ACTIVATEAPP and/or WM_KILLFOCUS.
|
||
|
if (m_hwndFocusOnEnter)
|
||
|
{
|
||
|
SetFocus(m_hwndFocusOnEnter);
|
||
|
m_hwndFocusOnEnter = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitAltTabMode ( )\n",
|
||
|
this ));
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::OnMessage
|
||
|
//
|
||
|
// Synopsis: Handles window message processing
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [msg] -- the window message
|
||
|
// [uParam] -- the first argument
|
||
|
// [lParam] -- the second argument
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: LRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm: a big switch to deal with the different commands
|
||
|
// see comments below
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_OnMessage)
|
||
|
LRESULT CFrameFilter::OnMessage(UINT msg, WPARAM uParam, LPARAM lParam)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
LRESULT lresult;
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnMessage ( %u , %u ,"
|
||
|
" %ld )\n", this, msg, PtrToUlong((void*)uParam),
|
||
|
PtrToLong((void*)lParam)));
|
||
|
|
||
|
// We come to this routine only if the message is not WM_SYSCOMMAND
|
||
|
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_SETFOCUS:
|
||
|
if (m_fInMenuMode)
|
||
|
{
|
||
|
lresult = SSDefWindowProc (m_hwndFrame, msg, uParam, lParam);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_MENUSELECT:
|
||
|
if (m_fInMenuMode)
|
||
|
{
|
||
|
#ifdef WIN32
|
||
|
HMENU hmenu = (HMENU) lParam;
|
||
|
UINT fwMenu = HIWORD(uParam);
|
||
|
UINT uItem = 0;
|
||
|
|
||
|
// There is a subtle difference in the message between
|
||
|
// Win16 & Win32 here. In Win16, the item is either
|
||
|
// an item id or a menu handle for a pop up menu.
|
||
|
// In Win32, the item is an item id or an offset
|
||
|
// in a menu if it is a popup menu handle. To minimize
|
||
|
// changes, we map this field as was appropriate for
|
||
|
// Win16.
|
||
|
|
||
|
if ( (fwMenu & MF_POPUP) &&
|
||
|
(hmenu != 0) )
|
||
|
{
|
||
|
uItem = (UINT) PtrToUlong(GetSubMenu(hmenu, (int) LOWORD(uParam)));
|
||
|
}
|
||
|
else {
|
||
|
uItem = LOWORD(uParam);
|
||
|
}
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
if (!uItem) {
|
||
|
uItem = LOWORD(uParam);
|
||
|
}
|
||
|
#endif // _CHICAGO_
|
||
|
|
||
|
#else // !WIN32
|
||
|
HMENU hmenu = (HMENU)HIWORD(lParam);
|
||
|
UINT fwMenu = LOWORD(lParam);
|
||
|
UINT uItem = uParam;
|
||
|
#endif // else !WIN32
|
||
|
|
||
|
|
||
|
m_uCurItemID = uItem;
|
||
|
m_fCurItemPopup = fwMenu & MF_POPUP;
|
||
|
|
||
|
if (hmenu == 0 && fwMenu == 0xFFFF)
|
||
|
{
|
||
|
// end of menu processing
|
||
|
|
||
|
// We can not set m_fObjectMenu to FALSE yet,
|
||
|
// because we could be recieving the
|
||
|
// WM_COMMAND (if a menu item is selected),
|
||
|
// which is posted by the windows' menu
|
||
|
// processing code, and will be recieved at
|
||
|
// a later time.
|
||
|
|
||
|
// There is no way to figure whether the user
|
||
|
// has selected a menu (which implies that
|
||
|
// WM_COMMAND is posted), or ESCaped out of
|
||
|
// menu selection.
|
||
|
|
||
|
// This problem is handled by posting a
|
||
|
// message to ourselves to clear the flag.
|
||
|
// See CFrameFilter::OnSysCommand() for
|
||
|
// more details...
|
||
|
|
||
|
m_fGotMenuCloseEvent = TRUE;
|
||
|
SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (fwMenu & MF_SYSMENU)
|
||
|
{
|
||
|
m_fObjectMenu = FALSE;
|
||
|
// if it is top level menu, see whose
|
||
|
// menu it is
|
||
|
|
||
|
}
|
||
|
else if (IsHmenuEqual(hmenu, m_hmenuCombined))
|
||
|
{
|
||
|
// set m_fObjectMenu
|
||
|
IsObjectMenu (uItem, fwMenu);
|
||
|
|
||
|
// this flag must not be modified
|
||
|
// when nested menus are selected.
|
||
|
}
|
||
|
|
||
|
if (m_fObjectMenu)
|
||
|
{
|
||
|
lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
} // else
|
||
|
} // if (m_fInMenuMode)
|
||
|
break; // WM_MENUSELECT
|
||
|
|
||
|
case WM_MEASUREITEM:
|
||
|
case WM_DRAWITEM:
|
||
|
if (m_fInMenuMode && m_fObjectMenu)
|
||
|
{
|
||
|
lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_ENTERIDLE:
|
||
|
{
|
||
|
WCHAR wstr[10];
|
||
|
|
||
|
// We need to post this message if the server is
|
||
|
// SnapGraphics. See bug #18576.
|
||
|
GetClassName(m_hwndObject, wstr, 10);
|
||
|
if (0 == lstrcmpW(OLESTR("MGX:SNAP2"), wstr))
|
||
|
{
|
||
|
PostMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_INITMENU:
|
||
|
m_fObjectMenu = FALSE;
|
||
|
if (m_fInMenuMode && IsHmenuEqual(m_hmenuCombined, (HMENU)uParam))
|
||
|
{
|
||
|
SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_INITMENUPOPUP:
|
||
|
if (!m_fInMenuMode)
|
||
|
{
|
||
|
// Accelarator translation....
|
||
|
|
||
|
if (! ((BOOL) HIWORD(lParam)))
|
||
|
{
|
||
|
// if not a system menu, see whether windows
|
||
|
// generated WM_INITMENUPOPUP for object's
|
||
|
// menu because of menu collision. If so
|
||
|
// fix it and route it to container
|
||
|
|
||
|
// menu collisions can occur with combined
|
||
|
// menus (from object and container)
|
||
|
if (IsMenuCollision(uParam, lParam))
|
||
|
{
|
||
|
lresult = 0L;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_fObjectMenu)
|
||
|
{
|
||
|
lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_SYSCHAR:
|
||
|
if (SSInSendMessage())
|
||
|
{
|
||
|
SSReplyMessage(NULL);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
#ifdef _CHICAGO_
|
||
|
case WM_NCACTIVATE:
|
||
|
//Note: On chicago with new rpc WM_NCACTIVATE gets dispatched
|
||
|
// recursively until stack overflow.
|
||
|
// Needs to be reviewed. (OS problem)
|
||
|
// See bug 25313, 25490, 25549
|
||
|
|
||
|
if (m_fInNCACTIVATE)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
m_fInNCACTIVATE = TRUE;
|
||
|
break;
|
||
|
#endif // _CHICAGO_
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
// End of menu processing or accelartor translation.
|
||
|
// Check whether we should give the message to the object
|
||
|
// or not.
|
||
|
|
||
|
// If the LOWORD of lParam is NON-NULL, then the message
|
||
|
// must be from a control, and the control must belong to
|
||
|
// the container app.
|
||
|
|
||
|
// REVIEW32: what about app-specific commands with NULL
|
||
|
// lParams???
|
||
|
|
||
|
if (LOWORD(lParam) == 0)
|
||
|
{
|
||
|
m_cmdId = 0;
|
||
|
|
||
|
if (m_fDiscardWmCommand)
|
||
|
{
|
||
|
m_fDiscardWmCommand = FALSE;
|
||
|
lresult = 0L;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (m_fObjectMenu)
|
||
|
{
|
||
|
m_fObjectMenu = FALSE;
|
||
|
lresult = PostMessage(m_hwndObject, msg, uParam,lParam);
|
||
|
goto errRtn;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_ACTIVATEAPP:
|
||
|
case WM_KILLFOCUS:
|
||
|
// If in ALT-TAB mode, we get these messages only if we are
|
||
|
// going to ALT-TAB out in to some other task. In this case,
|
||
|
// on exit from ALT-TAB mode we wouldn't want to set
|
||
|
// focus back to the window that had the focus on
|
||
|
// entering the ALT-TAB mode.
|
||
|
|
||
|
if (m_cAltTab)
|
||
|
{
|
||
|
m_hwndFocusOnEnter = NULL;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (msg == uOleMessage)
|
||
|
{
|
||
|
switch(uParam)
|
||
|
{
|
||
|
case OM_CLEAR_MENU_STATE:
|
||
|
m_fObjectMenu = FALSE;
|
||
|
break;
|
||
|
|
||
|
case OM_COMMAND_ID:
|
||
|
// this message is sent by
|
||
|
// OleTranslateAccelerator, before it actually
|
||
|
// calls the lpFrame->TranslateAccelerator
|
||
|
// method.
|
||
|
// We remember the command id here, later it
|
||
|
// gets used if the container's calling of
|
||
|
// TranslateAccelerator results in a
|
||
|
// WM_INITMENUPOPUP for the object because
|
||
|
// of command id collision. In that case we
|
||
|
// scan the menu list to see whether there is
|
||
|
// any container menu which has the same
|
||
|
// command id, if so we generate
|
||
|
// WM_INITMENUPOPUP for that menu.
|
||
|
m_cmdId = LOWORD(lParam);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
AssertSz(FALSE, "Unexpected OLE private message");
|
||
|
break;
|
||
|
} // switch
|
||
|
|
||
|
lresult = 0L;
|
||
|
goto errRtn;
|
||
|
} // if (msg == uOleMessage)
|
||
|
else if (m_fInMenuMode && (msg == uOmPostWmCommand))
|
||
|
{
|
||
|
// if the current selection is a popup menu then
|
||
|
// return its menu handle else post the command
|
||
|
// and return NULL.
|
||
|
|
||
|
if (m_fCurItemPopup)
|
||
|
{
|
||
|
lresult = m_uCurItemID;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
HWND hwnd;
|
||
|
|
||
|
hwnd = m_hwndFrame;
|
||
|
if (m_fObjectMenu)
|
||
|
{
|
||
|
hwnd = m_hwndObject;
|
||
|
}
|
||
|
PostMessage (hwnd, WM_COMMAND, m_uCurItemID, 0L);
|
||
|
|
||
|
m_fObjectMenu = FALSE;
|
||
|
lresult = 0L;
|
||
|
goto errRtn;
|
||
|
} // else if
|
||
|
|
||
|
break; // default
|
||
|
|
||
|
} // switch
|
||
|
|
||
|
lresult = SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
|
||
|
msg, uParam, lParam);
|
||
|
|
||
|
errRtn:
|
||
|
#ifdef _CHICAGO_
|
||
|
m_fInNCACTIVATE = FALSE;
|
||
|
#endif
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnMessage ( %lu )\n",
|
||
|
this, lresult));
|
||
|
|
||
|
return lresult;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::IsObjectMenu
|
||
|
//
|
||
|
// Synopsis: This gets called when WM_MENUSELECT is sent for a
|
||
|
// top level (either POPUP or normal) menu item. Figures
|
||
|
// out whether [uMenuItem] really belongs to the in-place object
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [uMenuItem] -- the menu in question
|
||
|
// [fwMenu] -- the menu type
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm: Searchs through our ole menu descriptor to find a match
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_IsObjectMenu)
|
||
|
void CFrameFilter::IsObjectMenu(UINT uMenuItem, UINT fwMenu)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
int i,
|
||
|
iMenuCnt;
|
||
|
LPOLEMENUITEM lpMenuList;
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsObjectMenu ( %u , "
|
||
|
"%u )\n", this, uMenuItem, fwMenu));
|
||
|
|
||
|
if (m_hmenuCombined == NULL)
|
||
|
{
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
|
||
|
m_fObjectMenu = FALSE;
|
||
|
|
||
|
lpMenuList = m_lpOleMenu->menuitem;
|
||
|
iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
|
||
|
|
||
|
for (i = 0; i < iMenuCnt; i++)
|
||
|
{
|
||
|
// Are the types of the menus the same?
|
||
|
if ((fwMenu & MF_POPUP) == lpMenuList[i].fwPopup)
|
||
|
{
|
||
|
HMENU hmenuMenuListItem = (HMENU)UlongToPtr(lpMenuList[i].item);
|
||
|
|
||
|
// Are we dealing with a menu handle?
|
||
|
if (fwMenu & MF_POPUP)
|
||
|
{
|
||
|
// See if windows handles are equal
|
||
|
if (IsHmenuEqual((HMENU)IntToPtr(uMenuItem),
|
||
|
hmenuMenuListItem))
|
||
|
{
|
||
|
m_fObjectMenu = lpMenuList[i].fObjectMenu;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// Are item handles equal?
|
||
|
else if (uMenuItem == lpMenuList[i].item)
|
||
|
{
|
||
|
m_fObjectMenu = lpMenuList[i].fObjectMenu;
|
||
|
|
||
|
// If the menu isn't hilited, another menu with a duplicate
|
||
|
// menu ID must have been selected. The duplicate menu was
|
||
|
// probably created by the other application.
|
||
|
if (!(GetMenuState(m_hmenuCombined, uMenuItem, MF_BYCOMMAND)
|
||
|
& MF_HILITE))
|
||
|
{
|
||
|
m_fObjectMenu = !m_fObjectMenu;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
errRtn:
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsObjectMenu ( )\n",
|
||
|
this ));
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::IsMenuCollision
|
||
|
//
|
||
|
// Synopsis: Determines if we've had a menu collission. This gets called
|
||
|
// as a result of WM_INITMENUPOPUP during accelerator translation
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [uParam] -- the first window message argument
|
||
|
// [lParam] -- the second argument
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: BOOL
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo changed Assert(hmenuPopup) to an if
|
||
|
// in merging with 16bit RC9 sources
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CFrameFilter::IsMenuCollision(WPARAM uParam, LPARAM lParam)
|
||
|
{
|
||
|
BOOL fRet;
|
||
|
int iCntrMenu, iObjMenu, iMenuCnt;
|
||
|
BOOL fGenerateWmCommand;
|
||
|
HMENU hmenuPopup;
|
||
|
LPOLEMENUITEM lpMenuList;
|
||
|
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsMenuCollision ( %u ,"
|
||
|
" %ld )\n", this, uParam, lParam ));
|
||
|
|
||
|
if (m_hmenuCombined == NULL)
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if (m_lpOleMenu == NULL)
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
hmenuPopup = (HMENU) uParam;
|
||
|
iObjMenu = (int) LOWORD(lParam);
|
||
|
|
||
|
lpMenuList = m_lpOleMenu->menuitem;
|
||
|
iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
|
||
|
|
||
|
if (iObjMenu >= iMenuCnt)
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
if( hmenuPopup != (HMENU)UlongToPtr(lpMenuList[iObjMenu].item) )
|
||
|
{
|
||
|
// this could be the container's popmenu, not associated
|
||
|
// with the frame
|
||
|
fRet = FALSE;
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
Assert(lpMenuList[iObjMenu].fwPopup);
|
||
|
|
||
|
if (! lpMenuList[iObjMenu].fObjectMenu)
|
||
|
{
|
||
|
fRet = FALSE; // container's pop-up menu
|
||
|
goto errRtn;
|
||
|
}
|
||
|
|
||
|
// Otherwise the popup menu belongs to the object. This can only
|
||
|
// happen because of id collision. Start scanning the menus starting
|
||
|
// from the next top level menu item to look for a match in
|
||
|
// container's menus (while scanning skip object's menus)
|
||
|
|
||
|
|
||
|
// It is possible that the colliding command id may not be associated
|
||
|
// with any of the container's menus. In that case we must send
|
||
|
// WM_COMMAND to the container.
|
||
|
|
||
|
fGenerateWmCommand = TRUE;
|
||
|
m_fDiscardWmCommand = FALSE;
|
||
|
iCntrMenu = iObjMenu + 1;
|
||
|
|
||
|
|
||
|
while (iCntrMenu < iMenuCnt)
|
||
|
{
|
||
|
if (! lpMenuList[iCntrMenu].fObjectMenu)
|
||
|
{
|
||
|
if (lpMenuList[iCntrMenu].fwPopup & MF_POPUP)
|
||
|
{
|
||
|
HMENU hmenuListItem = (HMENU)UlongToPtr(lpMenuList[iCntrMenu].item);
|
||
|
if (GetMenuState(hmenuListItem, m_cmdId, MF_BYCOMMAND) != -1)
|
||
|
{
|
||
|
// We found match in the container's
|
||
|
// menu list Generate WM_INITMENUPOPUP
|
||
|
// for the corresponding popup
|
||
|
SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc,
|
||
|
m_hwndFrame,
|
||
|
WM_INITMENUPOPUP,
|
||
|
lpMenuList[iCntrMenu].item /*uParam*/,
|
||
|
MAKELONG(iCntrMenu, HIWORD(lParam)));
|
||
|
|
||
|
// We have sent WM_INITMENUPOPUP to
|
||
|
// the container.
|
||
|
// Now rechek the menu state. If
|
||
|
// disabled or grayed then
|
||
|
// don't generate WM_COMMAND
|
||
|
if (GetMenuState(hmenuListItem, m_cmdId, MF_BYCOMMAND) &
|
||
|
(MF_DISABLED | MF_GRAYED))
|
||
|
{
|
||
|
fGenerateWmCommand = FALSE;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// top-level, non-popup container menu
|
||
|
HMENU hmenuCombined = (HMENU)UlongToPtr(m_lpOleMenu->hmenuCombined);
|
||
|
if (GetMenuItemID(hmenuCombined, iCntrMenu) == m_cmdId)
|
||
|
{
|
||
|
// No need to generate
|
||
|
// WM_INITMENUPOPUP
|
||
|
|
||
|
// Chek the menu state. If disabled or
|
||
|
// grayed then don't generate
|
||
|
// WM_COMMAND
|
||
|
if (GetMenuState(hmenuCombined, m_cmdId, MF_BYCOMMAND) &
|
||
|
(MF_DISABLED | MF_GRAYED))
|
||
|
{
|
||
|
fGenerateWmCommand = FALSE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iCntrMenu++;
|
||
|
}
|
||
|
|
||
|
// Check the object's colliding menu's status
|
||
|
if (GetMenuState((HMENU)UlongToPtr(lpMenuList[iObjMenu].item), m_cmdId,
|
||
|
MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED))
|
||
|
{
|
||
|
// Then windows is not going to genearte WM_COMMAND for the
|
||
|
// object's menu, so we will generate
|
||
|
// the command and send it to the container
|
||
|
|
||
|
if (fGenerateWmCommand)
|
||
|
{
|
||
|
SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc,
|
||
|
m_hwndFrame, WM_COMMAND, m_cmdId,
|
||
|
MAKELONG(0, 1)); /* not from control */
|
||
|
// & and as result of
|
||
|
// accelerator
|
||
|
m_cmdId = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
// Wait for WM_COMMAND generated by windows to come to our
|
||
|
// frame filter wndproc which would have been sent to the
|
||
|
// container anyway because we have not set the m_fObjectMenu
|
||
|
// flag.
|
||
|
//
|
||
|
// But we need to throw it away if the container's menu
|
||
|
// associated with the command is disabled or grayed
|
||
|
|
||
|
if (! fGenerateWmCommand)
|
||
|
{
|
||
|
m_fDiscardWmCommand = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fRet = TRUE;
|
||
|
|
||
|
errRtn:
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsMenuCollision "
|
||
|
"( %lu )\n", this, fRet));
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::DoContextSensitiveHelp
|
||
|
//
|
||
|
// Synopsis: Calls IOIPF->ContextSensitive help on both the container
|
||
|
// and the object.
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: void
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: FALSE if we're in popup menu mode, TRUE otherwise
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
// 07-Dec-93 alexgo removed inlining
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_DoContextSensitiveHelp)
|
||
|
BOOL CFrameFilter::DoContextSensitiveHelp(void)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
BOOL fRet;
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::DoContextSensitiveHelp"
|
||
|
" ( )\n", this ));
|
||
|
|
||
|
if (m_fCurItemPopup)
|
||
|
{
|
||
|
fRet = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_lpFrame->ContextSensitiveHelp(TRUE);
|
||
|
m_lpObject->ContextSensitiveHelp (TRUE);
|
||
|
|
||
|
PostMessage (m_hwndFrame, WM_COMMAND, m_uCurItemID, 0L);
|
||
|
fRet = TRUE;
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::DoContextSensitiveHelp"
|
||
|
" ( %lu )\n", this, fRet));
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CFrameFilter::GetActiveObject
|
||
|
//
|
||
|
// Synopsis: Returns the IOleInplaceActiveObject interface pointer
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: lplpOIAO
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: NOERROR or E_INVALIDARG
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Derivation:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 28-Jul-94 bobday created for WinWord hack
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(CFrameFilter_GetActiveObject)
|
||
|
STDMETHODIMP CFrameFilter::GetActiveObject( LPOLEINPLACEACTIVEOBJECT *lplpOIAO)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::GetActiveObject"
|
||
|
" ( %p )\n", this, lplpOIAO ));
|
||
|
|
||
|
VDATEPTROUT( lplpOIAO, LPOLEINPLACEACTIVEOBJECT);
|
||
|
|
||
|
*lplpOIAO = m_lpObject;
|
||
|
|
||
|
if ( m_lpObject )
|
||
|
{
|
||
|
m_lpObject->AddRef();
|
||
|
}
|
||
|
|
||
|
LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::GetActiveObject"
|
||
|
" ( %lx ) [ %p ]\n", this, NOERROR , *lplpOIAO ));
|
||
|
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: wGetFrameFilterPtr
|
||
|
//
|
||
|
// Synopsis: Gets the CFrame object from the window
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [hwndFrame] -- the window to get the CFrame object from
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: pointer to the frame filter
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
inline PCFRAMEFILTER wGetFrameFilterPtr(HWND hwndFrame)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
#ifdef WIN32
|
||
|
|
||
|
return (PCFRAMEFILTER) GetProp (hwndFrame, szPropFrameFilter);
|
||
|
#else
|
||
|
WORD hiword;
|
||
|
WORD loword;
|
||
|
|
||
|
if (!(hiword = GetProp (hwndFrame, szPropFrameFilterH)))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
loword = GetProp (hwndFrame, szPropFrameFilterL);
|
||
|
|
||
|
return (PCFRAMEFILTER) (MAKELONG(loword, hiword));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: wGetOleMenuPtr
|
||
|
//
|
||
|
// Synopsis: Locks a handle to an ole menu and returns the pointer
|
||
|
// (after some error checking)
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [holemenu]
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: pointer to the ole menu
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
LPOLEMENU lpOleMenu;
|
||
|
|
||
|
if (! (holemenu &&
|
||
|
(lpOleMenu = (LPOLEMENU) GlobalLock((HGLOBAL) holemenu))))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (lpOleMenu->wSignature != wSignature)
|
||
|
{
|
||
|
AssertSz(FALSE, "Error - handle is not a HOLEMENU");
|
||
|
GlobalUnlock((HGLOBAL) holemenu);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return lpOleMenu;
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: wReleaseOleMenuPtr
|
||
|
//
|
||
|
// Synopsis: calls GlobalUnlock
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [holemenu] -- handle to the ole menu
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
inline void wReleaseOleMenuPtr(HOLEMENU holemenu)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
|
||
|
GlobalUnlock((HGLOBAL) holemenu);
|
||
|
}
|
||
|
|
||
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: MessageFilterProc
|
||
|
//
|
||
|
// Synopsis: The message filter installed when entering menu mode;
|
||
|
// handles context sensitive help
|
||
|
//
|
||
|
// Effects:
|
||
|
//
|
||
|
// Arguments: [nCode] -- hook code
|
||
|
// [wParam] -- first arg
|
||
|
// [lParam] -- second arg
|
||
|
//
|
||
|
// Requires:
|
||
|
//
|
||
|
// Returns: LRESULT
|
||
|
//
|
||
|
// Signals:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
// Algorithm:
|
||
|
//
|
||
|
// History: dd-mmm-yy Author Comment
|
||
|
// 01-Dec-93 alexgo 32bit port
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#pragma SEG(MessageFilterProc)
|
||
|
STDAPI_(LRESULT) MessageFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
VDATEHEAP();
|
||
|
LRESULT lresult;
|
||
|
LPMSG lpMsg = (LPMSG) lParam;
|
||
|
|
||
|
|
||
|
LEDebugOut((DEB_TRACE, "%p _IN MessageFilterProc ( %d , %ld , %lu )\n",
|
||
|
NULL, nCode, (LONG)wParam, lParam));
|
||
|
|
||
|
// If it is not the F1 key then let the message (wihtout modification)
|
||
|
// go to the next proc in the hook/filter chain.
|
||
|
|
||
|
if (lpMsg && lpMsg->message == WM_KEYDOWN
|
||
|
&& lpMsg->wParam == VK_F1 && pFrameFilter)
|
||
|
{
|
||
|
if (pFrameFilter->DoContextSensitiveHelp())
|
||
|
{
|
||
|
// Change message value to be WM_CANCELMODE and then
|
||
|
// call the next hook. When the windows USER.EXE's
|
||
|
// menu processing code sees this message it will
|
||
|
// bring down menu state and come out of its
|
||
|
// menu processing loop.
|
||
|
|
||
|
lpMsg->message = WM_CANCELMODE;
|
||
|
lpMsg->wParam = NULL;
|
||
|
lpMsg->lParam = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lresult = TRUE; // otherwise throw away this message.
|
||
|
goto errRtn;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lresult = CallNextHookEx (hMsgHook, nCode, wParam, lParam);
|
||
|
|
||
|
errRtn:
|
||
|
LEDebugOut((DEB_TRACE, "%p OUT MessageFilterProc ( %ld )\n", NULL,
|
||
|
lresult));
|
||
|
|
||
|
return lresult;
|
||
|
}
|