gecko-dev/cmd/winfe/statbar.cpp
1998-07-23 17:48:39 +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
//
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)