基于VS2010的MFC对话框编程之图片浏览器(附源代码)

–>本文先给出了基于VS2010的MFC对话框编程之图片浏览器所能实现的功能以及采用的技术,然后展示效果图,做出总结,最后附上源代码。

–>效果图 1:在最大化状态下的效果图
基于VS2010的MFC对话框编程之图片浏览器(附源代码)_第1张图片

–>效果图 2:正常状态下的效果图,这时图片铺满窗口
基于VS2010的MFC对话框编程之图片浏览器(附源代码)_第2张图片

–>效果图 3:对于长宽比不是4:3的图片,将自适应显示
基于VS2010的MFC对话框编程之图片浏览器(附源代码)_第3张图片

–>效果图 4:可随意对图片进行拖拽和放缩,且窗口不会产生闪烁
基于VS2010的MFC对话框编程之图片浏览器(附源代码)_第4张图片

本文源代码下载地址:http://download.csdn.net/detail/destiny0321/9490494
–>所实现的功能:
1.采用双缓冲技术解决屏幕闪烁问题;
2.浏览过程中实现图片的拖拽;
3.浏览过程中实现图片的放缩;
4.对当前文件下所支持图片格式(BMP、JPG、PNG)进行显示;
5.实现“上一张图片”和“下一张图片”功能;
6.随时进行窗口的最小化、正常、最大化显示的切换;
–>所用到的工具:CImage类
–>图片的放缩和拖拽主要用到了投影矩形的技术,即:投影矩形所在位置和大小就是图像在屏幕上位置和大小,随着投影矩形的移动和放缩,图像也在屏幕上移动和放缩,当然这里的屏幕指的是与窗口等尺寸的内存屏幕(解决闪烁问题)。我们只需要对投影矩形操作,就能实现一些列诸如放缩、拖拽等的功能。
–>不足之处:
1.由于能力有限,目前不能实现“双击图像文件,打开该图像”的功能,只好点击鼠标右键打开图像;
2.放缩功能有待改进;
3.更多功能将在今后逐渐添加进来!

–>现附上源代码:
以下是需要改动的地方,其他文件无需改动

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件

#pragma once

#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
#endif

#include "targetver.h"

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的

// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
#define _AFX_ALL_WARNINGS

#include          // MFC 核心组件和标准组件
#include          // MFC 扩展



#ifndef _AFX_NO_OLE_SUPPORT
#include            // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include              // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT

#include      // 功能区和控件条的 MFC 支持

#include 
#include        //对 CStringList 的支持

//窗口状态条尺寸
#define RECT_WINDOWBAR  (CRect(0,0,70,16))      //窗口状态条尺寸
#define RECT_MINIMIZE       (CRect(0,0,20,16))      //最小化图标尺寸
#define RECT_MAXIMIZE       (CRect(20,0,40,16))     //最大化图标尺寸
#define RECT_CLOSE          (CRect(40,0,70,16))     //关闭窗口图标尺寸
//左右箭头图标尺寸
#define RECT_ARROW_LEFT (CRect(0,0,47,47))      //左箭头图标尺寸
#define RECT_ARROW_RIGHT    (CRect(0,0,47,47))      //右箭头图标尺寸

//客户区背景颜色
#define BKCOLOR             (RGB(40,40,40))

//正常窗口的宽和高
#define NORMAL_WINDOW_WIDTH     800
#define NORMAL_WINDOW_HEIGHT        600

//窗口状态
enum{   WINDOW_STATE_MINIMIZED,     //最小化
            WINDOW_STATE_NORMAL,            //正常
            WINDOW_STATE_MAXIMIZED      //最大化
};

//虚拟按钮类型
enum{   BUTTON_TYPE_WINDOWBAR,      //窗口状态条
            BUTTON_TYPE_CLOSE,              //关闭
            BUTTON_TYPE_MAXIMAIZE,      //最大化
            BUTTON_TYPE_MINIMIZE,           //最小化
            BUTTON_TYPE_NEXT,               //下一张图片
            BUTTON_TYPE_PREVIOUS            //上一张图片
};

