鱼C论坛

 找回密码
 立即注册
查看: 661|回复: 9

图片放大缩小滚动条

[复制链接]
发表于 2024-10-22 18:24:07 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
C++ MFC 将Mat图置于Picture control中,怎样将图片放大缩小预览,当图像变大时Picture control控件自动显示水平和垂直滚动条用于上下左右移动图片
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-22 18:31:06 | 显示全部楼层
在C++ MFC中将Mat图像放置于Picture Control中,并实现图像的缩放和滚动条功能,可以按以下步骤进行:

1. **Picture Control的初始化与Mat图像显示**:
   - 在对话框资源编辑器中添加一个Picture Control。
   - 使用OpenCV将Mat图像转化为HBITMAP,然后在`OnPaint`函数中使用`CDC::BitBlt`或`CDC::StretchBlt`将HBITMAP绘制到Picture Control上。

2. **缩放功能的实现**:
   - 添加鼠标滚轮消息的处理,在`OnMouseWheel`中实现缩放逻辑。
   - 可以通过调整Mat格式图像的尺寸(使用OpenCV的`resize`函数)来实现缩放。
   
3. **滚动条的处理**:
   - 使用CScrollView代替默认的CWnd。这样可以自动管理滚动条。
   - 重载`SetScrollSizes(MM_TEXT, CSize)`来设置滚动区域的大小。
   - 在缩放时,根据新的图像尺寸调整滚动条大小。

4. **示例代码框架**:

  
  1. BOOL CYourDlg::OnInitDialog()
  2.    {
  3.        CDialogEx::OnInitDialog();

  4.        // 初始化滚动条、加载图片等
  5.        UpdateImageView();

  6.        return TRUE;
  7.    }

  8.    void CYourDlg::UpdateImageView()
  9.    {
  10.        CClientDC dc(this);
  11.        CRect rect;
  12.        GetClientRect(&rect);

  13.        // 计算图像显示区域,注意缩放比例调整
  14.        // 使用OpenCV的resize函数调整Mat图像尺寸

  15.        // Set滚动条
  16.        SetScrollSizes(MM_TEXT, CSize(image.cols, image.rows));
  17.    }

  18.    void CYourDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  19.    {
  20.        // 根据zDelta来调整缩放比例
  21.        double scaleFactor = (zDelta > 0) ? 1.1 : 0.9;
  22.        // 对Mat图像进行resize
  23.        cv::resize(originalImage, scaledImage, Size(), scaleFactor, scaleFactor);

  24.        // 更新视图和滚动条
  25.        UpdateImageView();

  26.        CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
  27.    }
复制代码


通过以上步骤,完善你的对话框类,使其能够支持图像的缩放和滚动。请注意具体实现时需要检查各个OpenCV和MFC函数的适用情况。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-22 18:47:59 | 显示全部楼层
FishC 发表于 2024-10-22 18:31
在C++ MFC中将Mat图像放置于Picture Control中,并实现图像的缩放和滚动条功能,可以按以下步骤进行:

1 ...

请给出详细的代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 18:56:45 | 显示全部楼层
cxnet 发表于 2024-10-22 18:47
请给出详细的代码


实现该功能需要详细进行以下步骤:

### 1. 添加控件和类

确保在MFC对话框中添加一个Picture Control,并创建一个新的对话框类(例如,`CImageViewerDlg`)。

### 2. 转换Mat为HBITMAP

使用OpenCV将Mat图像转换为HBITMAP:

  1. HBITMAP MatToHBITMAP(const cv::Mat& mat)
  2. {
  3.     cv::Mat temp;
  4.     cv::cvtColor(mat, temp, cv::COLOR_BGR2BGRA);

  5.     HBITMAP hBitmap = CreateBitmap(temp.cols, temp.rows, 1, 32, temp.data);
  6.     return hBitmap;
  7. }
复制代码


### 3. 初始化滚动视图

在对话框类中初始化滚动条和处理绘图:

  1. BOOL CImageViewerDlg::OnInitDialog()
  2. {
  3.     CDialogEx::OnInitDialog();

  4.     // 将图片加载到Mat对象
  5.     m_matImage = cv::imread("your_image_path.jpg");

  6.     // 初始化滚动条
  7.     CScrollBar* pHScrollBar = GetScrollBarCtrl(SB_HORZ);
  8.     CScrollBar* pVScrollBar = GetScrollBarCtrl(SB_VERT);

  9.     if (pHScrollBar && pVScrollBar)
  10.     {
  11.         SCROLLINFO si;
  12.         si.fMask = SIF_RANGE | SIF_PAGE;
  13.         si.nMin = 0;
  14.         si.nMax = m_matImage.cols - 1;
  15.         si.nPage = 100; // 视图大小
  16.         pHScrollBar->SetScrollInfo(&si);

  17.         si.nMax = m_matImage.rows - 1;
  18.         pVScrollBar->SetScrollInfo(&si);
  19.     }

  20.     return TRUE;
  21. }
