所谓的标签页,无非就是一个对话框显示多个对话框的内容,需要相互切换
1 建立三个对话框,分别为IDD_page,IDD_page1,IDD_page2,分别对应类Cpage,Cpage1,Cpage2.
在IDD_page加入TAB Control控件,关联其变量为m_ctrltab,响应切换标签函数OnTab,再加一计算按钮并响应其事件处理OnCompution(),重写OnInitDialog()消息;
在Cpage头文件page.h中加入 Cpage1,Cpage2和项目的头文件
在声明中声明 Cpage1 page1;
Cpage2 page2;
在page.cpp中
在OnInitDialog()函数中加入代码
CDialog::OnInitDialog();
TCITEM item;
item.mask=TCIF_TEXT;
item.pszText=_T("数据参数");
m_tabctrl.InsertItem(0,&item);
item.pszText=_T("图形参数");
m_tabctrl.InsertItem(1,&item);
page1.Create(IDD_page1,&m_tabctrl);
page2.Create(IDD_page2,&m_tabctrl);
CRect rect;
m_tabctrl.GetClientRect(&rect);
rect.top+=20;
rect.bottom-=4;
rect.left+=4;
rect.right-=4;
page1.MoveWindow(&rect);
page2.MoveWindow(&rect);
page1.ShowWindow(TRUE);
m_tabctrl.SetCurSel(0);
return TRUE; // return TRUE unless you set the focus to a control
在OnTab中加入代码:
*pResult = 0;
int CurSel;
CurSel=m_tabctrl.GetCurSel();
switch(CurSel)
{
case 0:
page1.ShowWindow(TRUE);
page2.ShowWindow(FALSE);
break;
case 1:
page1.ShowWindow(FALSE);
page2.ShowWindow(TRUE);
break;
default:
break;
}
如此,一个标签页大体就搭建好了,能切换,但是往往我们还是要在标签页和主窗口实现某些功能,譬如说绘图,列出数据,响应计算等等。
2 主程序处理
由于做的项目需要使用vs2010与matlab互调,关于互调的生成文件以及设置,前两篇文件已经写,这里不再重述。
这里的page1,page2,page3与1中所说的不同
我们设定的是,在page1上输入参数,计算出的数据一部分显示于page1的Cedit控件中,一部分用于在page2中绘图,另一部分在page3中的list control控件中显示相应数据。而这些都是在响应page函数的OnCompution()函数以后出现
因此需要在其中写相应的处理程序
以下程序以单回分裂大于4为例介绍:
先加入initRIsingle()函数用于初始化matlab生成的库函数,这个是要在OnCompution()函数中调用的
CRISGPARAMETERDlg
中需要包含matlab生成的RI_g_single.h头文件
bool CRISGPARAMETERDlg::initRIgsingle()
{
static bool IsInitialzied=false;
/************************************************************************/
/* 初始化RI_g_single库,仅能初始化一次,否则将会出现各种错误 */
/************************************************************************/
if(IsInitialzied==false)
{
if(!RI_g_singleInitialize())
return false;
IsInitialzied=true;
}
return true;
}
在OnCompution()函数中写入如下代码:
page1.ok();//更新page1数据
int sel1,selRISG1,selRISG2,selRISG3;
sel1=page1.m_comboNumble.GetCurSel();
selRISG1=page1.m_ComboCoorRISG1.GetCurSel();
selRISG2=page1.m_ComboCoorRISG2.GetCurSel();
selRISG3=page1.m_ComboCoorRISG3.GetCurSel();
if(-1==sel1)
{
MessageBox("请选择导线分列数!!!");
}
else
{
if(-1==selRISG1 || -1==selRISG2 || -1==selRISG3)
MessageBox("请选择导线相序!!!");
else if(selRISG1==selRISG2 || selRISG1==selRISG3 || selRISG3==selRISG2)
MessageBox("导线相序不能相同!!!");
else
{
int rett=MessageBox("是否调用matlab单回磁场计算模块!!","到底调不调快说!!",MB_YESNO);
if(rett==IDNO)
{
return ;
}
initRIgsingle();//初始化matlab
int len=(page1.m_editLevelEnd-page1.m_editLevelStart)/page1.m_editStepSize+1;
mwArray x(1,len,mxDOUBLE_CLASS);
mwArray e1(1,len,mxDOUBLE_CLASS);
mwArray e2(1,len,mxDOUBLE_CLASS);
mwArray e3(1,len,mxDOUBLE_CLASS);
mwArray Emax(1,len,mxDOUBLE_CLASS);
mwArray Ep(1,1,mxDOUBLE_CLASS);
mwArray u(1,1,mxDOUBLE_CLASS);
mwArray fm(1,1,mxDOUBLE_CLASS);
mwArray rou(1,1,mxDOUBLE_CLASS);
mwArray p(3,2,mxDOUBLE_CLASS);
mwArray X1(1,3,mxDOUBLE_CLASS);
mwArray Y1(1,3,mxDOUBLE_CLASS);
mwArray n(1,1,mxDOUBLE_CLASS);
mwArray d(1,1,mxDOUBLE_CLASS);
mwArray r(1,1,mxDOUBLE_CLASS);
mwArray s1(1,1,mxDOUBLE_CLASS);
mwArray s2(1,1,mxDOUBLE_CLASS);
mwArray step(1,1,mxDOUBLE_CLASS);
mwArray h(1,1,mxDOUBLE_CLASS);
mwArray px(1,1,mxDOUBLE_CLASS);
mwArray py(1,1,mxDOUBLE_CLASS);
u(1,1)=page1.m_editVoltage;
fm(1,1)=page1.m_editFm;
rou(1,1)=page1.m_editRou;
s1(1,1)=page1.m_editLevelStart;
s2(1,1)=page1.m_editLevelEnd;
step(1,1)=page1.m_editStepSize;
h(1,1)=page1.m_editVerticalHeight;
px(1,1)=page1.m_editGaussageX;
py(1,1)=page1.m_editGaussageY;
n(1,1)=sel1+1;
d(1,1)=page1.m_editDistance;
r(1,1)=page1.m_editSubRadius;
//先将对象存入数组,向矩阵中填写
double *xD;
double *e1D;
double *e2D;
double *e3D;
double *EmaxD;
double *EpD;
double pArray[3][2]=
{
{page1.m_editPlaceAx,page1.m_editPlaceAy},
{page1.m_editPlaceBx,page1.m_editPlaceBy},
{page1.m_editPlaceCx,page1.m_editPlaceCy}
};
double X1Array[3]={page1.m_editCoordinate1X,page1.m_editCoordinate2X,page1.m_editCoordinate3X};
double Y1Array[3]={page1.m_editCoordinate1Y,page1.m_editCoordinate2Y,page1.m_editCoordinate3Y};
//bool ret=false;
//填入矩阵
for(int i = 0;i < 3; i++)
{
for(int j = 0;j < 2; j++)
{
p(i + 1,j + 1) = pArray[i][j];
}
}
for(int j = 0;j < 3; j++)
{
X1(1,j + 1) = X1Array[j];
Y1(1,j + 1) = Y1Array[j];
}
RI_g_single(6,x,e1,e2,e3,Emax,Ep,u,p,fm,n,d,r,rou,s1,s2,step,h,X1,Y1,px,py);
//取出数据用于绘制
xD =new double[len];
e1D =new double [len];
e2D = new double[len];
e3D =new double[len];
EmaxD =new double [len];
EpD =new double [len];
/************************************************************************/
/* 从MxArray类型的返回值中得到数据,将矩阵x对应值存入数组xD。 */
/************************************************************************/
x.GetData(xD,len);
e1.GetData(e1D,len);
e2.GetData(e2D,len);
e3.GetData(e3D,len);
Emax.GetData(EmaxD,len);
Ep.GetData(EpD,1);
for(int i=0;i<len;i++)
{
xD[i]=page1.m_editLevelStart+page1.m_editStepSize*i;
}
/**********************************************************
* 生成曲线 *
***********************************************************/
page2.DrawPic(len,xD,e1D,e2D,e3D);
page1.m_editResult=*EpD;
page1.UpdateData(false);
page3.ShowData(len,xD,e1D,e2D,e3D,EmaxD);
MessageBox("计算完成");
}
}
3 page1中的程序
void CRISG1Dlg::OnPaint()
{
CRect rcclient;
CPaintDC dc2(GetDlgItem(IDC_PICTURERISG));
CRect rcclient2;
GetDlgItem(IDC_PICTURERISG)->GetClientRect(&rcclient2);
CDC memdc2;
memdc2.CreateCompatibleDC(&dc2);
CBitmap bitmap2;
bitmap2.CreateCompatibleBitmap(&dc2, rcclient.Width(), rcclient.Height());
memdc2.SelectObject( &bitmap2 );
CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc2.m_hDC , 0);
CBrush brush2;
brush2.CreatePatternBrush(&m_bmp2);
dc2.FillRect(rcclient2, &brush2);
dc2.BitBlt(rcclient2.left, rcclient2.top, rcclient2.Width(), rcclient2.Height(), &memdc2, rcclient2.left, rcclient2.top,SRCPAINT);
brush2.DeleteObject();
return ;
}
void CRISG1Dlg::OnSelchangeComboNumbleRisg()
/*这里使用了图片控件,以及combo box控件,需要实现的是,当combo box控件点下拉列表的某项时,显示相应的图片,图片路径需要根据不同系统不同路径做不同的设置*/
/*与OnPaint()函数共同实现了这个功能*/
{
// TODO: 在此添加控件通知处理程序代码
int nSel;
CString picname;
nSel = m_comboNumble.GetCurSel();
switch(nSel)
{
case 0: picname = _T("..\\picture\\fx1.bmp"); break;
case 1: picname = _T("..\\picture\\fx2.bmp"); break;
case 2: picname = _T("..\\picture\\fx3.bmp"); break;
case 3: picname = _T("..\\picture\\fx4.bmp"); break;
case 4: picname = _T("..\\picture\\fx5.bmp"); break;
case 5: picname = _T("..\\picture\\fx6.bmp"); break;
case 6: picname = _T("..\\picture\\fx7.bmp"); break;
case 7: picname = _T("..\\picture\\fx8.bmp"); break;
default: break;
}
//载入图片
if( m_bmp2.m_hObject != NULL )//判断 m_bmp2是否在使用,在使用则释放
m_bmp2.DeleteObject();
HBITMAP hbmp2 = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
picname, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
m_bmp2.Attach( hbmp2 );
DIBSECTION ds2;
BITMAPINFOHEADER &bminfo2 = ds2.dsBmih;
m_bmp2.GetObject( sizeof(ds2), &ds2 );
int cx2=bminfo2.biWidth;//得到图像宽度
int cy2=bminfo2.biHeight; //得到图像高度
//得到图像的宽度和高度后,对图像大小进行适应,即调整控件的大小,让它正好显示一张图片
CRect rect2;
GetDlgItem(IDC_PICTURERISG)->GetWindowRect(&rect2);
ScreenToClient(&rect2);
GetDlgItem(IDC_PICTURERISG)->MoveWindow(rect2.left,rect2.top,cx2,cy2,true);//调整大小
Invalidate();
return;
}
//以下三个为相序,由于是固定值,也根据combo box的下拉相应选项定不同值
void CRISG1Dlg::OnSelchangeCombocoorrisg1()
{
// TODO: 在此添加控件通知处理程序代码
int nsel;
nsel=m_ComboCoorRISG1.GetCurSel();
if(0==nsel)
{
m_editCoordinate1X=1;
m_editCoordinate1Y=0;
}
else if(1==nsel)
{
m_editCoordinate1X=-0.5;
m_editCoordinate1Y=-0.866;
}
else if(2==nsel)
{
m_editCoordinate1X=-0.5;
m_editCoordinate1Y=0.866;
}
else
{
m_editCoordinate1X=0;
m_editCoordinate1Y=0;
}
ok();
}
void CRISG1Dlg::OnSelchangeCombocoorrisg2()
{
// TODO: 在此添加控件通知处理程序代码
int nsel;
nsel=m_ComboCoorRISG2.GetCurSel();
if(0==nsel)
{
m_editCoordinate2X=1;
m_editCoordinate2Y=0;
}
else if(1==nsel)
{
m_editCoordinate2X=-0.5;
m_editCoordinate2Y=-0.866;
}
else if(2==nsel)
{
m_editCoordinate2X=-0.5;
m_editCoordinate2Y=0.866;
}
else
{
m_editCoordinate2X=0;
m_editCoordinate2Y=0;
}
ok();
}
void CRISG1Dlg::OnSelchangeCombocoorrisg3()
{
// TODO: 在此添加控件通知处理程序代码
int nsel;
nsel=m_ComboCoorRISG3.GetCurSel();
if(0==nsel)
{
m_editCoordinate3X=1;
m_editCoordinate3Y=0;
}
else if(1==nsel)
{
m_editCoordinate3X=-0.5;
m_editCoordinate3Y=-0.866;
}
else if(2==nsel)
{
m_editCoordinate3X=-0.5;
m_editCoordinate3Y=0.866;
}
else
{
m_editCoordinate3X=0;
m_editCoordinate3Y=0;
}
ok();
}
void CRISG1Dlg::ok()
{
UpdateData(TRUE);
}
4 page2中程序 头文件中需要包含viewLine.h
CRect CRISDlg2::GetRect()
{
CRect rect;
GetDlgItem(IDC_STATICDRAWRIS)->GetWindowRect((&rect));
return rect;
}
BOOL CRISDlg2::OnInitDialog()
{
CDialog::OnInitDialog();
CRect rect;
GetDlgItem(IDC_STATICDRAWRIS)->GetWindowRect((&rect));
ScreenToClient(rect);
rect.top+=25;
rect.bottom-=45;
rect.right-=4;
viewLine=new CViewLine;
viewLine->setText("电场");
viewLine->viewSignal=MAGNETISM_COORDINATE_DRAW;
viewLine->Create(NULL,NULL,0,rect,this,0,NULL);
viewLine->SetParent(this);
viewLine->ShowWindow(TRUE);
return TRUE;
}
BEGIN_MESSAGE_MAP(CRISDlg2, CDialog)
END_MESSAGE_MAP()
void CRISDlg2::DrawPic(int countTemp,double * pXx,double * pB,double * pBx,double * pBy)
{
viewLine->setCount( countTemp );
viewLine->setXx( pXx );
viewLine->setB( pB );
viewLine->setBx( pBx );
viewLine->setBy( pBy );
if( NULL == viewLine->pXxDraw )
{
MessageBox( _T( "观测点坐标为空!" ) );
return;
}
else if( NULL == viewLine->pBDraw )
{
MessageBox( _T( "观测点综合磁场强度为空!" ) );
return;
}
else if ( NULL == viewLine->pBxDraw )
{
MessageBox( _T( "观测点水平磁场强度为空!" ) );
return;
}
else if ( NULL == viewLine->pByDraw )
{
MessageBox( _T( "观测点垂直磁场强度为空!" ) );
return;
}
else
{
viewLine->viewSignal = MAGNETISM_CURVE_DRAW;//设置绘制曲线标志
viewLine->Invalidate();
viewLine->UpdateWindow();
}
}
5 page3中程序
BOOL CListDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_list.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT);
//m_list.SetExtendedStyle(LVS_EX_FLATSB
// |LVS_EX_FULLROWSELECT
// |LVS_EX_HEADERDRAGDROP
// |LVS_EX_ONECLICKACTIVATE
// |LVS_EX_GRIDLINES);
if(0==flog)
{
m_list.InsertColumn(0,"水平位置",LVCFMT_LEFT,100);
m_list.InsertColumn(1,"水平磁场强度",LVCFMT_LEFT,120);
m_list.InsertColumn(2,"垂直磁场强度",LVCFMT_LEFT,120);
m_list.InsertColumn(3,"综合磁场强度",LVCFMT_LEFT,120);
}
else if(1==flog)
{
m_list.InsertColumn(0,"水平位置",LVCFMT_CENTER,100);
m_list.InsertColumn(1,"水平电场强度",LVCFMT_CENTER,120);
m_list.InsertColumn(2,"垂直电场强度",LVCFMT_CENTER,120);
m_list.InsertColumn(3,"综合电场强度",LVCFMT_CENTER,120);
}
else if(2==flog)
{
m_list.InsertColumn(0,"水平位置",LVCFMT_LEFT,100);
m_list.InsertColumn(1,"x方向电场强度",LVCFMT_LEFT,120);
m_list.InsertColumn(2,"y方向电场强度",LVCFMT_LEFT,120);
m_list.InsertColumn(3,"z方向电场强度",LVCFMT_LEFT,120);
m_list.InsertColumn(4,"综合电场强度",LVCFMT_LEFT,120);
}
else
{}
// TODO: 在此添加额外的初始化
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CListDlg::ShowData(int count,double * pXx,double * pBx,double * pBy,double * pBz,double * pB)
{
if(0==flog || 1==flog)
{
int i=0;
CString strXx,strBx,strBy,strBz,strB;
//strBz.Format("%d",(*pBz));
while(i<count)
{
strXx.Format("%lf",(*pXx));
strBx.Format("%lf",(*pBx));
strBy.Format("%lf",(*pBy));
strB.Format("%lf",(*pB));
m_list.InsertItem(i,strXx);
m_list.SetItemText(i,1,strBx);
m_list.SetItemText(i,2,strBy);
m_list.SetItemText(i,3,strB);
i++;
pXx++;
pBx++;
pBy++;
pB++;
}
}
else if(2==flog)
{
int i=0;
CString strXx,strBx,strBy,strBz,strB;
while(i<count)
{
strXx.Format("%lf",(*pXx));
strBx.Format("%lf",(*pBx));
strBy.Format("%lf",(*pBy));
strBz.Format("%lf",(*pBz));
strB.Format("%lf",(*pB));
m_list.InsertItem(i,strXx);
m_list.SetItemText(i,1,strBx);
m_list.SetItemText(i,2,strBy);
m_list.SetItemText(i,3,strBz);
m_list.SetItemText(i,4,strB);
i++;
pXx++;
pBx++;
pBy++;
pBz++;
pB++;
}
}
else
{
}
}
这里由于多个程序都要调用page3,所以用flog作一判断,以响应不同程序的要求,如果只是单一的使用,不需要做这些if else判断
以上就是主要程序。
5 总结以及一些问题
4中也说了,有很多个类需要这样使用,而且有很多单个的标签页是大体相同的,譬如page2,page3;这样就在想是否可以只做一个page2,page3,其它类调用的时候包含它就行了,依照这个思路,对page2,page3进行编程,编程结果是page3能实现,而page2却会出bug。
分析了一下原因,page3中只有listbox控件,在使用此控件时只使用了它关联的变量m_list,而不是使用控件ID
而page2中有static控件,使用的时候需要使用控件ID,若多个类都使用这一个iD就会出bug。
由此,提出了设想:(1)可不可以动态的设定static控件的ID,并将其ID号保存于一个数组当中,根据标识FLAG的值来确定使用哪一个ID
(2)只使用这一个控件ID但是在窗口销毁的时候释放控件资源,让下一个窗口使用这个ID
(3)由于page1中有图片的显示,有想过用GDI+来绘制,GDI+的DrawImage函数是否需要释放
(4)关于用GDI+绘制数据的曲线,GDI绘制曲线的标注可能有些些不准
6 一下为子标签图形,第二幅还有些问题,需要做一些修改