打开老师给的框架

>>下载地址

搜索 资源视图 ,双击打开

添加bar

编辑属性

添加ID号

打开类视图,找到view类

右击打开view类属性

点击事件(闪电⚡状)

找到ID_InverseV

看到这里已经添加了

点击编辑代码

代码解释部分 (暂时跳过)

要用对话框类

首先得在前面包含头文件

打开资源视图,看对话框

1说明标签

2编辑控件,用来保存输入进去的或者是变换曲线求的值

3静态文本框,用来占位,将来在这个地方画曲线

右击打开静态文本框属性

查看其ID

通过这个ID号,找到这个地方,表示将来我们的曲线就在这个地方画

再做一个

到View类-属性-事件⚡给菜单增加一个函数

点击Add

然后跳转到代码界面,给它加代码

拷贝过来

CMFCApplication3Doc* pDoc = GetDocument();// 获取文档	
		
	long	lSrcLineBytes;		//图象每行的字节数
	long	lSrcWidth;         //图象的宽度和高度
	long	lSrcHeight;
	int     lpSrcBitCount;       //图像的位深
	LPSTR	lpSrcDib;		//指向源图象的指针	
	LPSTR	lpSrcStartBits;	//指向源像素的指针
	lpSrcDib = (LPSTR) ::GlobalLock((HGLOBAL)pDoc->GetHObject());// 锁定DIB
	if (!lpSrcDib) return;
	/*
	if (pDoc->m_dib.GetColorNum(lpSrcDib) != 256)// 判断是否是8-bpp位图
	{
		   AfxMessageBox(L"对不起,不是256色位图!");// 警告
		   ::GlobalUnlock((HGLOBAL) pDoc->GetHObject());// 解除锁定
		   return;									//返回
	 }										//判断是否是8-bpp位图,不是则返回
	 */
	lpSrcStartBits = pDoc->m_dib.GetBits(lpSrcDib);			// 找到DIB图象像素起始位置	
	lSrcWidth = pDoc->m_dib.GetWidth(lpSrcDib);					// 获取图象的宽度		
	lSrcHeight = pDoc->m_dib.GetHeight(lpSrcDib);					// 获取图象的高度	
	lpSrcBitCount = pDoc->m_dib.GetBitCount(lpSrcDib);                    //获取图像位深
	lSrcLineBytes = pDoc->m_dib.GetReqByteWidth(lSrcWidth * lpSrcBitCount);		// 计算图象每行的字节数
	/	
	int threshold;
	
	CDlgInverseV_test dlgPara;
	if (dlgPara.DoModal() != IDOK)// 显示对话框, 
	{
		return;
	}
	threshold = dlgPara.m_middle;
	delete dlgPara;

	int type = 1;
	Segmental2_Linear_Tran(lpSrcStartBits, lSrcWidth, lSrcHeight, type, threshold);//分段线性变换


	//设置文档修改标志
	pDoc->SetModifiedFlag(true);
	//更新视图
	pDoc->UpdateAllViews(NULL);
	//Invalidate();  //OK
	::GlobalUnlock((HGLOBAL)pDoc->GetHObject());// 解除锁定

粘贴到这个测试函数里

然后把这一块封上

	/*CDlgInverseV_test dlgPara;
	if (dlgPara.DoModal() != IDOK)// 显示对话框, 
	{
		return;
	}*/

现在对这一块进行操作

插入一个对话框

在对话框上右击打开属性

Caption改为TEST

(实际Test1)

ID改为IEE_Dlg_test

(实际IEE_Dlg_test1)

现在回到对话框页面,往上面拖东西

搜索 打开工具箱

往上面脱一个静态文本,再拖一个控件

再放一个静态文本,占位

改变第一个文本的caption

改变编辑框的ID

改占位符的ID

为对话框添加类

(实际添加CDlgTest1)

自动跳转类文件视图

类视图可以看到刚刚添加的类

查看.h代码,转到.cpp文件

右击函数转到定义

cpp里面的函数都是空的

既然这个类有了,那么view类那个菜单函数应该就能用了

回去view.cpp把那个注释放开

回去到最上面把这个类包含进来

把这个封上

这个先给一个具体的值

不然这个没法用

调试运行

现在我们虽然显示了对话框,但实际上对话框没有给值,用的是我们赋的初值

