一个文件预览对话框

一个文件预览对话框

说明

需要做个文件选择时的预览,发现MFC中原有的对话框功能有限,想起继承后自绘处理,找了一些资料,不能完美实现,最后结合一些资料,自我感觉良好,遂分享之。

实现步骤

资源文件

GROUPBOX的ID确定是1119,这个很重要!!!

/
//
// Dialog
//
IDD_FILEEX_DLG DIALOGEX 0, 0, 512, 230
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "",IDC_SC_DRAW,310,6,190,189
    CONTROL         "预览文件",IDC_CHECK_PREVIEW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,374,199,50,10
    GROUPBOX        "",1119,0,0,308,227
END

代码

FileDialogEx.h

//!< 这个类的目的是移除GroupBox的外边框
class CCustomGroupBox : public CButton
{
	DECLARE_DYNAMIC(CCustomGroupBox)

public:
	CCustomGroupBox();
	virtual ~CCustomGroupBox();

protected:
	DECLARE_MESSAGE_MAP()
	afx_msg void OnPaint();
};

class CFileDialogEx : public CFileDialog
{
	DECLARE_DYNAMIC(CFileDialogEx)

public:
	CFileDialogEx(BOOL bOpenFileDialog, // 对于 FileOpen 为 TRUE,对于 FileSaveAs 为 FALSE
		LPCTSTR lpszDefExt = NULL,
		LPCTSTR lpszFileName = NULL,
		DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		LPCTSTR lpszFilter = NULL,
		CWnd* pParentWnd = NULL);
	virtual ~CFileDialogEx();

#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_FILEEX_DLG };
#endif
    // 目的是选中文件后,解析生成BMP,让窗口调用,需要自己实现
	// 1. path1 选中的文件路径
	// 2. path2 需要保存到指定位置的图片路径
	std::function<bool(CString,CString)> m_fnTask;

private:
    float m_dbWidth, m_dbHeight;
	BOOL m_bOpenFilePreview;
	CString m_strViewImgPath, m_lstPath;
	CImage m_PreViewImg;

	CCustomGroupBox m_grp;
protected:
	DECLARE_MESSAGE_MAP()
public:
	virtual BOOL OnInitDialog();
	virtual void OnFileNameChange();
	virtual void OnTypeChange();
	void UpdateScImage();
	afx_msg void OnClose();
	afx_msg void OnBnClickedCheckPreview();
	afx_msg void OnStnClickedScFiledialog();
    afx_msg void OnPaint();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};

FileDialogEx.cpp

#include "FileDialogEx.h"
// CFileDialogEx
IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog)

CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
		DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
		CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
{
	m_ofn.Flags |= dwFlags;
	m_ofn.Flags |= OFN_FILEMUSTEXIST;
	m_ofn.Flags |= OFN_PATHMUSTEXIST;
	m_ofn.Flags |= OFN_ALLOWMULTISELECT;
	m_ofn.Flags |= OFN_EXPLORER;
	m_ofn.Flags |= OFN_ENABLETEMPLATE;

	DWORD dwMajorVer = NULL, dwMinorVer = NULL, dwBuildNumber = NULL;

	m_ofn.hInstance = AfxGetInstanceHandle();
	m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEEX_DLG);

	m_bVistaStyle = FALSE;      //可以vista以上运行
	m_dwRef = 1;
	m_bOpenFilePreview = TRUE;
    m_dbWidth = m_dbHeight = 1000;
	m_lstPath = m_strViewImgPath = _T("");
	m_fnTask = NULL;
}

CFileDialogEx::~CFileDialogEx()
{
    if (!m_PreViewImg.IsNull()) m_PreViewImg.Destroy();
	if (GetFileAttributes(m_strViewImgPath) > 0) DeleteFile(m_strViewImgPath);
}

BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog)
	ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_CHECK_PREVIEW, &CFileDialogEx::OnBnClickedCheckPreview)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// CFileDialogEx 消息处理程序