复制代码


### 4. 绘制图像

重载`OnPaint`来绘制Mat图像:

  1. void CImageViewerDlg::OnPaint()
  2. {
  3.     CPaintDC dc(this);

  4.     if (!m_matImage.empty())
  5.     {
  6.         HBITMAP hBitmap = MatToHBITMAP(m_matImage);
  7.         CBitmap bitmap;
  8.         bitmap.Attach(hBitmap);

  9.         CDC memDC;
  10.         memDC.CreateCompatibleDC(&dc);
  11.         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);

  12.         BITMAP bm;
  13.         bitmap.GetBitmap(&bm);
  14.         dc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0, SRCCOPY);

  15.         memDC.SelectObject(pOldBitmap);
  16.         DeleteObject(hBitmap);
  17.     }
  18. }
复制代码


### 5. 处理缩放

响应鼠标滚轮事件来缩放:

  1. BOOL CImageViewerDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  2. {
  3.     double scaleFactor = (zDelta > 0) ? 1.1 : 0.9;
  4.     cv::resize(m_matImage, m_matImage, cv::Size(), scaleFactor, scaleFactor);

  5.     // 更新滚动条信息
  6.     CScrollBar* pHScrollBar = GetScrollBarCtrl(SB_HORZ);
  7.     CScrollBar* pVScrollBar = GetScrollBarCtrl(SB_VERT);

  8.     if (pHScrollBar && pVScrollBar)
  9.     {
  10.         SCROLLINFO si;
  11.         si.fMask = SIF_RANGE | SIF_PAGE;
  12.         si.nMin = 0;
  13.         si.nMax = m_matImage.cols - 1;
  14.         si.nPage = 100;
  15.         pHScrollBar->SetScrollInfo(&si);

  16.         si.nMax = m_matImage.rows - 1;
  17.         pVScrollBar->SetScrollInfo(&si);
  18.     }

  19.     Invalidate();
  20.     return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
  21. }
复制代码


### 6. 滚动图片

处理滚动:

  1. void CImageViewerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2. {
  3.     // 滚动处理代码
  4.     CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
  5. }

  6. void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  7. {
  8.     // 滚动处理代码
  9.     CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
  10. }
复制代码


### 总结

以上代码为你的对话框添加了图片缩放和滚动条功能,但要测试和调试,以确保配置正确并适应你的应用场景。请根据你的具体需求做出相应调整。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-24 09:56:29 | 显示全部楼层
FishC 发表于 2024-10-22 18:56
实现该功能需要详细进行以下步骤:

### 1. 添加控件和类

这些代码中Picture Control的变量名称是或者ID名称是设置的什么?没有看明白
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-24 10:02:52 | 显示全部楼层
cxnet 发表于 2024-10-24 09:56
这些代码中Picture Control的变量名称是或者ID名称是 ...


在这些代码中,Picture Control的具体变量名称或ID没有指定,因为对Picture Control的操作通常是通过CDC在`OnPaint`中直接进行位图绘制。

如果你想通过变量进行访问,你可以为Picture Control添加一个控件变量。例如:

1. 在资源视图中,找到你的Picture Control。
2. 右键点击选择“添加变量”。
3. 为控件添加一个成员变量,例如:`m_PictureControl`。
4. 将控件的ID命名为合理的名称,例如:`IDC_PICTURE_CONTROL`。

之后,在代码中,你可以使用`m_PictureControl`进行访问和操作:

  1. void CImageViewerDlg::OnPaint()
  2. {
  3.     CPaintDC dc(this);

  4.     if (!m_matImage.empty())
  5.     {
  6.         HBITMAP hBitmap = MatToHBITMAP(m_matImage);
  7.         CBitmap bitmap;
  8.         bitmap.Attach(hBitmap);

  9.         CDC memDC;
  10.         memDC.CreateCompatibleDC(&dc);
  11.         CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);

  12.         BITMAP bm;
  13.         bitmap.GetBitmap(&bm);

  14.         // 在m_PictureControl中绘制
  15.         CRect rect;
  16.         m_PictureControl.GetClientRect(&rect);
  17.         dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);

  18.         memDC.SelectObject(pOldBitmap);
  19.         DeleteObject(hBitmap);
  20.     }
  21. }
复制代码


这样可以确保图像绘制在指定的Picture Control中。请根据具体设计调整代码。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-24 10:28:10 | 显示全部楼层
FishC 发表于 2024-10-22 18:56
实现该功能需要详细进行以下步骤:

### 1. 添加控件和类

请给出处理滚动的详细代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-24 10:28:32 | 显示全部楼层
cxnet 发表于 2024-10-24 10:28
请给出处理滚动的详细代码


下面是处理滚动条的详细代码示例:

### 滚动处理逻辑

1. **在类中添加成员变量**:

  1. CPoint m_ScrollPos;  // 记录滚动位置
复制代码


2. **初始化滚动条**:

在`OnInitDialog`中设置滚动条:

  1. BOOL CImageViewerDlg::OnInitDialog()
  2. {
  3.     CDialogEx::OnInitDialog();

  4.     // 假设图片已经被加载到 m_matImage
  5.     UpdateScrollInfo();

  6.     return TRUE;
  7. }
复制代码


3. **更新滚动信息**:

  1. void CImageViewerDlg::UpdateScrollInfo()
  2. {
  3.     if (!m_matImage.empty())
  4.     {
  5.         CScrollBar* pHScrollBar = GetScrollBarCtrl(SB_HORZ);
  6.         CScrollBar* pVScrollBar = GetScrollBarCtrl(SB_VERT);

  7.         if (pHScrollBar && pVScrollBar)
  8.         {
  9.             SCROLLINFO si;
  10.             si.fMask = SIF_RANGE | SIF_PAGE;
  11.             si.nMin = 0;
  12.             si.nPage = 100;
  13.             si.nMax = m_matImage.cols - 1;
  14.             pHScrollBar->SetScrollInfo(&si);

  15.             si.nMax = m_matImage.rows - 1;
  16.             pVScrollBar->SetScrollInfo(&si);
  17.         }
  18.     }
  19. }
复制代码


4. **处理水平滚动**:

  1. void CImageViewerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2. {
  3.     int scrollPos;
  4.     SCROLLINFO si = { sizeof(si), SIF_ALL };
  5.     pScrollBar->GetScrollInfo(&si);

  6.     switch (nSBCode)
  7.     {
  8.     case SB_LEFT:
  9.         scrollPos = si.nMin;
  10.         break;
  11.     case SB_RIGHT:
  12.         scrollPos = si.nMax;
  13.         break;
  14.     case SB_LINELEFT:
  15.         scrollPos = max(si.nMin, si.nPos - 10);
  16.         break;
  17.     case SB_LINERIGHT:
  18.         scrollPos = min(si.nMax, si.nPos + 10);
  19.         break;
  20.     case SB_PAGELEFT:
  21.         scrollPos = max(si.nMin, si.nPos - (int)si.nPage);
  22.         break;
  23.     case SB_PAGERIGHT:
  24.         scrollPos = min(si.nMax, si.nPos + (int)si.nPage);
  25.         break;
  26.     case SB_THUMBTRACK:
  27.         scrollPos = nPos;
  28.         break;
  29.     default:
  30.         return;
  31.     }

  32.     pScrollBar->SetScrollPos(scrollPos);
  33.     m_ScrollPos.x = scrollPos;
  34.     Invalidate();
  35. }
复制代码


5. **处理垂直滚动**:

  1. void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2. {
  3.     int scrollPos;
  4.     SCROLLINFO si = { sizeof(si), SIF_ALL };
  5.     pScrollBar->GetScrollInfo(&si);

  6.     switch (nSBCode)
  7.     {
  8.     case SB_TOP:
  9.         scrollPos = si.nMin;
  10.         break;
  11.     case SB_BOTTOM:
  12.         scrollPos = si.nMax;
  13.         break;
  14.     case SB_LINEUP:
  15.         scrollPos = max(si.nMin, si.nPos - 10);
  16.         break;
  17.     case SB_LINEDOWN:
  18.         scrollPos = min(si.nMax, si.nPos + 10);
  19.         break;
  20.     case SB_PAGEUP:
  21.         scrollPos = max(si.nMin, si.nPos - (int)si.nPage);
  22.         break;
  23.     case SB_PAGEDOWN:
  24.         scrollPos = min(si.nMax, si.nPos + (int)si.nPage);
  25.         break;
  26.     case SB_THUMBTRACK:
  27.         scrollPos = nPos;
  28.         break;
  29.     default:
  30.         return;
  31.     }

  32.     pScrollBar->SetScrollPos(scrollPos);
  33.     m_ScrollPos.y = scrollPos;
  34.     Invalidate();
  35. }
复制代码


### 总结

这些代码实现了滚动条的基本处理功能,记得在`OnPaint`中使用`m_ScrollPos`来调整图片绘制位置。例如:

  1. dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC, m_ScrollPos.x, m_ScrollPos.y, bm.bmWidth, bm.bmHeight, SRCCOPY);
复制代码


调整这些代码以适应你的具体需求和应用场景。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-24 11:45:51 | 显示全部楼层
FishC 发表于 2024-10-24 10:28
下面是处理滚动条的详细代码示例:

### 滚动处理逻辑

提示错误
“GetScrollBarCtrl”: 找不到标识符
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-24 11:48:17 | 显示全部楼层
cxnet 发表于 2024-10-24 11:45
提示错误
“GetScrollBarCtrl”: 找不到标识符


对于MFC对话框,`GetScrollBarCtrl`适用于视图类而非对话框。你需要手动管理滚动条。以下是如何修改代码来处理滚动条的示例:

### 修改初始化滚动条

在`OnInitDialog`中,手动设置滚动条的范围和位置:

  1. BOOL CImageViewerDlg::OnInitDialog()
  2. {
  3.     CDialogEx::OnInitDialog();

  4.     // 假设图片已经被加载到 m_matImage
  5.     UpdateScrollInfo();

  6.     return TRUE;
  7. }
复制代码


### 更新滚动信息

手动控制滚动条的更新:

  1. void CImageViewerDlg::UpdateScrollInfo()
  2. {
  3.     if (!m_matImage.empty())
  4.     {
  5.         SCROLLINFO si;
  6.         si.cbSize = sizeof(SCROLLINFO);
  7.         si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  8.         si.nMin = 0;
  9.         si.nPage = 100;

  10.         // 水平滚动信息
  11.         si.nMax = m_matImage.cols - 1;
  12.         si.nPos = m_ScrollPos.x;
  13.         SetScrollInfo(SB_HORZ, &si, TRUE);

  14.         // 垂直滚动信息
  15.         si.nMax = m_matImage.rows - 1;
  16.         si.nPos = m_ScrollPos.y;
  17.         SetScrollInfo(SB_VERT, &si, TRUE);
  18.     }
  19. }
复制代码


### 处理水平滚动

手动调整水平滚动:

  1. void CImageViewerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2. {
  3.     int scrollPos = GetScrollPos(SB_HORZ);

  4.     switch (nSBCode)
  5.     {
  6.     case SB_LEFT:
  7.         scrollPos = 0;
  8.         break;
  9.     case SB_RIGHT:
  10.         scrollPos = m_matImage.cols - 1;
  11.         break;
  12.     case SB_LINELEFT:
  13.         scrollPos = max(0, scrollPos - 10);
  14.         break;
  15.     case SB_LINERIGHT:
  16.         scrollPos = min(m_matImage.cols - 1, scrollPos + 10);
  17.         break;
  18.     case SB_PAGELEFT:
  19.         scrollPos = max(0, scrollPos - 100);
  20.         break;
  21.     case SB_PAGERIGHT:
  22.         scrollPos = min(m_matImage.cols - 1, scrollPos + 100);
  23.         break;
  24.     case SB_THUMBTRACK:
  25.         scrollPos = nPos;
  26.         break;
  27.     default:
  28.         return;
  29.     }

  30.     SetScrollPos(SB_HORZ, scrollPos);
  31.     m_ScrollPos.x = scrollPos;
  32.     Invalidate();
  33. }
复制代码


### 处理垂直滚动

手动调整垂直滚动:

  1. void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2. {
  3.     int scrollPos = GetScrollPos(SB_VERT);

  4.     switch (nSBCode)
  5.     {
  6.     case SB_TOP:
  7.         scrollPos = 0;
  8.         break;
  9.     case SB_BOTTOM:
  10.         scrollPos = m_matImage.rows - 1;
  11.         break;
  12.     case SB_LINEUP:
  13.         scrollPos = max(0, scrollPos - 10);
  14.         break;
  15.     case SB_LINEDOWN:
  16.         scrollPos = min(m_matImage.rows - 1, scrollPos + 10);
  17.         break;
  18.     case SB_PAGEUP:
  19.         scrollPos = max(0, scrollPos - 100);
  20.         break;
  21.     case SB_PAGEDOWN:
  22.         scrollPos = min(m_matImage.rows - 1, scrollPos + 100);
  23.         break;
  24.     case SB_THUMBTRACK:
  25.         scrollPos = nPos;
  26.         break;
  27.     default:
  28.         return;
  29.     }

  30.     SetScrollPos(SB_VERT, scrollPos);
  31.     m_ScrollPos.y = scrollPos;
  32.     Invalidate();
  33. }
复制代码


### 总结

确保调用`UpdateScrollInfo`来调整滚动条的信息,并在`OnPaint`中使用`m_ScrollPos`调整绘制位置。这些代码应适合用于MFC对话框中的手动滚动处理。根据你的具体需求,进一步调整代码。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-7 02:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表