我们现在还需要对对话框进行一系列的操作

给编辑框添加变量

运行

输入一个大数

现在我们已经设置了变量了,我们看看类里面有什么变化

多了一个变量

控件ID与变量绑定,最大值最小值设定

现在回去view.cpp把那个初值删了

这个再改一下

回去重新运行一下,不用曲线,只用输入框,看看能不能处理

可以!

到这里就基本实现功能了

现在要实现下图的功能

凡是小于52都提亮,大于52都变黑

输入一个值的时候,曲线就要变

曲线被拖动而改变时,编辑框的内容也要变

按tab键时,选中区域也要变化,从编辑框到确认再到取消

鼠标被按下(LButtonDown)、抬起(LButtonUp)、移动(MouseMove)

画对话框,绘制曲线,初始化对话框

要添加以下函数:

1)对话框的初始化

2)对话框的绘制 OnPaint

3)3种鼠标事件

4)对输入本身进行处理

所有这一切和view没关系了,就是和对话框类有关

这个EN是enter。输入失去焦点。意思就是输入完毕后焦点要转移到别的地方(手动按tab),这个给它添加一个焦点转移函数。

当焦点转移的时候执行这个操作

还有就是鼠标的属性,是消息函数

添加如下三个函数

添加绘制

添加初始对话框(重写)

操作完可以看见:

.cpp自动添加了消息处理

.h亦同

Windows的三种函数机制

事件函数:菜单(View类),对话框事件

消息函数:对话框消息如LButtonDown、LButtonUp、MouseMove、OnPaint

windows本身是消息驱动的,动鼠标->Windows发消息->相应函数被执行

重写函数:OnDraw、OpenDocument、OnSaveDocument

现在编写这个失去焦点函数

一旦输入完毕,自动保存

//保存用户设置
UpdateData(TRUE);
//重绘
InvalidateRect(m_MouseRect, TRUE);

现在为这个.h文件在public区域添加公共变量

//
int temp;
//响应鼠标的区域
CRect m_MouseRect;
//标识是否拖动
BOOL m_bIsDrawing;
//

这样这里就不再报错了

在.cpp中添加OnPaint函数

CPaintDC dc(this); // device context for painting
					   // TODO: 在此处添加消息处理程序代码
					   // 不为绘图消息调用 CDialogEx::OnPaint()
	if (m_middle < 1 || m_middle>254) return;
	//获取绘制坐标的文本框
	CWnd* pWnd = GetDlgItem(IDC_COORD);
	//字符串
	CString str;
	CPoint pLeft, pRight, pCenterTop, pCenterBottom;
	//指针
	CDC* pDC = pWnd->GetDC();
	pWnd->Invalidate();
	pWnd->UpdateWindow();
	//x1(left),y1(top),x2(right),y2(bottom)
	pDC->Rectangle(0, 0, 330, 300);//画一个矩形
	//创建画笔对象
	CPen* pPenRed = new CPen;
	//红色画笔,红绿蓝
	pPenRed->CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
	//创建画笔对象
	CPen* pPenBlue = new CPen;
	//蓝色画笔,红绿蓝
	pPenBlue->CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
	//创建画笔对象
	CPen* pPenGreen = new CPen;
	//绿色画笔,红绿蓝
	pPenGreen->CreatePen(PS_DOT, 1, RGB(0, 255, 0));

	//选中当前红色画笔,并保存以前的画笔
	CGdiObject* pOldPen = pDC->SelectObject(pPenRed);

	//绘制坐标轴
	pDC->MoveTo(10, 10);
	//垂直轴
	pDC->LineTo(10, 280);
	//水平轴
	pDC->LineTo(320, 280);
	//写坐标
	str.Format(L"0");
	pDC->TextOut(10, 281, str);
	str.Format(L"255");
	pDC->TextOut(265, 281, str);
	//pDC->TextOut(11, 25, str);
	pDC->TextOutW(11, 25, str);
	//绘制X箭头
	pDC->LineTo(315, 275);
	pDC->MoveTo(320, 280);
	pDC->LineTo(315, 285);
	//绘制Y箭头
	pDC->MoveTo(10, 10);
	pDC->LineTo(5, 15);
	pDC->MoveTo(10, 10);
	pDC->LineTo(15, 15);
	//更改成绿色画笔,画垂直线

	pDC->SelectObject(pPenGreen);
	pCenterTop.x = 10 + m_middle;//128;
	pCenterTop.y = 25;

	pCenterBottom.x = 10 + m_middle;//128;
	pCenterBottom.y = 280;
	pDC->MoveTo(pCenterTop);
	pDC->LineTo(pCenterBottom);

	//更改成蓝色画笔
	pDC->SelectObject(pPenBlue);
	//画两条变换线,没有计算斜率,没有交互
	pLeft.x = 10;
	pLeft.y = 280;
	//pDC->MoveTo(10,280);
	pDC->MoveTo(pLeft);
	pCenterTop.x = 10 + m_middle;//128;
	pCenterTop.y = 25;
	//pDC->LineTo(138,25);
	pDC->LineTo(pCenterTop);
	pRight.x = 265;
	pRight.y = 280;
	//pDC->LineTo(265,280);
	pDC->LineTo(pRight);

	pDC->SelectObject(pOldPen);

