📄 edfscheduledlg.cpp
字号:
// EDFScheduleDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "EDFSchedule.h"
#include "EDFScheduleDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// 对话框数据
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
// 实现
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CEDFScheduleDlg 对话框
CEDFScheduleDlg::CEDFScheduleDlg(CWnd* pParent /*=NULL*/)
: CExpandingDialog(CEDFScheduleDlg::IDD, pParent,IDC_DEFUALTBOX,IDC_EXPAND,
_T("展开>>"),_T("简缩<<"))
, m_bWorking(FALSE)
, m_TaskName(_T(""))
, m_Period(0)
, m_CPUTime(0)
, m_U(0)
, m_Tid(-1)
, m_TimeCounter(0)
, m_TidNT(-1)
, m_TimeCounterNT(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CEDFScheduleDlg::DoDataExchange(CDataExchange* pDX)
{
CExpandingDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_NAME, m_TaskName);
DDX_Text(pDX, IDC_PERIOD, m_Period);
DDX_Text(pDX, IDC_CPUTIME, m_CPUTime);
DDX_Control(pDX, IDC_CURTITLE, m_TCBTitle);
DDX_Control(pDX, IDC_PROGRESS, m_TCBProgress);
}
BEGIN_MESSAGE_MAP(CEDFScheduleDlg, CExpandingDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_CREATE()
ON_BN_CLICKED(IDC_RUN, &CEDFScheduleDlg::OnBnClickedRun)
ON_BN_CLICKED(IDC_ADD, &CEDFScheduleDlg::OnBnClickedAdd)
ON_BN_CLICKED(IDC_END, &CEDFScheduleDlg::OnBnClickedEnd)
ON_WM_TIMER()
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CEDFScheduleDlg 消息处理程序
BOOL CEDFScheduleDlg::OnInitDialog()
{
CExpandingDialog::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_TCBProgress.SetBarColor(RGB(80,50,50));
CreateBitmapCtrl();
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CEDFScheduleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CExpandingDialog::OnSysCommand(nID, lParam);
}
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CEDFScheduleDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CExpandingDialog::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CEDFScheduleDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CEDFScheduleDlg::OnOK()
{
//CDialog::OnOK();
}
int CEDFScheduleDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_TSB.CreateEx(this,SBARS_SIZEGRIP))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);//这句很关键
return 0;
}
void CEDFScheduleDlg::OnBnClickedAdd()
{
UpdateData();
if (Satisfy())
{
TCB *pTCB=new TCB;
pTCB->TaskName=m_TaskName;
pTCB->Period=m_Period;
pTCB->CPUTime=m_CPUTime;
pTCB->RemainTime=m_CPUTime;
pTCB->nCount=0;
pTCB->RemainTimeNT=m_CPUTime;
pTCB->nCountNT=0;
m_TCBPtrArray.Add(pTCB);
}
return;
}
BOOL CEDFScheduleDlg::Satisfy()
{
if (m_Period<0||m_CPUTime<0||m_Period<m_CPUTime)
{
MessageBox(_T("CPU时间必须小于周期而且两者都不能小于零!"));
return FALSE;
}
if (m_TaskName.IsEmpty())
{
MessageBox(_T("任务名称不能为空!"));
return FALSE;
}
int Sum=m_TCBPtrArray.GetCount();
TCB *pTCB=NULL;
for (int i=0;i<Sum;i++)
{
pTCB=(TCB*)m_TCBPtrArray.GetAt(i);
if (m_TaskName==pTCB->TaskName)
{
MessageBox(_T("任务名称已存在!"));
return FALSE;
}
}
m_U+=m_CPUTime/m_Period;
if (m_U>1)
{
MessageBox(_T("添加任务后CPU利用率大于零!"));
m_U-=m_CPUTime/m_Period;
return FALSE;
}
else
return TRUE;
}
void CEDFScheduleDlg::OnBnClickedRun()
{
int Sum=m_TCBPtrArray.GetCount();
if (Sum<1)
{
MessageBox(_T("当前队列中没有任务"));
return;
}
m_bWorking=TRUE;
EnableCtrls();
if (!SetTimer(CLOCK_TIMER, 1000, NULL))
{
MessageBox(_T("创建时钟失败!"));
PostMessage(WM_QUIT);
return;
}
//SelectTask();
//以上是时间驱动的调度过程,形象的显示了某一时刻哪个任务正在执行。
//下面进行一个非时间驱动的调度,以便把整个调度流程图绘制出来。
ScheduleNotTimeDrived();
m_BitmapCtrl.ReSetBitmap(m_ShowFlowBitmap);
}
void CEDFScheduleDlg::OnBnClickedEnd()
{
m_bWorking=FALSE;
KillTimer(CLOCK_TIMER);
m_TimeCounter=0;
CString strTitle;
strTitle=_T("00:00:00");
m_TSB.m_strTime=strTitle;
m_TSB.SetTime();
strTitle=_T("未进行调度");
m_TCBTitle.SetWindowTextW(strTitle);
m_TCBProgress.SetPos(0);
ResetTask();
EnableCtrls();
}
void CEDFScheduleDlg::OnTimer(UINT_PTR nIDEvent)
{
if (!m_bWorking)//不是处于调度状态
;
else
{
CString strTime,strH,strM,strC;//时,分,秒。
if (m_TimeCounter/3600<10)
strH.Format(_T("0%d"),(m_TimeCounter/3600)%24);
else
strH.Format(_T("%d"),(m_TimeCounter/3600)%24);
if ((m_TimeCounter/60)%60<10)//分钟数
strM.Format(_T("0%d"),(m_TimeCounter/60)%60);
else
strM.Format(_T("%d"),(m_TimeCounter/60)%60);
if (m_TimeCounter%60<10)
strC.Format(_T("0%d"),m_TimeCounter%60);
else
strC.Format(_T("%d"),m_TimeCounter%60);
strTime.Format(_T("%s:%s:%s"),strH,strM,strC);
m_TSB.m_strTime=strTime;
m_TSB.SetTime();
int nPos=0;
nPos=m_TCBProgress.GetPos();
nPos++;
m_TCBProgress.SetPos(nPos);
TCB * pTCB=NULL;
if (m_Tid==-1)//CPU空跑
SelectTask();
else
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(m_Tid);
pTCB->RemainTime--;
if (pTCB->RemainTime<=0)
{
pTCB->nCount++;
pTCB->RemainTime=pTCB->CPUTime;
}
m_Tid=-1;
SelectTask();
}
m_TimeCounter++;
}
CDialog::OnTimer(nIDEvent);
}
void CEDFScheduleDlg::SelectTask()
{
int Sum=m_TCBPtrArray.GetCount();
TCB * pTCB=NULL;
double ET=LONG_MAX;//最早截止时间
double SET=LONG_MAX;//下一个最早开始的任务的开始时间。
for (int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
if (SET>((pTCB->nCount)*pTCB->Period))
SET=(pTCB->nCount)*pTCB->Period;
if ((pTCB->nCount*pTCB->Period)<=m_TimeCounter)//此刻在该任务的周期内
{
if (ET>((pTCB->nCount+1)*pTCB->Period))
{
ET=(pTCB->nCount+1)*pTCB->Period;//最早截止时间
m_Tid=i;//选择最早截止时间的任务
}
}
}
StartToRun();
return;
}
void CEDFScheduleDlg::StartToRun()
{
TCB * pTCB=NULL;
CString strTitle;
if (m_Tid==-1)//CPU空跑
{
m_TCBProgress.SetRange(0,1);
m_TCBProgress.SetPos(0);
strTitle=_T("CPU空跑");
}
else
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(m_Tid);
m_TCBProgress.SetRange(0,pTCB->CPUTime);
m_TCBProgress.SetPos(pTCB->CPUTime-pTCB->RemainTime+1);
strTitle.Format(_T("任务%s正在执行第%d秒"),pTCB->TaskName,int((pTCB->CPUTime) - (pTCB->RemainTime)+1));
}
m_TCBTitle.SetWindowTextW(strTitle);
}
void CEDFScheduleDlg::EnableCtrls()
{
CButton *pBA=(CButton *)GetDlgItem(IDC_ADD);
CButton *pBR=(CButton *)GetDlgItem(IDC_RUN);
if (m_bWorking)
{
pBA->EnableWindow(FALSE);
pBR->EnableWindow(FALSE);
}
else
{
pBA->EnableWindow(TRUE);
pBR->EnableWindow(TRUE);
}
return;
}
void CEDFScheduleDlg::ResetTask()
{
m_Tid=-1;
m_TimeCounter=0;
int Sum=m_TCBPtrArray.GetCount();
TCB * pTCB=NULL;
for (int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
pTCB->nCount=0;
pTCB->RemainTime=pTCB->CPUTime;
}
}
void CEDFScheduleDlg::OnDestroy()
{
int Sum=m_TCBPtrArray.GetCount();
TCB * pTCB=NULL;
for (int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
delete pTCB;
}
m_TCBPtrArray.RemoveAll();
CDialog::OnDestroy();
}
BOOL CEDFScheduleDlg::OnDialogExpanding(BOOL bExpanded)
{
return TRUE;
}
void CEDFScheduleDlg::OnDialogExpanded(BOOL bExpanded)
{
CRect rect1,rect2;
GetClientRect(&rect1);
m_TSB.GetWindowRect(&rect2);
rect1.top=rect1.bottom-rect2.Height();
m_TSB.MoveWindow(rect1);
}
BOOL CEDFScheduleDlg::CreateBitmapCtrl()
{
CRect rect;
CWnd* pCtrl=NULL;
pCtrl=GetDlgItem(IDC_BITMAPBOX);
if (pCtrl==NULL)
return FALSE;
pCtrl->GetWindowRect(&rect);
ScreenToClient(&rect);//记得要把屏幕坐标转换为客户区坐标。
m_BitmapCtrl.Create(RECT(rect),this,2000);
return TRUE;
}
void CEDFScheduleDlg::ScheduleNotTimeDrived()
{
double MaxPeriod=GetMaxPeriod();
double MaxCounter=3*MaxPeriod;
//下面做计数驱动,最大计数为所有任务的最大周期的三倍。
TCB * pTCB=NULL;
m_TimeCounterNT=0;
DrawFitBitmap(MaxCounter);
while (m_TimeCounterNT<=MaxCounter)
{
if (m_TidNT==-1)//CPU空跑
SelectTaskNT();
else
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(m_TidNT);
pTCB->RemainTimeNT--;
if (pTCB->RemainTimeNT<=0)
{
pTCB->nCountNT++;
pTCB->RemainTimeNT=pTCB->CPUTime;
}
m_TidNT=-1;
SelectTaskNT();
}
DrawThePeriod();
m_TimeCounterNT++;
}
m_dcMem.SelectObject(m_pOldBitmap);
ResetTaskNT();
}
void CEDFScheduleDlg::SelectTaskNT()
{
int Sum=m_TCBPtrArray.GetCount();
TCB * pTCB=NULL;
double ET=LONG_MAX;//最早截止时间。
double SET=LONG_MAX;//下一个最早开始的任务的开始时间。
for (int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
if (SET>((pTCB->nCountNT)*pTCB->Period))
SET=(pTCB->nCountNT)*pTCB->Period;
if ((pTCB->nCountNT*pTCB->Period)<=m_TimeCounterNT)//此刻在该任务的周期内
{
if (ET>((pTCB->nCountNT+1)*pTCB->Period))
{
ET=(pTCB->nCountNT+1)*pTCB->Period;//最早截止时间
m_TidNT=i;//选择最早截止时间的任务
}
}
}
}
void CEDFScheduleDlg::ResetTaskNT()
{
m_TidNT=-1;
m_TimeCounterNT=0;
int Sum=m_TCBPtrArray.GetCount();
TCB * pTCB=NULL;
for(int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
pTCB->nCountNT=0;
}
}
double CEDFScheduleDlg::GetMaxPeriod()
{
int Sum=m_TCBPtrArray.GetCount();
double MaxPeriod=-1;
TCB * pTCB=NULL;
for(int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
if (MaxPeriod<pTCB->Period)
MaxPeriod=pTCB->Period;
}
return MaxPeriod;
}
void CEDFScheduleDlg::DrawFitBitmap(double MaxCounter)
{
if (HBITMAP(m_ShowFlowBitmap)!=NULL)
m_ShowFlowBitmap.DeleteObject();
CClientDC dc(this);
int Sum=m_TCBPtrArray.GetCount();
double nWidth=MaxCounter*BLOCKWIDTH+LEFTOFFSET+RIGHTOFFSET;
long nHeight=LINEHEIGHT*Sum+BOTTOMOFFSET;
m_ShowFlowBitmap.CreateCompatibleBitmap(&dc,nWidth,nHeight);
if (m_dcMem.m_hDC!=NULL)
m_dcMem.DeleteDC();
m_dcMem.CreateCompatibleDC(&dc);
CBrush brush(RGB(255,255,255));
m_pOldBitmap=m_dcMem.SelectObject(&m_ShowFlowBitmap);
m_dcMem.FillRect(CRect(0,0,nWidth,nHeight),&brush);
CPoint point(0,0);
TCB * pTCB=NULL;
for (int i=0;i<Sum;i++)
{
pTCB=(TCB *)m_TCBPtrArray.GetAt(i);
m_dcMem.TextOut(3,(i+1)*LINEHEIGHT-BLOCKHEIGHT,pTCB->TaskName);
m_dcMem.MoveTo(LEFTOFFSET,(i+1)*LINEHEIGHT);
m_dcMem.LineTo(nWidth,(i+1)*LINEHEIGHT);
for(int j=0;j<=MaxCounter;j++)
{
point=CPoint(LEFTOFFSET+j*BLOCKWIDTH,(i+1)*LINEHEIGHT+3);
CString strTime;
strTime.Format(_T("%d"),j);
m_dcMem.TextOut(point.x,point.y,strTime);
}
}
}
void CEDFScheduleDlg::DrawThePeriod()
{
if (m_TidNT==-1)
return;
if (HBITMAP(m_ShowFlowBitmap)==NULL)
return;
CBrush brush(RGB(60,120,60));
CRect rect;
rect.left=LEFTOFFSET+m_TimeCounterNT*BLOCKWIDTH;
rect.top=(m_TidNT+1)*LINEHEIGHT-BLOCKHEIGHT;
rect.right=LEFTOFFSET+(m_TimeCounterNT+1)*BLOCKWIDTH;
rect.bottom=(m_TidNT+1)*LINEHEIGHT;
m_dcMem.FillRect(&rect,&brush);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -