windows-nt/Source/XPSP1/NT/multimedia/media/mplayer2/inplace.c
2020-09-26 16:20:57 +08:00

1441 lines
45 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------
| INPLACE.C
| This file has the InPlace activation related interfaces and functions.
| This file has the function DoInPlaceEdit which initiaites the server side
| operations for InPlace activation.
|
| Created By: Vij Rajarajan (VijR)
+---------------------------------------------------------------------------*/
#define SERVERONLY
#include <windows.h>
#include <windowsx.h>
#include "mpole.h"
#include <mmsystem.h>
#include "mplayer.h"
#include "toolbar.h"
#include "ole2ui.h"
#define DEF_HATCH_SZ 4 //Width of the hatch marks
#define EW_HATCH_HANDLE 10 //GetWindowWord offset to check
//if resize handle needed in hatch window
//#define DUMMY_TOOLBAR_WIDTH 58 //Width of dummy toolbar transferred during play.
#define DUMMY_TOOLBAR_WIDTH 0 //Width of dummy toolbar transferred during play.
HWND ghwndIPHatch = NULL; //Hatch window surrounding object.
HWND ghwndIPToolWindow; //The toolwindow appearing on top
HWND ghwndIPScrollWindow; //Tool window appearing at bottom with tthe scrollbar
//if the container does not give us space on top.
HMENU ghInPlaceMenu;
POINT gHatchOffset;
WNDPROC gfnHatchWndProc = NULL;
BOOL gfOle2Open = FALSE;
BOOL gfOle2IPEditing = FALSE;
BOOL gfOle2IPPlaying = FALSE;
BOOL gfInPlaceResize = FALSE; //TRUE: We have resized when InPlace
BOOL gfTopAndBottomTool = TRUE; // We have toolbars both on top and bottom
RECT gInPlacePosRect; //Our position in the container.
HWND ghwndCntr; //Container
HWND ghwndFrame = NULL; //Frame of the container.
int toolbarwidth;
BOOL gfPosRectChange = FALSE;
RECT gPrevPosRect;
BOOL gfInPPViewer; /* Hack to stop PowerPoint Viewer crashing */
extern TCHAR szToolBarClass[];
extern HMENU ghDeviceMenu; /* handle to the Device menu */
extern UINT gwPlaybarHeight; //tell playbar how tall to make
//itself so it covers the title
void AllocInPlaceDataBlock (LPDOC lpdoc);
void FreeInPlaceDataBlock (LPDOC lpdoc);
void DeactivateTools(LPDOC lpdoc);
HRESULT ActivateTools(LPDOC lpdoc, BOOL fPlayOnly);
void InPlaceCreateControls(BOOL fPlayOnly);
LONG_PTR FAR PASCAL SubClassedHatchWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
/**************************************************************************
* TransferTools:
* This function changes parents and positions the toolbar buttons
* from the main Mplayer window to the toolbar window/windows we will
* display in the client.
***************************************************************************/
void TransferTools(HWND hwndToolWindow)
{
SetParent(ghwndToolbar, hwndToolWindow);
MoveWindow(ghwndToolbar, 5,0,7*BUTTONWIDTH+15,TOOL_WIDTH,TRUE);
SetParent(ghwndMark, hwndToolWindow);
MoveWindow(ghwndMark, 7*BUTTONWIDTH+16,0,2*BUTTONWIDTH+15,TOOL_WIDTH,TRUE);
SetParent(ghwndFSArrows, hwndToolWindow);
MoveWindow(ghwndFSArrows, 9*BUTTONWIDTH+16+10+3,0,toolbarwidth-9*BUTTONWIDTH-25,TOOL_WIDTH,TRUE);
if(!ghwndMCI) {
toolbarModifyState(ghwndToolbar, BTN_EJECT, TBINDEX_MAIN, BTNST_GRAYED);
toolbarModifyState(ghwndToolbar, BTN_STOP, TBINDEX_MAIN, BTNST_GRAYED);
toolbarModifyState(ghwndToolbar, BTN_PLAY, TBINDEX_MAIN, BTNST_GRAYED);
toolbarModifyState(ghwndMark, BTN_MARKIN, TBINDEX_MARK, BTNST_GRAYED);
toolbarModifyState(ghwndMark, BTN_MARKOUT, TBINDEX_MARK, BTNST_GRAYED);
toolbarModifyState(ghwndFSArrows, ARROW_PREV, TBINDEX_ARROWS, BTNST_GRAYED);
toolbarModifyState(ghwndFSArrows, ARROW_NEXT, TBINDEX_ARROWS, BTNST_GRAYED);
}
if(hwndToolWindow == ghwndApp)
{
SetParent(ghwndTrackbar,ghwndApp);
SetParent(ghwndMap,ghwndApp);
}
}
/**************************************************************************
* ActivateTools:
* This function negotiates for toolbar space with the client. If possible
* one broad toolbar is placed at the top of the client, if not the
* toolbar is split and one is placed on top and other at bottom. If even
* that is not possible then the function fails. The top toolbar window is
* ghwndIPToolWindow and the bottom one is ghwndIPScrollWindow (because it
* has the scrolling trackbar.
*
* fPlayOnly is TRUE if we are just going to play. In that case a dummy, empty
* tool bar is transferred. No, we don't want anything. But we have to
* negotiate space, even empty space, otherwise Word doesn't think we're
* in-place active.
***************************************************************************/
HRESULT ActivateTools(LPDOC lpdoc, BOOL fPlayOnly)
{
RECT rect, size;
SCODE sc;
size.left = 0;
size.top = 0;
size.bottom = 0;
size.right = 0;
IOleInPlaceFrame_GetBorder(lpdoc->lpIpData->lpFrame, &rect);
if (fPlayOnly)
size.top = DUMMY_TOOLBAR_WIDTH; /* This is now 0 - no toolbar space needed */
else
size.top = 3*TOOL_WIDTH+1;
size.bottom = 0;
sc = GetScode(IOleInPlaceFrame_RequestBorderSpace(lpdoc->lpIpData->lpFrame,
&size));
if (sc == S_OK)
{
size.bottom = size.left = size.right = 0;
if (fPlayOnly)
size.top = DUMMY_TOOLBAR_WIDTH;
else
size.top = 3*TOOL_WIDTH+1;
sc = GetScode(IOleInPlaceFrame_SetBorderSpace(lpdoc->lpIpData->lpFrame,
&size));
if (sc != S_OK)
goto ToolBottom;
IOleInPlaceFrame_GetBorder(lpdoc->lpIpData->lpFrame, &rect);
IOleInPlaceFrame_GetWindow (lpdoc->lpIpData->lpFrame, &ghwndFrame);
if (GetParent(ghwndIPToolWindow) != ghwndFrame)
SetParent(ghwndIPToolWindow, ghwndFrame);
if (!fPlayOnly)
MoveWindow(ghwndIPToolWindow, rect.left, rect.top,
toolbarwidth, 3*TOOL_WIDTH+1, TRUE);
else
return NOERROR; /* That's all folks, if we're just playing. */
if(ghwndIPToolWindow != GetParent(ghwndTrackbar))
{
SetParent(ghwndTrackbar,ghwndIPToolWindow);
SetWindowPos(ghwndTrackbar, NULL,3,TOOL_WIDTH+2,
11*BUTTONWIDTH+15,FSTRACK_HEIGHT,SWP_NOZORDER | SWP_NOACTIVATE);
SetParent(ghwndMap,ghwndIPToolWindow);
SetWindowPos(ghwndMap, NULL,3,TOOL_WIDTH+FSTRACK_HEIGHT+2+2,
11*BUTTONWIDTH+50,MAP_HEIGHT,SWP_NOZORDER | SWP_NOACTIVATE);
}
ShowWindow(ghwndIPToolWindow, SW_SHOW);
ShowWindow(ghwndMark, SW_SHOW);
ShowWindow(ghwndFSArrows, SW_SHOW);
gfTopAndBottomTool = FALSE;
return NOERROR;
}
else
{
ToolBottom:
if (!fPlayOnly)
{
size.top = TOOL_WIDTH+1;
size.bottom = 2*TOOL_WIDTH+1;
}
else
{
ShowWindow(ghwndFSArrows, SW_HIDE);
ShowWindow(ghwndStatic, SW_HIDE);
ShowWindow(ghwndMark, SW_HIDE);
return NOERROR;
}
sc = GetScode(IOleInPlaceFrame_RequestBorderSpace(lpdoc->lpIpData->lpFrame,
&size));
size.left = size.right = 0;
size.top = TOOL_WIDTH+1;
size.bottom = 2*TOOL_WIDTH+1;
if (sc != S_OK)
goto error;
sc = GetScode(IOleInPlaceFrame_SetBorderSpace(lpdoc->lpIpData->lpFrame,
&size));
if (sc != S_OK)
goto error;
IOleInPlaceFrame_GetBorder(lpdoc->lpIpData->lpFrame, &rect);
if (GetParent(ghwndIPToolWindow) != ghwndFrame)
{
SetParent(ghwndIPToolWindow, ghwndFrame);
SetParent(ghwndIPScrollWindow, ghwndFrame);
}
if(ghwndIPScrollWindow != GetParent(ghwndTrackbar))
{
SetParent(ghwndTrackbar,ghwndIPScrollWindow);
SetWindowPos(ghwndTrackbar, NULL,3,4,
11*BUTTONWIDTH+15,FSTRACK_HEIGHT,SWP_NOZORDER | SWP_NOACTIVATE);
SetParent(ghwndMap,ghwndIPScrollWindow);
SetWindowPos(ghwndMap, NULL,3,FSTRACK_HEIGHT+4+2,
11*BUTTONWIDTH+50,MAP_HEIGHT,SWP_NOZORDER | SWP_NOACTIVATE);
}
MoveWindow(ghwndIPToolWindow, rect.left, rect.top,
toolbarwidth, TOOL_WIDTH+1, TRUE);
ShowWindow(ghwndIPToolWindow, SW_SHOW);
MoveWindow(ghwndIPScrollWindow, rect.left,rect.bottom-2*TOOL_WIDTH,//-1,
toolbarwidth,2*TOOL_WIDTH+1,TRUE);
ShowWindow(ghwndIPScrollWindow, SW_SHOW);
gfTopAndBottomTool = TRUE;
return NOERROR;
}
error:
RETURN_RESULT(sc);
}
/**************************************************************************
* DeactivateTools:
* Hides the toolbars.
***************************************************************************/
void DeactivateTools(LPDOC lpdoc)
{
ShowWindow(ghwndIPToolWindow, SW_HIDE);
SetParent(ghwndIPToolWindow, NULL);
if (gfTopAndBottomTool)
{
ShowWindow(ghwndIPScrollWindow, SW_HIDE);
SetParent(ghwndIPScrollWindow, NULL);
}
}
/**************************************************************************
************ IOleInPlaceObject INTERFACE IMPLEMENTATION.
***************************************************************************/
//Delegate to the common IUnknown implementation.
STDMETHODIMP IPObjQueryInterface (
LPOLEINPLACEOBJECT lpIPObj, // inplace object ptr
REFIID riidReq, // IID required
LPVOID FAR * lplpUnk // pre for returning the interface
)
{
return UnkQueryInterface((LPUNKNOWN)lpIPObj, riidReq, lplpUnk);
}
STDMETHODIMP_(ULONG) IPObjAddRef(
LPOLEINPLACEOBJECT lpIPObj // inplace object ptr
)
{
return UnkAddRef((LPUNKNOWN) lpIPObj);
}
STDMETHODIMP_(ULONG) IPObjRelease(
LPOLEINPLACEOBJECT lpIPObj // inplace object ptr
)
{
return UnkRelease((LPUNKNOWN) lpIPObj);
}
STDMETHODIMP IPObjGetWindow(
LPOLEINPLACEOBJECT lpIPObj, // inplace object ptr
HWND FAR* lphwnd // window handle of the object
)
{
DPF("IPObjGetWindow\n");
*lphwnd = docMain.hwnd;
return NOERROR;
}
STDMETHODIMP IPObjContextSensitiveHelp(
LPOLEINPLACEOBJECT lpIPObj, // inplace object ptr
BOOL fEnable
)
{
//Not very useful at this time.
LPDOC lpdoc;
lpdoc = ((struct COleInPlaceObjectImpl FAR*)lpIPObj)->lpdoc;
lpdoc->lpIpData->fInContextHelpMode = fEnable;
return NOERROR;
}
STDMETHODIMP IPObjInPlaceDeactivate(
LPOLEINPLACEOBJECT lpIPObj // inplace object ptr
)
{
LPDOC lpdoc;
LPINPLACEDATA lpIpData;
static int EntryCount; /* OLE sometimes calls us recursively. */
DPF("IPObjInPlaceDeactivate\n");
if (EntryCount++ == 0)
{
lpdoc = ((struct COleInPlaceObjectImpl FAR*)lpIPObj)->lpdoc;
lpIpData = lpdoc->lpIpData;
if (lpIpData)
{
// This stops PowerPoint crashing, since it forces UpdateObject
// to send change notification when there's an empty Media Clip.
if (gwDeviceID == 0)
fDocChanged = TRUE;
//Make sure the container has the correct metafile before we are hidden
UpdateObject();
IOleInPlaceObject_UIDeactivate ((LPOLEINPLACEOBJECT)&lpdoc->m_InPlace);
if (lpIpData && lpIpData->lpSite)
{
if (!gfInPPViewer)
IOleInPlaceSite_OnInPlaceDeactivate (lpIpData->lpSite);
IOleInPlaceSite_Release (lpIpData->lpSite);
}
FreeInPlaceDataBlock (lpdoc);
}
}
else
{
/* This sometimes happens during the above OnInPlaceDeactivate call,
* which resulted in an access violation because the data block had
* been freed when the call returned.
* According to the OLE guys, apps should guard against this.
*/
DPF("Attempt to re-enter IPObjInPlaceDeactivate\n");
}
--EntryCount;
/* Dontcha just love these global variables!
*/
gfOle2IPEditing = FALSE;
gfOle2IPPlaying = FALSE;
gfPlayingInPlace = FALSE;
return NOERROR;
}
//Hide our inplace UI.
STDMETHODIMP IPObjUIDeactivate(
LPOLEINPLACEOBJECT lpIPObj // inplace object ptr
)
{
LPDOC lpdoc;
DPF("IPObjUIDeactivate\n");
lpdoc = ((struct COleInPlaceObjectImpl FAR*)lpIPObj)->lpdoc;
if (!(lpdoc->lpIpData && lpdoc->lpIpData->lpFrame))
return NOERROR;
IOleInPlaceFrame_SetMenu (lpdoc->lpIpData->lpFrame, NULL, NULL, lpdoc->hwnd);
// clear inplace-state
IOleInPlaceFrame_SetActiveObject (lpdoc->lpIpData->lpFrame, NULL, NULL);
if (lpdoc->lpIpData->lpUIWindow)
IOleInPlaceUIWindow_SetActiveObject (lpdoc->lpIpData->lpUIWindow, NULL, NULL);
if(gfOle2IPPlaying)
PostMessage(ghwndApp, WM_COMMAND, ID_STOP, 0L);
/* We could also be playing if we're in-place editing:
*/
else if(gfOle2IPEditing && (gwStatus == MCI_MODE_PLAY || gwStatus == MCI_MODE_SEEK))
PostMessage(ghwndApp, WM_COMMAND, ID_STOP, 0L);
ShowWindow(ghwndIPHatch,SW_HIDE);
DeactivateTools(lpdoc);
DisassembleMenus (lpdoc);
if (lpdoc->lpIpData->lpUIWindow) {
IOleInPlaceUIWindow_Release (lpdoc->lpIpData->lpUIWindow);
lpdoc->lpIpData->lpUIWindow = NULL;
}
if (lpdoc->lpIpData->lpFrame) {
IOleInPlaceFrame_Release (lpdoc->lpIpData->lpFrame);
lpdoc->lpIpData->lpFrame = NULL;
}
// Set the parent back to hwndClient window
SetParent(ghwndIPHatch,NULL);
gPrevPosRect.left = gPrevPosRect.top =gPrevPosRect.right = gPrevPosRect.bottom = 0;
lpdoc->hwndParent = NULL;
if (!gfInPPViewer)
IOleInPlaceSite_OnUIDeactivate (lpdoc->lpIpData->lpSite, FALSE);
return NOERROR;
}
/**************************************************************************
* IPObjSetObjectRects:
* The client specifies our window position and size. Move our
* window accordingly. Also size the Hatch window to fit around the
* ghwndApp. If the change is very small compared to the previous
* size ignore and return. This account for slop speeds things up.
***************************************************************************/
STDMETHODIMP IPObjSetObjectRects(
LPOLEINPLACEOBJECT lpIPObj, // inplace object ptr
LPCRECT lprcPosRect,
LPCRECT lprcVisRect
)
{
LPDOC lpdoc;
RECT rc;
GetWindowRect(ghwndApp, (LPRECT)&rc);
DPFI("\n*IPObjSetObjectRects");
DPFI("\n^^^^^^^^ LPRECPOSRECT: %d, %d, %d, %d ^^^^\n", *lprcPosRect);
DPFI("\n^^^^^^^^ PREVRECT: %d, %d, %d, %d ^^^^\n", gPrevPosRect);
DPFI("\n^^^^^^^^ HWNDRECT: %d, %d, %d, %d ^^^^\n", rc);
lpdoc = ((struct COleInPlaceObjectImpl FAR*)lpIPObj)->lpdoc;
if (!ghwndIPHatch || (ghwndCntr != GetParent(ghwndIPHatch)))
return NOERROR;
if (!(lpdoc->lpIpData))
return NOERROR;
rc = *lprcPosRect;
if (!(gwDeviceID == (UINT)0 || !(gwDeviceType & DTMCI_CANWINDOW)))
SetHatchWindowSize(ghwndIPHatch, (LPRECT)&rc,lprcVisRect, (LPPOINT)&gHatchOffset,TRUE);
else
SetHatchWindowSize(ghwndIPHatch, (LPRECT)&rc,lprcVisRect, (LPPOINT)&gHatchOffset,FALSE);
if(!(gwDeviceType & DTMCI_CANWINDOW) && (gwOptions & OPT_BAR))
rc.top = rc.bottom - gwPlaybarHeight;
if(!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
rc.bottom = rc.top = rc.left = rc.right = 0;
MapWindowPoints(ghwndCntr,ghwndIPHatch,(LPPOINT)&rc, 2);
gfPosRectChange = TRUE;
if (gwDeviceID)
MoveWindow(lpdoc->hwnd, rc.left, rc.top,
rc.right - rc.left,
rc.bottom - rc.top, TRUE);
else
MoveWindow(lpdoc->hwnd, rc.left, rc.top,
rc.right - rc.left,
rc.bottom - rc.top, FALSE);
GetWindowRect(lpdoc->hwnd, &gInPlacePosRect);
gPrevPosRect = *lprcPosRect;
/* I've commented out the below line, because PowerPoint calls
* SetObjectRects after we deactivate, and this was causing the
* MPlayer window to reappear when it was supposed to be hidden.
* This line seems to have been superfluous in any case.
*/
// ShowWindow(ghwndIPHatch,SW_SHOW);
return NOERROR;
}
//We don't have an Undo state.
STDMETHODIMP IPObjReactivateAndUndo(
LPOLEINPLACEOBJECT lpIPObj // inplace object ptr
)
{
RETURN_RESULT(INPLACE_E_NOTUNDOABLE);
}
/**************************************************************************
************** IOleInPlaceActiveObject INTERFACE IMPLEMENTATION.
***************************************************************************/
//delegate to the common IUnknown implementation.
STDMETHODIMP IPActiveQueryInterface (
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
REFIID riidReq, // IID required
LPVOID FAR * lplpUnk // pre for returning the interface
)
{
return UnkQueryInterface((LPUNKNOWN)lpIPActive, riidReq, lplpUnk);
}
STDMETHODIMP_(ULONG) IPActiveAddRef(
LPOLEINPLACEACTIVEOBJECT lpIPActive // inplace active object ptr
)
{
return UnkAddRef((LPUNKNOWN) lpIPActive);
}
STDMETHODIMP_(ULONG) IPActiveRelease (
LPOLEINPLACEACTIVEOBJECT lpIPActive // inplace active object ptr
)
{
return UnkRelease((LPUNKNOWN) lpIPActive);
}
STDMETHODIMP IPActiveGetWindow(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
HWND FAR* lphwnd // window handle of the object
)
{
DPF("IPActiveGetWindow\n");
*lphwnd = ghwndIPHatch;
return NOERROR;
}
//Not very useful at this time.
STDMETHODIMP IPActiveContextSensitiveHelp(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
BOOL fEnable
)
{
LPDOC lpdoc;
lpdoc = ((struct COleInPlaceActiveObjectImpl FAR*)lpIPActive)->lpdoc;
lpdoc->lpIpData->fInContextHelpMode = fEnable;
return NOERROR;
}
STDMETHODIMP IPActiveTranslateAccelerator(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
LPMSG lpmsg
)
{
// This will never be called because this server is implemented as an EXE
RETURN_RESULT(S_FALSE);
}
STDMETHODIMP IPActiveOnFrameWindowActivate(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
BOOL fActivate
)
{
DPF("IPActiveOnFrameWindowActivate = %d **\r\n", (int)fActivate);
if (gwStatus == MCI_MODE_PAUSE)
PostMessage(ghwndApp, WM_COMMAND, ID_STOP, 0L);
return NOERROR;
}
//If activating show the toolbar and menu. If not hide the toolbar and menu.
STDMETHODIMP IPActiveOnDocWindowActivate(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
BOOL fActivate
)
{
LPDOC lpdoc;
RECT rc;
DPF("IPActiveOnDocWindowActivate\n");
lpdoc = ((struct COleInPlaceActiveObjectImpl FAR*)lpIPActive)->lpdoc;
GetWindowRect(lpdoc->hwnd, &rc);
ScreenToClient(lpdoc->hwndParent, (POINT FAR *)&rc);
ScreenToClient(lpdoc->hwndParent, (POINT FAR *)&(rc.right));
if (fActivate) {
if(gfOle2IPEditing)
{
ActivateTools(lpdoc,FALSE);
TransferTools(ghwndIPToolWindow);
}
else
{
ActivateTools(lpdoc,TRUE);
TransferTools(ghwndApp);
}
Layout();
IOleInPlaceFrame_SetMenu (lpdoc->lpIpData->lpFrame,
lpdoc->lpIpData->hmenuShared,
lpdoc->lpIpData->holemenu,
lpdoc->hwnd);
}
else {
DeactivateTools(lpdoc);
if(gfOle2IPPlaying)
PostMessage(ghwndApp, WM_COMMAND, ID_STOP, 0L);
IOleInPlaceFrame_SetMenu (lpdoc->lpIpData->lpFrame,
NULL, NULL, lpdoc->hwnd);
}
return NOERROR;
}
//If we have a toolwindow at the bottom reposition that window to match
//the new frame window size.
STDMETHODIMP IPActiveResizeBorder(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
LPCRECT lprectBorder,
LPOLEINPLACEUIWINDOW lpIPUiWnd,
BOOL fFrameWindow
)
{
DPF("IPActiveResizeBorder\n");
if (fFrameWindow)
{
LPDOC lpdoc;
lpdoc = ((struct COleInPlaceActiveObjectImpl FAR*)lpIPActive)->lpdoc;
if (gfTopAndBottomTool && (GetParent(ghwndIPScrollWindow) != NULL))
MoveWindow(ghwndIPScrollWindow, lprectBorder->left,lprectBorder->bottom-2*TOOL_WIDTH,
toolbarwidth,2*TOOL_WIDTH+1,TRUE);
}
return NOERROR;
}
STDMETHODIMP IPActiveEnableModeless(
LPOLEINPLACEACTIVEOBJECT lpIPActive, // inplace active object ptr
BOOL fEnable
)
{
return NOERROR;
}
/**************************************************************************
* DoInplaceEdit:
* This is the function that initiates the InPlace activation from the
* server side. It sets up the InPlace data structures required by us,
* makes sure that the client supports the required interfaces and
* can provide the space we require. It also prepares the toolbar to be
* displayed and the layout of the Mplayer window.
***************************************************************************/
STDMETHODIMP DoInPlaceEdit(
LPDOC lpdoc,
LPMSG lpmsg,
LPOLECLIENTSITE lpActiveSite,
LONG verb,
HWND FAR * lphwnd,
LPRECT lprect
)
{
SCODE error = S_OK;
LPOLEINPLACESITE lpIPSite;
RECT rcPos;
RECT rcVis;
RECT hatchrc;
LPWSTR lpObjName;
if (!(lpdoc->lpoleclient))
RETURN_RESULT( E_FAIL);
if (!(lpdoc->lpIpData))
{
if ((error = GetScode(IOleClientSite_QueryInterface(
lpdoc->lpoleclient,
&IID_IOleInPlaceSite,
(void FAR* FAR*) &lpIPSite))) != S_OK)
RETURN_RESULT( error);
if ((error = GetScode(IOleInPlaceSite_CanInPlaceActivate(lpIPSite))) != S_OK)
goto errActivate;
if (!gfInPPViewer)
IOleInPlaceSite_OnInPlaceActivate(lpIPSite);
AllocInPlaceDataBlock (lpdoc);
lpdoc->lpIpData->lpSite = lpIPSite;
}
if ((error = GetScode(IOleInPlaceSite_GetWindow (lpdoc->lpIpData->lpSite, &lpdoc->hwndParent))) != S_OK)
goto errRtn;
if (!(lpdoc->hwndParent))
goto errRtn;
if (!gfInPPViewer)
IOleInPlaceSite_OnUIActivate(lpdoc->lpIpData->lpSite);
if ((error = GetScode(IOleInPlaceSite_GetWindowContext(
lpdoc->lpIpData->lpSite,
&lpdoc->lpIpData->lpFrame,
&lpdoc->lpIpData->lpUIWindow,
&rcPos, &rcVis,
&lpdoc->lpIpData->frameInfo))) != S_OK)
goto errRtn;
#ifdef LATER
if (gscaleInitXY[SCALE_X].denom)
{
gscaleInitXY[SCALE_X].num = (rcPos.right - rcPos.left) * HIMETRIC_PER_INCH / giXppli;
gscaleInitXY[SCALE_Y].num = (rcPos.bottom - rcPos.top) * HIMETRIC_PER_INCH / giYppli;
DPF0("Scale: %d%c X %d%c (%d/%d X %d/%d)\n",
gscaleInitXY[SCALE_X].num * 100 / gscaleInitXY[SCALE_X].denom, '%',
gscaleInitXY[SCALE_Y].num * 100 / gscaleInitXY[SCALE_Y].denom, '%',
gscaleInitXY[SCALE_X].num,
gscaleInitXY[SCALE_X].denom,
gscaleInitXY[SCALE_Y].num,
gscaleInitXY[SCALE_Y].denom);
}
#endif
#ifdef UNICODE
lpObjName = gachClassRoot;
#else
lpObjName = AllocateUnicodeString(gachClassRoot);
if (!lpObjName)
RETURN_RESULT(E_OUTOFMEMORY);
#endif /* UNICODE */
IOleInPlaceFrame_SetActiveObject (lpdoc->lpIpData->lpFrame,
(LPOLEINPLACEACTIVEOBJECT) &lpdoc->m_IPActive,
lpObjName);
if (lpdoc->lpIpData->lpUIWindow) {
IOleInPlaceUIWindow_SetActiveObject (lpdoc->lpIpData->lpUIWindow,
(LPOLEINPLACEACTIVEOBJECT) &lpdoc->m_IPActive,
lpObjName);
}
#ifndef UNICODE
FreeUnicodeString(lpObjName);
#endif
ghwndCntr = lpdoc->hwndParent;
//Create and initialize the hatch window to surround the Mplayer window.
if (!ghwndIPHatch)
{
RegisterHatchWindowClass(ghInst);
if ( !(ghwndIPHatch = CreateHatchWindow(lpdoc->hwndParent,ghInst)))
goto errRtn;
gfnHatchWndProc = (WNDPROC)GetWindowLongPtr(ghwndIPHatch, GWLP_WNDPROC);
SetWindowLongPtr(ghwndIPHatch, GWLP_WNDPROC, (LONG_PTR)SubClassedHatchWndProc);
}
SetParent(ghwndIPHatch, ghwndCntr);
SetFocus(ghwndIPHatch);
CopyRect(&hatchrc, &rcPos);
#define EB_HATCHWIDTH (0 * sizeof(INT))
if (verb == OLEIVERB_PRIMARY)
{
/* I don't want to show the hatch window on play, because it looks
* really bad in PowerPoint. Can't make it invisible, because
* the app window is its child, and it inherits the flag.
* Instead, just make it of zero width.
*/
SETWINDOWUINT(ghwndIPHatch, EB_HATCHWIDTH, 0);
}
else
{
SETWINDOWUINT(ghwndIPHatch, EB_HATCHWIDTH, DEF_HATCH_SZ);
InflateRect(&hatchrc, DEF_HATCH_SZ, DEF_HATCH_SZ);
}
SetHatchRect(ghwndIPHatch,(LPRECT)&hatchrc);
*lphwnd = ghwndIPHatch;
//If we are going to Play inplace, do the minimum stuff and return.
if (verb == OLEIVERB_PRIMARY)
{
gfOle2IPPlaying = TRUE;
GetWindowRect(ghwndCntr,(LPRECT)&rcVis);
MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&rcVis, 2);
SetHatchWindowSize(ghwndIPHatch, (LPRECT)&rcPos,(LPRECT)&rcVis, (LPPOINT)&gHatchOffset,FALSE);
MoveWindow(ghwndApp, 0, 0, rcPos.right - rcPos.left, rcPos.bottom - rcPos.top, TRUE);
InPlaceCreateControls(TRUE);
ActivateTools(lpdoc, TRUE);
TransferTools(ghwndApp);
ClientToScreen(lpdoc->hwndParent, (LPPOINT)&rcPos);
ClientToScreen(lpdoc->hwndParent, (LPPOINT)&rcPos+1);
lpdoc->hwndParent = NULL;
/* MENU STUFF */
/* We have to set the menus even if we're only playing, because otherwise
* Word doesn't believe we're in-place active, and doesn't send us any
* deactivation notification when the user clicks outside us.
*/
AssembleMenus (lpdoc, TRUE);
if ((error = GetScode(IOleInPlaceFrame_SetMenu (lpdoc->lpIpData->lpFrame,
lpdoc->lpIpData->hmenuShared,
lpdoc->lpIpData->holemenu,
lpdoc->hwnd))) != S_OK)
goto errRtn;
/* END MENU STUFF */
*lprect = rcPos;
ShowWindow(ghwndIPHatch, SW_SHOW);
return NOERROR;
}
//Edit InPlace.
if (!(gwDeviceID == (UINT)0 || !(gwDeviceType & DTMCI_CANWINDOW)))
//No resize handles.
SetHatchWindowSize(ghwndIPHatch, (LPRECT)&rcPos,(LPRECT)&rcVis, (LPPOINT)&gHatchOffset,TRUE);
else
//There will be resize handles.
SetHatchWindowSize(ghwndIPHatch, (LPRECT)&rcPos,(LPRECT)&rcVis, (LPPOINT)&gHatchOffset,FALSE);
gfOle2IPEditing = TRUE;
if (!SkipInPlaceEdit) //don't layout and transfer the tools
{ // if we are just reactivating.
DestroyWindow(ghwndStatic);
ghwndStatic = CreateStaticStatusWindow(ghwndApp, FALSE);
SendMessage(ghwndStatic, WM_SETFONT, (UINT_PTR)ghfontMap, 0);
Layout();
InPlaceCreateControls(FALSE);
}
else
SetParent (lpdoc->hwnd, ghwndIPHatch);
TransferTools(ghwndIPToolWindow);
if ((error = GetScode(AssembleMenus (lpdoc, FALSE))) != S_OK)
goto errRtn;
ShowWindow (lpdoc->hwnd, SW_HIDE);
// currently we are not using the pane
// prevent OnDataChange() notification
lpdoc->lpIpData->fNoNotification = FALSE;
if ((error = GetScode(IOleInPlaceFrame_SetMenu (lpdoc->lpIpData->lpFrame,
lpdoc->lpIpData->hmenuShared,
lpdoc->lpIpData->holemenu,
lpdoc->hwnd))) != S_OK)
goto errRtn;
if ((error = GetScode(ActivateTools(lpdoc,FALSE))) != S_OK)
goto errRtn;
ShowWindow(ghwndIPHatch,SW_SHOW);
ShowWindow(ghwndMCI,SW_SHOW);
ClientToScreen(lpdoc->hwndParent, (LPPOINT)&rcPos);
ClientToScreen(lpdoc->hwndParent, (LPPOINT)&rcPos+1);
*lprect = rcPos;
if (SkipInPlaceEdit)
OffsetRect(&gInPlacePosRect,rcPos.left-gInPlacePosRect.left,
rcPos.top-gInPlacePosRect.top);
else
gInPlacePosRect = rcPos;
return NOERROR;
errRtn:
DoInPlaceDeactivate(lpdoc);
TransferTools(ghwndApp);
RETURN_RESULT(error);
errActivate:
IOleInPlaceSite_Release(lpIPSite);
FreeInPlaceDataBlock (lpdoc);
RETURN_RESULT( error);
}
#if 0
HMENU GetInPlaceMenu(void)
{
if (ghInPlaceMenu)
return GetSubMenu(ghInPlaceMenu,0);
else
{
ghInPlaceMenu = LoadMenu(ghInst, TEXT("InPlaceMenu"));
return GetSubMenu(ghInPlaceMenu,0);
}
}
#endif
/**************************************************************************
* AssembleMenus:
* This function merges our menu with that of the client.
***************************************************************************/
STDMETHODIMP AssembleMenus (LPDOC lpdoc, BOOL fPlayOnly)
{
HMENU hmenuMain = ghMenu;
HMENU hmenuEditPopup = GetSubMenu(hmenuMain, menuposEdit);
HMENU hmenuDevicePopup = GetSubMenu(hmenuMain, menuposDevice);
HMENU hmenuScalePopup = GetSubMenu(hmenuMain, menuposScale);
//HMENU hmenuCommandPopup = GetInPlaceMenu();
HMENU hmenuHelpPopup = GetSubMenu(hmenuMain, menuposHelp);
HMENU hmenuShared;
LONG FAR* lpMenuWidths;
SCODE error = S_OK;
UINT uPos;
UINT uPosStart;
static TCHAR szEdit[40] = TEXT("");
static TCHAR szInsert[40] = TEXT("");
static TCHAR szScale[40] = TEXT("");
//static TCHAR szCommand[40] = TEXT("");
static TCHAR szHelp[40] = TEXT("");
if (szEdit[0] == TEXT('\0'))
{
LOADSTRING(IDS_EDITMENU, szEdit);
LOADSTRING(IDS_INSERTMENU, szInsert);
LOADSTRING(IDS_SCALEMENU, szScale);
//LOADSTRING(IDS_COMMANDMENU, szCommand);
LOADSTRING(IDS_HELPMENU, szHelp);
}
lpMenuWidths = lpdoc->lpIpData->menuWidths.width;
hmenuShared = CreateMenu();
if((error = GetScode(IOleInPlaceFrame_InsertMenus (lpdoc->lpIpData->lpFrame,
hmenuShared, &lpdoc->lpIpData->menuWidths))) !=S_OK)
{
if (hmenuShared)
DestroyMenu(hmenuShared);
RETURN_RESULT( error);
}
if(fPlayOnly)
{
/* No server menu items if we're only playing:
*/
lpMenuWidths[1] = lpMenuWidths[3] = lpMenuWidths[5] = 0;
}
else
{
uPos = (UINT)lpMenuWidths[0]; /* # of menus in the FILE group */
uPosStart = uPos;
InsertMenu (hmenuShared, (WORD)uPos,
MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuEditPopup, szEdit);
uPos++;
lpMenuWidths[1] = uPos - uPosStart;
/* Insert OBJECT group menus */
uPos += (UINT)lpMenuWidths[2];
uPosStart = uPos;
InsertMenu (hmenuShared, (WORD)uPos,
MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuDevicePopup, szInsert);
uPos++;
InsertMenu (hmenuShared, (WORD)uPos,
MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuScalePopup, szScale);
uPos++;
//InsertMenu (hmenuShared, (WORD)uPos,
// MF_BYPOSITION | MF_POPUP, (UINT)hmenuCommandPopup, szCommand);
//uPos++;
lpMenuWidths[3] = uPos - uPosStart;
/* Insert HELP group menus */
uPos += (UINT) lpMenuWidths[4]; /* # of menus in WINDOW group */
uPosStart = uPos;
InsertMenu (hmenuShared, (WORD)uPos, MF_BYPOSITION | MF_POPUP, (UINT_PTR)hmenuHelpPopup,
szHelp);
uPos++;
lpMenuWidths[5] = uPos - uPosStart;
}
if(!(lpdoc->lpIpData->holemenu = OleCreateMenuDescriptor (hmenuShared,
&lpdoc->lpIpData->menuWidths)))
RETURN_RESULT( E_OUTOFMEMORY);
lpdoc->lpIpData->hmenuShared = hmenuShared;
RETURN_RESULT( error);
}
//Removes our menu from the shared menu,
STDMETHODIMP DisassembleMenus (LPDOC lpdoc)
{
HMENU hmenuMain = ghMenu;
HMENU hmenuEditPopup = GetSubMenu(hmenuMain, menuposEdit);
HMENU hmenuDevicePopup = GetSubMenu(hmenuMain, menuposDevice);
HMENU hmenuScalePopup = GetSubMenu(hmenuMain, menuposScale);
//HMENU hmenuCommandPopup = GetInPlaceMenu();
HMENU hmenuHelpPopup = GetSubMenu(hmenuMain, menuposHelp);
HMENU hmenuTmp;
HMENU hmenuShared = lpdoc->lpIpData->hmenuShared;
int i, n, cnt;
SCODE error = S_OK;
OleDestroyMenuDescriptor (lpdoc->lpIpData->holemenu);
lpdoc->lpIpData->holemenu = NULL;
if(!(lpdoc->lpIpData->hmenuShared))
RETURN_RESULT( error);
n = GetMenuItemCount(hmenuShared);
cnt = 0;
i = 0;
while (i < n) {
hmenuTmp = GetSubMenu(hmenuShared, i);
if (hmenuTmp == hmenuEditPopup
|| hmenuTmp == hmenuDevicePopup
|| hmenuTmp == hmenuHelpPopup
//|| hmenuTmp == hmenuCommandPopup
|| hmenuTmp == hmenuScalePopup ) {
RemoveMenu (hmenuShared, i, MF_BYPOSITION);
++cnt;
if (cnt == 4) { // added 3 (4 if command menu included) popup menus.
break;
}
--n;
}
else
++i;
}
IOleInPlaceFrame_RemoveMenus (lpdoc->lpIpData->lpFrame,
lpdoc->lpIpData->hmenuShared);
DestroyMenu(lpdoc->lpIpData->hmenuShared);
lpdoc->lpIpData->hmenuShared = NULL;
RETURN_RESULT( error);
}
void AllocInPlaceDataBlock (LPDOC lpdoc)
{
// When this app is ready to support mutiple objects (documents), these
// structures should be allocated dynamically one per object.
static INPLACEDATA IpData;
lpdoc->lpIpData = (LPINPLACEDATA) &IpData;
lpdoc->lpIpData->lpFrame = NULL;
lpdoc->lpIpData->lpUIWindow = NULL;
lpdoc->lpIpData->fInContextHelpMode = FALSE;
}
void FreeInPlaceDataBlock (LPDOC lpdoc)
{
lpdoc->lpIpData = NULL;
}
void DoInPlaceDeactivate (LPDOC lpdoc)
{
if (!(lpdoc->lpIpData))
return;
ShowWindow(ghwndApp,SW_HIDE);
IOleInPlaceObject_InPlaceDeactivate ((LPOLEINPLACEOBJECT)&lpdoc->m_InPlace);
}
/**************************************************************************
* ToolWndProc:
* This is the Window proc for the ToolWindow/Windows we will be trasnferring
* to the client window. Some messages are routed to the MPlayer main window
* to ensure proper operation.
***************************************************************************/
LONG_PTR FAR PASCAL ToolWndProc (HWND hwnd, unsigned message, WPARAM wparam,
LPARAM lparam)
{
switch(message)
{
case WM_COMMAND:
PostMessage(ghwndApp,WM_COMMAND,
wparam,lparam);
break;
case WM_NEXTDLGCTL:
case WM_CTLCOLOR:
case WM_HSCROLL:
return (SendMessage(ghwndApp,message,wparam,lparam));
default:
return DefWindowProc(hwnd,message,wparam,lparam);
}
return 0;
}
/**************************************************************************
* RegisterToolWinClasses:
* Register the WindowClasses for the Toolbar windows we use to display
* in the client document.
***************************************************************************/
BOOL RegisterToolWinClasses()
{
WNDCLASS wc;
wc.lpszClassName = TEXT("ObjTool");
wc.lpfnWndProc = ToolWndProc;
wc.style = 0;
wc.hInstance = ghInst;
wc.hIcon = NULL;
wc.cbClsExtra = 4;
wc.cbWndExtra = 0;
wc.lpszMenuName = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
/**************************************************************************
* InPlaceCreateControls:
* This function creates the toolbar windows we will display in the client
* and transfers the tool button to these windows by changing parents
* and repositioning them.
* If fPlayOnly is true all we need is a Dummy toolbar to fill space on
* the top of the container. Don't transfer the tools.
***************************************************************************/
void InPlaceCreateControls(BOOL fPlayOnly)
{
RECT rc;
if(IsWindow(ghwndIPToolWindow))
return;
RegisterToolWinClasses();
GetWindowRect(GetDesktopWindow(),&rc);
toolbarwidth = 2*(rc.right - rc.left);
IOleInPlaceFrame_GetWindow (docMain.lpIpData->lpFrame, &ghwndFrame);
ghwndIPToolWindow = CreateWindowEx(gfdwFlagsEx,
TEXT("ObjTool"),
NULL,
WS_CHILD | WS_BORDER,
0, 0,
toolbarwidth,
3*TOOL_WIDTH+1,
ghwndFrame,
NULL,
ghInst,
NULL);
ShowWindow(ghwndIPToolWindow, SW_HIDE);
if (fPlayOnly)
return;
ghwndIPScrollWindow = CreateWindowEx(gfdwFlagsEx,
TEXT("ObjTool"),
NULL,
WS_CHILD | WS_BORDER,
0, 0,
toolbarwidth,
3*TOOL_WIDTH+1,
ghwndFrame,
NULL,
ghInst,
NULL);
ShowWindow(ghwndIPScrollWindow, SW_HIDE);
}
/**************************************************************************
* SubClassedHatchWndProc:
* The Hatch Window is created in the OLE2UI.LIB. The window proc
* is also specified there. But in order to do things like resizing
* the Mplayer when the handles in the hatch window are dragged
* we need to subclass the window.
***************************************************************************/
LONG_PTR FAR PASCAL SubClassedHatchWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
static BOOL fCapture = FALSE;
static RECT hatchRC;
RECT rc;
static POINT ptLast;
POINT pt;
HDC hdcDeskTop;
HPEN hpenOld;
HBRUSH hbrushOld;
int nropOld;
int nBkOld;
HPEN hpen;
static int dL,dR, dT, dB;
static int left, right, top, bottom;
switch(wMsg)
{
case WM_LBUTTONDOWN: //Check to see if the click is on the resize handles.
//If yes then capture the mouse.
if(!GETWINDOWUINT(ghwndIPHatch,EW_HATCH_HANDLE))
break;
if(gfOle2IPPlaying)
break;
GetHatchRect(ghwndIPHatch, &hatchRC);
pt.x = (int)(SHORT)LOWORD(lParam);
pt.y = (int)(SHORT)HIWORD(lParam);
left = right = top = bottom = 0;
rc.left = hatchRC.left;
rc.top = hatchRC.top;
rc.right = rc.left + DEF_HATCH_SZ + 1;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
left = top = 1;
rc.top = hatchRC.top+(hatchRC.bottom-hatchRC.top-DEF_HATCH_SZ-1)/2;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
left = 1;
rc.top = hatchRC.bottom-DEF_HATCH_SZ-1;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
{
bottom = 1;
left = 1;
}
rc.left = hatchRC.right - DEF_HATCH_SZ-1;
rc.right = rc.left + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
{
bottom = 1;
right = 1;
}
rc.top = hatchRC.top+(hatchRC.bottom-hatchRC.top-DEF_HATCH_SZ-1)/2;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
right = 1;
rc.top = hatchRC.top;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
{
top = 1;
right = 1;
}
rc.left = hatchRC.left + (hatchRC.right - hatchRC.left - DEF_HATCH_SZ-1)/2;
rc.right = rc.left + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
top = 1;
rc.top = hatchRC.bottom-DEF_HATCH_SZ-1;
rc.bottom = rc.top + DEF_HATCH_SZ + 1;
if(PtInRect((LPRECT)&rc,pt))
bottom = 1;
if (!(left || right || top || bottom))
break;
fCapture = TRUE;
SetCapture(hwnd);
ptLast = pt;
MapWindowPoints(hwnd,NULL,(LPPOINT)&hatchRC,2);
dL = dR = dT = dB = 0;
hpen = CreatePen(PS_DASH, 1, 0x00000000);
hdcDeskTop = GetDC(NULL);
hpenOld = SelectObject (hdcDeskTop, hpen);
hbrushOld = SelectObject (hdcDeskTop,
GetStockObject(HOLLOW_BRUSH));
nropOld = GetROP2(hdcDeskTop);
SetROP2(hdcDeskTop, R2_NOT);
nBkOld = GetBkMode(hdcDeskTop);
SetBkMode(hdcDeskTop, TRANSPARENT);
Rectangle(hdcDeskTop, hatchRC.left+dL, hatchRC.top+dT,
hatchRC.right+dR, hatchRC.bottom+dB);
SetBkMode(hdcDeskTop, nBkOld);
SetROP2(hdcDeskTop, nropOld);
SelectObject(hdcDeskTop, hbrushOld);
SelectObject(hdcDeskTop, hpenOld);
DeleteObject (hpen);
ReleaseDC(NULL, hdcDeskTop);
break;
case WM_MOUSEMOVE: //If we have the capture draw the resize rectangles.
if (!fCapture)
break;
else {
pt.x = (int)(SHORT)LOWORD(lParam);
pt.y = (int)(SHORT)HIWORD(lParam);
hpen = CreatePen(PS_DASH, 1, 0x00000000);
hdcDeskTop = GetDC(NULL);
hpenOld = SelectObject (hdcDeskTop, hpen);
hbrushOld = SelectObject (hdcDeskTop,
GetStockObject(HOLLOW_BRUSH));
nropOld = GetROP2(hdcDeskTop);
SetROP2(hdcDeskTop, R2_NOT);
nBkOld = GetBkMode(hdcDeskTop);
SetBkMode(hdcDeskTop, TRANSPARENT);
Rectangle(hdcDeskTop, hatchRC.left+dL, hatchRC.top+dT,
hatchRC.right+dR, hatchRC.bottom+dB);
dL = dR = pt.x - ptLast.x;
dT = dB = pt.y - ptLast.y;
dL *= left;
dR *= right;
dT *= top;
dB *= bottom;
Rectangle(hdcDeskTop, hatchRC.left+dL, hatchRC.top+dT,
hatchRC.right+dR, hatchRC.bottom+dB);
SetBkMode(hdcDeskTop, nBkOld);
SetROP2(hdcDeskTop, nropOld);
SelectObject(hdcDeskTop, hbrushOld);
SelectObject(hdcDeskTop, hpenOld);
if (hpen)
DeleteObject (hpen);
ReleaseDC(NULL, hdcDeskTop);
}
break;
case WM_LBUTTONUP: //release capture and resize.
if (!fCapture)
break;
else {
hpen = CreatePen(PS_DASH, 1, 0x00000000);
hdcDeskTop = GetDC(NULL);
hpenOld = SelectObject (hdcDeskTop, hpen);
hbrushOld = SelectObject (hdcDeskTop,
GetStockObject(HOLLOW_BRUSH));
nropOld = GetROP2(hdcDeskTop);
SetROP2(hdcDeskTop, R2_NOT);
nBkOld = GetBkMode(hdcDeskTop);
SetBkMode(hdcDeskTop, TRANSPARENT);
Rectangle(hdcDeskTop, hatchRC.left+dL, hatchRC.top+dT,
hatchRC.right+dR, hatchRC.bottom+dB);
SetBkMode(hdcDeskTop, nBkOld);
SetROP2(hdcDeskTop, nropOld);
SelectObject(hdcDeskTop, hbrushOld);
SelectObject(hdcDeskTop, hpenOld);
DeleteObject (hpen);
ReleaseDC(NULL, hdcDeskTop);
ReleaseCapture();
}
fCapture = FALSE;
GetWindowRect(ghwndApp,&hatchRC);
hatchRC.left += dL;
hatchRC.right += dR;
hatchRC.top += dT;
hatchRC.bottom += dB;
MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&hatchRC, 2);
if (gwStatus != MCI_MODE_STOP)
PostMessage(ghwndApp, WM_COMMAND, ID_STOP, 0L);
// Negotiate with client for space. We accept the size specified by client.
DPFI("Hatch Resize: Before OnPosRectChange: %d, %d, %d, %d\r\n", hatchRC);
if (!gfInPPViewer)
IOleInPlaceSite_OnPosRectChange(docMain.lpIpData->lpSite, &hatchRC);
SendDocMsg((LPDOC)&docMain, OLE_CHANGED);
break;
case WM_PAINT:
{
HDC hdc;
HDC hdcmem;
RECT rcH;
HBITMAP hbm;
BITMAP bm;
if(ghwndMCI)
break;
CallWindowProc(gfnHatchWndProc, hwnd, wMsg, wParam, lParam);
hdc = GetDC(hwnd);
GetHatchRect(hwnd, (LPRECT)&rcH);
InflateRect((LPRECT)&rcH,-DEF_HATCH_SZ,-DEF_HATCH_SZ);
hbm = BitmapMCI();
hdcmem = CreateCompatibleDC(hdc);
if(!hdcmem)
return(E_FAIL);
SelectObject(hdcmem,hbm);
GetObject(hbm,sizeof(bm),(LPVOID)&bm);
StretchBlt(hdc,rcH.left,rcH.top,rcH.right-rcH.left,rcH.bottom-rcH.top,hdcmem,
0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
DeleteDC(hdcmem);
ReleaseDC(ghwndIPHatch,hdc);
return 0L;
}
}
return CallWindowProc(gfnHatchWndProc, hwnd, wMsg, wParam, lParam);
}