–>本文先给出了基于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);
}