BOOL CFileDialogEx::OnInitDialog()
{
	CFileDialog::OnInitDialog();

	m_grp.SubclassDlgItem(1119,this);
	CRect rc, rcFileDialog, rcWnd;
	GetDlgItem(IDC_SC_DRAW)->GetClientRect(rc);
	ClientToScreen(rc);

	int nDefault = rc.Width() < rc.Height() ? rc.Width() : rc.Height();
	GetDlgItem(IDC_SC_DRAW)->SetWindowPos(NULL, 0, 0, nDefault, nDefault, SWP_NOZORDER | SWP_NOMOVE);

	((CButton*)GetDlgItem(IDC_CHECK_PREVIEW))->SetCheck(m_bOpenFilePreview);

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

void CFileDialogEx::UpdateScImage()
{
	CDC* pDc = GetDlgItem(IDC_SC_DRAW)->GetDC();
    if (!m_PreViewImg.IsNull() && pDc)
    {
		/*
			在使用 CImage 的Draw 输入一个图像时,有时候会造成图像失真严重,解决的方法如下
			失真主要是由于变形造成的.只要设置一下变形的模式就可以了
		*/
		::SetStretchBltMode(*pDc, HALFTONE);
		::SetBrushOrgEx(*pDc, 0, 0, NULL);

		CRect rc;
		GetDlgItem(IDC_SC_DRAW)->GetClientRect(rc);
		m_PreViewImg.StretchBlt(pDc->GetSafeHdc(), 0, 0, rc.Width(), rc.Height(), SRCCOPY);
	}
	if (pDc) ReleaseDC(pDc);
}

void CFileDialogEx::OnTypeChange()
{
	CString folderPath = GetFolderPath();
	SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH, folderPath, NULL);
	CFileDialog::OnTypeChange();
}

void CFileDialogEx::OnFileNameChange()
{
	// TODO: 在此添加专用代码和/或调用基类
	CFileDialog::OnFileNameChange();
	CString path = GetPathName();
	CString ext = GetFileExt();

	if (!m_bOpenFilePreview || m_lstPath == path)
		return;

	if (m_fnTask)
	{
		if (!m_fnTask(path, m_strViewImgPath))
			return;

		if (!m_PreViewImg.IsNull()) m_PreViewImg.Destroy();
		m_PreViewImg.Load(m_strViewImgPath);
		m_lstPath = path;
	}
	UpdateScImage();
}

void CFileDialogEx::OnClose()
{
	// TODO:  在此添加消息处理程序代码和/或调用默认值
	CFileDialog::OnClose();
}

void CFileDialogEx::OnBnClickedCheckPreview()
{
	// TODO:  在此添加控件通知处理程序代码
	m_bOpenFilePreview = ((CButton*)GetDlgItem(IDC_CHECK_PREVIEW))->GetCheck();
    if (!m_bOpenFilePreview)
    {
		if (!m_PreViewImg.IsNull()) m_PreViewImg.Destroy();
		UpdateScImage();
    }
}

void CFileDialogEx::OnStnClickedScFiledialog()
{
	// TODO: 在此添加控件通知处理程序代码
}

void CFileDialogEx::OnPaint()
{
	CPaintDC dc(this); // device context for painting
    UpdateScImage();
}

BOOL CFileDialogEx::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return TRUE;
	//return CFileDialog::OnEraseBkgnd(pDC);
}

/
IMPLEMENT_DYNAMIC(CCustomGroupBox, CButton)
CCustomGroupBox::CCustomGroupBox()
{
}

CCustomGroupBox::~CCustomGroupBox()
{
}

BEGIN_MESSAGE_MAP(CCustomGroupBox, CButton)
	ON_WM_PAINT()
END_MESSAGE_MAP()

void CCustomGroupBox::OnPaint()
{
	CPaintDC dc(this); // device context for painting
}

效果预览

一个文件预览对话框

最后

感谢各位大佬的无私奉献。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值