MFC习题|RGB颜色模型演示程序

前言

习题来源:《计算机图形学基础教程》孔令德(第二版)

用mfc基于对话框的编程,实现下图的RGB颜色模型演示程序。点击颜色按钮能将“颜色及代码”这个组框中的静态文本框变成对应的颜色,调色板按钮可以调出自带的颜色选择对话框。滚动条和旁边的编辑框都可以调整颜色。

设计对话框过程不详述,直接开始代码和思路介绍。参考链接见文末。

改变演示块颜色

我在这里将用于演示颜色的静态文本框称为演示块,对应的ID为IDC_COLOR_BOX

查找了很久关于“如何修改控件颜色”的资料。

改变控件颜色需要在对话框类的OnCltColor()成员函数里面写对应代码。要生成这个方法,需要添加WM_CTLCOLOR这个消息的响应函数,在Class View的对话框类上右键可以找到Add Windows Message Handler,在这里添加就可以了。

生成的代码如下:

HBRUSH CComputerGraphcisExercise2Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	
	// TODO: Change any attributes of the DC here

	// TODO: Return a different brush if the default is not desired
	return hbr;
}

这个函数会在每个控件被重绘时调用,所以将改变控件颜色的代码放在这里就行了。

参数pWnd可以用来识别现在是哪个控件正在被重绘。

它的返回值是用于填充控件的画刷。

可以先判断是哪个控件正在被重绘,当演示块被重绘时,将它的颜色调整为自己设置的颜色。

HBRUSH CComputerGraphcisExercise2Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	
	// TODO: Change any attributes of the DC here
	if(pWnd->GetDlgCtrlID() == IDC_COLOR_BOX)//判断控件
	{
		hbr=CreateSolidBrush(m_color);//调整颜色
	}

	// TODO: Return a different brush if the default is not desired
	return hbr;
}

上面代码的m_color是一个对话框类的protected变量,我把它和自动生成的m_hIcon放在了一起。

注意:如果这个变量被设置为public,就会在运行时产生错误,原因未知。

此变量在对话框类的初始化函数OnInitDialog()内初始化。

有了以上代码之后,想要改变演示块的颜色,只需要改变m_color的值并刷新对话框(例如使用Invalidate())就可以了。

显示颜色代码

在演示块下面有一个静态文本框用于显示当前颜色的十六进制代码,例如“#ffffff”。

由于颜色每次都是在对话框刷新的时候被改变的,可以将这个功能写在OnPaint()内。获取方式也不难,看代码基本能看懂,不赘述。

void CComputerGraphcisExercise2Dlg::OnPaint() 
{
	//其他代码
	//获取颜色代码
	
	CStatic *color_code = (CStatic*)GetDlgItem(IDC_COLOR_CODE);
	CString color;
	color.Format("#%02x%02x%02x",GetRValue(m_color),GetGValue(m_color),GetBValue(m_color));
	color_code ->SetWindowText(color);
}

实现颜色按钮

双击每个颜色按钮,添加它们的响应事件,例如:

void CComputerGraphcisExercise2Dlg::OnButtonRed() 
{
	// TODO: Add your control notification handler code here
	m_color = RGB(255,0,0);
	Invalidate();
}

调整它们的颜色,并进行刷新重绘。

至于调色板按钮,需要使用mfc内置的颜色对话框CColorDlg:

void CComputerGraphcisExercise2Dlg::OnButtonPalette() 
{
	// TODO: Add your control notification handler code here
	CColorDialog palette;
	int nResponse = palette.DoModal();
	if(nResponse == IDOK)
	{
		m_color = palette.GetColor();//获取调色板的颜色
	}
	Invalidate();
	
}

实现滚动条

初始化滚动条

首先需要在对话框的OnInitDialog()方法内,新增初始化滚动条范围值的代码。

BOOL CComputerGraphcisExercise2Dlg::OnInitDialog()
{
	//其它代码
    //...

	CScrollBar *scroll=(CScrollBar*)GetDlgItem(IDC_SCROLLBAR_R);

	scroll->SetScrollRange(0,255);

	scroll = (CScrollBar*)GetDlgItem(IDC_SCROLLBAR_G);

	scroll->SetScrollRange(0,255);

	scroll = (CScrollBar*)GetDlgItem(IDC_SCROLLBAR_B);
	scroll->SetScrollRange(0,255);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

这段代码初始化了三个滚动条控件,首先用GetDlgItem()来获取ID对应的控件对象的指针,然后调用SetScrollRange()来设定其范围为0~255。

响应滚动条事件

滚动条的响应事件不像按钮一样是每个按钮分开的,而是分为水平滚动条事件响应函数,和垂直滚动条响应函数。

Class View里对对话框类右键,在右键菜单中找到Add Windows Message Handler,添加WM_HSCROLL消息的响应函数(如果是垂直滚动条,应该是WM_VSCROLL消息)。

生成的响应函数是这样的:

void CComputerGraphcisExercise2Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}

没看文档,不过参数大概意思可能是:

  • nSBCode:滚动条响应的消息类型
  • nPos:滚动条改变状态之后的值
  • pScrollBar:指向被改变状态的滚动条控件的指针

滚动条拖动的代码需要自己写,在实现功能之前,你即使用鼠标拖动滑块,滑块也会回到原来的位置。

在这个响应函数里面,我只让滚动条改变对应的编辑框对应的数值。

void CComputerGraphcisExercise2Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	// TODO: Add your message handler code here and/or call default
	
	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);

	int pos = pScrollBar->GetScrollPos();//获取当前位置

	switch(nSBCode)
	{
	case SB_THUMBPOSITION://被拖动
		pos = nPos;
		break;
	//其实这里还可以写别的事件响应,丰富功能
	}
	pScrollBar->SetScrollPos(pos);

	//设置与滚动条对应的编辑框的数值
	switch(pScrollBar->GetDlgCtrlID())
	{
	case IDC_SCROLLBAR_R:
		SetDlgItemInt(IDC_EDIT_R,pos);
		break;
	case IDC_SCROLLBAR_G:
		SetDlgItemInt(IDC_EDIT_G,pos);
		break;
	case IDC_SCROLLBAR_B:
		SetDlgItemInt(IDC_EDIT_B,pos);
		break;
	}
	
}

响应编辑框变化事件

现在已经可以滑动滚动条来修改编辑框内的值了,但演示块的颜色还不会改变,我把这个功能写在编辑框里面了,这样,可以顺便实现“在编辑框内修改值来修改颜色”的功能。

这是其中一个编辑框的响应函数代码,其他两个类似,要说的内容都写在注释里面了。

void CComputerGraphcisExercise2Dlg::OnChangeEditR() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	UpdateData();//更新数据,将数据从控件上同步到绑定的变量
	int pos = atoi(m_R_value.GetBuffer(0));
	((CScrollBar*)GetDlgItem(IDC_SCROLLBAR_R))->SetScrollPos(pos);
	
    //根据滚动条位置设置当前颜色值
	int R=0,G=0,B=0;
	R=((CScrollBar*)GetDlgItem(IDC_SCROLLBAR_R))->GetScrollPos();
	G=((CScrollBar*)GetDlgItem(IDC_SCROLLBAR_G))->GetScrollPos();
	B=((CScrollBar*)GetDlgItem(IDC_SCROLLBAR_B))->GetScrollPos();
	m_color = RGB(R,G,B);

    //为了防止整个对话框闪烁,只刷新演示块
	CRect rect;
	((CStatic*)GetDlgItem(IDC_COLOR_BOX))->GetWindowRect(&rect);
	ScreenToClient(&rect);//转换为对话框上的客户坐标
	InvalidateRect(rect);//只刷新控件位置
}

完成这一步之后,已经能够实现使用滚动条或者编辑框来改变颜色了,但是当你在点击颜色按钮时,虽然颜色改变了,但是滚动条的位置和编辑框的值不会随之改变。

因此还需要一步:

滚动条随颜色而变化位置

这个对话框内只有颜色按钮能够改变颜色,所以简单地在所有颜色按钮的代码内添加改变位置的代码即可。

而改变滚动条的位置只需要改变对应的编辑框的数值就可以了。

于是颜色按钮代码变成了这样

void CComputerGraphcisExercise2Dlg::OnButtonRed() 
{
	// TODO: Add your control notification handler code here
	m_color = RGB(255,0,0);
	
	//调整滚动条位置
	int R=0,G=0,B=0;
	R=GetRValue(m_color);
	G=GetGValue(m_color);
	B=GetBValue(m_color);
	SetDlgItemInt(IDC_EDIT_R,R);
	SetDlgItemInt(IDC_EDIT_G,G);
	SetDlgItemInt(IDC_EDIT_B,B);
    
	Invalidate();
}

部分用到的MFC函数或宏的简介

详细的自己百度

  • GetRValue()GetGValue()GetBValue(),分别用于获取颜色值的RGB三个通道的值
  • SetDlgItemInt(),可以将值送入ID对应的控件
  • GetDlgItem(),通过ID来获取指向控件的指针,记得转换指针类型
  • Invalidate(),使客户区无效化,引起重绘

参考链接

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值