改参数

以下middle均改为middle1

改成

代码解释

得到窗口指针

先画一个矩形外框,再创建红黄蓝画笔

然后开始画坐标

然后根据设定的值画图

还没有初始化,现在运行没有效果

先初始化

.cpp中找到初始化函数复制代码(实际操作是自己写,这里只是演示)

CDialogEx::OnInitDialog();
	// TODO:  在此添加额外的初始化
	//获取绘制图形的标签
	CWnd* pWnd = GetDlgItem(IDC_COORD);
	//计算接受鼠标事件的有效区域
	pWnd->GetClientRect(m_MouseRect);
	pWnd->ClientToScreen(&m_MouseRect);

	CRect rect;
	GetClientRect(rect);
	ClientToScreen(&rect);

	m_MouseRect.top -= rect.top;
	m_MouseRect.left -= rect.left;
	//设置接受鼠标事件的有效区域
	m_MouseRect.top += 25;
	m_MouseRect.left += 10;
	m_MouseRect.bottom = m_MouseRect.top + 255;
	m_MouseRect.right = m_MouseRect.left + 256;
	//初始化拖动状态
	m_bIsDrawing = FALSE;

	m_middle = 128;
	UpdateData(FALSE);
	// TODO:  在此添加额外的初始化

	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE

粘贴到对应的.cpp中

记得改m_middle1

运行

(若是手动输入,按tab曲线才能更新,输入后不能立即更新,不知道为啥)

已经画出来了,但是还不能拖拉

添加LButtonDown、Up,MouseMove

运行

可以拖拉了(鼠标按下才能拖拽)

添加两个Radio Button

一般只能选一个,我们在一个的属性中改Group为true

就不互斥了

现在让它互斥

然后为第一个添加函数

同理

添加代码

这样是不会变的,一定要updatedata

UpdateData(FALSE);

FALSE就是从内存到控件

这一次,点击radio后曲线改变(不知道为啥要按tab四次,直到焦点再次从编辑控件离开曲线才更新)

唯一存在问题就是焦点要从控件离开曲线才更新,不能在值改变的瞬间立即更新

哦,这是老师新加的函数,原来给的这个框架没有,害得我找这么久

给输入框添加这个函数

EN_CHANGE

当输入改变的时候触发

触发更新和重绘

void CDlgTest1::OnEnChangeThreshold()
{
	// TODO:  如果该控件是 RICHEDIT 控件,它将不
	// 发送此通知,除非重写 CDialogEx::OnInitDialog()
	// 函数并调用 CRichEditCtrl().SetEventMask(),
	// 同时将 ENM_CHANGE 标志“或”运算到掩码中。

	// TODO:  在此添加控件通知处理程序代码
	//更新
	UpdateData(TRUE);
	//重绘
	InvalidateRect(m_MouseRect, TRUE);
}

注意:

反正不是true就是false,不行就换一个试试

UpdateData(true);       //用于将屏幕上控件中的数据交换到变量中。控件->内存。
UpdateData(false);      //用于将数据在屏幕中对应控件中显示出来。内存->控件。

之前错用false,导致不管输入什么数,都会立刻变回128

这是因为false是内存->控件。m_middle1内存初始值128

正确用法是控件到内存,就是true

posted on 2020-05-13 23:09  海月CSDN  阅读(902)  评论(0)    收藏  举报