介绍
在电力系统中,客户经常提出要实现电力系统监控主接线图的潮流实现。所谓潮流实现即是在电力监控系统的主接线图中能够动态反映各线路的运行情况,包含电流流动方向,各设备运行状态等。由于在水电站监控系统中很多用户提出要求能够反映发电机组的动态运行情况,即在主接线图中能够反映哪个机组正在运行。这里我采用贴图法进行动态贴图然后交替显示达到动态运行的目的。当然我们可以采用其他的很多方法,比如CDC类对象动态绘制等。
正文
采用CDC类对象动态绘制代码比较繁琐,而且效果不是很明显。如果采用贴图法实现就比较简单了。我们载入各个不同状态下的位图,然后利用定时器控制图片更替的速度和是否显示静止图片等。如果我们采用在VIEW类中定义定时器然后进行控制,这样也可以实现,但是如果有多个这样的功能控制,每个功能控制占用不同的定时的话,这样程序结构就会显得非常的繁琐和复杂,考虑到程序结构的完整,我们采用派生CSTATIC类方法实现。
重载CSTATIC类,取名CPowerStateCtrl,然后出发WM_PAINT,WM_CREATE,WM_TIMER消息。其简单实现如下:
private:
void Initialize();
HDC m_hPowerDC1;
HDC m_hPowerDC2;
HDC m_hPowerDC3;
HDC m_hPowerDC4;
HDC m_hMemDC;
BOOL m_bIsPowering;
int m_cxAngle,m_cyAngle;
protected:
int m_nControl;
定义一个载入图片函数,根据不同的载入返回不同的位图句柄
void CPowerStateCtrl::LoadPicture(int nResourceID, HDC &hDestinationDC, int &nWidth, int &nHeight, HDC hDC)
{
HDC hMemDC;
HDC hdcCompatible;
HBITMAP hbmScreen;
if (nResourceID != 0)
{
// if resourceid is given, load bitmap
HBITMAP hPicture = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(nResourceID));
BITMAP bm;
GetObject(hPicture, sizeof (BITMAP), (LPSTR)&bm);
hMemDC = CreateCompatibleDC(hDC);
HBITMAP hOldBMP = (HBITMAP)SelectObject(hMemDC, hPicture);
nWidth = bm.bmWidth;
nHeight = bm.bmHeight;
// Create the DC
hdcCompatible = CreateCompatibleDC(hDC);
// Temporary memory bitmap
hbmScreen = CreateCompatibleBitmap(hDC, nWidth, nHeight);
// select bitmap into dc
if (SelectObject(hdcCompatible, hbmScreen) == NULL)
{
// return null
hDestinationDC = NULL;
}
else
{
// return the DC
hDestinationDC = hdcCompatible;
}
if (hDestinationDC)
BitBlt(hDestinationDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOldBMP);
// Release temporary stuff
DeleteDC(hMemDC);
DeleteObject(hbmScreen);
DeleteObject(hPicture);
}
else // if no resourceid is given, create empty DC with specified width and height
{
// create the DC
hdcCompatible = CreateCompatibleDC(hDC);
// temporary memory bitmap
hbmScreen = CreateCompatibleBitmap(hDC, nWidth, nHeight);
// if the function fails
if (SelectObject(hdcCompatible, hbmScreen) == NULL)
{
// return null
hDestinationDC = NULL;
}
else
{
// if it suclearcase/" target="_blank" >cceeds, return the DC
hDestinationDC = hdcCompatible;
}
DeleteObject(hbmScreen);
}
}
启动定时器进行不同的状态交替控制
void CPowerStateCtrl::Initialize()
{
CDC *pDC = GetDC();
// Load powerstate picture1 and creates background DC
LoadPicture(IDB_STATE01, m_hPowerDC1, m_cxAngle, m_cyAngle, pDC->m_hDC);
// Load powerstate picture2 and creates background DC
LoadPicture(IDB_STATE02, m_hPowerDC2, m_cxAngle, m_cyAngle, pDC->m_hDC);
// Load powerstate picture3 and creates background DC
LoadPicture(IDB_STATE03, m_hPowerDC3, m_cxAngle, m_cyAngle, pDC->m_hDC);
// Load powerstate picture4 and creates background DC
LoadPicture(IDB_STATE04, m_hPowerDC4, m_cxAngle, m_cyAngle, pDC->m_hDC);
// create work area
LoadPicture(0, m_hMemDC, m_cxAngle, m_cyAngle, pDC->m_hDC);
ReleaseDC(pDC);
SetTimer(1,40,NULL);
}
由于我这里采用4个图片交替显示,所以定时器控制如下:
void CPowerStateCtrl::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
m_nControl ++;
if(m_nControl > 3)
m_nControl = 0;
Invalidate();
CStatic::OnTimer(nIDEvent);
}
至此该控件类基本功能完成,我们再定义几个外部程序接口来实现参数的传递就可以了。
void CPowerStateCtrl::SetCtrlTimer(int nTime)
{
KillTimer(1);
SetTimer(1,nTime,NULL);
}
void CPowerStateCtrl::SetPowerCtrlState(BOOL bState)
{
m_bIsPowering = bState;
Invalidate();
}
BOOL CPowerStateCtrl::GetPowerCtrlState()
{
return m_bIsPowering;
}
主程序调用:
新建一个SDI工程,然后加入该类的H和CPP文件,并定义变量对象。实例中我定义了4台发电机组,这里定义4个变量对象。
#include "PowerStateCtrl.h"
private :
CPowerStateCtrl m_GroupeCtrl[10];
CRect m_GroupeCtrlRect[10];
void CTestView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
//for main bmp
//main
m_GroupeCtrlRect[0].left = 160; m_GroupeCtrlRect[0].top = 460;
m_GroupeCtrlRect[0].right = 160+20; m_GroupeCtrlRect[0].bottom = 460+20;
m_GroupeCtrlRect[1].left = 366; m_GroupeCtrlRect[1].top = 460;
m_GroupeCtrlRect[1].right = 366+20; m_GroupeCtrlRect[1].bottom = 460+20;
m_GroupeCtrlRect[2].left = 505; m_GroupeCtrlRect[2].top = 460;
m_GroupeCtrlRect[2].right = 505+20; m_GroupeCtrlRect[2].bottom = 460+20;
m_GroupeCtrlRect[3].left = 663; m_GroupeCtrlRect[3].top = 460;
m_GroupeCtrlRect[3].right = 663+20; m_GroupeCtrlRect[3].bottom = 460+20;
for(int i = 0 ; i < 4 ; i ++)
{
m_GroupeCtrl[i].Create("",WS_CHILD|WS_VISIBLE,m_GroupeCtrlRect[i],this,NULL);
m_GroupeCtrl[i].ShowWindow(SW_SHOW);
m_GroupeCtrl[i].SetPowerCtrlState(TRUE);
}
}
然后出发菜单消息进行自动控制就可以看出效果了。
void CTestView::OnControl()
{
// TODO: Add your command handler code here
CPowerConDlg dlg;
if(dlg.DoModal() == IDOK)
{
if(dlg.bState)
{
m_GroupeCtrl[dlg.nGroupe].SetPowerCtrlState(TRUE);
m_GroupeCtrl[dlg.nGroupe].SetCtrlTimer(dlg.nTime);
}
else
{
m_GroupeCtrl[dlg.nGroupe].SetPowerCtrlState(FALSE);
m_GroupeCtrl[dlg.nGroupe].SetCtrlTimer(dlg.nTime);
}
}
}
演示界面如下:
文章添加比较仓促,具体演示效果可以参考下载程序文件。
如果有什么问题可以直接和我联系:13975102873@hnmcc.com
正文完