pjs/cmd/winfe/cxpane.cpp

1531 строка
47 KiB
C++
Исходник Обычный вид История

1998-03-28 05:44:41 +03:00
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "stdafx.h"
#include "cxpane.h"
#ifdef XP_WIN32
#include "intelli.h"
#endif
#include "navcontv.h"
// What is CPaneCX?
// A pane is part of a complete window.
//
// There is no relation from a pane to the chrome of a full window.
// There is no frame, no document, no view, no toolbar, etc.
// No assumptions should be made, or the pane becomes non-reusable in a
// window that is yet to be invented.
//
// A pane can be put many places:
// In a dialog.
// In a navigation tool.
// In a browser.
// It is up to the place to provide the chrome. It is up to the pane to
// provide the HTML.
#ifdef XP_WIN32
#define STR_CPANECX "CPaneCX"
#else
#define STR_CPANECX_HI "CPaneCXHi"
#define STR_CPANECX_LO "CPaneCXLo"
#endif
CPaneCX::CPaneCX(HWND hPane, BOOL bDestroyOnWMDestroy)
{
MWContext *pContext = GetContext();
m_MM = MM_TEXT;
m_bDestroyOnWMDestroy = bDestroyOnWMDestroy;
m_hPane = NULL;
m_pPrevProc = NULL;
m_hOwnDC = NULL;
m_hClassDC = NULL;
m_hSubstDC = NULL;
m_cxType = Pane;
pContext->type = MWContextPane;
m_pDrawable = NULL;
m_pOffscreenDrawable = NULL;
m_pOnscreenDrawable = NULL;
m_pResizeReloadTimeout = NULL;
m_bDynamicScrollBars = TRUE;
m_bAlwaysShowScrollBars = FALSE;
m_bHScrollBarOn = FALSE;
m_bVScrollBarOn = FALSE;
#ifdef _WIN32
m_iWheelDelta = 0;
#endif
#ifdef XP_WIN16
m_hTextElementSegment = NULL;
m_lpTextElementHeap = NULL;
#endif
// If a pane was passed in, perform the step manually.
SetPane(hPane);
}
CPaneCX::~CPaneCX()
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
SetPane(NULL);
// Destroy the compositor associated with the context
MWContext *pContext = GetContext();
if (pContext && pContext->compositor) {
CL_DestroyCompositor(pContext->compositor);
pContext->compositor = NULL;
}
if(m_pOnscreenDrawable) {
delete m_pOnscreenDrawable;
m_pOnscreenDrawable = NULL;
}
if(m_pOffscreenDrawable) {
delete m_pOffscreenDrawable;
m_pOffscreenDrawable = NULL;
}
m_pDrawable = NULL;
#ifdef XP_WIN16
if(m_hTextElementSegment) {
::GlobalFree(m_hTextElementSegment);
m_hTextElementSegment = NULL;
m_lpTextElementHeap = NULL;
}
#endif
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
// Set current pane for context.
// Can switch panes from one to another (wow).
// Can pass in NULL, which detaches current pane.
HWND CPaneCX::SetPane(HWND hPane)
{
HWND hRetval = GetPane();
if(hRetval) {
// Need to release all cached information.
CacheDCInfo(FALSE);
// Need to unsubclass old window.
BOOL bSub = SubClass(hRetval, FALSE);
ASSERT(bSub);
// Destroy any pending reload.
if(m_pResizeReloadTimeout) {
FE_ClearTimeout(m_pResizeReloadTimeout);
m_pResizeReloadTimeout = NULL;
}
}
m_hPane = hPane;
if(m_hPane) {
// Need to subclass new window.
BOOL bSub = SubClass(m_hPane, TRUE);
ASSERT(bSub);
// Need to gather all cached information.
CacheDCInfo(TRUE);
// Reflect current scroll bar state.
::EnableScrollBar(m_hPane, SB_VERT, ESB_ENABLE_BOTH);
::EnableScrollBar(m_hPane, SB_HORZ, ESB_ENABLE_BOTH);
::SetScrollRange(m_hPane, SB_VERT, 0, SCROLL_UNITS, FALSE);
::SetScrollRange(m_hPane, SB_HORZ, 0, SCROLL_UNITS, FALSE);
::ShowScrollBar(m_hPane, SB_BOTH, FALSE);
ShowScrollBars(SB_HORZ, IsHScrollBarOn());
ShowScrollBars(SB_VERT, IsVScrollBarOn());
}
// Shouldn't have a substituted DC at this point.
ASSERT(m_hSubstDC == NULL);
return(hRetval);
}
void CPaneCX::CacheDCInfo(BOOL bCache)
{
if(bCache) {
// Determine window class name.
char aClassName[128];
memset(aClassName, 0, sizeof(aClassName));
int iLen = GetClassName(GetPane(), aClassName, sizeof(aClassName));
ASSERT(iLen && iLen < sizeof(aClassName));
// Fill in WNDCLASS.
// This needs to be expanded if we ever attempt to take over
// windows outside of our instance.
WNDCLASS PaneClass;
memset(&PaneClass, 0, sizeof(PaneClass));
BOOL bClass = GetClassInfo(AfxGetInstanceHandle(), aClassName, &PaneClass);
ASSERT(bClass);
// OwnDC
if(PaneClass.style & CS_OWNDC) {
SetOwnDC(TRUE);
m_hOwnDC = ::GetDC(GetPane());
}
else if(PaneClass.style & CS_CLASSDC) {
SetClassDC(TRUE);
m_hClassDC = ::GetDC(GetPane());
}
else {
SetOwnDC(FALSE);
SetClassDC(FALSE);
}
}
else {
// Any persistent data needs to go.
ClearFontCache();
// OwnDC
SetOwnDC(FALSE);
m_hOwnDC = NULL;
SetClassDC(FALSE);
m_hClassDC = NULL;
}
}
BOOL CPaneCX::IsOwnDC() const
{
BOOL bRetval = FALSE;
if(m_pDrawable && (m_pDrawable == m_pOffscreenDrawable)) {
bRetval = FALSE;
}
else if(m_hSubstDC) {
// We want substituted DCs to act like OwnDCs
// until unsubstituted.
bRetval = TRUE;
}
else {
bRetval = CDCCX::IsOwnDC();
}
return(bRetval);
}
BOOL CPaneCX::IsClassDC() const
{
BOOL bRetval = FALSE;
if(m_pDrawable && (m_pDrawable == m_pOffscreenDrawable)) {
bRetval = FALSE;
}
else {
bRetval = CDCCX::IsClassDC();
}
return(bRetval);
}
HDC CPaneCX::SubstituteDC(HDC hDC)
{
// Flush cached info for old DC (take away any attributes
// we may have assumed as OwnDC).
// This could be further optimized if the font code
// didn't hold onto the DC for the life of a font.
if(m_hSubstDC) {
ClearFontCache();
}
HDC hRetval = m_hSubstDC;
m_hSubstDC = hDC;
// Set new mapping mode for new DC.
if(m_hSubstDC) {
SetMappingMode(m_hSubstDC);
}
return(hRetval);
}
// Return appropriate HDC
HDC CPaneCX::GetContextDC()
{
HDC hRetval = NULL;
if(m_pDrawable && (m_pDrawable == m_pOffscreenDrawable)) {
hRetval = m_pDrawable->GetDrawableDC();
}
else if(m_hSubstDC) {
hRetval = m_hSubstDC;
}
else if(IsClassDC()) {
hRetval = m_hClassDC;
}
else if(CDCCX::IsOwnDC()) {
hRetval = m_hOwnDC;
}
else if(GetPane()) {
hRetval = ::GetDC(GetPane());
SetMappingMode(hRetval);
}
return(hRetval);
}
// Release appropriate HDC
void CPaneCX::ReleaseContextDC(HDC hDC)
{
if(hDC != m_hSubstDC && IsClassDC() == FALSE && CDCCX::IsOwnDC() == FALSE && (!m_pOffscreenDrawable || hDC != m_pOffscreenDrawable->GetDrawableDC())) {
ASSERT(GetPane());
::ReleaseDC(GetPane(), hDC);
}
}
void CPaneCX::DestroyContext()
{
if(IsDestroyed() == FALSE) {
if(m_pResizeReloadTimeout) {
FE_ClearTimeout(m_pResizeReloadTimeout);
m_pResizeReloadTimeout = NULL;
}
}
CDCCX::DestroyContext();
}
void CPaneCX::Initialize(BOOL bOwnDC, RECT *pRect, BOOL bInitialPalette, BOOL bNewMemDC)
{
#ifndef MOZ_NGLAYOUT
1998-03-28 05:44:41 +03:00
MWContext *pContext = GetContext();
// Top of the document.
m_lOrgX = 0;
m_lOrgY = 0;
// Call base.
CDCCX::Initialize(bOwnDC, pRect, bInitialPalette, bNewMemDC);
// Get the DC.
HDC hDC = GetContextDC();
SetMappingMode(hDC);
// Init compositor.
CL_Drawable *pOnscreenDrawable = NULL;
CL_Drawable *pOffscreenDrawable = NULL;
m_pOnscreenDrawable = new COnscreenDrawable(hDC, this);
pOnscreenDrawable = CL_NewDrawable(
CASTUINT(m_lWidth),
CASTUINT(m_lHeight),
CL_WINDOW,
&wfe_drawable_vtable,
(void *)m_pOnscreenDrawable);
m_pOffscreenDrawable = COffscreenDrawable::AllocateOffscreen(hDC, GetPalette(), this);
pOffscreenDrawable = CL_NewDrawable(
CASTUINT(m_lWidth),
CASTUINT(m_lHeight),
CL_BACKING_STORE,
&wfe_drawable_vtable,
(void *)m_pOffscreenDrawable);
GetContext()->compositor = CL_NewCompositor(
pOnscreenDrawable,
pOffscreenDrawable,
m_lOrgX,
m_lOrgY,
m_lWidth,
m_lHeight,
20);
m_pDrawable = (CDrawable *)m_pOnscreenDrawable;
// If a grid cell, select the palette.
if(IsGridCell() && GetPalette()) {
::SelectPalette(hDC, GetPalette(), FALSE);
int iError = ::RealizePalette(hDC);
}
ReleaseContextDC(hDC);
hDC = NULL;
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
void CPaneCX::SetDrawable(MWContext *pContext, CL_Drawable *pDrawable)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
if(pDrawable) {
CDrawable *pFEDrawable = (CDrawable *)CL_GetDrawableClientData(pDrawable);
m_pDrawable = pFEDrawable;
}
else {
m_pDrawable = m_pOnscreenDrawable;
}
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
FE_Region CPaneCX::GetDrawingClip()
{
if (m_pDrawable) {
return m_pDrawable->GetClip();
}
else {
return NULL;
}
}
void CPaneCX::GetDrawingOrigin(int32 *plOrgX, int32 *plOrgY)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
if(m_pDrawable) {
m_pDrawable->GetOrigin(plOrgX, plOrgY);
}
else {
*plOrgX = *plOrgY = 0;
}
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
void CPaneCX::RefreshArea(int32 lLeft, int32 lTop, uint32 ulWidth, uint32 ulHeight)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
MWContext *pContext = GetContext();
// Simple validation, can pass in 0 for all.
if(ulWidth == 0) {
ulWidth = GetDocumentWidth() - lLeft;
}
if(ulHeight == 0) {
ulHeight = GetDocumentHeight() - lTop;
}
XP_Rect rect;
if(pContext->compositor) {
rect.left = lLeft - m_lOrgX;
rect.top = lTop - m_lOrgY;
rect.right = rect.left + ulWidth;
rect.bottom = rect.top + ulHeight;
CL_RefreshWindowRect(pContext->compositor, &rect);
}
#ifdef DDRAW
LTRB tempRect(rect.left, rect.top, rect.right, rect.bottom);
tempRect.left += GetWindowsXPos();
tempRect.right += GetWindowsXPos();
tempRect.top += GetWindowsYPos();
tempRect.bottom += GetWindowsYPos();
BltToScreen(tempRect, NULL);
#endif
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
// Window handle is about to go away; let go of it.
void CPaneCX::AftWMDestroy(PaneMessage *pMessage)
{
SetPane(NULL);
// If we are supposed to clean up ourselves, do so now.
if(m_bDestroyOnWMDestroy) {
DestroyContext();
}
}
void CPaneCX::PreWMErasebkgnd(PaneMessage *pMessage)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
HDC hEraseDC = (HDC)pMessage->wParam;
HDC hOldSubst = NULL;
if(hEraseDC != m_hClassDC && hEraseDC != m_hOwnDC) {
hOldSubst = SubstituteDC(hEraseDC);
}
// Layers may want to handle erasing of background.
MWContext *pContext = GetContext();
if(pContext->compositor && CL_GetCompositorEnabled(pContext->compositor)) {
pMessage->bSetRetval = TRUE;
pMessage->lRetval = (LPARAM)TRUE;
}
else {
RECT rClip;
::GetClipBox(hEraseDC, &rClip);
pMessage->bSetRetval = TRUE;
pMessage->lRetval = (LPARAM)_EraseBkgnd(hEraseDC, rClip, GetOriginX(), GetOriginY());
}
if(hEraseDC != m_hClassDC && hEraseDC != m_hOwnDC) {
HDC hUnSubst = SubstituteDC(hOldSubst);
// Someone forget to unsubst their DC?
ASSERT(hUnSubst == hEraseDC);
}
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
void CPaneCX::PreWMPaint(PaneMessage *pMessage)
{
pMessage->lRetval = NULL;
pMessage->bSetRetval = TRUE;
// Redirecting output in this fashion not supported yet.
ASSERT((HDC)pMessage->wParam == NULL);
BOOL bBeginPaint = ::GetUpdateRect(GetPane(), NULL, FALSE);
if(bBeginPaint) {
PAINTSTRUCT ps;
HDC hPaintDC = ::BeginPaint(GetPane(), &ps);
uint32 ulWidth = ps.rcPaint.right - ps.rcPaint.left;
uint32 ulHeight = ps.rcPaint.bottom - ps.rcPaint.top;
if(ulWidth && ulHeight) {
HDC hOldSubst = NULL;
if(hPaintDC != m_hClassDC && hPaintDC != m_hOwnDC) {
hOldSubst = SubstituteDC(hPaintDC);
}
RefreshArea(ps.rcPaint.left + GetOriginX(), ps.rcPaint.top + GetOriginY(), ulWidth, ulHeight);
if(hPaintDC != m_hClassDC && hPaintDC != m_hOwnDC) {
HDC hUnSubst = SubstituteDC(hOldSubst);
// Someone forget to unsubst their DC?
ASSERT(hUnSubst == hPaintDC);
}
}
::EndPaint(GetPane(), &ps);
}
else {
// No update area.
// Possible internal draw request (see RedrawWindow).
// Not supported until needed.
ASSERT(0);
}
}
void CPaneCX::AftWMSize(PaneMessage *pMessage)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
UINT uSizeType = (UINT)pMessage->wParam;
int iWidth = LOWORD(pMessage->lParam);
int iHeight = HIWORD(pMessage->lParam);
// Only care if resized visibly.
if(uSizeType == SIZE_MAXIMIZED || uSizeType == SIZE_RESTORED) {
BOOL bNiceReload = TRUE;
// Let frame contexts decide on their own if they would like to reload.
if(IsFrameContext()) {
bNiceReload = FALSE;
}
int iNewWidth = iWidth;
if(IsVScrollBarOn()) {
iNewWidth += sysInfo.m_iScrollWidth;
}
int iNewHeight = iHeight;
if(IsHScrollBarOn()) {
iNewHeight += sysInfo.m_iScrollHeight;
}
/* Resize the compositor's notion of the window area
* as well as the size of the background layer. This
* might all be moot, because we might relayout, but
* that doesn't happen all the time (e.g. HTML dialogs).
* We want the composited area - without the scrollbars
*/
MWContext *pContext = GetContext();
if (pContext->compositor) {
CL_Layer *bglayer, *doclayer;
CL_Compositor *compositor = pContext->compositor;
CL_ResizeCompositorWindow(compositor, iNewWidth, iNewHeight);
doclayer = CL_GetCompositorRoot(compositor);
if (doclayer) {
bglayer = CL_GetLayerChildByName(doclayer, LO_BACKGROUND_LAYER_NAME);
if (bglayer) {
XP_Rect bbox;
int32 layerWidth, layerHeight;
/* Make sure that the new dimensions are larger than the */
/* original ones before resizing the layer. We still want */
/* the layer size to be the maximum of the window and the */
/* document dimensions. */
CL_GetLayerBbox(bglayer, &bbox);
layerWidth = bbox.right - bbox.left;
layerHeight = bbox.bottom - bbox.top;
if (iNewWidth > layerWidth)
layerWidth = iNewWidth;
if (iNewHeight > layerHeight)
layerHeight = iNewHeight;
CL_ResizeLayer(bglayer, layerWidth, layerHeight);
}
}
}
m_lWidth = (int32)iNewWidth;
m_lHeight = (int32)iNewHeight;
// If we've resized bigger than the page,
// and we are scrolled, reset our position.
if((m_lDocWidth > 0) && (m_lDocWidth < m_lWidth) && (m_lOrgX != 0)) {
m_lOrgX = 0;
}
if((m_lDocHeight > 0) &&(m_lDocHeight < m_lHeight) && (m_lOrgY != 0)) {
m_lOrgY = 0;
}
RealizeScrollBars();
if(bNiceReload) {
#ifdef RELAYOUT_WITHOUT_RELOAD
LO_RelayoutOnResize(GetDocumentContext(), m_lWidth, m_lHeight, m_lLeftMargin, m_lTopMargin);
#else
NiceResizeReload();
#endif
}
}
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
static void resize_reload_timeout(void *closure)
{
CPaneCX *cw = VOID2CX(closure, CPaneCX);
cw->m_pResizeReloadTimeout = NULL;
cw->NiceReload();
}
// Wait to do the reload for just a wee bit.
void CPaneCX::NiceResizeReload()
{
// If there was already a resize timeout that hasn't fired, cancel it,
// since that means resize messages are still arriving close together
if(m_pResizeReloadTimeout) {
FE_ClearTimeout(m_pResizeReloadTimeout);
m_pResizeReloadTimeout = NULL;
}
// Can't reload anything
if(!CanCreateUrlFromHist()) {
return;
}
m_pResizeReloadTimeout = FE_SetTimeout(resize_reload_timeout, this, 200);
}
int CPaneCX::GetUrl(URL_Struct *pUrl, FO_Present_Types iFormatOut, BOOL bReallyLoading, BOOL bForceNew)
{
// Stop any reload timers, no need.
if(m_pResizeReloadTimeout) {
FE_ClearTimeout(m_pResizeReloadTimeout);
m_pResizeReloadTimeout = NULL;
}
return(CDCCX::GetUrl(pUrl, iFormatOut, bReallyLoading, bForceNew));
}
void CPaneCX::LayoutNewDocument(MWContext *pContext, URL_Struct *pURL, int32 *pWidth, int32 *pHeight, int32 *pmWidth, int32 *pmHeight)
{
m_lOrgY = 0;
m_lOrgX = 0;
// Stop any reload timers, no need.
if(m_pResizeReloadTimeout) {
FE_ClearTimeout(m_pResizeReloadTimeout);
m_pResizeReloadTimeout = NULL;
}
// Call the base.
CDCCX::LayoutNewDocument(pContext, pURL, pWidth, pHeight, pmWidth, pmHeight);
// Initialize Scrollbars for new document.
ShowScrollBars(SB_BOTH, FALSE);
m_nPageY = SCROLL_UNITS;
m_nPageX = SCROLL_UNITS;
#ifdef XP_WIN32
SCROLLINFO siY;
siY.cbSize = sizeof(SCROLLINFO);
siY.fMask = SIF_PAGE;
siY.nPage = 0;
if(GetPane() && IsVScrollBarOn() == TRUE) {
::SetScrollInfo(GetPane(), SB_VERT, &siY, FALSE);
}
SCROLLINFO siX;
siX.cbSize = sizeof(SCROLLINFO);
siX.fMask = SIF_PAGE;
siX.nPage = 0;
if(GetPane() && IsHScrollBarOn() == TRUE) {
::SetScrollInfo(GetPane(), SB_HORZ, &siX, FALSE);
}
#endif
if(*pmWidth || *pmHeight) {
// Layout wants to set these.
m_lLeftMargin = *pmWidth;
m_lTopMargin = *pmHeight;
m_lRightMargin = -1 * *pmWidth;
m_lBottomMargin = -1 * *pmHeight;
}
else {
// Set these to the old defaults which I'll never understand.
m_lLeftMargin = LEFT_MARGIN;
m_lTopMargin = TOP_MARGIN;
m_lRightMargin = RIGHT_MARGIN;
m_lBottomMargin = BOTTOM_MARGIN;
}
*pmWidth = m_lLeftMargin;
*pmHeight = m_lTopMargin;
// When we report the size to layout, we must always take care to subtract
// for the size of the scrollbars if we have dynamic or always on
// scrollers.
if(DynamicScrollBars() == FALSE && IsHScrollBarOn() == FALSE && IsVScrollBarOn() == FALSE) {
*pWidth = GetWidth();
*pHeight = GetHeight();
}
else {
*pWidth = GetWidth() - sysInfo.m_iScrollWidth;
*pHeight = GetHeight() - sysInfo.m_iScrollHeight;
}
}
void CPaneCX::FinishedLayout(MWContext *pContext)
{
CDCCX::FinishedLayout(pContext);
// Have the scroll bars correctly set themselves.
RealizeScrollBars();
}
void CPaneCX::ShowScrollBars(int iBars, BOOL bShow) {
// Don't do this if we don't have a view.
if(GetPane() != NULL) {
// Turning them off or on?
if(bShow == FALSE) {
// Decide which set of scrollers, if any, that we need to take
// action on, and take that action.
if(iBars == SB_BOTH) {
m_bVScrollBarOn = FALSE;
m_bHScrollBarOn = FALSE;
::ShowScrollBar(GetPane(), SB_BOTH, FALSE);
}
else if((iBars == SB_VERT) && IsVScrollBarOn()) {
m_bVScrollBarOn = FALSE;
::ShowScrollBar(GetPane(), SB_VERT, FALSE);
}
else if((iBars == SB_HORZ) && IsHScrollBarOn()) {
m_bHScrollBarOn = FALSE;
::ShowScrollBar(GetPane(), SB_HORZ, FALSE);
}
}
else {
// Decide which set of scrollers, if any, that we need to take
// action on, and take that action.
if(iBars == SB_BOTH) {
m_bVScrollBarOn = TRUE;
m_bHScrollBarOn = TRUE;
::ShowScrollBar(GetPane(), SB_BOTH, TRUE);
}
else if((iBars == SB_VERT) && !IsVScrollBarOn()) {
m_bVScrollBarOn = TRUE;
::ShowScrollBar(GetPane(), SB_VERT, TRUE);
}
else if((iBars == SB_HORZ) && !IsHScrollBarOn()) {
m_bHScrollBarOn = TRUE;
::ShowScrollBar(GetPane(), SB_HORZ, TRUE);
}
}
// We have just shown/hidden a scroll bar.
// Update the window to avoid flash (reduces overall invalidated
// rectangle, except when we show/hide both at the same time).
::UpdateWindow(GetPane());
}
}
void CPaneCX::RealizeScrollBars(int32 *pX, int32 *pY)
{
#ifdef MOZ_NGLAYOUT
XP_ASSERT(0);
#else
1998-03-28 05:44:41 +03:00
if(m_lDocHeight && m_lDocWidth) {
if(AlwaysShowScrollBars()) {
ShowScrollBars(SB_BOTH, TRUE);
}
// Are we checking for dynamic scroll bars?
if(DynamicScrollBars() == TRUE) {
// If the document fits in our client area, or if we have children, turn them off.
// If the document is larger than our client area, turn them on.
int iSB = -1;
BOOL bShow = FALSE;
BOOL vScrollBar = FALSE;
BOOL hScrollBar = FALSE;
if (m_lHeight >= m_lDocHeight && m_lWidth >= m_lDocWidth && (IsVScrollBarOn() == TRUE || IsHScrollBarOn() == TRUE)) {
ShowScrollBars(SB_BOTH, FALSE);
}
else if(m_lHeight < m_lDocHeight && m_lWidth < m_lDocWidth && (IsVScrollBarOn() == FALSE || IsHScrollBarOn() == FALSE)) {
ShowScrollBars(SB_BOTH, TRUE);
}
else {
if(m_lHeight >= m_lDocHeight && IsVScrollBarOn() == TRUE) {
ShowScrollBars(SB_VERT, FALSE);
}
else if(m_lHeight < m_lDocHeight && IsVScrollBarOn() == FALSE) {
ShowScrollBars(SB_VERT, TRUE);
}
if(m_lWidth >= m_lDocWidth && IsHScrollBarOn() == TRUE) {
ShowScrollBars(SB_HORZ, FALSE);
}
else if(m_lWidth < m_lDocWidth && IsHScrollBarOn() == FALSE) {
ShowScrollBars(SB_HORZ, TRUE);
}
}
}
// See if we're going to be changing the values.
BOOL bRefreshHorz = FALSE;
BOOL bRefreshVert = FALSE;
if(pX != NULL && m_lOrgX != *pX) {
m_lOrgX = *pX;
bRefreshHorz = TRUE;
}
if(pY != NULL && m_lOrgY != *pY) {
m_lOrgY = *pY;
bRefreshVert = TRUE;
}
// Make sure that the current origins are within the document iWidth
// and iHeight.
// In the event that they are exactly the same, make sure to refresh
// the scroll bar anyhow (this will happen if you scroll to the
// bottom of a page, go to a new page, and then go back; your scroll
// bars are wrong).
int32 lCalcHeight = m_lDocHeight - m_lHeight + (IsHScrollBarOn() ? sysInfo.m_iScrollHeight : 0);
if(m_lOrgY >= lCalcHeight && lCalcHeight > 0) {
m_lOrgY = lCalcHeight; // always show one screen
bRefreshVert = TRUE;
}
int32 lCalcWidth = m_lDocWidth - m_lWidth + (IsVScrollBarOn() ? sysInfo.m_iScrollWidth : 0);
if(m_lOrgX >= lCalcWidth && lCalcWidth > 0) {
m_lOrgX = lCalcWidth; // always leave some visible
bRefreshHorz = TRUE;
}
#ifdef XP_WIN32
// Special fun for proportional scrollbars.
SCROLLINFO siY;
siY.cbSize = sizeof(SCROLLINFO);
siY.fMask = SIF_PAGE;
// If the document is longer than a single page
if(m_lDocHeight > m_lHeight && IsVScrollBarOn() == TRUE) {
siY.nPage = m_lHeight * SCROLL_UNITS / m_lDocHeight;
if(GetPane()) {
::SetScrollInfo(GetPane(), SB_VERT, &siY, FALSE);
if((UINT)m_nPageY != SCROLL_UNITS - siY.nPage) {
m_nPageY = SCROLL_UNITS - siY.nPage;
bRefreshVert = TRUE;
}
} else
bRefreshVert = TRUE;
}
else if(IsVScrollBarOn() == TRUE) {
siY.nPage = SCROLL_UNITS;
if(GetPane()) {
::SetScrollInfo(GetPane(), SB_VERT, &siY, FALSE);
m_nPageY = SCROLL_UNITS;
}
}
SCROLLINFO siX;
siX.cbSize = sizeof(SCROLLINFO);
siX.fMask = SIF_PAGE;
// If the document is wider than a single screen
if((m_lDocWidth != 0) && (m_lDocWidth > m_lWidth) && IsHScrollBarOn() == TRUE) {
siX.nPage = m_lWidth * SCROLL_UNITS / m_lDocWidth;
if(GetPane()) {
::SetScrollInfo(GetPane(), SB_HORZ, &siX, FALSE);
if((UINT)m_nPageX != SCROLL_UNITS - siX.nPage) {
m_nPageX = SCROLL_UNITS - siX.nPage;
bRefreshHorz = TRUE;
}
} else
bRefreshHorz = TRUE;
}
else if(IsHScrollBarOn() == TRUE) {
siX.nPage = SCROLL_UNITS;
if(GetPane()) {
::SetScrollInfo(GetPane(), SB_HORZ, &siX, FALSE);
m_nPageX = SCROLL_UNITS;
}
}
#endif
// Figure the thumb position.
float fYPos = 0.0f;
float fXPos = 0.0f;
if(m_lDocHeight != 0) {
long lScrollHeight = m_lDocHeight - m_lHeight;
if(lScrollHeight != 0)
fYPos = (float)m_lOrgY / (float) lScrollHeight;
else
fYPos = 1.0f;
}
if(m_lDocWidth != 0) {
long lScrollWidth = m_lDocWidth - m_lWidth;
if(lScrollWidth != 0)
fXPos = (float)m_lOrgX / (float) lScrollWidth;
else
fXPos = 1.0f;
}
// See if we should turn off the scroll bars.
if(m_lDocWidth <= m_lWidth && IsHScrollBarOn() == TRUE && GetPane()) {
::EnableScrollBar(GetPane(), SB_HORZ, ESB_DISABLE_BOTH);
}
else if(IsHScrollBarOn() == TRUE && GetPane()) {
::EnableScrollBar(GetPane(), SB_HORZ, ESB_ENABLE_BOTH);
// only reset if different to avoid flashing on NT and Win16
int iNewPosX = (int) (fXPos * m_nPageX);
if(iNewPosX != ::GetScrollPos(GetPane(), SB_HORZ) || bRefreshHorz == TRUE) {
::SetScrollPos(GetPane(), SB_HORZ, iNewPosX, TRUE);
}
}
if(m_lDocHeight <= m_lHeight && IsVScrollBarOn() == TRUE && GetPane()) {
::EnableScrollBar(GetPane(), SB_VERT, ESB_DISABLE_BOTH);
}
else if(IsVScrollBarOn() == TRUE && GetPane()) {
::EnableScrollBar(GetPane(), SB_VERT, ESB_ENABLE_BOTH);
// only reset if different to avoid flashing on NT and Win16
int iNewPosY = (int) (fYPos * m_nPageY);
if(iNewPosY != ::GetScrollPos(GetPane(), SB_VERT) || bRefreshVert == TRUE) {
::SetScrollPos(GetPane(), SB_VERT, iNewPosY, TRUE);
}
}
MWContext *pContext = GetContext();
if(pContext->compositor) {
CL_ScrollCompositorWindow(pContext->compositor, m_lOrgX, m_lOrgY);
}
}
#endif /* MOZ_NGLAYOUT */
1998-03-28 05:44:41 +03:00
}
void CPaneCX::SetDocDimension(MWContext *pContext, int iLocation, int32 lWidth, int32 lLength) {
// Call the base.
CDCCX::SetDocDimension(pContext, iLocation, lWidth, lLength);
RealizeScrollBars();
}
void CPaneCX::PreWMVScroll(PaneMessage *pMsg)
{
#ifdef XP_WIN16
UINT uSBCode = (UINT)pMsg->wParam;
UINT uPos = LOWORD(pMsg->lParam);
HWND hwndCtrl = (HWND)HIWORD(pMsg->lParam);
#else
UINT uSBCode = LOWORD(pMsg->wParam);
UINT uPos = HIWORD(pMsg->wParam);
HWND hwndCtrl = (HWND)pMsg->lParam;
#endif
Scroll(SB_VERT, uSBCode, uPos, hwndCtrl);
pMsg->lRetval = NULL;
pMsg->bSetRetval = TRUE;
}
void CPaneCX::PreWMHScroll(PaneMessage *pMsg)
{
#ifdef XP_WIN16
UINT uSBCode = (UINT)pMsg->wParam;
UINT uPos = LOWORD(pMsg->lParam);
HWND hwndCtrl = (HWND)HIWORD(pMsg->lParam);
#else
UINT uSBCode = LOWORD(pMsg->wParam);
UINT uPos = HIWORD(pMsg->wParam);
HWND hwndCtrl = (HWND)pMsg->lParam;
#endif
Scroll(SB_HORZ, uSBCode, uPos, hwndCtrl);
pMsg->lRetval = NULL;
pMsg->bSetRetval = TRUE;
}
void CPaneCX::AftWMMouseActivate(PaneMessage *pMsg)
{
BOOL bSetFocus = FALSE;
if(pMsg->bSetRetval) {
// Check to see if we need to activate.
if(pMsg->lRetval == MA_ACTIVATE || pMsg->lRetval == MA_ACTIVATEANDEAT) {
bSetFocus = TRUE;
}
}
else {
// Real class didn't handle, take some action.
pMsg->bSetRetval = TRUE;
pMsg->lRetval = MA_ACTIVATE;
bSetFocus = TRUE;
}
if(bSetFocus) {
if(::GetFocus() != GetPane()) {
::SetFocus(GetPane());
}
}
}
#if defined(XP_WIN32) && _MSC_VER >= 1100
void CPaneCX::PreWMMouseWheel(PaneMessage *pMsg)
{
// Increase the delta.
m_iWheelDelta += MOUSEWHEEL_DELTA(pMsg->wParam, pMsg->lParam);
// Number of lines to scroll.
UINT uScroll = intelli.ScrollLines();
// Direction.
BOOL bForward = TRUE;
if(m_iWheelDelta < 0) {
bForward = FALSE;
}
// Scroll bar code to use.
UINT uSBCode = SB_LINEUP;
if(m_iWheelDelta / WHEEL_DELTA) {
if(uScroll == WHEEL_PAGESCROLL) {
if(bForward) {
uSBCode = SB_PAGEUP;
}
else {
uSBCode = SB_PAGEDOWN;
}
uScroll = 1;
}
else {
if(bForward) {
uSBCode = SB_LINEUP;
}
else {
uSBCode = SB_LINEDOWN;
}
}
// Take off scroll increment.
UINT uLoops = 0;
while(m_iWheelDelta / WHEEL_DELTA) {
if(bForward) {
m_iWheelDelta -= WHEEL_DELTA;
}
else {
m_iWheelDelta += WHEEL_DELTA;
}
uLoops++;
}
// Do it.
if(uLoops) {
Scroll(SB_VERT, uSBCode, 0, NULL, uScroll * uLoops);
}
}
pMsg->lRetval = (LPARAM)1;
pMsg->bSetRetval = TRUE;
}
void CPaneCX::PreWMHackedMouseWheel(PaneMessage *pMsg)
{
// Shunt.
WPARAM wSubst = pMsg->wParam;
pMsg->wParam = wSubst << 16;
PreWMMouseWheel(pMsg);
pMsg->wParam = wSubst;
}
#endif
void CPaneCX::Scroll(int iBars, UINT uSBCode, UINT uPos, HWND hCtrl, UINT uTimes)
{
// Provide a way to keep flow of control but not return early.
BOOL bContinue = TRUE;
if((iBars == SB_VERT || iBars == SB_BOTH) && IsVScrollBarOn() && GetHeight() < GetDocumentHeight()) {
// Calc an area leaving at least one page.
// Align the pixel and twips boundary, and check again to see if we're really
// doing anything.
// Account for Horiz scroll bar getting in the way.
int32 lScrollable = GetDocumentHeight() - GetHeight();
if(IsHScrollBarOn()) {
lScrollable += sysInfo.m_iScrollHeight;
}
if(lScrollable > 0) {
int32 lOldOrgY = GetOriginY();
int32 lScrollTwips = 0;
double fYPos = 0.0f;
int32 lTrack = 0;
// Figure out what we're doing.
switch(uSBCode) {
case SB_PAGEUP:
lScrollTwips = (-1 * GetHeight()) + VSCROLL_LINE;
break;
case SB_PAGEDOWN:
lScrollTwips = GetHeight() - VSCROLL_LINE;
break;
case SB_LINEUP:
lScrollTwips = -1 * VSCROLL_LINE;
break;
case SB_LINEDOWN:
lScrollTwips = VSCROLL_LINE;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
// User is dragging the thumb tack.
// Only move if we've moved more than a single pixel, or the display
// gets messed up
fYPos = (double)uPos / (double)GetPageY();
lTrack = (int32)((fYPos * lScrollable)+0.5);
break;
case SB_TOP:
lScrollTwips = -1 * GetOriginY();
break;
case SB_BOTTOM:
lScrollTwips = lScrollable - GetOriginY();
break;
default:
bContinue = FALSE;
break;
}
if(bContinue) {
// Check to see if we need to do further math....
if(uSBCode != SB_THUMBPOSITION && uSBCode != SB_THUMBTRACK) {
lTrack = GetOriginY();
lTrack += lScrollTwips * (int32)uTimes;
if (lTrack < 0)
lTrack = 0;
else if(lTrack > lScrollable)
lTrack = lScrollable;
}
// Position the scroll bar on an even pixel boundary
RealizeScrollBars(NULL, &lTrack);
// Figure the distance we actually scrolled.
int32 lPixAct = lOldOrgY - GetOriginY();
if(lPixAct) {
::ScrollWindowEx(GetPane(), 0, (int) lPixAct, NULL, NULL, NULL, NULL, SW_INVALIDATE |
SW_ERASE | SW_SCROLLCHILDREN);
::UpdateWindow(GetPane());
}
}
}
}
// Reset for horizontal test.
bContinue = TRUE;
if((iBars == SB_HORZ || iBars == SB_BOTH) && IsHScrollBarOn() && GetWidth() < GetDocumentWidth()) {
// Calc an area leaving at least one page.
// Align the pixel and twips boundary, and check again to see if we're really
// doing anything.
// Account for vertical scroller getting in the way.
int32 lScrollable = GetDocumentWidth() - GetWidth();
if(IsVScrollBarOn()) {
lScrollable += sysInfo.m_iScrollWidth;
}
if(lScrollable > 0) {
int32 lOldOrgX = GetOriginX();
int32 lScrollTwips = 0;
double fXPos = 0.0f;
int32 lTrack = 0;
// Figure out what we're doing.
switch(uSBCode) {
case SB_PAGELEFT:
lScrollTwips = -1 * GetWidth();
break;
case SB_PAGERIGHT:
lScrollTwips = GetWidth();
break;
case SB_LINELEFT:
case SB_LINERIGHT:
lScrollTwips = HSCROLL_LINE;
if(uSBCode == SB_LINELEFT) {
lScrollTwips *= -1;
}
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
// User is dragging the thumb tack.
// Only move if we've moved more than a single pixel, or the display
// gets messed up.
fXPos = (double)uPos / (double)GetPageX();
lTrack = (int32)((fXPos * lScrollable)+0.5);
break;
default:
bContinue = FALSE;
break;
}
if(bContinue) {
// Check to see if we need to do further math....
if(uSBCode != SB_THUMBPOSITION && uSBCode != SB_THUMBTRACK) {
lTrack = GetOriginX();
lTrack += lScrollTwips * (int32)uTimes;
if(lTrack > lScrollable)
lTrack = lScrollable;
if(lTrack < 0)
lTrack = 0;
}
// Position the scroll bar.
RealizeScrollBars(&lTrack);
// Figure the distance we actually scrolled.
int32 lPixAct = lOldOrgX - GetOriginX();
if(lPixAct) {
::ScrollWindowEx(GetPane(), (int) lPixAct, 0, NULL, NULL, NULL, NULL, SW_INVALIDATE |
SW_ERASE | SW_SCROLLCHILDREN);
::UpdateWindow(GetPane());
}
}
}
}
}
void CPaneCX::GetWindowOffset(int32 *pX, int32 *pY)
{
RECT rWindow;
::GetWindowRect(GetPane(), &rWindow);
*pX = rWindow.left;
*pY = rWindow.top;
return;
}
void CPaneCX::MakeElementVisible(int32 lX, int32 lY)
{
// Figure out if any element is there.
XY Point;
Point.x = lX;
Point.y = lY;
LO_Element *pElement = GetLayoutElement(Point, NULL);
if(pElement == NULL) {
SetDocPosition(GetContext(), FE_VIEW, lX, lY);
return;
}
// Figure up the coords of the element.
LTRB Rect;
LO_Any *pAny = &(pElement->lo_any);
Rect.left = pAny->x + pAny->x_offset;
Rect.top = pAny->y + pAny->y_offset;
Rect.right = Rect.left + pAny->width;
Rect.bottom = Rect.top + pAny->height;
// Is it currently Fully On Screen?
// Disregard the Y values (we'll want to scroll exactly on the Y, but perhaps not on the X).
// To the right?
if(Rect.left >= GetOriginX()) {
// To the left?
if(Rect.right <= GetOriginX() + GetWidth()) {
// It's on the X view.
// Use the current X origin.
lX = GetOriginX();
SetDocPosition(GetContext(), FE_VIEW, lX, lY);
return;
}
}
// X wasn't on screen fully, so we're going to use very exact values when scrolling
// for whatever effect this gives....
SetDocPosition(GetContext(), FE_VIEW, lX, lY);
}
void CPaneCX::PreNavCenterQueryPosition(PaneMessage *pMessage)
{
// Only handle if we're a NavCenter HTML Pane.
if(IsNavCenterHTMLPane()) {
NAVCENTPOS *pPos = (NAVCENTPOS *)pMessage->lParam;
// We like being at the bottom.
pPos->m_iYDisposition = INT_MAX;
// We like being this many units in size.
pPos->m_iYVector = 100;
// Handled.
pMessage->lRetval = NULL;
pMessage->bSetRetval = TRUE;
}
}
void CPaneCX::PreIdleUpdateCmdUI(PaneMessage *pMsg)
{
// Don't want to update CMD UI unless we have a frame parent.
// This effectively stops CMD UI in the NavCenter HTML pane
// from messing with the UI state when docked.
if(IsNavCenterHTMLPane()) {
// Handled.
pMsg->lRetval = NULL;
pMsg->bSetRetval = TRUE;
}
}
#ifdef XP_WIN16
HINSTANCE CPaneCX::GetSegment()
{
// Form elements on a per context basis receive their own segment.
HINSTANCE hRetval = NULL;
if(NULL == m_hTextElementSegment) {
m_hTextElementSegment = ::GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, (UINT) 8 * 1024);
}
if(m_hTextElementSegment && NULL == m_lpTextElementHeap) {
// Initialize the segment.
m_lpTextElementHeap = ::GlobalLock(m_hTextElementSegment);
if(m_lpTextElementHeap) {
::LocalInit(HIWORD((LONG)m_lpTextElementHeap), 0, (WORD)(::GlobalSize(m_hTextElementSegment) - 16));
::UnlockSegment(HIWORD((LONG)m_lpTextElementHeap));
}
}
if(m_lpTextElementHeap) {
hRetval = (HINSTANCE)HIWORD((LONG)m_lpTextElementHeap);
}
return(hRetval);
}
#endif
LRESULT
CALLBACK
#ifndef _WIN32
_export
#endif
PaneProc(HWND hPane, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
#ifdef XP_WIN32
const char *pPropName = STR_CPANECX; // Not a UI string.
#else
const char *pPropNameHi = STR_CPANECX_HI;
const char *pPropNameLo = STR_CPANECX_LO;
#endif
PaneMessage message(wParam, lParam);
// Get the property (which is a this pointer).
void *pvThis = NULL;
#ifdef XP_WIN32
pvThis = (void *)GetProp(hPane, pPropName);
#else
pvThis = (void *)MAKELONG(GetProp(hPane, pPropNameLo), GetProp(hPane, pPropNameHi));
#endif
if(pvThis) {
CPaneCX *pThis = VOID2CX(pvThis, CPaneCX);
// Messages handled BEFORE calling other window procedure.
// Make calls here when you don't care about the LRESULT
// of the normal message handler or don't want the normal
// message handler being called at all (by marking that
// the return value has been set).
switch(uMsg) {
case WM_PAINT:
pThis->PreWMPaint(&message);
break;
case WM_ERASEBKGND:
pThis->PreWMErasebkgnd(&message);
break;
case WM_VSCROLL:
pThis->PreWMVScroll(&message);
break;
case WM_HSCROLL:
pThis->PreWMHScroll(&message);
break;
case WM_NAVCENTER_QUERYPOSITION:
pThis->PreNavCenterQueryPosition(&message);
break;
case WM_IDLEUPDATECMDUI:
pThis->PreIdleUpdateCmdUI(&message);
break;
#if defined(XP_WIN32) && _MSC_VER >= 1100
case WM_MOUSEWHEEL:
pThis->PreWMMouseWheel(&message);
break;
#endif
default:
// Handle non constant messages here.
#if defined(XP_WIN32) && _MSC_VER >= 1100
if(uMsg == msg_MouseWheel) {
pThis->PreWMHackedMouseWheel(&message);
}
#endif
break;
}
// Call previous window proc.
if(!message.bSetRetval) {
WNDPROC pPrevProc = pThis->GetSubclassedProc();
if(pPrevProc) {
message.lRetval = CallWindowProc(pPrevProc, hPane, uMsg, wParam, lParam);
message.bSetRetval = TRUE;
}
}
// Notifications handled AFTER calling other window procedure.
// Make calls here when you care about the LRESULT
// of any above message handler, or want to handle a
// message if no one else did before the default window
// procedure is invoked..
switch(uMsg) {
case WM_SIZE:
pThis->AftWMSize(&message);
break;
case WM_DESTROY:
pThis->AftWMDestroy(&message);
break;
case WM_MOUSEACTIVATE:
pThis->AftWMMouseActivate(&message);
break;
default:
break;
}
// Default handler if nothing happened.
if(!message.bSetRetval) {
message.lRetval = DefWindowProc(hPane, uMsg, wParam, lParam);
message.bSetRetval = TRUE;
}
}
else {
// Either someone subclassed and we need to unsubclass in
// their stack, or this is getting called before we
// set the property on the window.
// Don't crash or do anything stupid, but we currently don't
// attempt to handle.
message.lRetval = DefWindowProc(hPane, uMsg, wParam, lParam);
message.bSetRetval = TRUE;
}
ASSERT(message.bSetRetval);
return(message.lRetval);
}
// Subclass or unsubclass a window.
BOOL CPaneCX::SubClass(HWND hWnd, BOOL bSubClass)
{
#ifdef MOZ_NGLAYOUT
// We want all events to go to the WebWidget window embedded in this
// one and not here at all.
return TRUE;
#else
1998-03-28 05:44:41 +03:00
BOOL bRetval = FALSE;
#ifdef XP_WIN32
const char *pPropName = STR_CPANECX; // Not a UI string.
#else
const char *pPropNameHi = STR_CPANECX_HI; // Not a UI string.
const char *pPropNameLo = STR_CPANECX_LO; // Not a UI string.
#endif
if(hWnd) {
if(bSubClass) {
ASSERT(!m_pPrevProc);
// Make sure no one else is already doing this window.
// We could add the support by making each property
// name unique by pid() then ptr, but no need right now.
if(!
#ifdef XP_WIN32
(::GetProp(hWnd, pPropName))
#else
(::GetProp(hWnd, pPropNameLo) || ::GetProp(hWnd, pPropNameHi))
#endif
) {
m_pPrevProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)PaneProc);
if(m_pPrevProc) {
BOOL bAddProp;
#ifdef XP_WIN32
bAddProp = ::SetProp(hWnd, pPropName, (HANDLE)this);
#else
bAddProp = ::SetProp(hWnd, pPropNameHi, (HANDLE)HIWORD(this));
if(bAddProp) {
bAddProp = ::SetProp(hWnd, pPropNameLo, (HANDLE)LOWORD(this));
}
#endif
if(bAddProp) {
bRetval = TRUE;
}
else {
LONG lCheck = ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)m_pPrevProc);
m_pPrevProc = NULL;
ASSERT(lCheck == (LONG)PaneProc);
}
}
}
}
else {
ASSERT(m_pPrevProc);
void *pThis = NULL;
#ifdef XP_WIN32
pThis = (void *)::RemoveProp(hWnd, pPropName);
#else
pThis = (void *)MAKELONG(::RemoveProp(hWnd, pPropNameLo), ::RemoveProp(hWnd, pPropNameHi));
#endif
ASSERT(pThis && pThis == (void *)this);
if(pThis && pThis == (void *)this) {
LONG lOurProc = ::GetWindowLong(hWnd, GWL_WNDPROC);
ASSERT(lOurProc && lOurProc == (LONG)PaneProc);
if(lOurProc && lOurProc == (LONG)PaneProc) {
LONG lCheck = ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)m_pPrevProc);
ASSERT(lCheck && lCheck == (LONG)PaneProc);
if(lCheck && lCheck == (LONG)PaneProc) {
bRetval = TRUE;
}
}
m_pPrevProc = NULL;
}
}
}
return(bRetval);
#endif
1998-03-28 05:44:41 +03:00
}