您的位置:首页 > 编程语言

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

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

–>效果图 1:在最大化状态下的效果图



–>效果图 2:正常状态下的效果图,这时图片铺满窗口



–>效果图 3:对于长宽比不是4:3的图片,将自适应显示



–>效果图 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 <afxwin.h>         // MFC 核心组件和标准组件
#include <afxext.h>         // MFC 扩展

#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT

#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持

#include <math.h>
#include <afxtempl.h>       //对 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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: