/*****************************************************************************
*
* Class: CNGStatusBarPaneInfo, CNGStatusBar
* Files: CNGStatusBar.Cpp, CNGStatusBar.H
* Description: With this class complex status lines can be administered.
* So can be represented in each Pane texts, bit-maps or
* progress Bars, be gescrollt horizontal, vertically or diagonally
* and be aligned left, on the right or centered. Also each time
* between the individual modes can be shifted up and down.
* For each Pane can be defined both switching on on and a switching
* off text, - background or - bit-map.
*
* Functions: operator=(), SetDefault(), SetFont(), SetMode(),
* (CNGStatusBarPaneInfo) SetFgColor(), SetBkColor(), SetBitmap(), SetText(),
* SetNumber(), HScroll(), VScroll(),
* Functions: CreateStatusBar(), SetIndicators(), OnPaint(),
* (CNGStatusBar) DrawSizing(), DrawTextPane(), DrawBitmapPane(),
* DrawProgressPane(), GetCNGStatusBarPaneInfo(), OnTimer(),
* SetStyle(), SetWidth(), GetStyle(), GetWidth(), GetID(),
* OnDestroy(), SavePane(), RestorePane(),
* GetPaneAtPosition(), OnMouseMove(),
* OnLButtonUp(), OnMButtonUp(), OnRButtonUp(),
* OnLButtonDown(), OnMButtonDown(), OnRButtonDown(),
* OnLButtonDblClk(), OnMButtonDblClk(), OnRButtonDblClk(),
*
****************************************************************************/
#include "StdAfx.h"
#include "NGStatusBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
volatile static char jrrcid[] = "%J%";
#define IDC_JRLIB_STATUSBAR_TIMER 20000
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: CNGStatusBarPaneInfo, ~CNGStatusBarPaneInfo
* Parameter: -
* Return:
*
* The constructor initialize a Pane. In the Desturktor a possibly
* available progress check is again deleted.
*
****************************************************************************/
CNGStatusBarPaneInfo::CNGStatusBarPaneInfo()
{
progress = NULL;
hScrollPos = 0;
vScrollPos = 0;
SetDefault();
}
CNGStatusBarPaneInfo::CNGStatusBarPaneInfo(const CNGStatusBarPaneInfo& paneInfo)
{
for (int i = 0; i < 2; i++)
{
fgColor[i] = paneInfo.fgColor[i];
bkColor[i] = paneInfo.bkColor[i];
string[i] = paneInfo.string[i];
}
font = paneInfo.font;
mode = paneInfo.mode;
progress = NULL;
hScrollPos = paneInfo.hScrollPos;
vScrollPos = paneInfo.vScrollPos;
}
CNGStatusBarPaneInfo::~CNGStatusBarPaneInfo()
{
if (progress) delete progress;
progress = NULL;
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: operator=
* Parameter: paneInfo Zweites CNGStatusBarPaneInfo-Element, dessen Informationen
* kopiert werden.
* Return: Kopie des CNGStatusBarPaneInfo-Elements
*
* Allocation operator!!! NOTE!!! ' progress ' is not copied! Possibly
* available progress bar one deletes
*
*
****************************************************************************/
CNGStatusBarPaneInfo CNGStatusBarPaneInfo::operator=(const CNGStatusBarPaneInfo& paneInfo)
{
for (int i = 0; i < 2; i++)
{
fgColor[i] = paneInfo.fgColor[i];
bkColor[i] = paneInfo.bkColor[i];
string[i] = paneInfo.string[i];
}
font = paneInfo.font;
mode = paneInfo.mode;
hScrollPos = paneInfo.hScrollPos;
vScrollPos = paneInfo.vScrollPos;
if (progress) delete progress;
progress = NULL;
return *this;
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetDefault
* Parameter: -
* Return: -
*
* Here the Members is initialized
****************************************************************************/
void CNGStatusBarPaneInfo::SetDefault()
{
bkColor[1] = COLORREF(GetSysColor(COLOR_3DFACE));
bkColor[0] = bkColor[1];
fgColor[1] = GetSysColor(COLOR_BTNTEXT);
fgColor[0] = RGB(GetRValue(bkColor[1])/2, GetGValue(bkColor[1])/2, GetBValue(bkColor[1])/2);
mode = XSB_TEXT | DT_LEFT;
SetFont(CFont::FromHandle((HFONT) GetStockObject(ANSI_VAR_FONT)));
if (progress) delete progress;
progress = NULL;
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetFont
* Parameter: name Name der Schriftart (Bsp.: Arial)
* size Gr��e der Schriftart in 1/10 Pt (Bsp.: 120)
* Return: -
*
* The Font for a Pane sets on the basis the font name and the point size
* (10 * Point).
****************************************************************************/
void CNGStatusBarPaneInfo::SetFont(LPCSTR name, int size)
{
CFont pointFont;
pointFont.CreatePointFont(size, name);
pointFont.GetLogFont(&font);
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetMode
* Parameter: newMode Neuer Anzeigemodus
* Return: -
*
* Sets the mode for the current Pane. If this Pane were filled with progress
* CTRL before, this is deleted before.
*
****************************************************************************/
void CNGStatusBarPaneInfo::SetMode(int newMode)
{
if ((mode = newMode) & XSB_PROGRESS)
{
if (!progress)
{
UINT style = WS_VISIBLE | WS_CHILD;
if (mode & XSB_SMOOTH) style |= PBS_SMOOTH;
progress = new CProgressCtrl();
progress->Create(style, CRect(0,0,0,0), CNGStatusBar::aktBar, 1);
}
}
else if (progress)
{
delete progress;
progress = NULL;
}
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetFgColor
* Parameter: on Text-Farbe im aktiven Zustand
* off Text-Farbe im inaktiven Zustand
* Return: -
*
* Defines the colours for a displayed text. Here two colours for the active
* and the inactive status can be defined. If the second colour is forgotten,
* it is pre-defined with the half intensity of the background colour.
****************************************************************************/
void CNGStatusBarPaneInfo::SetFgColor(COLORREF on, COLORREF off)
{
fgColor[1] = on;
if (off != -1)
fgColor[0] = off;
else
{
COLORREF bk = GetSysColor(COLOR_3DFACE);
fgColor[0] = RGB(GetRValue(bk)/2, GetGValue(bk)/2, GetBValue(bk)/2);
}
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetBkColor
* Parameter: on Hintergrundfarbe im aktiven Zustand
* off Hintergrundfarbe im inaktiven Zustand
* Return: -
*
* Defines the background colours for a displayed text. Here two colours for
* the active and the inactive status can be defined. If the second colour is
* forgotten, it is pre-defined with the background colour.
****************************************************************************/
void CNGStatusBarPaneInfo::SetBkColor(COLORREF on, COLORREF off)
{
bkColor[1] = on;
if (off != -1) bkColor[0] = off;
else bkColor[0] = GetSysColor(COLOR_3DFACE);
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: SetBitmap, SetText, SetNumber
* Parameter: newBitmap Name des im Pane anzuzeigenden Bitmaps
* newText Im Pane anzuzeigender Text
* newNumber Im Pane anzuzeigende Nummer
* Return: -
*
* With these functions the bit-maps, texts or numbers for the display
* in the current Pane are set.
****************************************************************************/
void CNGStatusBarPaneInfo::SetBitmap(LPCSTR newOnBitmap, LPCSTR newOffBitmap)
{
string[1] = newOnBitmap;
string[0] = newOffBitmap;
}
void CNGStatusBarPaneInfo::SetText(LPCSTR newOnText, LPCSTR newOffText)
{
string[1] = newOnText;
string[0] = newOffText;
}
void CNGStatusBarPaneInfo::SetIconAndText(DWORD iconResourceID, LPCSTR text)
{
string[1].Format("%d", iconResourceID);
string[0] = text;
}
void CNGStatusBarPaneInfo::SetNumber(int newOnNumber, int newOffNumber)
{
string[1].Format("%d", newOnNumber);
string[0].Format("%d", newOffNumber);
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: HScroll, VScroll
* Parameter: rect Ausgaberechteck des aktuellen Panes
* maxWidth Maximale Breite, bzw. H�he beim Scrollen
* maxHeight (z. B. Textl�nge oder Bitmapbreite)
* nullValue Wert f�r Turnaround
* Return: -
*
* Increments the respective Scrollvariable, so that the text or the bit-map
* of the current Panes is gescrollt represented. If the max. size is exceeded,
* the scrolling begins again from the front.
****************************************************************************/
void CNGStatusBarPaneInfo::HScroll(CRect& rect, int maxWidth, int nullValue)
{
if (++hScrollPos > maxWidth) hScrollPos = nullValue;
rect.left -= hScrollPos;
}
void CNGStatusBarPaneInfo::VScroll(CRect& rect, int maxHeight, int nullValue)
{
if (++vScrollPos > maxHeight) vScrollPos = nullValue;
rect.top -= vScrollPos;
}
/*****************************************************************************
* Klasse: CNGStatusBarPaneInfo
* Funktion: Dump, AssertValid, operator<<
* Parameter: dc CDumpContext
* paneInfo Ausgabelement
* Return: -
*
*
*
*
****************************************************************************/
#ifdef _DEBUG
void CNGStatusBarPaneInfo::Dump(CDumpContext& dc) const
{
dc << "FgColor / BkColor / Value:\t"
<< fgColor[1] << " - " << fgColor[0] << " / "
<< bkColor[1] << " - " << bkColor[0] << " / "
<< string[1] << " - " << string[0] << "\n"
<< "Mode:\t" << mode << "\n";
}
void CNGStatusBarPaneInfo::AssertValid() const
{
ASSERT((progress == NULL) || _CrtIsValidHeapPointer(progress));
}
CDumpContext& AFXAPI operator<<(CDumpContext& dc, CNGStatusBarPaneInfo& paneInfo)
{
paneInfo.Dump(dc);
return dc;
}
#endif // _DEBUG
//****************************************************************************
//****************************************************************************
//****************************************************************************
CNGStatusBar *CNGStatusBar::aktBar = NULL;
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: CNGStatusBar, ~CNGStatusBar
* Parameter: -
* Return:
*
* Constructor and Destructor.
****************************************************************************/
CNGStatusBar::CNGStatusBar()
{
aktBar = this;
timerID = 0;
}
CNGStatusBar::~CNGStatusBar()
{}
BEGIN_MESSAGE_MAP(CNGStatusBar, CStatusBar)
//{{AFX_MSG_MAP(CNGStatusBar)
ON_WM_DESTROY()
ON_WM_TIMER()
ON_WM_PAINT()
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MBUTTONDBLCLK()
ON_WM_MBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_RBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
int CNGStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CStatusBar::OnCreate(lpCreateStruct) == -1)
return -1;
CStatusBarCtrl & rCtrl = GetStatusBarCtrl();
rCtrl.SetMinHeight(22);
m_ToolTip.Create(this, TTS_ALWAYSTIP );
m_ToolTip.SetDelayTime(250); //delay before tip appears
m_ToolTip.SetDelayTime(4000, TTDT_AUTOPOP); // linger time once tip is up
m_IconImageList.Create(16,16,ILC_MASK|ILC_COLOR, 0, 1);
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// PreTranslateMessage() - standard handler.
BOOL CNGStatusBar::PreTranslateMessage(MSG* pMsg)
{
// Because modal dialogs will cause all CToolTipCtrls to get deactivated,
// the tool tip control needs to be manually reactivated.
// TT 3 TT Step 6
m_ToolTip.Activate(TRUE);
// RelayEvent is required for CToolTipCtrl objects -
// it passes mouse messages on to the tool tip control
// so it can decide when to show the tool tip
// TT 3 TT Step 4
m_ToolTip.RelayEvent(pMsg);
return CStatusBar::PreTranslateMessage(pMsg);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: CreateStatusBar
* Parameter: lpIDArray Array mit den ID's der einzelnen Panes
* nIDCount Anzahl der Panes in der Statuszeile
* pane0Style Zusatzstyle f�r Pane 0 (normalerweise SBPS_STRETCH)
* Return: true wenn die Erzeugung erfolgreich war, sonst false
*
* Produces a status line at the lower edge of window. Here all necessary steps
* in a function are united: Produce the Toolbar, define the individual Panes,
* possibly a changing of the 0-Panes over.
****************************************************************************/
bool CNGStatusBar::CreateStatusBar(CWnd *pWnd, const UINT* lpIDArray, int nIDCount, UINT pane0Style)
{
bool ret = (Create(pParent = pWnd) &&
SetIndicators(lpIDArray, nIDCount));
if (ret) SetStyle(0, pane0Style);
else AfxMessageBox("Unable to create Statusbar.");
return ret;
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: SetIndicators
* Parameter: lpIDArray
* nIDCount
* Return: BOOL
*
* This (overridden) function produces the einzlenen Panes and defines then
* for each Pane a CNGStatusBarPaneInfo variable in a list. Additionally a timer defined
* for scrolling.
****************************************************************************/
BOOL CNGStatusBar::SetIndicators(const UINT* lpIDArray, int nIDCount)
{
CNGStatusBarPaneInfo defaultInfo;
paneInfo.RemoveAll();
paneInfo.SetSize(nIDCount);
for (int i = 0; i < nIDCount; i++)
paneInfo[i] = defaultInfo;
BOOL ret = CStatusBar::SetIndicators(lpIDArray, nIDCount);
return ret;
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: OnPaint
* Parameter: -
* Return: -
*
* Here the actual status line is produced. For this first the background is
* deleted and drawn then on each Pane a 3D-Rechteck and output the information.
* Over flickering the picture to avoid takes place the entire output first in
* a MemoryDC and into the actual PaintDC is only then copied.
****************************************************************************/
void CNGStatusBar::OnPaint()
{
CPaintDC dc(this);
CRect client;
GetClientRect(client);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap bitmap;
bitmap.CreateCompatibleBitmap(&dc, client.Width(), client.Height());
CBitmap *oldBitmap = (CBitmap *) memDC.SelectObject(&bitmap);
COLORREF hell = GetSysColor(COLOR_3DHILIGHT);
COLORREF dunkel = GetSysColor(COLOR_3DSHADOW);
memDC.FillSolidRect(client, GetSysColor(COLOR_3DFACE));
//========================================================================
// Zeichne alle Pane-Rechtecke mit ihrem Inhalt
//========================================================================
bool scroll = false;
for (int i = 0, n = paneInfo.GetSize(); i < n; i++)
{
CNGStatusBarPaneInfo &aktPane = paneInfo[i];
CRect rect;
GetItemRect(i, rect);
UINT style = GetPaneStyle(i);
if (style & SBPS_POPOUT)
memDC.Draw3dRect(rect, hell, dunkel);
else if (!(style & SBPS_NOBORDERS))
memDC.Draw3dRect(rect, dunkel, hell);
on = (GetPaneStyle(i) & SBPS_DISABLED) == 0;
rect.DeflateRect(1, 1);
memDC.FillSolidRect(rect, aktPane.GetBkColor(on));
CRgn clip;
clip.CreateRectRgnIndirect(&rect);
memDC.SelectClipRgn(&clip);
rect.DeflateRect(1,1);
switch (aktPane.GetMode() & XSB_MODE)
{
case XSB_TEXT:
case XSB_NUMBER:
DrawTextPane( &memDC, i, rect, aktPane);
break;
case XSB_BITMAP:
DrawBitmapPane( &memDC, i, rect, aktPane);
break;
case XSB_ICON_AND_TEXT:
DrawIconAndText( &memDC, i, rect, aktPane);
break;
case XSB_PROGRESS:
DrawProgressPane(&memDC, i, rect, aktPane);
break;
default:
break;
}
if (aktPane.GetMode() & XSB_SCROLL) scroll = true;
memDC.SelectClipRgn(NULL);
}
if (scroll && (timerID == 0))
{
timerID = SetTimer(IDC_JRLIB_STATUSBAR_TIMER, 100, NULL);
}
else if (!scroll && (timerID != 0))
{
KillTimer(timerID);
timerID = 0;
}
if (!GetParent()->IsZoomed())
{
DrawSizing(&memDC);
}
dc.BitBlt(0, 0, client.Width(), client.Height(), &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(oldBitmap);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: DrawSizing
* Parameter: pDC aktueller Device-Kstring[1]
* Return: -
*
* This function draws the diagonal lines at the right, lower edge of window.
****************************************************************************/
void CNGStatusBar::DrawSizing(CDC *pDC)
{
CRect rect;
GetWindowRect(&rect);
rect.OffsetRect(-rect.left, -rect.top);
CPen hellPen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
CPen dunkelPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
CPen *oldPen = pDC->SelectObject(&dunkelPen);
for (int i = 1; i < 16; i++)
{
switch (i % 4)
{
case 0:
pDC->SelectObject(&dunkelPen);
break;
case 1:
pDC->SelectObject(&hellPen);
break;
case 2:
continue;
case 3:
pDC->SelectObject(&dunkelPen);
break;
}
CPoint from(rect.right-1 - i, rect.bottom-1);
CPoint to(rect.right-1, rect.bottom-1 - i);
pDC->MoveTo(from);
pDC->LineTo(to);
}
pDC->SelectObject(oldPen);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: DrawTextPane
* Parameter: pDC Aktueller Device-Kstring[1]
* ix Index des aktuellen Panes
* rect Bounding Rectangle des aktuellen Panes
* aktPane Aktueller Pane
* Return: -
*
* Outputs a text in a Pane. If required, can this text in horizontal and/or
* vertical direction are gescrollt or aligned left, on the right or centered.
* With the Scrollen several copies of the text secondary or one above the other
* can be set, so that a continuous movement develops.
****************************************************************************/
void CNGStatusBar::DrawTextPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
CString text = aktPane.GetText(on);
if (text.IsEmpty())
text = GetPaneText(ix);
if (text.IsEmpty())
return;
CFont font;
font.CreateFontIndirect(&aktPane.GetFont());
COLORREF textColor = aktPane.GetFgColor(on);
CFont *oldFont = pDC->SelectObject(&font);
int oldBkMode = pDC->SetBkMode(TRANSPARENT);
COLORREF oldFgColor = pDC->SetTextColor(textColor);
const int mode = aktPane.GetMode();
const int repeat = mode & XSB_REPEAT;
const int hScroll = mode & XSB_HSCROLL;
const int vScroll = mode & XSB_VSCROLL;
int textAlign = mode & XSB_ALIGN;
if (hScroll)
textAlign &= ~(DT_CENTER | DT_RIGHT);
if (repeat)
{
text += " ";
CSize s = pDC->GetTextExtent(text);
if (hScroll)
aktPane.HScroll(rect, s.cx, 1);
if (vScroll)
aktPane.VScroll(rect, s.cy, 1);
int y = rect.top;
if (hScroll && vScroll)
{
for ( ; rect.left <= rect.right; rect.left += s.cx)
{
for (rect.top = y ; rect.top <= rect.bottom; rect.top += s.cy)
{
pDC->DrawText(text, rect, textAlign);
}
}
}
else if (hScroll)
{
for ( ; rect.left <= rect.right; rect.left += s.cx)
{
pDC->DrawText(text, rect, textAlign);
}
}
else if (vScroll)
{
for ( ; rect.top <= rect.bottom; rect.top += s.cy)
{
pDC->DrawText(text, rect, textAlign);
}
}
else
{
pDC->DrawText(text, rect, textAlign);
}
}
else
{
CSize s = pDC->GetTextExtent(text);
if (hScroll)
aktPane.HScroll(rect, s.cx, -rect.Width());
if (vScroll)
aktPane.VScroll(rect, s.cy, -rect.Height());
pDC->DrawText(text, rect, textAlign);
}
pDC->SelectObject(oldFont);
pDC->SetTextColor(oldFgColor);
pDC->SetBkMode(oldBkMode);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: DrawIconAndText
* Parameter: pDC Aktueller Device-Kstring[1]
* ix Index des aktuellen Panes
* rect Bounding Rectangle des aktuellen Panes
* aktPane Aktueller Pane
* Return: -
*
* Outputs icon and text in a Pane.
****************************************************************************/
void CNGStatusBar::DrawIconAndText(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
CSize iconSize(16,16);
int nIndex = m_IconImageList.AddIcon(aktPane.GetIcon());
m_IconImageList.Draw(pDC, nIndex, rect.TopLeft(), ILD_NORMAL|ILD_TRANSPARENT);
rect.left += iconSize.cx + 3;
//::DestroyIcon(hIcon);
CString text = aktPane.GetIconText();
if (text.IsEmpty())
{
text = GetPaneText(ix);
}
if (!text.IsEmpty())
{
CFont font;
font.CreateFontIndirect(&aktPane.GetFont());
COLORREF textColor = aktPane.GetFgColor(on);
const int mode = aktPane.GetMode();
CFont *oldFont = pDC->SelectObject(&font);
int oldBkMode = pDC->SetBkMode(TRANSPARENT);
COLORREF oldFgColor = pDC->SetTextColor(textColor);
int textAlign = mode & XSB_ALIGN;
CSize s = pDC->GetTextExtent(text);
pDC->DrawText(text, rect, textAlign|DT_END_ELLIPSIS);
pDC->SelectObject(oldFont);
pDC->SetTextColor(oldFgColor);
pDC->SetBkMode(oldBkMode);
}
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: DrawBitmapPane
* Parameter: pDC Aktueller Device-Kstring[1]
* ix Index des aktuellen Panes
* rect Bounding Rectangle des aktuellen Panes
* aktPane Aktueller Pane
* Return: -
*
* A bit-map in a Pane outputs. If, gescrollt can this bit-map in horizontal
* and/or vertical direction is required. The adjustment can take place left,
* on the right or centered or the bit-map can to the current Pane size be adapted
* (stretching). With the scrollen several pictures can be secondary or set,
* so that a continuous movement develops.
****************************************************************************/
void CNGStatusBar::DrawBitmapPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
UNUSED_ALWAYS(ix);
CString bmString = aktPane.GetBitmap(on);
if (bmString.IsEmpty())
return;
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bitmap;
bitmap.LoadBitmap(bmString);
BITMAP bm;
bitmap.GetBitmap(&bm);
CBitmap *oldBitmap = memDC.SelectObject(&bitmap);
const int mode = aktPane.GetMode();
const int hScroll = mode & XSB_HSCROLL;
const int vScroll = mode & XSB_VSCROLL;
const int repeat = mode & XSB_REPEAT;
const int stretch = mode & XSB_STRETCH;
if (repeat)
{
if (hScroll)
aktPane.HScroll(rect, bm.bmWidth, 1);
if (vScroll)
aktPane.VScroll(rect, bm.bmHeight, 1);
if (hScroll && !vScroll)
{
for (int x = rect.left; x < rect.right; x += bm.bmWidth)
{
pDC->BitBlt(x, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
}
}
else if (vScroll && !hScroll)
{
for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
{
pDC->BitBlt(rect.left, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
}
}
else
{
for (int x = rect.left; x < rect.right; x += bm.bmWidth)
{
for (int y = rect.top; y < rect.bottom; y += bm.bmHeight)
{
pDC->BitBlt(x, y, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
}
}
}
}
else
{
if (hScroll)
aktPane.HScroll(rect, bm.bmWidth, -rect.Width());
if (vScroll)
aktPane.VScroll(rect, bm.bmHeight, -rect.Height());
if (hScroll || vScroll)
{
pDC->BitBlt(rect.left, rect.top, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);
}
else if (stretch)
{
pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
}
else
{
if (mode & DT_RIGHT)
rect.left = rect.right - bm.bmWidth;
if (mode & DT_CENTER)
rect.left = (rect.left + rect.right - bm.bmWidth) / 2;
if (mode & DT_BOTTOM)
rect.top = rect.bottom - bm.bmHeight;
if (mode & DT_VCENTER)
rect.top = (rect.top + rect.bottom - bm.bmHeight) / 2;
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
}
}
memDC.SelectObject(oldBitmap);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: DrawProgressPane
* Parameter: pDC Aktueller Device-Kstring[1]
* ix Index des aktuellen Panes
* rect Bounding Rectangle des aktuellen Panes
* aktPane Aktueller Pane
* Return: -
*
* This function draws the progress check. For this only the definition of the size is necessary.
****************************************************************************/
void CNGStatusBar::DrawProgressPane(CDC *pDC, int ix, CRect& rect, CNGStatusBarPaneInfo& aktPane)
{
UNUSED_ALWAYS(pDC);
UNUSED_ALWAYS(aktPane);
rect.InflateRect(1, 1);
GetProgressCtrl(ix)->MoveWindow(rect, FALSE);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: GetCNGStatusBarPaneInfo
* Parameter: ix
* Return: CNGStatusBarPaneInfo&
*
* This function returns the CNGStatusBarPaneInfo variable for the current Pane as reference,
* so that the Members of this variables can be changed directly.
****************************************************************************/
CNGStatusBarPaneInfo& CNGStatusBar::GetCNGStatusBarPaneInfo(int ix)
{
ASSERT(ix < GetCount());
return paneInfo[ix];
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: OnTimer
* Parameter: nIDEvent Aktuelle Timer-Event-ID
* Return: -
*
* After each timer vent ethose is again drawn status bar.
****************************************************************************/
void CNGStatusBar::OnTimer(UINT nIDEvent)
{
if (nIDEvent == timerID) Invalidate(FALSE);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: SetStyle, SetWidth, GetStyle, GetWidth, GetID
* Parameter: ix Index des Panes
* style Neuer Style f�r das Pane
* width Neue Breite f�r das Pane
* Return: Vorheriger Style bzw. vorherige Breite des Panes bzw.
* gew�nschter Style
*
* Or new width for the indicated Pane sets a new Style or gives the value back
*
****************************************************************************/
#define GET_PANE_INFO(ix) ASSERT(ix < GetCount()); \
UINT id, style; int width; \
GetPaneInfo(ix, id, style, width)
UINT CNGStatusBar::SetStyle(int ix, UINT newStyle)
{
GET_PANE_INFO(ix);
SetPaneInfo(ix, id, newStyle, width);
return style;
}
int CNGStatusBar::SetWidth(int ix, int newWidth)
{
GET_PANE_INFO(ix);
SetPaneInfo(ix, id, style, newWidth);
return width;
}
UINT CNGStatusBar::GetStyle(int ix)
{
GET_PANE_INFO(ix);
return style;
}
int CNGStatusBar::GetWidth(int ix)
{
GET_PANE_INFO(ix);
return width;
}
UINT CNGStatusBar::GetID(int ix)
{
GET_PANE_INFO(ix);
return id;
}
#undef GET_PANE_INFO
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: OnDestroy
* Parameter: -
* Return: -
*
* When destroying the status line the timer must be deleted.
****************************************************************************/
void CNGStatusBar::OnDestroy()
{
if (timerID) KillTimer(timerID);
timerID = 0;
CStatusBar::OnDestroy();
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: SavePane, RestorePane
* Parameter: ix Aktueller Paneindex
* Return: -
*
* With these two functions the current status of a Panes can be restored
* temporarly secured and at a later point in time again, or into another Pane
* to be copied. This is then meaningful for example if in a Pane temporarily
* to another mode (for example a progress bar) is switched. For each Pane
* a buffer is available.
****************************************************************************/
void CNGStatusBar::SavePane(int ix)
{
ASSERT(ix < GetCount());
CNGStatusBarPaneInfo value;
if (!buffer.Lookup(ix, value))
buffer[ix] = paneInfo[ix];
}
void CNGStatusBar::RestorePane(int ix)
{
ASSERT(ix < GetCount());
CNGStatusBarPaneInfo value;
if (buffer.Lookup(ix, value))
{
paneInfo[ix] = value;
buffer.RemoveKey(ix);
}
Invalidate(FALSE);
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: GetPaneAtPosition
* Parameter: point Aktuelle Mausposition
* Return: Index des Panes, der unter der Maus liegt
*
* With this function one tests, which is to Pane under the mouse and which
* index of this Panes returned. It must be noted that the mouse position
* must be transferred to the status line in Client coordinates. If the father
* window is a dialog, a coordinate adjustment must be executed before the position
* examination.
****************************************************************************/
int CNGStatusBar::GetPaneAtPosition(CPoint& point)
{
if (pParent->IsKindOf(RUNTIME_CLASS(CDialog)))
{
pParent->ClientToScreen(&point);
ScreenToClient(&point);
}
CRect rect;
for (int i = 0, n = GetCount(); i < n; i++)
{
GetItemRect(i, rect);
if (rect.PtInRect(point)) return i;
}
return -1;
}
/*****************************************************************************
* Klasse: CNGStatusBar
* Funktion: OnLButtonUp, OnMButtonUp, OnRButtonUp, OnMouseMove,
* OnLButtonDown, OnMButtonDown, OnRButtonDown,
* OnLButtonDblClk, OnMButtonDblClk, OnRButtonDblClk
* Parameter: nFlags Zusatztasten bei der Mausoperation
* point Aktuelle Mausposition
* Return: -
*
* These mouse functions pass the message on directly to the parent window.
*
****************************************************************************/
#define TO_PARENT(fkt, event) \
void CNGStatusBar::fkt(UINT nFlags, CPoint point) \
{ \
pParent->SendMessage(event, (WPARAM) nFlags, MAKELPARAM(point.x, point.y)); \
CStatusBar::fkt(nFlags, point); \
}
TO_PARENT(OnLButtonUp, WM_LBUTTONUP);
TO_PARENT(OnMButtonUp, WM_MBUTTONUP);
TO_PARENT(OnRButtonUp, WM_RBUTTONUP);
TO_PARENT(OnLButtonDown, WM_LBUTTONDOWN);
TO_PARENT(OnMButtonDown, WM_MBUTTONDOWN);
TO_PARENT(OnRButtonDown, WM_RBUTTONDOWN);
TO_PARENT(OnLButtonDblClk, WM_LBUTTONDBLCLK);
TO_PARENT(OnMButtonDblClk, WM_MBUTTONDBLCLK);
TO_PARENT(OnRButtonDblClk, WM_RBUTTONDBLCLK);
TO_PARENT(OnMouseMove, WM_MOUSEMOVE);
#undef TO_PARENT
BOOL CNGStatusBar::OnEraseBkgnd(CDC* pDC)
{
UNUSED_ALWAYS(pDC);
return TRUE;//CMDIFrameWnd::OnEraseBkgnd(pDC);
}
/////////////////////////////////////////////////////////////////////////////
// Tool tip operations
void CNGStatusBar::AddToolTip(LPCTSTR lpszText, LPCRECT lpRectTool, UINT nIDTool)
{
m_ToolTip.AddTool(this, lpszText, lpRectTool, nIDTool);
}
void CNGStatusBar::SetToolRects()
{
CRect rect;
for (int i = 1, n = GetCount(); i < n; i++)
{
GetItemRect(i, &rect);
m_ToolTip.SetToolRect(this, i, &rect);
}
}
void CNGStatusBar::UpdateTipText(LPCTSTR lpszText, UINT nIDTool)
{
m_ToolTip.UpdateTipText(lpszText, this, nIDTool);
}
void CNGStatusBar::DeleteToolTip(UINT nIDTool)
{
m_ToolTip.DelTool(this, nIDTool);
}