在状态栏上添加状态指示灯的探索过程

本文介绍了一种在状态栏上模拟LED指示灯的方法,通过重绘控件或利用特定类实现,可在不影响原有文本显示的情况下增添视觉提示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    为了了解系统的工作状态,我们常常需要在一些较为显眼的地方增加特定的标识。比如,在硬件设计时,我们会利用一些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文件中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值