自定义一组向导页面(1)

作为程序的一个环节,想设计一套选择题程序,点击进入后开始做5道选择题,下图是父窗口(CDlgSEL_MAIN)


点击进去后,进入答题界面,



每个答题界面都和上图一样,除了图片载入内容不同外, 按钮、字体、缩放大小等设置都一样。一种最直接的方法是定义5个类,然后对每个类的对象进行操作。这样设计太麻烦,如果选择题数目增大,工作量会成倍增加。

还有一种方法是使用属性向导页面的方法,但是按钮什么的调整不够灵活,也不太熟悉。

于是考虑只定义一个对话框类,然后定义5个不同的对象,再把5个对象串联起来,最后设计好每个对象上一页和下一页的向导按钮。

对话框类资源如下,

  添加类名为CDlgSEL (选择题对话框)。在OnInitialDialog( ) 中设置好缩放比例,字体,GDI+的初始化,在头文件DlgSEL.h中,设置好GDI+的定义,在OnDestroy( ) 消息中设置好GDI+的删除。因为每个对象要载入的图像是不一样的。因此还需要设置好一些public 变量,以便在类的外部进行初始化。

public    

    Image * m_pImage;   //要载入的指向图片的指针

	int ise;                    //选择题序号
	int flag;                 //标志号,用于标记该对象是否已经打开
	CDlgSEL *last, *next,*p1;         //每个对象的头指针,尾指针,和指向该对象的指针,把对象串起来的时候用。

    有了这些公有变量,就可以在其他的类中,对这些变量进行赋值,从而初始化得到不同的对象。在父类(CDlgSEL_MAIN)的头文件中,包含选择题类头文件

    

 #include "DlgSEL.h" 
public:
CDlgSEL selmain0, selmain1, selmain2,selmain3, selmain4; \\5个对象

并定义好5个对象。接着,在OnInitialDialog()中,对不同的选择题界面进行初始化,设置好头尾指针,序号。

selmain0.m_pImage = Image::FromFile(_T("D:\\sel1.jpg"));
	selmain0.ise = 0;
	selmain0.last = &selmain4;
	selmain0.next = &selmain1;
	selmain1.m_pImage = Image::FromFile(_T("D:\\sel2.jpg"));
	selmain1.ise = 1;
	selmain1.last =&selmain0;
	selmain1.next = &selmain2;;
	selmain2.m_pImage = Image::FromFile(_T("D:\\sel3.jpg"));
	selmain2.ise = 2;
	selmain2.last = &selmain1;
	selmain2.next = &selmain3;
	selmain3.m_pImage = Image::FromFile(_T("D:\\sel4.jpg"));
	selmain3.ise = 3;
	selmain3.last = &selmain2;
	selmain3.next = &selmain4;

	selmain4.m_pImage = Image::FromFile(_T("D:\\sel5.jpg"));
	selmain4.ise = 4;
	selmain4.last = &selmain3;
	selmain4.next = &selmain0;
再在父窗口开始按钮中添加消息,由于父窗口有一个列表控件,所以要对列表选中状态进行查询。查询完后,根据状态,弹出对应的选择题对话框或者是消息对话框。
//m_list_selmain是程序中定义个列表控件变量

/*

dlgmsg1.str1 = str_sel;
		dlgmsg1.str2 = _T(" ");
		dlgmsg1.cap = _T("确认");
		dlgmsg1.DoModal();             这是程序自定义的消息对话框,通过设置标题,来弹出提示消息。
*/
int ncount, count_sel, flag;  //对各个界面的标志位进行设置,0代表没有打开过。
	selmain0.flag = 0;
	selmain1.flag = 0;
	selmain2.flag = 0;
	selmain3.flag = 0;
	selmain4.flag = 0;
	
	CDlgMsg dlgmsg1;
	CString str_sel;
	count_sel = -1;  
	ncount = -1;
	flag = 0;
	for (ncount = 0; ncount < 5; ncount++)
	{
		if (m_list_selmain.GetItemState(ncount, LVIS_SELECTED) == LVIS_SELECTED)  
		{
			count_sel = ncount;
			flag = 1;
			m_list_selmain.SetItemState(ncount, 0, LVIS_SELECTED);

		}
	}
	if (flag == 1)//如果有选中,弹出消息框
	{
		str_sel = m_list_selmain.GetItemText(count_sel, 0);
		dlgmsg1.str1 = str_sel;
		dlgmsg1.str2 = _T(" ");
		dlgmsg1.cap = _T("确认");
		dlgmsg1.DoModal();
	}
	else//否则弹出提示框
	{
		dlgmsg1.str1 = _T("没有选中题号 ");
		dlgmsg1.str2 = _T(" ");
		dlgmsg1.cap = _T("确认");
		dlgmsg1.DoModal();
	}
//打开对应的选择题界面
	if(count_sel==0)
		{
			  selmain0.flag = 1;
			  selmain0.DoModal();
	}
	if (count_sel == 1)
	{
			  selmain1.flag = 1;
			  selmain1.DoModal(); }
	if(count_sel ==2)
	{
			  selmain2.flag = 1;
			  selmain2.DoModal(); }
	if (count_sel == 3)
	{
			  selmain3.flag = 1;
			  selmain3.DoModal(); }
	if(count_sel == 4)
	{  selmain4.flag = 1;
			  selmain4.DoModal(); }
由于采用的是模态对话框,所以专门对标志位进行了设置。因为后边会出现打开很多个模态对话框的情况,所以要通过标志位进行判断,模态对话框是不是已经打开了,要是打开了,不能再重复打开,避免程序出错。为什么不用非模态对话框?因为,设置起来很麻烦,还要注意指针是不是随时关闭了。而且做选择题的时候,应该是一种独占式的应用。
selmain0.flag = 0;
	selmain1.flag = 0;
	selmain2.flag = 0;
	selmain3.flag = 0;
	selmain4.flag = 0;

做好了上面的事情以后,选中父对话框列表,然后点击父对话框相应的按钮,就能弹出相应的选择题。但是,向导按钮还不能使用。接下来,需要对导航按钮的消息代码进行编辑。这是本案例中最麻烦的事情。因为自己c++不太会用,以前都是做数值计算。中间出了好多错误,也没搞明白是怎么回事,最后终于找到了一种合适的方法,vs2013编译通过。至于,编写代码过程中报错的原因,很多错误到现在还是不太清楚,记录在下边,以后有机会再慢慢搞清楚。

      首先,在CDlgSEL中,需要包含CDlgSEL_Main.h 。这是因为,在父类中,有5个选择题界面的对象成员。在点击CDlgSEL中的“上一题”或者“下一题”按钮时,需要链接上相应的成员。所以只有获取了父类对象指针, 才能达到这个目的。如果,在 DlgSEL.h中直接

#include "CDlgSEL_Main.h " 会报错,因为在DlgSELMain.h 中也包含了DlgSEL.h。这样循环包含,在编译时是不允许的。

可以有两种方法解决这个问题,第一种,是采用前置声明。 在DlgSEL.h中加一条语句,

class CDlgSEL_MAIN

这是专门用于解决类和类之间互相调用的问题。第二种方法,亲测有效,就是把头文件包含在DlgSEL.cpp中。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值