鱼C论坛

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

图片放大缩小滚动条

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

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

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

x
C++ MFC 将Mat图置于Picture control中,怎样将图片放大缩小预览,当图像变大时Picture control控件自动显示水平和垂直滚动条用于上下左右移动图片
想知道小甲鱼最近在做啥?请访问 -> 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. **示例代码框架**:

BOOL CYourDlg::OnInitDialog()
   {
       CDialogEx::OnInitDialog();

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

       return TRUE;
   }

   void CYourDlg::UpdateImageView()
   {
       CClientDC dc(this);
       CRect rect;
       GetClientRect(&rect);

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

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

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

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

       CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
   }

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

1 ...

请给出详细的代码
想知道小甲鱼最近在做啥?请访问 -> 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:
HBITMAP MatToHBITMAP(const cv::Mat& mat)
{
    cv::Mat temp;
    cv::cvtColor(mat, temp, cv::COLOR_BGR2BGRA);

    HBITMAP hBitmap = CreateBitmap(temp.cols, temp.rows, 1, 32, temp.data);
    return hBitmap;
}

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

在对话框类中初始化滚动条和处理绘图:
BOOL CImageViewerDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

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

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

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

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

    return TRUE;
}

### 4. 绘制图像

重载`OnPaint`来绘制Mat图像:
void CImageViewerDlg::OnPaint()
{
    CPaintDC dc(this);

    if (!m_matImage.empty())
    {
        HBITMAP hBitmap = MatToHBITMAP(m_matImage);
        CBitmap bitmap;
        bitmap.Attach(hBitmap);

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

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

        memDC.SelectObject(pOldBitmap);
        DeleteObject(hBitmap);
    }
}

### 5. 处理缩放

响应鼠标滚轮事件来缩放:
BOOL CImageViewerDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    double scaleFactor = (zDelta > 0) ? 1.1 : 0.9;
    cv::resize(m_matImage, m_matImage, cv::Size(), scaleFactor, scaleFactor);

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

    if (pHScrollBar && pVScrollBar)
    {
        SCROLLINFO si;
        si.fMask = SIF_RANGE | SIF_PAGE;
        si.nMin = 0;
        si.nMax = m_matImage.cols - 1;
        si.nPage = 100; 
        pHScrollBar->SetScrollInfo(&si);

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

    Invalidate();
    return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
}

### 6. 滚动图片

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

void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // 滚动处理代码
    CDialogEx::OnVScroll(nSBCode, nPos, pScrollBar);
}

### 总结

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

### 1. 添加控件和类