//图像尺寸类型
enum
{
    IMG_SIZE_NORMAL,                            //图像宽高均在绘图范围内
    IMG_SIZE_WIDTH_BEYOND,              //仅图像宽度超出绘图范围
    IMG_SIZE_HEIGHT_BEYOND,             //仅图像高度超出绘图范围
    IMG_SIZE_BOTH_BEYOND                    //图像宽高均超出绘图范围
};

#ifdef _UNICODE
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
#endif
// PicSeeDlg.h : 头文件
//
#pragma once

// CPicSeeDlg 对话框
class CPicSeeDlg : public CDialogEx
{
// 构造
public:
    CPicSeeDlg(CWnd* pParent = NULL);   // 标准构造函数

// 对话框数据
    enum { IDD = IDD_PICSEE_DIALOG };

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
    HICON m_hIcon;

    // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
    afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    afx_msg void OnOpen();
    DECLARE_MESSAGE_MAP()
private:
    CImage          m_Image;                            //当前图像
    CImage          m_ImgWindowBar;             //窗口状态条图像
    CImage          m_ImgLeftArrow;                 //左箭头图像
    CImage          m_ImgRightArrow;                //右箭头图像

    CRect               m_RectMem;                      //内存绘图区矩形区域
    CRect               m_RectScn;                      //屏幕绘图区区域
    CRect               m_RectImg;                          //图像矩形区域
    CRect               m_RectProj;                     //投影到内存屏幕的矩形区域

    CRect               m_RectWindowBar;                //当前窗口状态条所在矩形区域
    CRect               m_RectClose;                        //当前关闭按钮所在矩形区域
    CRect               m_RectMaximize;                 //当前最大化按钮所在矩形区域
    CRect               m_RectMinimize;                 //当前最小化按钮所在矩形区域
    CRect               m_RectLeftArrow;                    //当前左箭头图标所在区域
    CRect               m_RectRightArrow;               //当前右箭头图标所在区域

    BOOL                m_bLButttonDown;                //鼠标左键状态
    BOOL                m_bPtInLeft;                        //鼠标指针是否在左侧
    BOOL                m_bPtInRight;                       //鼠标指针是否在右侧

    int                 m_WindowState;                  //窗口状态
    int                 m_ImgPos;                           //当前图像所在文件夹中的图像中的位置
    int                 m_ImgSizeType;                  //图像尺寸类型

    CStringList     m_ImgPathList;                  //当前目录下的所支持的图像全路径链表

    CPoint          m_ptOriginal;                       //原点
    CPoint          m_ptTotalOffSet;                    //到原点的总偏移量

    float               m_ZoomScale;                        //缩放尺度


public:
    //加载图像资源
    static BOOL LoadImageFromResource(IN CImage* pImage, IN UINT nResID, IN LPCSTR lpType);
    //更新按钮所在内存屏幕区域
    void UpdateButtonRect(int nButtonType);
    //更新投影区域
    void UpDateProjRect(void);
    //拖拽图像
    void DragImage(CPoint point);
    //关闭窗口,退出程序
    void Close(void);
    //最大化窗口
    void Maximize(void);
    //最小化窗口
    void Minimize(void);
    //前一张图像
    void Previous(void);
    //后一张图像
    void Next(void);
    //获取除任务栏以外的桌面区域矩形
    void GetDesktopRect(LPRECT lpRect) const;
};
// PicSeeDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "PicSee.h"
#include "PicSeeDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CPicSeeDlg 对话框


CPicSeeDlg::CPicSeeDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CPicSeeDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    //初始状态
    m_bLButttonDown = FALSE;
    m_bPtInLeft      = FALSE;
    m_bPtInRight         = FALSE;

    m_ImgPathList.RemoveAll();
    m_Image.Destroy();

    m_ptTotalOffSet = 0;
    m_ImgPos = -1;
    m_ZoomScale = 1.0;

    //加载资源
    m_ImgWindowBar.Destroy();
    m_ImgLeftArrow.Destroy();
    m_ImgRightArrow.Destroy();
    LoadImageFromResource(&m_ImgWindowBar, IDB_WINDOWBAR, "BMP");
    LoadImageFromResource(&m_ImgLeftArrow, IDB_LEFTARROW, "PNG");
    LoadImageFromResource(&m_ImgRightArrow, IDB_RIGHTARROW, "PNG");
}

void CPicSeeDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPicSeeDlg, CDialogEx)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_COMMAND(IDM_OPEN, &CPicSeeDlg::OnOpen)
    ON_WM_RBUTTONUP()
    ON_WM_ERASEBKGND()
    ON_WM_MOUSEMOVE()
    ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()


// CPicSeeDlg 消息处理程序

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

    // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);         // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    //初始化
    GetDesktopRect(&m_RectMem);
    m_RectScn = m_RectMem;
    //显示窗口
    MoveWindow(&m_RectScn);
    //更改窗口状态
    m_WindowState = WINDOW_STATE_MAXIMIZED;
    //更新虚拟按钮所在矩形区域
    UpdateButtonRect(BUTTON_TYPE_WINDOWBAR);
    UpdateButtonRect(BUTTON_TYPE_CLOSE);
    UpdateButtonRect(BUTTON_TYPE_MAXIMAIZE);
    UpdateButtonRect(BUTTON_TYPE_MINIMIZE);
    UpdateButtonRect(BUTTON_TYPE_PREVIOUS);
    UpdateButtonRect(BUTTON_TYPE_NEXT);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CPicSeeDlg::OnPaint()
{
    CClientDC       dc(this);
    CDC             MemDC;
    CBitmap         MemBitmap;

    MemDC.CreateCompatibleDC(&dc);
    MemBitmap.CreateCompatibleBitmap(&dc, m_RectMem.Width(), m_RectMem.Height());
    MemDC.SelectObject(&MemBitmap);
    MemDC.SetStretchBltMode(COLORONCOLOR);

    //填充背景颜色
    MemDC.FillSolidRect(&m_RectMem, BKCOLOR);

    //画图像
    if(!m_Image.IsNull())
    {
        m_Image.Draw(MemDC.GetSafeHdc(), m_RectProj, m_RectImg);
    }

    //画窗口工具条
    m_ImgWindowBar.Draw(MemDC.GetSafeHdc(), m_RectWindowBar, RECT_WINDOWBAR);

    //画左箭头
    if(m_bPtInLeft)
    {   
        m_ImgLeftArrow.Draw(MemDC.GetSafeHdc(), m_RectLeftArrow, RECT_ARROW_LEFT);
    }

    //画右箭头
    if(m_bPtInRight)
    {   
        m_ImgRightArrow.Draw(MemDC.GetSafeHdc(), m_RectRightArrow, RECT_ARROW_RIGHT);
    }


    //贴图
    dc.BitBlt(0, 0, m_RectScn.Width(), m_RectScn.Height(), &MemDC, 0, 0, SRCCOPY);

    //释放资源
    MemDC.DeleteDC();
    MemBitmap.DeleteObject();
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CPicSeeDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}


BOOL CPicSeeDlg::LoadImageFromResource(IN CImage* pImage, IN UINT nResID, IN LPCSTR lpType)
{
    //////////////////////////////////////////////////////////////////////////
    /// 从资源文件中加载图片
    /// @param [in] pImage 图片指针
    /// @param [in] nResID 资源号
    /// @param [in] lpTyp 资源类型
    //////////////////////////////////////////////////////////////////////////
    if ( pImage == NULL)
        return false;
    pImage->Destroy();

    // 查找资源
    HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpType);
    if (hRsrc == NULL) return false;

    // 加载资源
    HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc);
    if (hImgData == NULL)
    {
        ::FreeResource(hImgData);
        return false;
    }

    // 锁定内存中的指定资源
    LPVOID lpVoid    = ::LockResource(hImgData);

    LPSTREAM pStream = NULL;
    DWORD dwSize    = ::SizeofResource(AfxGetResourceHandle(), hRsrc);
    HGLOBAL hNew    = ::GlobalAlloc(GHND, dwSize);
    LPBYTE lpByte    = (LPBYTE)::GlobalLock(hNew);
    ::memcpy(lpByte, lpVoid, dwSize);

    // 解除内存中的指定资源
    ::GlobalUnlock(hNew);

    // 从指定内存创建流对象
    HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream);
    if ( ht != S_OK )
    {
        GlobalFree(hNew);
    }
    else
    {
        // 加载图片
        pImage->Load(pStream);
        GlobalFree(hNew);
    }

    // 释放资源
    ::FreeResource(hImgData);

    return 0;
}

void CPicSeeDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_bLButttonDown = TRUE;
    m_ptOriginal = point;

    //前一张图片
    if(m_RectLeftArrow.PtInRect(point))
    {
        Previous();
    }//后一张图片
    else if(m_RectRightArrow.PtInRect(point))
    {
        Next();
    }

    CDialogEx::OnLButtonDown(nFlags, point);
}


void CPicSeeDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    //左键按下
    if(m_bLButttonDown)
    {
        //关闭窗口,结束程序
        if(m_RectClose.PtInRect(point))
        {
            Close();
        }
        //最大化窗口
        if(m_RectMaximize.PtInRect(point))
        {
            Maximize();
        }
        //最小化窗口
        if(m_RectMinimize.PtInRect(point))
        {
            Minimize();
        }
    }

    m_bLButttonDown = FALSE;

    CDialogEx::OnLButtonUp(nFlags, point);
}


void CPicSeeDlg::UpdateButtonRect(int nButtonType)
{
    //选择虚拟按钮类型
    switch(nButtonType)
    {
    case BUTTON_TYPE_WINDOWBAR:
        m_RectWindowBar = CRect(    m_RectMem.right - RECT_WINDOWBAR.Width(),
                                                0,
                                                m_RectMem.right,
                                                RECT_WINDOWBAR.Height());
        break;

    case BUTTON_TYPE_CLOSE:
        m_RectClose = CRect(    m_RectMem.right - RECT_CLOSE.Width(),
                                        0,
                                        m_RectMem.right,
                                        RECT_CLOSE.Height());
        break;

    case BUTTON_TYPE_MAXIMAIZE:
        m_RectMaximize = CRect( m_RectMem.right - RECT_CLOSE.Width() - RECT_MAXIMIZE.Width(),
                                            0,
                                            m_RectMem.right - RECT_CLOSE.Width(),
                                            RECT_MAXIMIZE.Height());
        break;

    case BUTTON_TYPE_MINIMIZE:
        m_RectMinimize = CRect( m_RectMem.right - RECT_WINDOWBAR.Width(),
                                            0,
                                            m_RectMem.right - RECT_CLOSE.Width() - RECT_MAXIMIZE.Width(),
                                            RECT_MINIMIZE.Height());
        break;
    case BUTTON_TYPE_NEXT:
        m_RectLeftArrow = CRect(    10,
                                            (m_RectMem.bottom - m_ImgLeftArrow.GetHeight())/2,
                                            10 + m_ImgLeftArrow.GetWidth(),
                                            (m_RectMem.bottom + m_ImgLeftArrow.GetHeight())/2);
        break;
    case BUTTON_TYPE_PREVIOUS:
        m_RectRightArrow = CRect(-10 + m_RectMem.right - m_ImgRightArrow.GetWidth(),
                                            (m_RectMem.bottom - m_ImgRightArrow.GetHeight())/2,
                                            -10 + m_RectMem.right,
                                            (m_RectMem.bottom + m_ImgRightArrow.GetHeight())/2);
        break;
    }
}


void CPicSeeDlg::Close(void)
{
    AfxGetMainWnd()->PostMessage(WM_QUIT);
}


