- BORLAND/: Borland C++ 4.52 (chosen over 4.5 by byte-match: CODE/RP/CW32.LIB
is identical to 4.52's install lib). BCC32/TLINK32/TLIB/MAKE run natively on
Win11; CODE/BT/OPT.MAK is the shipped BTL4OPT.EXE's exact flag recipe
(extender = Borland PowerPack DPMI32, not Phar Lap TNT).
- restoration/source410/: the literal 1995-form reconstruction of the missing
BT game source (never mixed into CODE/). Round 1-3 state:
* 6 of 10 surviving original TUs COMPILE CLEAN under the period toolchain
(BTMSSN, BTCNSL, BTSCNRL, BTTEAM, BTL4MODE, BTL4ARND) - first builds
since 1996.
* BT_L4/BTL4APP.CPP pilot reconstruction: 12/12 functions, Fail() lands on
its binary-recorded line 400 exactly.
* BT/BTCNSL.HPP: console wire IDs recovered from the binary's ctors
(Killed=9, Damaged=10, ScoreUpdate=13, DeathWithoutHonor=15 [T1];
TeamScore=12 flagged [T4]).
* MUNGA/: 8 engine-header backfills back-dated from the BT412 WinTesla tree
(VDATA numbering decomp-verified; AUDREND's OpenAL-era virtual removed -
the period compiler is the drift detector).
* Tooling: backdate.py (WinTesla->1995 header transform), compile410.sh
(per-TU verification sweep under authentic OPT.MAK flags).
* README: corrected roadmap - MECH.HPP is the capstone grown with the mech
TU reconstructions; BTREG.CPP green = the header-family milestone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
773 lines
26 KiB
C++
773 lines
26 KiB
C++
//
|
|
//**************************************************************************
|
|
//
|
|
// Bhatch.cpp - An implementation of the hatched border around inplace
|
|
// active windows.
|
|
//
|
|
// Modifications to OLE2UI version:
|
|
// - C++ version
|
|
// - removed restriction that parent must be non-null in CreateHatchWindow
|
|
// - changed window from a child to a popup to allow null parent
|
|
// - "extra bytes" removed in favor of member data
|
|
// - added Paint() and InitWidth() to unclutter wnd proc
|
|
// - added hit testing and correct cursors for handles
|
|
// - added resizing for handles
|
|
// - added NegotiateSize() to mediate inplace size negotiations between
|
|
// the container and the server
|
|
//
|
|
// Copyright (c) 1993,94 by Borland International, Inc. All rights reserved
|
|
//
|
|
//**************************************************************************
|
|
|
|
#include "BOle.h"
|
|
|
|
// #define STRICT 1
|
|
#define STRICT
|
|
#include "OLE2UI.h"
|
|
#include "BHatch.h"
|
|
|
|
// class name of hatch window
|
|
#ifdef ANSI
|
|
#define CLASS_HATCH "BOle Hatch Window"
|
|
#else
|
|
#define CLASS_HATCH OLESTR("BOle Hatch Window")
|
|
#endif
|
|
|
|
// local function prototypes
|
|
LRESULT FAR PASCAL EXPORT BOleHatchWndProc (HWND, UINT, WPARAM, LPARAM);
|
|
|
|
// static initializer
|
|
UINT BOleHatchWindow::hatchWidth = 0;
|
|
|
|
// global functions
|
|
void SetRectExt (LPRECT r, UINT x, UINT y, UINT extent)
|
|
{
|
|
r->left = x;
|
|
r->top = y;
|
|
r->right = x + extent;
|
|
r->bottom = y + extent;
|
|
}
|
|
|
|
BOleHatchWindow::BOleHatchWindow(HWND hWndParent, HINSTANCE hInst, BOleSite *p)
|
|
{
|
|
pBack = p; // assign BOleSite
|
|
#ifdef ANSI
|
|
hWndHatch = ::CreateWindowExA(
|
|
0,
|
|
CLASS_HATCH, // Class name
|
|
"Hatch Window", // Window name
|
|
WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
0, 0, 0, 0,
|
|
GetDesktopWindow(),
|
|
(HMENU)NULL,
|
|
hInst,
|
|
this
|
|
);
|
|
#else
|
|
hWndHatch = ::CreateWindowEx(
|
|
0,
|
|
CLASS_HATCH, // Class name
|
|
OLESTR("Hatch Window"), // Window name
|
|
WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
0, 0, 0, 0,
|
|
GetDesktopWindow(),
|
|
(HMENU)NULL,
|
|
hInst,
|
|
this
|
|
);
|
|
#endif
|
|
|
|
hatchRect.left = hatchRect.top = hatchRect.bottom = hatchRect.right = 0;
|
|
MoveRect.left = MoveRect.top = MoveRect.bottom = MoveRect.right = 0;
|
|
nClippedFlag = 0;
|
|
pSite = NULL;
|
|
fInMouseDown = FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Destructor: ~BOleHatchWindow
|
|
//
|
|
// Purpose:
|
|
// Public destructor to destroy the hWnd
|
|
//
|
|
//***************************************************************************
|
|
BOleHatchWindow::~BOleHatchWindow ()
|
|
{
|
|
if (hWndHatch)
|
|
::DestroyWindow (hWndHatch);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Static member function: Register
|
|
//
|
|
// Purpose:
|
|
// Register the hatch window
|
|
//
|
|
// Parameters:
|
|
// hInst Process instance
|
|
//
|
|
// Return Value:
|
|
// TRUE if successful
|
|
// FALSE if failed
|
|
//
|
|
//***************************************************************************
|
|
BOOL BOleHatchWindow::Register (HINSTANCE hInst)
|
|
{
|
|
#ifdef ANSI
|
|
WNDCLASSA wc;
|
|
#else
|
|
WNDCLASS wc;
|
|
#endif
|
|
|
|
// Register Hatch Window Class
|
|
wc.style = CS_BYTEALIGNWINDOW;
|
|
wc.lpfnWndProc = BOleHatchWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(BOleHatchWindow*); // 'this' in extra bytes
|
|
wc.hInstance = hInst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = CLASS_HATCH;
|
|
|
|
#ifdef ANSI
|
|
if (!::RegisterClassA(&wc))
|
|
#else
|
|
if (!::RegisterClass(&wc))
|
|
#endif
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Static member function: InitWidth
|
|
//
|
|
// Purpose:
|
|
// Initialize hatch border with from WIN.INI
|
|
//
|
|
//***************************************************************************
|
|
void BOleHatchWindow::InitWidth ()
|
|
{
|
|
#ifdef ANSI
|
|
hatchWidth = GetProfileIntA("windows", "oleinplaceborderwidth",
|
|
DEFAULT_HATCHBORDER_WIDTH);
|
|
#else
|
|
hatchWidth = GetProfileInt(OLESTR("windows"), OLESTR("oleinplaceborderwidth"),
|
|
DEFAULT_HATCHBORDER_WIDTH);
|
|
#endif
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Member function: GetWidth
|
|
//
|
|
// Purpose:
|
|
// Get width of hatch border
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return Value:
|
|
// UINT width of the hatch border
|
|
//***************************************************************************
|
|
UINT BOleHatchWindow::GetWidth ()
|
|
{
|
|
if (!::IsWindow(hWndHatch))
|
|
return 0;
|
|
|
|
return hatchWidth;
|
|
}
|
|
|
|
//****************************************************************
|
|
// window messages related member functions
|
|
//
|
|
// Purpose:
|
|
// Window Procedure dispatches all messages here.
|
|
// Each member functions got the message name.
|
|
// Do messages processing here.
|
|
// Refer to windows help to get information about messages
|
|
//
|
|
//****************************************************************
|
|
|
|
//****************************************************************
|
|
// Member function: wmCreate
|
|
//
|
|
// Parameters:
|
|
// LPCREATESTRUCT struct containing information about the window
|
|
// to be created. Not used
|
|
//
|
|
// Return Value:
|
|
// LRESULT 0L to continue creation process
|
|
//
|
|
//****************************************************************
|
|
#ifdef ANSI
|
|
LRESULT BOleHatchWindow::wmCreate (LPCREATESTRUCTA)
|
|
#else
|
|
LRESULT BOleHatchWindow::wmCreate (LPCREATESTRUCT)
|
|
#endif
|
|
{
|
|
BOleHatchWindow::InitWidth ();
|
|
return 0L;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Member function: wmPaint
|
|
//
|
|
// Purpose:
|
|
// Draw hatched border and handles
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return Value:
|
|
// LRESULT 0L
|
|
//
|
|
//***************************************************************************
|
|
LRESULT BOleHatchWindow::wmPaint ()
|
|
{
|
|
HDC hDC;
|
|
PAINTSTRUCT ps;
|
|
RECT rcHatchRect;
|
|
|
|
hDC = ::BeginPaint(hWndHatch, &ps);
|
|
// get hatchRect to paint hatch border
|
|
rcHatchRect = hatchRect;
|
|
SetRect((LPRECT)&rcHatchRect,rcHatchRect.left, rcHatchRect.top,
|
|
rcHatchRect.right,
|
|
rcHatchRect.bottom);
|
|
OleUIDrawShading(&rcHatchRect, hDC, OLEUI_SHADE_BORDERIN,
|
|
hatchWidth);
|
|
// get the real visible rect to draw handles
|
|
GetWindowRect(hWndHatch, (LPRECT)&rcHatchRect);
|
|
SetRect((LPRECT)&rcHatchRect,0, 0, rcHatchRect.right-rcHatchRect.left,
|
|
rcHatchRect.bottom-rcHatchRect.top);
|
|
::InflateRect ((LPRECT)&rcHatchRect, -hatchWidth, -hatchWidth);
|
|
OleUIDrawHandles (&rcHatchRect, hDC, OLEUI_HANDLES_OUTSIDE,
|
|
hatchWidth+1, TRUE);
|
|
::EndPaint (hWndHatch, &ps);
|
|
|
|
return 0L;
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmNCHitTest
|
|
//
|
|
// Purpose:
|
|
// Find out which handle the cursor is over
|
|
//
|
|
// Parameters:
|
|
// LPPOINT mouse position
|
|
//
|
|
// Return Value:
|
|
// UINT a value indicating the position of the cursor
|
|
//
|
|
//****************************************************************
|
|
UINT BOleHatchWindow::wmNCHitTest (LPPOINT lpPoint)
|
|
{
|
|
RECT handleRect;
|
|
RECT rc; // contain hatch window rect
|
|
|
|
// we want lpPoint to be in client coordinates
|
|
::ScreenToClient (hWndHatch, lpPoint);
|
|
|
|
GetWindowRect(hWndHatch, (LPRECT)&rc);
|
|
SetRect((LPRECT)&rc,0,0,rc.right-rc.left,rc.bottom-rc.top);
|
|
|
|
SetRectExt (&handleRect, rc.left, rc.top, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTTOPLEFT;
|
|
|
|
SetRectExt (&handleRect, rc.left, (rc.top+rc.bottom-hatchWidth + 1)/2, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTLEFT;
|
|
|
|
SetRectExt (&handleRect, rc.left, rc.bottom - hatchWidth + 1, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTBOTTOMLEFT;
|
|
|
|
SetRectExt (&handleRect, (rc.left+rc.right-hatchWidth + 1)/2, rc.top, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTTOP;
|
|
|
|
SetRectExt (&handleRect, (rc.left+rc.right-hatchWidth + 1)/2, rc.bottom - hatchWidth + 1, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTBOTTOM;
|
|
|
|
SetRectExt (&handleRect, rc.right-hatchWidth + 1, rc.top, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTTOPRIGHT;
|
|
|
|
SetRectExt (&handleRect, rc.right-hatchWidth + 1, (rc.top+rc.bottom-hatchWidth + 1)/2, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTRIGHT;
|
|
|
|
SetRectExt (&handleRect, rc.right-hatchWidth + 1, rc.bottom-hatchWidth + 1, hatchWidth + 1);
|
|
if (::PtInRect(&handleRect, *lpPoint)) return HTBOTTOMRIGHT;
|
|
|
|
// If we've gotten this far, the cursor is not over a handle, but it
|
|
// is over the hatch window (because we got the message). This means
|
|
// the cursor is over the hatched border. It can't be over our client
|
|
// area because the server object takes up the client area.
|
|
//
|
|
// So, by telling Windows that the cursor is over the caption bar, we
|
|
// can piggy-back on Windows' code for dragging windows around.
|
|
//
|
|
return HTCAPTION;
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmSetCursor
|
|
//
|
|
// Purpose:
|
|
// Set the cursor bitmap to match the handle it's over.
|
|
//
|
|
// Parameters:
|
|
// HWND handle of the window with the cursor
|
|
// UINT only used. Contains the value returned from wmNCHitTest
|
|
// UINT Mouse message number
|
|
//
|
|
// Return Value:
|
|
// LRESULT TRUE, to stop further processing
|
|
//
|
|
//****************************************************************
|
|
LRESULT BOleHatchWindow::wmSetCursor (HWND, UINT hitTestCode, UINT)
|
|
{
|
|
|
|
switch (hitTestCode) {
|
|
case HTTOPLEFT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
|
|
break;
|
|
case HTLEFT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
|
|
break;
|
|
case HTBOTTOMLEFT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
|
|
break;
|
|
case HTTOP:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENS)));
|
|
break;
|
|
case HTBOTTOM:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENS)));
|
|
break;
|
|
case HTTOPRIGHT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENESW)));
|
|
break;
|
|
case HTRIGHT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZEWE)));
|
|
break;
|
|
case HTBOTTOMRIGHT:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_SIZENWSE)));
|
|
break;
|
|
default:
|
|
::SetCursor (::LoadCursor (NULL, MAKEINTRESOURCE(IDC_ARROW)));
|
|
}
|
|
|
|
return (LRESULT)TRUE;
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmMouseActivate
|
|
//
|
|
// Parameters:
|
|
// HWND handle of the top level parent. Not used
|
|
// UINT hit test code. Not used
|
|
// UINT Mouse message identifier. Not used
|
|
//
|
|
// Return Value:
|
|
// UINT MA_NOACTIVATE does not activate the window
|
|
//
|
|
//****************************************************************
|
|
UINT BOleHatchWindow::wmMouseActivate (HWND, UINT, UINT)
|
|
{
|
|
return MA_NOACTIVATE;
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmNCLButtonDown
|
|
//
|
|
// Parameters:
|
|
// UINT hit test code as returned from WM_NCHITTEST
|
|
// LPOINT cursor coordinates
|
|
//
|
|
// Return Value:
|
|
// LRESULT let it process by DefWindowProc
|
|
//
|
|
//****************************************************************
|
|
LRESULT BOleHatchWindow::wmNCLButtonDown (UINT nTestCode, LPPOINT lpPoint)
|
|
{
|
|
// first resize window if needed
|
|
if (nClippedFlag & CLIPPED) {
|
|
RECT WinRect;
|
|
// get the real (visible) window in client coordinates
|
|
GetWindowRect( hWndHatch, (LPRECT)&WinRect);
|
|
ScreenToClient( GetParent( hWndHatch), (LPPOINT)&WinRect);
|
|
|
|
// if clipped left or top hatchRect adjust top and/or left
|
|
if (nClippedFlag & CLIPPED_LEFT)
|
|
WinRect.left += hatchRect.left;
|
|
if (nClippedFlag & CLIPPED_TOP)
|
|
WinRect.top += hatchRect.top;
|
|
// move window
|
|
MoveWindow( hWndHatch, WinRect.left, WinRect.top,
|
|
hatchRect.right - hatchRect.left,
|
|
hatchRect.bottom - hatchRect.top,
|
|
FALSE);
|
|
}
|
|
|
|
// set flag indicating the user is moving the window and initiating
|
|
// all space negotiation procedure
|
|
fInMouseDown=TRUE;
|
|
|
|
return ::DefWindowProc (hWndHatch, WM_NCLBUTTONDOWN, nTestCode, *((long *)lpPoint));
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmGetMinMaxInfo
|
|
//
|
|
// Parameters:
|
|
// LPMINMAXINFO struct containing resizing information
|
|
//
|
|
// Return Value:
|
|
// LRESULT 0L when processing this message
|
|
//
|
|
//****************************************************************
|
|
LRESULT BOleHatchWindow::wmGetMinMaxInfo (MINMAXINFO* pMMI)
|
|
{
|
|
int minWidth = (GetWidth() * 2) + 15;
|
|
pMMI->ptMinTrackSize.x = minWidth;
|
|
pMMI->ptMinTrackSize.y = minWidth;
|
|
return 0L;
|
|
}
|
|
|
|
//****************************************************************
|
|
// Member function: wmWindowPosChanging
|
|
//
|
|
// Purpose:
|
|
// Call negotiate size to activate the space negotiation
|
|
// procedure and, in case, changes the WINDOWPOS values
|
|
// so to accomplish the new size
|
|
//
|
|
// Parameters:
|
|
// LPWINDOWPOS structure containing information about
|
|
// resizing values
|
|
//
|
|
// Return Value:
|
|
// LRESULT
|
|
//
|
|
//****************************************************************
|
|
LRESULT BOleHatchWindow::wmWindowPosChanging (LPWINDOWPOS pWP)
|
|
{
|
|
if (hWndHatch == GetCapture()) {
|
|
RECT TempRect;
|
|
fInMouseDown = TRUE;
|
|
::DefWindowProc (hWndHatch, WM_WINDOWPOSCHANGING, 0, (DWORD)(LPVOID)pWP);
|
|
::InvalidateRect(hWndHatch, NULL, FALSE);
|
|
::CopyRect((LPRECT)&TempRect, (LPRECT)&hatchRect);
|
|
::InflateRect((LPRECT)&TempRect, -hatchWidth, -hatchWidth);
|
|
::ValidateRect(hWndHatch, (LPRECT)&TempRect);
|
|
return 0L;
|
|
}
|
|
|
|
if (fInMouseDown) {
|
|
int minWidth = (GetWidth() * 2) + 15;
|
|
if (pWP->cx < minWidth) {
|
|
pWP->cx = minWidth;
|
|
}
|
|
if (pWP->cy < minWidth) {
|
|
pWP->cy = minWidth;
|
|
}
|
|
NegotiateSize (pWP);
|
|
if (nClippedFlag & CLIPPED) {
|
|
pWP->x = MoveRect.left;
|
|
pWP->y = MoveRect.top;
|
|
pWP->cx = MoveRect.right;
|
|
pWP->cy = MoveRect.bottom;
|
|
pWP->flags = 0;
|
|
}
|
|
::InvalidateRect(hWndHatch, NULL, TRUE);
|
|
fInMouseDown = FALSE;
|
|
return 0L;
|
|
}
|
|
|
|
return ::DefWindowProc (hWndHatch, WM_WINDOWPOSCHANGING, 0, (DWORD)(LPVOID)pWP);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Member function: Show
|
|
//
|
|
// Purpose:
|
|
// Show or hide the hatch window; provide access to the site
|
|
//
|
|
// Parameters:
|
|
// BOOL TRUE to show the hatch window, FALSE to hide it
|
|
// LPOLEINPLACESITE Pointer to the in place site, which is used to
|
|
// negotiate new size when a handle is dragged
|
|
//
|
|
//***************************************************************************
|
|
void BOleHatchWindow::Show (BOOL fShow, LPOLEINPLACESITE pS)
|
|
{
|
|
pSite = pS;
|
|
::ShowWindow (hWndHatch, fShow ? SW_SHOW : SW_HIDE);
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Member function: SetSize
|
|
//
|
|
// Purpose:
|
|
// Move/size the HatchWindow correctly given the rect required by the
|
|
// in-place server object window and the lprcClipRect imposed by the
|
|
// in-place container. both rect's are expressed in the client coord.
|
|
// of the in-place container's window (which is the parent of the
|
|
// HatchWindow). When fInMouseDown is TRUE must not use MoveWindow
|
|
// but change the values in the WINDOWPOS struct inside the
|
|
// WM_WINDOWPOSCHANGING message (it seems Windows code is not re-entrant
|
|
// there)
|
|
//
|
|
// OLE2NOTE: the in-place server must honor the lprcClipRect specified
|
|
// by its in-place container. it must NOT draw outside of the ClipRect.
|
|
// in order to achieve this, the hatch window is sized to be
|
|
// exactly the size that should be visible (rcVisRect). the
|
|
// rcVisRect is defined as the intersection of the full size of
|
|
// the HatchRect window and the lprcClipRect.
|
|
// the ClipRect could infact clip the HatchRect on the
|
|
// right/bottom and/or on the top/left. if it is clipped on the
|
|
// right/bottom then it is sufficient to simply resize the hatch
|
|
// window. but if the HatchRect is clipped on the top/left then
|
|
// in-place server document window (child of HatchWindow) must be moved
|
|
// by the delta that was clipped. the window origin of the
|
|
// in-place server window will then have negative coordinates relative
|
|
// to its parent HatchWindow.
|
|
//
|
|
// Parameters:
|
|
// LPRECT full size of in-place server object window
|
|
// LPRECT clipping rect imposed by in-place container
|
|
// LPPOINT offset required to position in-place server object
|
|
// window properly. caller should call:
|
|
// OffsetRect(&rcObjRect,lpptOffset->x,lpptOffset->y)
|
|
//
|
|
// Return Value: None
|
|
//
|
|
//***************************************************************************
|
|
void BOleHatchWindow::SetSize(
|
|
LPRECT lprcIPObjRect,
|
|
LPRECT lprcClipRect,
|
|
LPPOINT lpptOffset)
|
|
{
|
|
|
|
RECT rcHatchRect;
|
|
RECT rcVisRect;
|
|
UINT uHatchWidth;
|
|
POINT ptOffset;
|
|
|
|
if (!::IsWindow(hWndHatch))
|
|
return;
|
|
|
|
rcHatchRect = *lprcIPObjRect;
|
|
uHatchWidth = GetWidth();
|
|
::InflateRect((LPRECT)&rcHatchRect, uHatchWidth + 1, uHatchWidth + 1);
|
|
|
|
// find the intersection between hatch (server) window and
|
|
// clipping area (area where the object is allowed to paint)
|
|
::IntersectRect (&rcVisRect, &rcHatchRect, lprcClipRect);
|
|
|
|
// move the hatch window at the intersection rectangle if you are not
|
|
// dragging the window around
|
|
if (!fInMouseDown) {
|
|
::MoveWindow(
|
|
hWndHatch,
|
|
rcVisRect.left,
|
|
rcVisRect.top,
|
|
rcVisRect.right-rcVisRect.left,
|
|
rcVisRect.bottom-rcVisRect.top,
|
|
TRUE /* fRepaint */
|
|
);
|
|
::InvalidateRect(hWndHatch, NULL, TRUE);
|
|
}
|
|
else {
|
|
// this information will be used in the WM_WINDOWPOSCHANGING
|
|
// message to change WINDOWPOS structure values
|
|
::SetRect(&MoveRect, rcVisRect.left, rcVisRect.top,
|
|
rcVisRect.right-rcVisRect.left,
|
|
rcVisRect.bottom-rcVisRect.top);
|
|
}
|
|
|
|
|
|
nClippedFlag = 0; // clear clipped flag
|
|
// store clipping information
|
|
if (!(::EqualRect(&rcVisRect,&rcHatchRect))) {
|
|
nClippedFlag |= CLIPPED;
|
|
if (rcVisRect.left != rcHatchRect.left ) {
|
|
nClippedFlag |= CLIPPED_LEFT;
|
|
}
|
|
if (rcVisRect.top != rcHatchRect.top) {
|
|
nClippedFlag |= CLIPPED_TOP;
|
|
}
|
|
}
|
|
|
|
// convert the rcHatchRect into the client coordinate system of the
|
|
// HatchWindow itself
|
|
ptOffset.x = - rcVisRect.left;
|
|
ptOffset.y = - rcVisRect.top;
|
|
::OffsetRect(&rcHatchRect, ptOffset.x, ptOffset.y);
|
|
hatchRect = rcHatchRect;
|
|
|
|
// calculate offset required to position in-place
|
|
// server doc window (output value)
|
|
lpptOffset->x = ptOffset.x;
|
|
lpptOffset->y = ptOffset.y;
|
|
|
|
return;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Member function: NegotiateSize
|
|
//
|
|
// Purpose:
|
|
// When the user drags a handle of the hatch window, Windows attempts
|
|
// to resize the window. This routine catches that attempt and validates
|
|
// it with the client. We don't need to validate it with the server
|
|
// because the client will call the server back from OnPosRectChange to
|
|
// BOleSite::SetObjectRects.
|
|
//
|
|
// Parameters:
|
|
// WINDOWPOS* Pointer to Windows' WINDOWPOS structure
|
|
//
|
|
//***************************************************************************
|
|
void BOleHatchWindow::NegotiateSize (WINDOWPOS *pwp)
|
|
{
|
|
RECT rcWnd; // The pre-resize size of the hatch window
|
|
|
|
// As an optimization, get the current size of the hatch window
|
|
// and bail out if it's the same as the new size. This saves the
|
|
// potentially expensive renegotiation.
|
|
//
|
|
::GetWindowRect (hWndHatch, &rcWnd);
|
|
HWND parent = ::GetParent (hWndHatch);
|
|
::ScreenToClient (parent, (LPPOINT) &rcWnd.left);
|
|
::ScreenToClient (parent, (LPPOINT) &rcWnd.right);
|
|
//if ( rcWnd.left == pwp->x && rcWnd.top == pwp->y &&
|
|
// (rcWnd.bottom - rcWnd.top == pwp->cy) &&
|
|
// (rcWnd.right - rcWnd.left == pwp->cx))
|
|
// return;
|
|
|
|
// Ask the client to resize to the new size of the window
|
|
//
|
|
RECT rcNew;
|
|
|
|
// The new size of the server's inplace window
|
|
::SetRect (&rcNew, pwp->x, pwp->y, pwp->x + pwp->cx, pwp->y + pwp->cy);
|
|
::InflateRect (&rcNew, -(hatchWidth + 1), -(hatchWidth + 1));
|
|
if (pSite) {
|
|
// Ask the server to show more/less of object
|
|
//
|
|
if (!SUCCEEDED(pBack->SetSiteRect(&rcNew))) {
|
|
SIZE size;
|
|
// undo resize of the server
|
|
size.cx = rcWnd.right - rcWnd.left;
|
|
size.cy = rcWnd.bottom - rcWnd.top;
|
|
pBack->pPart->SetPartSize(&size);
|
|
|
|
// If the client refuses the new size, give the pre-resize
|
|
// size of the hatch window, back to Windows through the WINDOWPOS
|
|
//
|
|
pwp->x = rcWnd.left;
|
|
pwp->y = rcWnd.top;
|
|
pwp->cx = rcWnd.right - rcWnd.left;
|
|
pwp->cy = rcWnd.bottom - rcWnd.top;
|
|
}
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
// BOleHatchWndProc
|
|
//
|
|
// Purpose:
|
|
// WndProc for hatch window
|
|
//
|
|
// Parameters:
|
|
// hWnd
|
|
// Message
|
|
// wParam
|
|
// lParam
|
|
//
|
|
// Return Value:
|
|
// message dependent
|
|
//***************************************************************************
|
|
LRESULT FAR PASCAL EXPORT BOleHatchWndProc (HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
#ifdef ANSI
|
|
BOleHatchWindow *pHW = (BOleHatchWindow*) ::GetWindowLongA(hWnd, 0);
|
|
#else
|
|
BOleHatchWindow *pHW = (BOleHatchWindow*) ::GetWindowLong(hWnd, 0);
|
|
#endif
|
|
// if pHW is NULL, assign it if WM_NCCREATE otherwise
|
|
// return DefWindowProc
|
|
if (!pHW) {
|
|
if (Message==WM_NCCREATE) {
|
|
#ifdef ANSI
|
|
CREATESTRUCTA FAR* lpcs = (CREATESTRUCTA FAR*)lParam;
|
|
::SetWindowLongA(hWnd, 0, (DWORD)(LPVOID)(lpcs->lpCreateParams));
|
|
#else
|
|
CREATESTRUCT FAR* lpcs = (CREATESTRUCT FAR*)lParam;
|
|
::SetWindowLong(hWnd, 0, (DWORD)(LPVOID)(lpcs->lpCreateParams));
|
|
#endif
|
|
}
|
|
return ::DefWindowProc (hWnd, Message, wParam, lParam);
|
|
}
|
|
|
|
switch (Message) {
|
|
case WM_CREATE:
|
|
#ifdef ANSI
|
|
return pHW->wmCreate((LPCREATESTRUCTA)lParam);
|
|
#else
|
|
return pHW->wmCreate((LPCREATESTRUCT)lParam);
|
|
#endif
|
|
|
|
case WM_PAINT:
|
|
return pHW->wmPaint ();
|
|
|
|
case WM_GETMINMAXINFO:
|
|
return pHW->wmGetMinMaxInfo((MINMAXINFO*)lParam);
|
|
|
|
// The cursor setting strategy here is to catch the WM_NCHITTEST
|
|
// first to figure out which hit-test area the cursor is over.
|
|
// Then Windows calls us back with WM_SETCURSOR so we can make
|
|
// the cursor the correct shape for that hit-test area.
|
|
//
|
|
case WM_NCHITTEST:
|
|
if (pHW) {
|
|
POINT pt;
|
|
pt.x = LOWORD(lParam);
|
|
pt.y = HIWORD(lParam);
|
|
return pHW->wmNCHitTest ((LPPOINT) &pt);
|
|
}
|
|
|
|
// Any window that is used during in-place activation
|
|
// must handle the WM_SETCURSOR message or else the cursor
|
|
// of the in-place parent will be used. if WM_SETCURSOR is
|
|
// not handled, then DefWindowProc sends the message to the
|
|
// window's parent.
|
|
//
|
|
case WM_SETCURSOR:
|
|
return pHW->wmSetCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
return pHW->wmMouseActivate((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
|
|
|
|
// The window move/resize strategy here is:
|
|
// - Keep control so we can allow the OLE2 client app to refuse
|
|
// the new dimensions. Don't wait until the window has already
|
|
// been moved and then move it back.
|
|
// - In order to keep control, we catch the WM_WINDOWPOSCHANGING
|
|
// and set appropriate flags in the WINDOWPOS struct.
|
|
// - Since WM_WINDOWPOSCHANGING is sent for both user-interface
|
|
// initiated actions and for ::MoveWindow-initiated changes, we
|
|
// keep a flag which prevents changes during mousedowns
|
|
//
|
|
case WM_NCLBUTTONDOWN:
|
|
return pHW->wmNCLButtonDown(wParam, (LPPOINT)&lParam);
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
return pHW->wmWindowPosChanging((WINDOWPOS*) lParam);
|
|
|
|
default:
|
|
return ::DefWindowProc (hWnd, Message, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|