
打开老师给的框架
![]()
搜索 资源视图 ,双击打开


添加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


浙公网安备 33010602011771号