void CPicSeeDlg::Maximize(void)
{
    m_ptTotalOffSet = 0;
    m_ZoomScale = 1.0;

    CRect rectMax;  //除任务栏外的桌面矩形区域
    CRect rectWnd;  //当前窗口矩形区域
    GetDesktopRect(&rectMax);
    GetWindowRect(&rectWnd);
    if(rectWnd.EqualRect(&rectMax))
    {   //若果窗口处于最大化状态
        CRect rect( (rectWnd.right-NORMAL_WINDOW_WIDTH)/2,
                        (rectWnd.bottom-NORMAL_WINDOW_HEIGHT)/2,
                        (rectWnd.right+NORMAL_WINDOW_WIDTH)/2,
                        (rectWnd.bottom+NORMAL_WINDOW_HEIGHT)/2);
        MoveWindow(&rect);

        //屏幕坐标转客户区坐标
        ScreenToClient(&rect);
        m_RectMem = rect;
        m_RectScn = m_RectMem;
        //更新窗口状态
        m_WindowState = WINDOW_STATE_NORMAL;
        //更新投影区区域
        UpDateProjRect();
    }
    else
    {   //如果窗口没有处于最大化,则最大化窗口
        m_RectMem = rectMax;
        m_RectScn = m_RectMem;
        MoveWindow(&m_RectScn);

        m_WindowState = WINDOW_STATE_MAXIMIZED;
        UpDateProjRect();
    }
    //更新虚拟按钮矩形区域
    UpdateButtonRect(BUTTON_TYPE_WINDOWBAR);
    UpdateButtonRect(BUTTON_TYPE_CLOSE);
    UpdateButtonRect(BUTTON_TYPE_MAXIMAIZE);
    UpdateButtonRect(BUTTON_TYPE_MINIMIZE);
    UpdateButtonRect(BUTTON_TYPE_PREVIOUS);
    UpdateButtonRect(BUTTON_TYPE_NEXT);
}


void CPicSeeDlg::Minimize(void)
{   //最小化窗口
    ShowWindow(SW_MINIMIZE);
    m_WindowState = WINDOW_STATE_MINIMIZED;
}


