基于MFC的ActiveX控件,主要功能是
Demo小样:
1.新建MFC ActiveX项目
2.添加对话框MyDlg类,对话框ID为IDD_MYDLG;
3.在控件类CActiveXDemoCtrl类中进行改写如下函数
CMyDlg m_mydlg;
int CActiveXDemoCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
m_mydlg.Create(IDD_MYDLG, this);
return 0;
}
void CActiveXDemoCtrl::OnSize(UINT nType, int cx, int cy)
{
COleControl::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
m_mydlg.MoveWindow(0,0,cx,cy);
}
void CActiveXDemoCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& /* rcInvalid */)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
}
4.为控件添加组件,设置好ID
5.相应的组件的初始化
BOOL CMyDlg::OnInitDialog()
{
//TheImage Picture控件的初始化代码
CvSize ImgSize;
ImgSize.height = 127;
ImgSize.width = 127;
TheImage = cvCreateImage(ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS);
//TheBigImage Picture控件的初始化代码
CvSize ImgBigSize;
ImgBigSize.height = 160;
ImgBigSize.width = 480;
TheBigImage = cvCreateImage(ImgBigSize, IPL_DEPTH_8U, IMAGE_CHANNELS);
//滑动条代码
CSliderCtrl *pSlidCtrl = (CSliderCtrl*)GetDlgItem(IDC_SLIDER_NUM);
pSlidCtrl->SetRange(1, 5, TRUE);//设置滑动条范围
pSlidCtrl->SetPos(1);//设置滑动条
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
6.添加点击Button的相应函数
void CMyDlg::OnBnClickedOpen()
{
Filestr = OpenFileName();
IplImage* ipl = cvLoadImage(Filestr, 1);
// 判断是否成功读取图片
if (!ipl)
{
MessageBox(_T("读取不到图片"));
return;
}
// 对上一幅显示的图片数据清零
if (TheImage)
cvZero(TheImage);
// 对读入的图片进行缩放,使其宽或高最大值者刚好等于 180,再复制到 TheImage 中
ResizeImage(ipl);
// 调用显示图片函数
ShowImage(TheImage, IDC_STATIC_PIC);
// 释放 ipl 占用的内存
cvReleaseImage(&ipl);
}
CString CMyDlg::OpenFileName()
{
if (CString strFile = _T("")){
CFileDialog dlg(
TRUE, _T("*.jpg"), NULL,
OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
_T("image files (*.bmp; *.jpg) |*.bmp;*.jpg;*.png | All Files (*.*) |*.*||"), NULL
);
// 打开文件对话框的标题名
dlg.m_ofn.lpstrTitle = _T("Open Image");
// 判断是否获得图片
if (dlg.DoModal() != IDOK)
return 0;
// 获取图片路径
strFile = dlg.GetPathName();
return strFile;
}
else
return strFile;
}
7.将图片加载进Picure控件,用到了两个函数ResizeImage()和ShowImage()
void CMyDlg::ResizeImage(IplImage* img)
{
// 读取图片的宽和高
int imgwidth = img->width;
int imgheight = img->height;
// 找出宽和高中的较大值者
int max = (imgwidth > imgheight) ? imgwidth : imgheight;
// 计算将图片缩放到TheImage区域所需的比例因子
scale = (float)((float)max / 127.0f);
// 缩放后图片的宽和高
int nw = (int)(imgwidth / scale);
int nh = (int)(imgheight / scale);
// 设置 TheImage 的 ROI 区域,用来存入图片 img
cvSetImageROI(TheImage, cvRect(0, 0, nw, nh));
// 对图片 img 进行缩放,并存入到 TheImage 中
cvResize(img, TheImage);
// 重置 TheImage 的 ROI 准备读入下一幅图片
cvResetImageROI(TheImage);
}
void CMyDlg::ShowImage(IplImage* img, UINT ID)
{
// 获得显示控件的 DC
CDC* pDC = GetDlgItem(ID)->GetDC();
// 获取 HDC(设备句柄) 来进行绘图操作
HDC hDC = pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
// 求出图片控件的宽和高
PicControlWidth = rect.right - rect.left;
PicControlHeight = rect.bottom - rect.top;
// 使图片的显示位置正好在控件的正中
SetRect(rect, 0, 0, PicControlWidth, PicControlHeight);
// 复制图片
CvvImage cimg;
cimg.CopyOf(img);
// 将图片绘制到显示控件的指定区域内
cimg.DrawToHDC(hDC, &rect);
ReleaseDC(pDC);
}
8.通过以上步骤就可以把图片加载到Picture控件中了,下面写鼠标在picture控件上的点击事件,注意一下几点
9.鼠标点击Picture控件上的处理函数
void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (Filestr == "")
{
MessageBox(_T("Please open the image!"));
return;
}
CRect rect_ctr;
(this->GetDlgItem(IDC_STATIC_PIC))->GetWindowRect(&rect_ctr); //获取Picture控件相对屏幕左上角的坐标,
//存储到rect_ctr中
ScreenToClient(rect_ctr);//获取Picture控件相对对话框客户区左上角的坐标
point.x -= rect_ctr.left;//point获取的是鼠标相对对话框客户区左上角的坐标,减去rect_ctr.left和
point.y -= rect_ctr.top;//rect_ctr.top后,即为鼠标相对Picture控件左上角的坐标
if (point.x > (rect_ctr.right - rect_ctr.left) || point.y > (rect_ctr.bottom - rect_ctr.top)
|| point.x < 0 || point.y < 0)
{
}
else
{
//上图缩放比例系数
original_x = scale * point.x;
original_y = scale * point.y;
CPoint point = CPoint(original_x, original_y);
// 判断是否成功读取图片
CString mPath = Filestr;
IplImage* ipl2 = cvLoadImage(mPath, 1);
// 对上一幅显示的图片数据清零
if (TheBigImage)
cvZero(TheBigImage);
// 对读入的图片进行缩放,使其宽或高最大值者刚好等于 180,再复制到 TheImage 中
ResizeBigImage(ipl2, point);
// 调用显示图片函数
ShowImage(TheBigImage, IDC_STATIC_BIGPIC);
// 释放 ipl 占用的内存
cvReleaseImage(&ipl2);
}
}
10.放大至Picture控件上
void CMyDlg::ResizeBigImage(IplImage* img, CPoint point)
{
//读取原图的坐标
int x = point.x;
int y = point.y;
//读取原图的长宽
int ori_height = img->height;
int ori_width = img->width;
int pic_size_set_h = 32;
int pic_size_set_w = 96;
//设置原图的ROI区域
CvRect rect;
//滑块的值
int b = m_ctrlSlider;
if (ori_height <= 100 && ori_width <= 100)
{
pic_size_set_h = 1;
pic_size_set_w = 3;
}
if (ori_height > 100 || ori_height <= 200 && ori_width > 100 || ori_width <= 200)
{
pic_size_set_h = 8;
pic_size_set_w = 24;
}
if (ori_height > 200 || ori_height <= 300 && ori_width >200|| ori_width <= 300)
{
pic_size_set_h = 15;
pic_size_set_w = 45;
}
if (ori_height > 300 || ori_height <= 500 && ori_width >300 || ori_width <= 500)
{
pic_size_set_h = 30;
pic_size_set_w = 90;
}
if (ori_height > 500&& ori_width > 500)
{
pic_size_set_h = 35;
pic_size_set_w = 35*3;
}
rect.height = b * pic_size_set_h;
rect.width = b * pic_size_set_w;
rect.x = x - 0.4*(rect.width);
rect.y = y - 0.4*(rect.height);
//对感兴趣区域越界进行处理
if (rect.x<0)
{
rect.x = 0;
}
if (rect.x + rect.width > ori_width)
{
rect.x = rect.x - (rect.x + rect.width - ori_width);
}
if (rect.y + rect.height > ori_height)
{
rect.y = rect.y - (rect.y + rect.height - ori_height);
}
if (rect.y < 0)
{
rect.y = 0;
}
cvSetImageROI(img, rect);
cvResize(img, TheBigImage);
// 重置 TheImage 的 ROI 准备读入下一幅图片
cvResetImageROI(TheBigImage);
}
11.为Slide bar滑块添加滚轮响应函数
1.测试控件工具ActiveX Control text Container,在CSDN上可以下载到编译好添加至工具栏就可以使用了
2.添加控件,点击File->Insert Control
3.控件显示
)
1.新建一个基于对话框的MFC程序
2.为控件添加包装类 VS2013下
3.添加你的包装类的控件变量
4.运行后卡死
这个问题困扰了我很久,在其他的C#和C++窗体函数中调用控件中都没有出现点击卡死问题
具体的原因是因为:
解决办法