为了了解系统的工作状态,我们常常需要在一些较为显眼的地方增加特定的标识。比如,在硬件设计时,我们会利用一些LED标识系统的某些工作状态。
之所以要在状态栏上添加状态指示灯是因为我的主对话框上已经被图片控件覆盖,除了状态栏、菜单栏和标题栏之外,没有其他地方可以更直观地观察到系统工作的状态信息。
为了在状态栏中模拟硬件系统LED指示灯的效果,我做了如下尝试:
1、直接从CStatusBar类派生新的类,对控件进行重绘。主要添加了如下代码:
void CMyStatusBar::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代码以绘制指定项
if(lpDrawItemStruct->itemID==m_nPane)
{
CRect rect;
GetItemRect(m_nPane,&rect);//得到pane的大小
CDC *pDC = GetDC();
pDC->ExcludeClipRect(&rect);//创建新的裁剪区域
CStatusBar::OnPaint();//描绘状态条(status bar)的其余部分
CBrush brGRN(RGB(0,255,0));
CBrush brRED(RGB(255,0,0));
for(int i=0;i<6;i++)
{
CRect rectLed;
int nLen=(rect.Width()/6-2)<rect.Height() ? (rect.Width()/6-2):rect.Height();
rectLed.left=rect.left+nLen*i;
rectLed.top=rect.top+(rect.Height()-nLen)/2;
rectLed.right=rectLed.left+nLen;
rectLed.bottom=rectLed.top+nLen;
CRgn paneRgn;
paneRgn.CreateEllipticRgnIndirect(rectLed);
pDC->SelectClipRgn(&paneRgn);//选择裁剪区域
if(State[i]==1)
pDC->FillRgn(&paneRgn,&brGRN);
else
pDC->FillRgn(&paneRgn,&brRED);
}
}
}
void CMyStatusBar::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CStatusBar::OnPaint()
CRect rect;
GetItemRect(m_nPane,&rect);//得到pane的大小
CDC *pDC = GetDC();
pDC->ExcludeClipRect(&rect);//创建新的裁剪区域
CStatusBar::OnPaint();//描绘状态条(status bar)的其余部分
CBrush brGRN(RGB(0,255,0));
CBrush brRED(RGB(255,0,0));
for(int i=0;i<6;i++)
{
CRect rectLed;
int nLen=(rect.Width()/6-2)<rect.Height() ? (rect.Width()/6-2):rect.Height();
rectLed.left=rect.left+nLen*i;
rectLed.top=rect.top+(rect.Height()-nLen)/2;
rectLed.right=rectLed.left+nLen;
rectLed.bottom=rectLed.top+nLen;
CRgn paneRgn;
paneRgn.CreateEllipticRgnIndirect(rectLed);
pDC->SelectClipRgn(&paneRgn);//选择裁剪区域
if(State[i]==1)
pDC->FillRgn(&paneRgn,&brGRN);
else
pDC->FillRgn(&paneRgn,&brRED);
}
}
void CMyStatusBar::SetState(int* pState)
{
for(int i=0;i<6;i++)
State[i]=pState[i];
CRect rect;
GetItemRect(m_nPane,&rect);//得到pane的大小
InvalidateRect(&rect,1);
}
测试结果是:能够在状态栏上模拟红绿指示灯,但是原来状态栏上显示文本的地方现在不显示文本了。
2、我在优快云上下载了“特色状态栏”,发现可以不重绘状态栏也能实现在状态栏上添加其他控件的目的。于是,我利用了其中的CStatusControl和CStatusStatic类,在CStatusStatic.cpp中添加如下代码:
void CStatusStatic::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CStatic::OnPaint()
CRect rect;
GetClientRect(&rect);//得到pane的大小
CDC *pDC = GetDC();
pDC->ExcludeClipRect(&rect);//创建新的裁剪区域
CStatic::OnPaint();//描绘状态条(status bar)的其余部分
CBrush brGRN(RGB(0,255,0));
CBrush brRED(RGB(255,0,0));
for(int i=0;i<6;i++)
{
CRect rectLed;
int nLen=(rect.Width()/6-2)<rect.Height() ? (rect.Width()/6-2):rect.Height();
rectLed.left=rect.left+nLen*i;
rectLed.top=rect.top+(rect.Height()-nLen)/2;
rectLed.right=rectLed.left+nLen;
rectLed.bottom=rectLed.top+nLen;
CRgn paneRgn;
paneRgn.CreateEllipticRgnIndirect(rectLed);
pDC->SelectClipRgn(&paneRgn);//选择裁剪区域
if(State[i]==1)
pDC->FillRgn(&paneRgn,&brGRN);
else
pDC->FillRgn(&paneRgn,&brRED);
}
}
void CStatusStatic::SetState(int* pState)
{
for(int i=0;i<6;i++)
State[i]=pState[i];
CRect rect;
GetClientRect(&rect);//得到pane的大小
InvalidateRect(&rect,1);
}
测试结果:完美地达到了我的目的。
备注:
1、关于CStatusControl、CStatusStatic的使用,请参照“特色状态栏”。
2、State[6]在CStatusStatic.h中定义,要记得初始化。
3、在头文件中添加#pragma once可以避免重包含的问题。
4、CStatusStatic中内联函数的实现最好放在.cpp文件中。