这些代码中Picture Control的变量名称是或者ID名称是设置的什么?没有看明白
想知道小甲鱼最近在做啥?请访问 -> 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`进行访问和操作:
void CImageViewerDlg::OnPaint()
{
    CPaintDC dc(this);

    if (!m_matImage.empty())
    {
        HBITMAP hBitmap = MatToHBITMAP(m_matImage);
        CBitmap bitmap;
        bitmap.Attach(hBitmap);

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

        BITMAP bm;
        bitmap.GetBitmap(&bm);

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

        memDC.SelectObject(pOldBitmap);
        DeleteObject(hBitmap);
    }
}

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

### 1. 添加控件和类

请给出处理滚动的详细代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

### 滚动处理逻辑

1. **在类中添加成员变量**:
CPoint m_ScrollPos;  // 记录滚动位置

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

在`OnInitDialog`中设置滚动条:
BOOL CImageViewerDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

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

    return TRUE;
}

3. **更新滚动信息**:
void CImageViewerDlg::UpdateScrollInfo()
{
    if (!m_matImage.empty())
    {
        CScrollBar* pHScrollBar = GetScrollBarCtrl(SB_HORZ);
        CScrollBar* pVScrollBar = GetScrollBarCtrl(SB_VERT);

        if (pHScrollBar && pVScrollBar)
        {
            SCROLLINFO si;
            si.fMask = SIF_RANGE | SIF_PAGE;
            si.nMin = 0;
            si.nPage = 100; 
            si.nMax = m_matImage.cols - 1;
            pHScrollBar->SetScrollInfo(&si);

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

4. **处理水平滚动**:
void CImageViewerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    int scrollPos;
    SCROLLINFO si = { sizeof(si), SIF_ALL };
    pScrollBar->GetScrollInfo(&si);

    switch (nSBCode)
    {
    case SB_LEFT:
        scrollPos = si.nMin;
        break;
    case SB_RIGHT:
        scrollPos = si.nMax;
        break;
    case SB_LINELEFT:
        scrollPos = max(si.nMin, si.nPos - 10);
        break;
    case SB_LINERIGHT:
        scrollPos = min(si.nMax, si.nPos + 10);
        break;
    case SB_PAGELEFT:
        scrollPos = max(si.nMin, si.nPos - (int)si.nPage);
        break;
    case SB_PAGERIGHT:
        scrollPos = min(si.nMax, si.nPos + (int)si.nPage);
        break;
    case SB_THUMBTRACK:
        scrollPos = nPos;
        break;
    default:
        return;
    }

    pScrollBar->SetScrollPos(scrollPos);
    m_ScrollPos.x = scrollPos;
    Invalidate();
}

5. **处理垂直滚动**:
void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    int scrollPos;
    SCROLLINFO si = { sizeof(si), SIF_ALL };
    pScrollBar->GetScrollInfo(&si);

    switch (nSBCode)
    {
    case SB_TOP:
        scrollPos = si.nMin;
        break;
    case SB_BOTTOM:
        scrollPos = si.nMax;
        break;
    case SB_LINEUP:
        scrollPos = max(si.nMin, si.nPos - 10);
        break;
    case SB_LINEDOWN:
        scrollPos = min(si.nMax, si.nPos + 10);
        break;
    case SB_PAGEUP:
        scrollPos = max(si.nMin, si.nPos - (int)si.nPage);
        break;
    case SB_PAGEDOWN:
        scrollPos = min(si.nMax, si.nPos + (int)si.nPage);
        break;
    case SB_THUMBTRACK:
        scrollPos = nPos;
        break;
    default:
        return;
    }

    pScrollBar->SetScrollPos(scrollPos);
    m_ScrollPos.y = scrollPos;
    Invalidate();
}

### 总结

这些代码实现了滚动条的基本处理功能,记得在`OnPaint`中使用`m_ScrollPos`来调整图片绘制位置。例如:
dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &memDC, m_ScrollPos.x, m_ScrollPos.y, bm.bmWidth, bm.bmHeight, SRCCOPY);

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

### 滚动处理逻辑

提示错误
“GetScrollBarCtrl”: 找不到标识符
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


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

### 修改初始化滚动条

在`OnInitDialog`中,手动设置滚动条的范围和位置:
BOOL CImageViewerDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

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

    return TRUE;
}

### 更新滚动信息

手动控制滚动条的更新:
void CImageViewerDlg::UpdateScrollInfo()
{
    if (!m_matImage.empty())
    {
        SCROLLINFO si;
        si.cbSize = sizeof(SCROLLINFO);
        si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
        si.nMin = 0;
        si.nPage = 100;

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

        // 垂直滚动信息
        si.nMax = m_matImage.rows - 1;
        si.nPos = m_ScrollPos.y;
        SetScrollInfo(SB_VERT, &si, TRUE);
    }
}

### 处理水平滚动

手动调整水平滚动:
void CImageViewerDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    int scrollPos = GetScrollPos(SB_HORZ);

    switch (nSBCode)
    {
    case SB_LEFT:
        scrollPos = 0;
        break;
    case SB_RIGHT:
        scrollPos = m_matImage.cols - 1;
        break;
    case SB_LINELEFT:
        scrollPos = max(0, scrollPos - 10);
        break;
    case SB_LINERIGHT:
        scrollPos = min(m_matImage.cols - 1, scrollPos + 10);
        break;
    case SB_PAGELEFT:
        scrollPos = max(0, scrollPos - 100);
        break;
    case SB_PAGERIGHT:
        scrollPos = min(m_matImage.cols - 1, scrollPos + 100);
        break;
    case SB_THUMBTRACK:
        scrollPos = nPos;
        break;
    default:
        return;
    }

    SetScrollPos(SB_HORZ, scrollPos);
    m_ScrollPos.x = scrollPos;
    Invalidate();
}

### 处理垂直滚动

手动调整垂直滚动:
void CImageViewerDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    int scrollPos = GetScrollPos(SB_VERT);

    switch (nSBCode)
    {
    case SB_TOP:
        scrollPos = 0;
        break;
    case SB_BOTTOM:
        scrollPos = m_matImage.rows - 1;
        break;
    case SB_LINEUP:
        scrollPos = max(0, scrollPos - 10);
        break;
    case SB_LINEDOWN:
        scrollPos = min(m_matImage.rows - 1, scrollPos + 10);
        break;
    case SB_PAGEUP:
        scrollPos = max(0, scrollPos - 100);
        break;
    case SB_PAGEDOWN:
        scrollPos = min(m_matImage.rows - 1, scrollPos + 100);
        break;
    case SB_THUMBTRACK:
        scrollPos = nPos;
        break;
    default:
        return;
    }

    SetScrollPos(SB_VERT, scrollPos);
    m_ScrollPos.y = scrollPos;
    Invalidate();
}

### 总结

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 19:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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