gecko-dev/cmd/winfe/statbar.cpp
hyatt%netscape.com 29ad2836fa Improvements to the control strip on the nav bar. Fix for the status bar bug
where the status bar isn't taking over the whole area at the bottom like it
should.
1998-08-04 08:25:37 +00:00

1241 lines
33 KiB
C++
Executable File

/* -*- 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.
*/
///
//
// STATBAR.CPP
//
// DESCRIPTION:
// This file contains the implementation of the CNetscapeStatusBar
// class.
//
// CREATED: 03/01/96, 12:18:16 AUTHOR: Scott Jones
//
///
/** INCLUDE **/
#include "stdafx.h"
#include "rosetta.h"
#include "statbar.h"
#include "ssl.h"
#include "tooltip.h"
#include "secnav.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
#ifndef DYNAMIC_DOWNCAST
#define DYNAMIC_DOWNCAST( classname, ptr ) (classname *)(ptr)
#endif
//------------------------------------------------------------------------------
// CONSTANTS
static const int nSEC_KEY_WIDTH = 34;
#ifdef _WIN32
static const char szNSStatusProp[] = "NSStatusProp";
#else
static const char szNSStatusProp1[] = "NSStatusProp1";
static const char szNSStatusProp2[] = "NSStatusProp2";
#endif
#define IDT_PULSE 1966 // Pulsing vapor trails timer id
#define PULSE_INTERVAL 100 // Pulse interval for timer (ms)
#define IDT_STATBARMONITOR 1968
#define MONITOR_INTERVAL 50
// status bar format
static const UINT BASED_CODE pPaneIndicators[] =
{
HG21326
IDS_TRANSFER_STATUS,
ID_SEPARATOR
#ifdef MOZ_OFFLINE
,IDS_ONLINE_STATUS
#endif //MOZ_OFFLINE
#ifdef MOZ_TASKBAR
,IDS_TASKBAR
#endif /* MOZ_TASKBAR */
};
static const UINT BASED_CODE pSimpleIndicators[] =
{
ID_SEPARATOR
};
BEGIN_MESSAGE_MAP(CNetscapeStatusBar, CNetscapeStatusBarBase)
//{{AFX_MSG_MAP(CNetscapeStatusBar)
ON_WM_PAINT()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
HBITMAP CNetscapeStatusBar::sm_hbmpSecure = NULL;
SIZE CNetscapeStatusBar::sm_sizeSecure = {0,0};
int CNetscapeStatusBar::sm_iRefCount = 0;
#ifdef MOZ_OFFLINE
HBITMAP CNetscapeStatusBar::sm_hbmpOnline = NULL;
SIZE CNetscapeStatusBar::sm_sizeOnline = {0, 0};
int CNetscapeStatusBar::sm_iOnlineRefCount = 0;
CPtrArray CNetscapeStatusBar::gStatusBars;
#endif //MOZ_OFFLINE
//------------------------------------------------------------------------------
CNetscapeStatusBar::CNetscapeStatusBar()
{
m_nDone = 0L;
m_uTimerId = 0;
m_uVaporPos = 0;
m_iStatBarPaneWidth = 0;
m_pTaskBar = NULL;
m_anIDSaved = NULL;
m_iSavedCount = 0;
m_enStatBarMode = eSBM_Panes;
m_iAnimRef = 0;
pParentSubclass = NULL;
m_pTooltip = NULL;
m_pProxy2Frame = NULL;
HG22121
sm_iRefCount++;
#ifdef MOZ_OFFLINE
if( !sm_hbmpOnline )
{
VERIFY( sm_hbmpOnline = ::LoadBitmap( AfxGetResourceHandle(), MAKEINTRESOURCE( IDB_OFFLINE_STATUS ) ));
BITMAP bm;
::GetObject( sm_hbmpOnline, sizeof(bm), &bm );
sm_sizeOnline.cx = bm.bmWidth / 2;
sm_sizeOnline.cy = bm.bmHeight;
}
sm_iOnlineRefCount++;
#endif //MOZ_OFFLINE
}
//------------------------------------------------------------------------------
CNetscapeStatusBar::~CNetscapeStatusBar()
{
delete pParentSubclass;
if( m_pTooltip )
{
delete m_pTooltip;
}
delete [] m_anIDSaved;
if (!--sm_iRefCount) {
HG28363
sm_hbmpSecure = NULL;
}
#ifdef MOZ_OFFLINE
if (!--sm_iOnlineRefCount) {
VERIFY(::DeleteObject(sm_hbmpOnline));
sm_hbmpOnline = NULL;
}
#endif //MOZ_OFFLINE
}
//------------------------------------------------------------------------------
#ifdef MOZ_OFFLINE
BOOL CNetscapeStatusBar::Create( CWnd *pParent, BOOL bxxx /*=TRUE*/, BOOL bTaskbar /*=TRUE*/,
BOOL bOnlineStatus /*TRUE*/)
{
m_bTaskbar = bTaskbar;
HG26545
m_bOnlineStatus = bOnlineStatus;
if( !CNetscapeStatusBarBase::Create( pParent ) )
return FALSE;
if( m_bSecurityStatus || m_bOnlineStatus)
{
m_pTooltip = new CNSToolTip2;
if( !m_pTooltip )
{
return FALSE;
}
m_pTooltip->Create( this );
HG12421
if(m_bOnlineStatus)
{
m_pTooltip->AddTool(this, IDS_STATBAR_ONLINE, CRect(0,0,0,0), IDS_ONLINE_STATUS);
}
}
if (!CreateDefaultPanes())
return FALSE;
pParentSubclass = new CNetscapeStatusBar::CParentSubclass( pParent, this );
ASSERT( pParentSubclass );
#ifdef MOZ_TASKBAR
if( m_bTaskbar )
{
//
// Tell the Task Bar manager about us so it can be docked on our status bar.
//
((CNetscapeApp *)AfxGetApp())->GetTaskBarMgr().RegisterStatusBar( this );
SaveModeState();
}
#endif /* MOZ_TASKBAR*/
// add to status bar array
gStatusBars.Add(m_hWnd);
return TRUE;
}
#else //MOZ_OFFLINE
BOOL CNetscapeStatusBar::Create( CWnd *pParent, BOOL bxxx /*=TRUE*/, BOOL bTaskbar /*=TRUE*/ )
{
m_bTaskbar = bTaskbar;
m_bSecurityStatus = bxxx;
if( !CNetscapeStatusBarBase::Create( pParent ) )
return FALSE;
if( m_bSecurityStatus )
{
m_pTooltip = new CNSToolTip2;
if( !m_pTooltip )
{
return FALSE;
}
m_pTooltip->Create( this );
HG17231
}
if (!CreateDefaultPanes())
return FALSE;
pParentSubclass = new CNetscapeStatusBar::CParentSubclass( pParent, this );
ASSERT( pParentSubclass );
#ifdef MOZ_TASKBAR
if( m_bTaskbar )
{
//
// Tell the Task Bar manager about us so it can be docked on our status bar.
//
((CNetscapeApp *)AfxGetApp())->GetTaskBarMgr().RegisterStatusBar( this );
SaveModeState();
}
#endif /* MOZ_TASKBAR */
return TRUE;
}
#endif //MOZ_OFFLINE
#ifdef _WIN32
//------------------------------------------------------------------------------
CWnd *CNetscapeStatusBar::SetParent( CWnd *pWndNewParent )
{
ASSERT( ::IsWindow( m_hWnd ) );
if( m_pDockSite )
{
m_pDockSite->RemoveControlBar( this );
m_pDockSite = NULL;
}
CWnd *pOld = CWnd::FromHandle( ::SetParent( m_hWnd, pWndNewParent->GetSafeHwnd() ) );
return pOld;
}
#endif
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::CreateDefaultPanes()
{
if( m_bSecurityStatus ) {
if( !SetIndicators( pPaneIndicators, sizeof(pPaneIndicators)/sizeof(UINT) ) )
return FALSE;
} else {
if( !SetIndicators( pPaneIndicators + 1, sizeof(pPaneIndicators)/sizeof(UINT) - 1 ) )
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
BOOL res = CNetscapeStatusBarBase::SetIndicators(lpIDArray, nIDCount);
if (res) {
m_iSavedCount = nIDCount;
delete [] m_anIDSaved;
if (m_iSavedCount) {
m_anIDSaved = new UINT[m_iSavedCount];
for (int i = 0; i < m_iSavedCount; i++) {
m_anIDSaved[i] = lpIDArray[i];
}
} else {
m_anIDSaved = NULL;
}
SetupMode();
#ifdef MOZ_TASKBAR
((CNetscapeApp *)AfxGetApp())->GetTaskBarMgr().OnSizeStatusBar( this );
#endif /* MOZ_TASKBAR */
SaveModeState();
}
return res;
}
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::ResetPanes( EStatBarMode enStatBarMode, BOOL bForce /*=FALSE*/ )
{
if( !bForce && (m_enStatBarMode == enStatBarMode) )
{
return TRUE;
}
if( m_enStatBarMode != enStatBarMode )
{
// Save state info of the current pane mode
SaveModeState();
}
//
// Set new panes/indicators
//
m_enStatBarMode = enStatBarMode;
if( enStatBarMode != eSBM_Simple )
{
// The previous mode shall never be eSBM_Simple (eSBM_Simple is for menu help text)
pParentSubclass->SetPrevMode( enStatBarMode );
}
SetupMode();
return TRUE;
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::SaveModeState()
{
switch( m_enStatBarMode )
{
case eSBM_Panes:
{
#ifdef MOZ_TASKBAR
if( m_bTaskbar )
{
// Save the IDS_TASKBAR pane width
UINT u;
GetPaneInfo( CommandToIndex( IDS_TASKBAR ), u, u, m_iStatBarPaneWidth );
}
#endif /* MOZ_TASKBAR */
break;
}
case eSBM_Simple:
{
// Don't care to save anything
break;
}
default:
{
break;
}
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::SetupMode()
{
switch( m_enStatBarMode )
{
case eSBM_Simple:
{
if (!CNetscapeStatusBarBase::SetIndicators(pSimpleIndicators, 1))
return;
SetPaneInfo( 0, ID_SEPARATOR, SBPS_STRETCH | SBPS_NOBORDERS, 0 );
// Hide the task bar window (if docked)
#ifdef MOZ_TASKBAR
ShowTaskBar( SW_HIDE );
#endif /* MOZ_TASKBAR */
break;
}
case eSBM_Panes:
{
if (!m_anIDSaved)
return;
if (!CNetscapeStatusBarBase::SetIndicators(m_anIDSaved, m_iSavedCount))
return;
#ifdef _WIN32
int iFudge = 4;
#else
int iFudge = 2;
#endif
RECT rcTool;
HG26576
//
// Set common pane info (size, style, etc).
// WHS -- I'm assuming we'll always have these, probably not good in the long term
//
SetPaneInfo( CommandToIndex( ID_SEPARATOR ), ID_SEPARATOR, SBPS_STRETCH, 0 );
idx = CommandToIndex(IDS_TRANSFER_STATUS);
if(idx > -1) {
SetPaneInfo( idx, IDS_TRANSFER_STATUS, SBPS_NORMAL, 90 );
}
#ifdef MOZ_OFFLINE
idx = CommandToIndex(IDS_ONLINE_STATUS);
if (idx > -1) {
SetPaneInfo(idx, IDS_ONLINE_STATUS, SBPS_DISABLED, sm_sizeOnline.cx - iFudge);
if (m_pTooltip) {
GetItemRect(idx, &rcTool);
m_pTooltip->SetToolRect(this, IDS_ONLINE_STATUS, &rcTool);
}
}
#endif
// Note the taskbar mgr sets the width of the taskbar pane
// Also note we must call these SetPaneXXX methods even if m_bTaskbar is FALSE because
// pPaneIndicators specifies the IDS_TASKBAR. If we don't, the default CStatusBar
// implementation is to display the IDS_TASKBAR string resource in the status - not good.
#ifdef MOZ_TASKBAR
idx = CommandToIndex( IDS_TASKBAR );
if (idx > -1)
{
SetPaneInfo( idx, IDS_TASKBAR, SBPS_NOBORDERS, m_iStatBarPaneWidth );
SetPaneText( idx, "", FALSE );
// Show the task bar window (if docked)
if( m_iStatBarPaneWidth )
ShowTaskBar( SW_SHOWNA );
if( m_pTaskBar )
{
CRect rc;
GetItemRect( CommandToIndex( IDS_TASKBAR ), &rc );
//Get Item Rect is returning us the wrong dimensions. It's off by 6 pixels
//Eventually figure out what's going wrong
rc.right -= 6;
m_pTaskBar->MoveWindow( &rc );
m_pTaskBar = NULL;
}
}
#endif /* MOZ_TASKBAR */
break;
}
default:
{
break;
}
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::ShowTaskBar( int iCmdShow )
{
#ifdef MOZ_TASKBAR
if( !m_bTaskbar )
{
return;
}
CWnd *pChild = GetWindow( GW_CHILD );
while( pChild )
{
pChild->ShowWindow( iCmdShow );
pChild = pChild->GetWindow( GW_HWNDNEXT );
}
#endif
}
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::SetTaskBarPaneWidth( int iWidth )
{
#ifdef MOZ_TASKBAR
if( !m_bTaskbar || (iWidth < 0) )
{
return FALSE;
}
int nIndex = CommandToIndex( IDS_TASKBAR );
if( nIndex != -1 )
{
UINT nID, nStyle;
int nWidth;
GetPaneInfo( nIndex, nID, nStyle, nWidth );
SetPaneInfo( nIndex, nID, nStyle, iWidth );
}
else
{
// The pane is not available right now. We'll resize the pane later.
m_iStatBarPaneWidth = iWidth;
}
#endif /* MOZ_TASKBAR */
return TRUE;
}
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::SetTaskBarSize( CDockedTaskBar *pTaskBar )
{
#ifdef MOZ_TASKBAR
if( !m_bTaskbar || !pTaskBar )
{
return FALSE;
}
CRect rc;
int iIndex = CommandToIndex( IDS_TASKBAR );
if( iIndex != -1 )
{
GetItemRect( iIndex, &rc );
//Get Item Rect is returning us the wrong dimensions. It's off by 6 pixels
//Eventually figure out what's going wrong
rc.right -= 6;
pTaskBar->MoveWindow( &rc );
}
else
{
// The pane is not available right now. We'll resize the task bar later.
m_pTaskBar = pTaskBar;
}
#endif /* MOZ_TASKBAR */
return TRUE;
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::StartAnimation()
{
m_iAnimRef = TRUE;
SetPercentDone( -1 );
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::StopAnimation()
{
if( m_iAnimRef )
{
m_iAnimRef = FALSE;
}
if( !m_iAnimRef )
{
SetPercentDone( 0 );
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::SetPercentDone(const int32 nPercent)
{
// Destroying the context in response to the window being destroyed
// sometimes calls this, so we need to check that the window
// still exists or we die.
if (!m_hWnd)
return;
if( m_nDone != nPercent )
{
if( m_iAnimRef && (nPercent == 0) )
{
m_nDone = -1;
}
else
{
m_nDone = nPercent;
}
DrawProgressBar();
if( m_nDone >= 100 )
{
//
// Ensure progress never sits on 100% i.e., the back end might never
// reset progress to 0 after specifying 100.
//
m_nDone = m_iAnimRef ? -1 : 0;
DrawProgressBar();
}
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::OnDestroy()
{
#ifdef MOZ_OFFLINE
//remove the status bar;
int count = gStatusBars.GetSize();
for(int i = 0; i < count; i++)
{
HWND hWnd = (HWND)gStatusBars.GetAt(i);
if(hWnd == m_hWnd)
{
gStatusBars.RemoveAt(i);
break;
}
}
#endif //MOZ_OFFLINE
#ifdef MOZ_TASKBAR
if( m_bTaskbar )
{
// Tell the Task Bar manager not to worry about us anymore
((CNetscapeApp *)AfxGetApp())->GetTaskBarMgr().UnRegisterStatusBar( this );
}
#endif /* MOZ_TASKBAR */
CNetscapeStatusBarBase::OnDestroy();
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::OnLButtonDown( UINT nFlags, CPoint point )
{
if( m_bSecurityStatus )
{
RECT rc;
GetItemRect( CommandToIndex( IDS_SECURITY_STATUS ), &rc );
if( PtInRect( &rc, point ) )
{
CGenericFrame *pGenFrame = DYNAMIC_DOWNCAST( CGenericFrame, GetParentFrame() );
if( pGenFrame )
{
MWContext *pContext = pGenFrame->GetMainContext()->GetContext();
if( pContext )
{
CAbstractCX *pCX = ABSTRACTCX(pContext);
if( pCX )
{
URL_Struct *pURL = pCX->CreateUrlFromHist( TRUE );
SECNAV_SecurityAdvisor( pContext, pURL );
}
}
}
}
}
CNetscapeStatusBarBase::OnLButtonDown( nFlags, point );
}
//------------------------------------------------------------------------------
// We process the WM_SIZE message just to notify the Task Bar manager
// that we've changed, so it can do what it needs with any task bars
// docked on top of us.
//
void CNetscapeStatusBar::OnSize( UINT nType, int cx, int cy )
{
CNetscapeStatusBarBase::OnSize( nType, cx, cy );
if ( nType != SIZE_MINIMIZED && cx && cy) {
#ifdef MOZ_TASKBAR
if( m_bTaskbar )
{
// Tell the Task Bar manager
((CNetscapeApp *)AfxGetApp())->GetTaskBarMgr().OnSizeStatusBar( this );
}
#endif /* MOZ_TASKBAR */
RECT rcTool;
HG26522
#ifdef MOZ_OFFLINE
idx = CommandToIndex(IDS_ONLINE_STATUS);
if (idx > -1) {
if (m_pTooltip) {
GetItemRect(idx, &rcTool);
m_pTooltip->SetToolRect(this, IDS_ONLINE_STATUS, &rcTool);
}
}
#endif
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::OnPaint()
{
#if defined(MSVC4)
CStatusBar::OnPaint();
CClientDC dc(this);
#else
CPaintDC dc(this);
// Do not call CStatusBar::OnPaint()!
CNetscapeStatusBarBase::DoPaint( &dc );
#endif // MSVC4
//
// Special per mode painting
//
switch( m_enStatBarMode )
{
case eSBM_Panes:
{
// Nothing to do
break;
}
case eSBM_Simple:
default:
{
// Nothing to do
break;
}
}
DrawSecureStatus(dc.m_hDC);
DrawSignedStatus(dc.m_hDC);
#ifdef MOZ_OFFLINE
DrawOnlineStatus(dc.m_hDC);
#endif //MOZ_OFFLINE
DrawProgressBar();
}
//------------------------------------------------------------------------------
BOOL CNetscapeStatusBar::PreTranslateMessage( MSG *pMsg )
{
if( m_pTooltip && (m_enStatBarMode != eSBM_Simple) )
{
if (pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
m_pTooltip->RelayEvent( pMsg );
}
return CNetscapeStatusBarBase::PreTranslateMessage( pMsg );
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::DrawSecureStatus(HDC hdc)
{
int idx = CommandToIndex( IDS_SECURITY_STATUS );
if (idx < 0)
return;
HG87236
UINT nID, nStyle;
int cxWidth;
GetPaneInfo(idx, nID, nStyle, cxWidth);
BOOL bSecure = !(nStyle & SBPS_DISABLED);
RECT rect;
GetItemRect( idx, &rect );
HDC hdcBitmap = ::CreateCompatibleDC( hdc );
HBITMAP hbmOld = (HBITMAP)::SelectObject( hdcBitmap, sm_hbmpSecure );
FEU_TransBlt( hdc, rect.left+1, rect.top+1, sm_sizeSecure.cx, sm_sizeSecure.cy, hdcBitmap, bSecure ? sm_sizeSecure.cx : 0, 0,WFE_GetUIPalette(GetParentFrame()) );
::SelectObject( hdcBitmap, hbmOld );
VERIFY( ::DeleteDC( hdcBitmap ));
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::DrawSignedStatus(HDC hdc)
{
int idx = CommandToIndex( IDS_SIGNED_STATUS );
if (idx < 0)
return;
HG17236
UINT nID, nStyle;
int cxWidth;
GetPaneInfo(idx, nID, nStyle, cxWidth);
BOOL bSigned = !(nStyle & SBPS_DISABLED);
if (bSigned) {
RECT rect;
GetItemRect( idx, &rect );
HDC hdcBitmap = ::CreateCompatibleDC( hdc );
HBITMAP hbmOld = (HBITMAP)::SelectObject( hdcBitmap, sm_hbmpSecure );
FEU_TransBlt( hdc, rect.left+1, rect.top+1, sm_sizeSecure.cx, sm_sizeSecure.cy, hdcBitmap, sm_sizeSecure.cx * 2, 0 ,WFE_GetUIPalette(GetParentFrame()));
::SelectObject( hdcBitmap, hbmOld );
VERIFY( ::DeleteDC( hdcBitmap ));
}
}
#ifdef MOZ_OFFLINE
//------------------------------------------------------------------------------
void CNetscapeStatusBar::DrawOnlineStatus(HDC hdc)
{
int idx = CommandToIndex( IDS_ONLINE_STATUS );
if (idx < 0)
return;
UINT nID, nStyle;
int cxWidth;
GetPaneInfo(idx, nID, nStyle, cxWidth);
//BOOL bOnline = !(nStyle & SBPS_DISABLED);
BOOL bOnline = !NET_IsOffline();
RECT rect;
GetItemRect( idx, &rect );
HDC hdcBitmap = ::CreateCompatibleDC( hdc );
HBITMAP hbmOld = (HBITMAP)::SelectObject( hdcBitmap, sm_hbmpOnline );
FEU_TransBlt( hdc, rect.left+1, rect.top+1, sm_sizeOnline.cx, sm_sizeOnline.cy, hdcBitmap, bOnline ? sm_sizeOnline.cx : 0, 0,WFE_GetUIPalette(GetParentFrame()) );
::SelectObject( hdcBitmap, hbmOld );
VERIFY( ::DeleteDC( hdcBitmap ));
}
#endif //MOZ_OFFLINE
//------------------------------------------------------------------------------
void CNetscapeStatusBar::DrawProgressBar()
{
int idx = CommandToIndex( IDS_TRANSFER_STATUS );
if (idx < 0)
return;
RECT rcBarArea;
GetItemRect( idx, &rcBarArea );
CClientDC dc( this );
if( m_nDone == 0 )
{
StopPulse();
::InflateRect( &rcBarArea, -1, -1 );
dc.FillRect( &rcBarArea, CBrush::FromHandle( sysInfo.m_hbrBtnFace ) );
return;
}
if( m_nDone == -1 )
{
if( !m_uTimerId )
{
StartPulse();
}
return;
}
// Decide the correct size of the thermo.
InflateRect( &rcBarArea, -5, -2 );
CDC dcMem;
dcMem.CreateCompatibleDC( &dc );
// Create a bitmap big enough for progress bar area
CBitmap bmMem;
bmMem.CreateCompatibleBitmap( &dc, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top );
CBitmap *pbmOld = dcMem.SelectObject( &bmMem );
// Select the font
CFont *pOldFont = NULL;
if( GetFont() )
{
pOldFont = dcMem.SelectObject( GetFont() );
}
char szPercent[8];
wsprintf( szPercent, "%u%%", m_nDone );
dcMem.SetBkMode( TRANSPARENT );
RECT rcBm = { 0, 0, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top };
int iNumColors = dc.GetDeviceCaps( NUMCOLORS );
if( iNumColors == -1 || iNumColors > 256 )
{
// Render the image into the mem DC
dcMem.FillRect( &rcBm, CBrush::FromHandle( sysInfo.m_hbrBtnFace ) );
dcMem.SetTextColor( GetSysColor( COLOR_BTNTEXT ) );
dcMem.DrawText( szPercent, -1, &rcBm, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
RECT rcBar = { 0, 0, CASTINT(rcBm.right * m_nDone / 100), CASTINT(rcBm.bottom) };
dcMem.InvertRect( &rcBar );
}
else
{
// There's reasonable probability that the inverse color of btnface and btnshadow could be the same
// when we are dealing with a palette of 256 colors or less. So instead of using the invertrect
// algorithm above, we'll just ensure the text is legible by painting a white background for it.
// Render the image into the mem DC
dcMem.FillRect( &rcBm, CBrush::FromHandle( (HBRUSH)GetStockObject( WHITE_BRUSH ) ) );
dcMem.SetTextColor( RGB(0,0,0) );
dcMem.DrawText( szPercent, -1, &rcBm, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
RECT rcBar = { 0, 0, CASTINT(rcBm.right * m_nDone / 100), CASTINT(rcBm.bottom) };
dcMem.InvertRect( &rcBar );
}
dc.BitBlt( rcBarArea.left, rcBarArea.top, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top, &dcMem, 0, 0, SRCCOPY );
// Tidy up
if( pOldFont )
{
dcMem.SelectObject( pOldFont );
}
dcMem.SelectObject( pbmOld );
}
//------------------------------------------------------------------------------
#define VAPOR_PERIOD 40 // Note, must be divisible by 2
void CNetscapeStatusBar::PulsingVaporTrails()
{
RECT rcBarArea;
GetItemRect( CommandToIndex( IDS_TRANSFER_STATUS ), &rcBarArea );
CClientDC dc( this );
InflateRect( &rcBarArea, -5, -2 );
CDC dcMem;
dcMem.CreateCompatibleDC( &dc );
// Create a bitmap big enough for progress bar area
CBitmap bmMem;
bmMem.CreateCompatibleBitmap( &dc, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top );
CBitmap *pbmOld = dcMem.SelectObject( &bmMem );
// Render the image into the mem DC
RECT rcBm = { 0, 0, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top };
dcMem.FillRect( &rcBm, CBrush::FromHandle( sysInfo.m_hbrBtnFace ) );
COLORREF crTrail = GetSysColor( COLOR_BTNSHADOW );
COLORREF crFade = GetSysColor( COLOR_BTNFACE );
int iTrailR = (int)GetRValue( crTrail );
int iTrailG = (int)GetGValue( crTrail );
int iTrailB = (int)GetBValue( crTrail );
int iFadeR = (int)GetRValue( crFade );
int iFadeG = (int)GetGValue( crFade );
int iFadeB = (int)GetBValue( crFade );
int iTrailLen = rcBm.right/2;
UINT uHalfPeriod = m_uVaporPos;
int iNumColors = dc.GetDeviceCaps( NUMCOLORS );
if( m_uVaporPos <= VAPOR_PERIOD/2 )
{
for( int u = 0; u < iTrailLen; u++ )
{
COLORREF crVapor = RGB( (BYTE)(iTrailR - ((float)(iTrailR - iFadeR)/(float)iTrailLen * (float)u)),
(BYTE)(iTrailG - ((float)(iTrailG - iFadeG)/(float)iTrailLen * (float)u)),
(BYTE)(iTrailB - ((float)(iTrailB - iFadeB)/(float)iTrailLen * (float)u)) );
RECT rcVapor = rcBm;
rcVapor.right = -u + (rcBm.right / (VAPOR_PERIOD/2))*uHalfPeriod+1;
rcVapor.left = rcVapor.right - (iTrailLen-u);
CBrush br( crVapor );
dcMem.FillRect( &rcVapor, &br );
if( (iNumColors != -1) && (iNumColors <= 256) )
{
// Just paint a solid bouncing block for 8-bit (or less) color
break;
}
}
}
else
{
uHalfPeriod = m_uVaporPos - VAPOR_PERIOD/2;
for( int u = 0; u < iTrailLen; u++ )
{
COLORREF crVapor = RGB( (BYTE)(iTrailR - ((float)(iTrailR - iFadeR)/(float)iTrailLen * (float)u)),
(BYTE)(iTrailG - ((float)(iTrailG - iFadeG)/(float)iTrailLen * (float)u)),
(BYTE)(iTrailB - ((float)(iTrailB - iFadeB)/(float)iTrailLen * (float)u)) );
RECT rcVapor = rcBm;
rcVapor.left = (rcVapor.right + u) - ((rcBm.right / (VAPOR_PERIOD/2))*uHalfPeriod-1);
rcVapor.right = rcVapor.left + (iTrailLen-u);
CBrush br( crVapor );
dcMem.FillRect( &rcVapor, &br );
if( (iNumColors != -1) && (iNumColors <= 256) )
{
// Just paint a solid bouncing block for 8-bit (or less) color
break;
}
}
}
if( m_uVaporPos == VAPOR_PERIOD )
{
m_uVaporPos = 0;
}
else
{
m_uVaporPos++;
}
dc.BitBlt( rcBarArea.left, rcBarArea.top, rcBarArea.right-rcBarArea.left, rcBarArea.bottom-rcBarArea.top, &dcMem, 0, 0, SRCCOPY );
// Tidy up
dcMem.SelectObject( pbmOld );
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::StartPulse()
{
m_uVaporPos = 0;
m_uTimerId = SetTimer( IDT_PULSE, PULSE_INTERVAL, CNetscapeStatusBar::PulseTimerProc );
if( !m_uTimerId )
{
return;
}
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::StopPulse()
{
if( !m_uTimerId )
{
return;
}
KillTimer( IDT_PULSE );
m_uTimerId = 0;
}
//------------------------------------------------------------------------------
void CALLBACK EXPORT
CNetscapeStatusBar::PulseTimerProc( HWND hwnd, UINT uMsg, UINT uTimerId, DWORD dwTime )
{
CNetscapeStatusBar *pBar = (CNetscapeStatusBar *)CWnd::FromHandle( hwnd );
if( (pBar->m_nDone == -1) && (pBar->GetStatBarMode() == eSBM_Panes) )
{
pBar->PulsingVaporTrails();
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
CNetscapeStatusBar::CParentSubclass::CParentSubclass( CWnd *pParent, CNetscapeStatusBar *pStatusBar )
{
VERIFY( m_pStatusBar = pStatusBar );
VERIFY( m_pParent = pParent );
ASSERT( IsWindow( m_pParent->m_hWnd ) );
m_uTimerId = 0;
//
// Subclass the parent window so we can process the WM_MENUSELECT msg i.e., so we
// can switch modes from Simple/Panes without client intervention.
//
#ifdef _WIN32
VERIFY( SetProp( pParent->m_hWnd, szNSStatusProp, this ) );
#else
VERIFY( SetProp( pParent->m_hWnd, szNSStatusProp1, (HANDLE)LOWORD((DWORD)this) ) );
VERIFY( SetProp( pParent->m_hWnd, szNSStatusProp2, (HANDLE)HIWORD((DWORD)this) ) );
#endif
m_pfOldWndProc = (WNDPROC)SetWindowLong( m_pParent->m_hWnd, GWL_WNDPROC,
(LONG)CNetscapeStatusBar::CParentSubclass::ParentSubclassProc );
}
//------------------------------------------------------------------------------
CNetscapeStatusBar::CParentSubclass::~CParentSubclass()
{
if( IsWindow( m_pParent->m_hWnd ) &&
GetWindowLong( m_pParent->m_hWnd, GWL_WNDPROC ) == (LONG)CNetscapeStatusBar::CParentSubclass::ParentSubclassProc )
{
//
// Unsubclass the parent window
//
#ifdef _WIN32
VERIFY( RemoveProp( m_pParent->m_hWnd, szNSStatusProp ) );
#else
VERIFY( RemoveProp( m_pParent->m_hWnd, szNSStatusProp1 ) );
VERIFY( RemoveProp( m_pParent->m_hWnd, szNSStatusProp2 ) );
#endif
SetWindowLong( m_pParent->m_hWnd, GWL_WNDPROC, (LONG)m_pfOldWndProc );
}
}
//------------------------------------------------------------------------------
LRESULT CALLBACK EXPORT
CNetscapeStatusBar::CParentSubclass::ParentSubclassProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam )
{
CNetscapeStatusBar::CParentSubclass *pThis = NULL;
#ifdef _WIN32
pThis = (CNetscapeStatusBar::CParentSubclass *)GetProp( hWnd, szNSStatusProp );
#else
pThis = (CNetscapeStatusBar::CParentSubclass *)MAKELONG( GetProp( hWnd, szNSStatusProp1 ),
GetProp( hWnd, szNSStatusProp2 ) );
#endif
ASSERT( pThis );
LRESULT lRet = 0L;
switch( uMessage )
{
case WM_MENUSELECT:
{
#ifdef _WIN32
UINT uFlags = (UINT)HIWORD(wParam);
HMENU hMenu = (HMENU)lParam;
#else
UINT uFlags = (UINT)LOWORD(lParam);
HMENU hMenu = (HMENU)HIWORD(lParam);
#endif
//
// Put the status bar into the correct mode for either:
// 1.) Menu help text (aka Simple Text)
// 2.) Multiple panes of info for progress etc.
//
BOOL bMenuClosed = (uFlags & 0xffff) && !hMenu;
if( !bMenuClosed )
{
if( eSBM_Simple != pThis->m_pStatusBar->GetStatBarMode() )
{
pThis->SetPrevMode( pThis->m_pStatusBar->GetStatBarMode() );
pThis->m_pStatusBar->ResetPanes( eSBM_Simple );
// Start the timer for monitoring when the menu closes
pThis->StartMonitor();
}
}
//## We have to reset on a timer notification because Windows doesn't
//## always send the WM_MENUSELECT when menus close. Typical.
// else
// {
// pThis->m_pStatusBar->ResetPanes( pThis->GetPrevMode() );
// }
lRet = CallWindowProc( (WNDPROC)pThis->m_pfOldWndProc, hWnd, uMessage, wParam, lParam );
break;
}
case WM_DESTROY:
{
pThis->StopMonitor();
lRet = CallWindowProc( (WNDPROC)pThis->m_pfOldWndProc, hWnd, uMessage, wParam, lParam );
break;
}
default:
lRet = CallWindowProc( (WNDPROC)pThis->m_pfOldWndProc, hWnd, uMessage, wParam, lParam );
}
return lRet;
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::CParentSubclass::StartMonitor()
{
m_uTimerId = ::SetTimer( m_pStatusBar->m_hWnd, IDT_STATBARMONITOR, MONITOR_INTERVAL, CNetscapeStatusBar::CParentSubclass::MonitorTimerProc );
}
//------------------------------------------------------------------------------
void CNetscapeStatusBar::CParentSubclass::StopMonitor()
{
if( !m_uTimerId )
{
return;
}
::KillTimer( m_pStatusBar->m_hWnd, IDT_STATBARMONITOR );
m_uTimerId = 0;
}
//------------------------------------------------------------------------------
void CALLBACK EXPORT
CNetscapeStatusBar::CParentSubclass::MonitorTimerProc( HWND hwnd, UINT uMsg, UINT uTimerId, DWORD dwTime )
{
CNetscapeStatusBar *pBar = (CNetscapeStatusBar *)CWnd::FromHandlePermanent( hwnd );
if( !pBar )
{
return;
}
CNetscapeStatusBar::CParentSubclass *pThis = pBar->pParentSubclass;
if( !GetCapture() && (eSBM_Simple == pThis->m_pStatusBar->GetStatBarMode()) )
{
pThis->m_pStatusBar->ResetPanes( pThis->GetPrevMode() );
pThis->StopMonitor();
}
}
IMPLEMENT_DYNAMIC(CNetscapeStatusBar, CNetscapeStatusBarBase)