void CPicSeeDlg::OnOpen()
{
    m_ptTotalOffSet = 0;    //初始化图像总偏移量
    m_ZoomScale = 1.0;

    CString szFilter = "所有支持的文件|*.jpg;*.bmp;*.png;| \
                            JPG文件|*.jpg| \
                            BMP文件|*.bmp| \
                            PNG文件|*.png||";

    CFileDialog dlg(TRUE, 0, 0, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
    if(IDCANCEL == dlg.DoModal())
        return;

    //文件完整路径
    CString szWholePath = dlg.GetPathName();
    //文件名
    CString szFileName   = dlg.GetFileName();
    //文件纯路径
    CString szFilePath       = szWholePath.Left(szWholePath.GetLength()-szFileName.GetLength());
    //清空图像
    if(!m_Image.IsNull())
    {
        m_Image.Destroy();
    }
    //加载图像
    m_Image.Load(szWholePath);
    //更新投影区
    UpDateProjRect();

    //在当前路径下查找所有支持的图像文件
    CFileFind finder;
    BOOL bWorking = finder.FindFile(szFilePath + "*.*");
    while(bWorking)
    {
        bWorking = finder.FindNextFile();
        CString szName = finder.GetFileName();
        if(!finder.IsDirectory())
        {   //如果找到的不是路径
            //获取图像类型
            CString szType = szName.Right(3);
            if( (!szType.CompareNoCase("jpg")) ||
                (!szType.CompareNoCase("bmp")) ||
                (!szType.CompareNoCase("png")))
            {   //如果是支持的图像格式,添加至链表
                m_ImgPathList.AddTail(szFilePath+szName);
            }
            if(!szName.CompareNoCase(szFileName))
            {   //如果文件名与当前所显示图像名一致,则记录下该图像的位置
                m_ImgPos = m_ImgPathList.GetCount();
            }
        }
    }
}


void CPicSeeDlg::UpDateProjRect(void)
{   //如果当前图像为空,则返回
    if(m_Image.IsNull())
        return;
    //获取图像矩形区域
    m_RectImg = CRect(0, 0, m_Image.GetWidth(), m_Image.GetHeight());
    int MemWidth = m_RectMem.Width();
    int MemHeight = m_RectMem.Height();
    int ImgWidth = m_RectImg.Width();
    int ImgHeight = m_RectImg.Height();

    //默认不收缩投影区域
    int nGap = 0;
    //如果窗口处于最大化状态,则投影区域四周各收缩10个像素
    if(m_WindowState == WINDOW_STATE_MAXIMIZED)
    {
        nGap = 10;
    }

    //获取当前图像尺寸类型
    if( (ImgWidth <= MemWidth-nGap) && (ImgHeight <= MemHeight-nGap) )
        m_ImgSizeType = IMG_SIZE_NORMAL;
    else if( (ImgWidth>MemWidth-nGap) && (ImgHeight<=MemHeight-nGap) )
        m_ImgSizeType = IMG_SIZE_WIDTH_BEYOND;
    else if( (ImgWidth<=MemWidth-nGap) && (ImgHeight>MemHeight-nGap) )
        m_ImgSizeType = IMG_SIZE_HEIGHT_BEYOND;
    else
        m_ImgSizeType = IMG_SIZE_BOTH_BEYOND;

    //对不同的图像尺寸,计算投影区域矩形
    switch(m_ImgSizeType)
    {   
        float fScaleW,fScaleH;      //X、Y方向的缩小率
        int nW,nH;
    //长、宽均在显示范围内
    case IMG_SIZE_NORMAL:
        m_RectProj = CRect( (MemWidth-ImgWidth)/2,
            (MemHeight-ImgHeight)/2,
            (MemWidth+ImgWidth)/2,
            (MemHeight+ImgHeight)/2);
        break;
    //只有宽超出显示范围
    case IMG_SIZE_WIDTH_BEYOND:
        fScaleW = ((double)MemWidth)/ImgWidth;
        nW = MemWidth;
        nH = fScaleW*ImgHeight;
        m_RectProj = CRect( (MemWidth-nW)/2 + nGap,
            (MemHeight-nH)/2,
            (MemWidth+nW)/2 - nGap,
            (MemHeight+nH)/2);
        break;
    //只有高超出显示范围
    case IMG_SIZE_HEIGHT_BEYOND:
        fScaleH = ((double)MemHeight)/ImgHeight;
        nW = fScaleH*ImgWidth;
        nH = MemHeight;
        m_RectProj = CRect( (MemWidth-nW)/2,
            (MemHeight-nH)/2 + nGap,
            (MemWidth+nW)/2,
            (MemHeight+nH)/2 - nGap);
        break;
    //宽高都超出显示范围
    case IMG_SIZE_BOTH_BEYOND:
        fScaleW = ((double)MemWidth)/ImgWidth;
        fScaleH = ((double)MemHeight)/ImgHeight;
        float fScale = min(fScaleW, fScaleH);
        nW = fScale*ImgWidth;
        nH = fScale*ImgHeight;
        m_RectProj = CRect( (MemWidth-nW)/2 + nGap,
            (MemHeight-nH)/2 + nGap,
            (MemWidth+nW)/2 - nGap,
            (MemHeight+nH)/2 - nGap);
        break;
    }
}


void CPicSeeDlg::OnRButtonUp(UINT nFlags, CPoint point)
{
    CPoint pt = point;
    ClientToScreen(&pt);

    //加载右键菜单
    CMenu menu;
    menu.LoadMenu(IDR_MENU);
    menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, this);

    CDialogEx::OnRButtonUp(nFlags, point);
}


BOOL CPicSeeDlg::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;

//  return CDialogEx::OnEraseBkgnd(pDC);
}


void CPicSeeDlg::OnMouseMove(UINT nFlags, CPoint point)
{
    //如果鼠标指针在左侧,则激活左箭头
    if(point.x < 100)
        m_bPtInLeft = TRUE;
    else
        m_bPtInLeft = FALSE;

    //如果鼠标指针在右侧,则激活右箭头
    if(point.x > m_RectMem.right - 100)
        m_bPtInRight = TRUE;
    else
        m_bPtInRight = FALSE;

    //如果鼠标在图像内,更改光标图案
    if(m_RectProj.PtInRect(point))
    {   
        HCURSOR hCursor = (HCURSOR)AfxGetApp()->LoadStandardCursor(IDC_HAND);
        ::SetCursor(hCursor);

        //如果有鼠标左键按下,拖拽图像
        if(m_bLButttonDown)
        {
            DragImage(point);
        }
    }
    CDialogEx::OnMouseMove(nFlags, point);
}


void CPicSeeDlg::DragImage(CPoint point)
{   
    //当前图像总的偏移量的累积
    m_ptTotalOffSet += point-m_ptOriginal;

    int MemWidth = m_RectMem.Width();
    int MemHeight = m_RectMem.Height();
    int ProjWidth = m_RectProj.Width();
    int ProjHeight = m_RectProj.Height();
    //更新投影区域
    m_RectProj = CRect( (MemWidth-ProjWidth)/2 + m_ptTotalOffSet.x,
        (MemHeight-ProjHeight)/2 + m_ptTotalOffSet.y,
        (MemWidth+ProjWidth)/2 + m_ptTotalOffSet.x,
        (MemHeight+ProjHeight)/2 + m_ptTotalOffSet.y);
    //更新原点
    m_ptOriginal = point;
}


void CPicSeeDlg::Previous(void)
{
    //如果链表为空,则没有图像文件传入
    if(m_ImgPathList.IsEmpty())
    {
        return;
    }

    m_ptTotalOffSet = 0;
    m_ZoomScale = 1.0;

    CString szFilePath;
    if(m_ImgPos == 1)
    {   //如果当前图像是当前路径下的第一张图像,则显示最后一张图像
        szFilePath = m_ImgPathList.GetTail();
        m_ImgPos = m_ImgPathList.GetCount();
    }
    else
    {   //否则显示前一张图像
        m_ImgPos--;
        szFilePath = m_ImgPathList.GetAt(m_ImgPathList.FindIndex(m_ImgPos-1));
    }
    m_Image.Destroy();
    m_Image.Load(szFilePath);
    UpDateProjRect();
}


void CPicSeeDlg::Next(void)
{
    //如果链表为空,则没有图像文件传入
    if(m_ImgPathList.IsEmpty())
    {
        return;
    }

    m_ptTotalOffSet = 0;
    m_ZoomScale = 1.0;

    CString szFilePath;
    if(m_ImgPos == m_ImgPathList.GetCount())
    {   //如果当前图像是当前路径下的最后一张图像,则显示第一张图像
        szFilePath = m_ImgPathList.GetHead();
        m_ImgPos = 1;
    }
    else
    {   //否则显示后一张图像
        szFilePath = m_ImgPathList.GetAt(m_ImgPathList.FindIndex(m_ImgPos));
        m_ImgPos++;
    }
    m_Image.Destroy();
    m_Image.Load(szFilePath);
    UpDateProjRect();
}


BOOL CPicSeeDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    //如果链表为空,则没有图像文件传入
    if(m_ImgPathList.IsEmpty())
    {
        return FALSE;
    }

    //如果图像面积小于一定值且zDelta为负
    //或者图像面积大于一定值且zDelta,则不放缩图像
    if( ((m_RectProj.Width()*m_RectProj.Height() < 3600) && (zDelta < 0)) ||
        ((m_RectProj.Width()*m_RectProj.Height() > 1366*768*100) && (zDelta > 0)))
    {   
        m_ZoomScale = 1.0;
    }   //否则放缩图像
    else
    {
    //      m_ZoomScale = pow(1.168, zDelta/120.0 + 29.655)/100.0;
        m_ZoomScale = 1 + 0.2*zDelta/120.0;
    }

    int ProjWidth = m_RectProj.Width();
    int ProjHeight = m_RectProj.Height();

    int ProjTop = m_RectProj.top;
    int ProjLeft = m_RectProj.left;
    int ProjBottom = m_RectProj.bottom;
    int ProjRight = m_RectProj.right;
    int ProjWidthNew = ProjWidth*m_ZoomScale;
    int ProjHeightNew = ProjHeight*m_ZoomScale;
    int nDiffW = (ProjWidthNew - ProjWidth)/2;
    int nDiffH = (ProjHeightNew - ProjHeight)/2;
    m_RectProj = CRect(ProjLeft - nDiffW, ProjTop - nDiffH, ProjRight + nDiffW, ProjBottom + nDiffH);


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


void CPicSeeDlg::GetDesktopRect(LPRECT lpRect) const
{
    //查找任务栏,获取任务栏窗口句柄
    HWND hWnd = ::FindWindow("Shell_TrayWnd", NULL);
    CRect rectTask;
    ::GetWindowRect(hWnd, &rectTask);
    *lpRect = CRect(0, 0, rectTask.right, rectTask.top);
}

你可能感兴趣的:(C++)