VS2012下自定义打开文件对话框
VS2012下自定义打开文件对话框,MFC的CFileDialog封装了太多,太复杂,绕得头晕,自己封装一个得了
#pragma once
#include <objbase.h>
#include <commdlg.h>
#include "ImagePreviewStatic.h"
// XFileDialog
class XFileDialog : public CWnd
{
DECLARE_DYNAMIC(XFileDialog)
public:
XFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL, LPCTSTR lpszInitFolder = NULL,
CWnd* pParentWnd = NULL);
virtual ~XFileDialog();
public:
void EndDialog(int nResult);
virtual BOOL OnInitDialog();
virtual long DoModal();
virtual void DoDataExchange(CDataExchange *pDX);
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
virtual void ProcFileChange(TCHAR* strFullName);
protected:
OPENFILENAME m_ofn;
BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save
CString m_strFilter; // filter string
TCHAR m_szFileTitle[64]; // contains file title after return
TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return
CWnd* m_pParentWnd; // parent/owner window
HWND m_hWndTop; // top level parent window (may be disabled)
CImagePreviewStatic m_preview;
DECLARE_MESSAGE_MAP()
};
// XFileDialog.cpp : implementation file
//
#include "stdafx.h"
#include "XFileDialog.h"
#include "resource.h"
// XFileDialog
UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
UINT_PTR CALLBACK OFNHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (hWnd == NULL)
return 0;
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
if (pThreadState->m_pAlternateWndInit != NULL && CWnd::FromHandlePermanent(hWnd) == NULL)
{
ASSERT_KINDOF(XFileDialog, pThreadState->m_pAlternateWndInit);
pThreadState->m_pAlternateWndInit->SubclassWindow(hWnd);
pThreadState->m_pAlternateWndInit = NULL;
}
if (message == WM_INITDIALOG)
{
/*
_afxMsgLBSELCHANGE = ::RegisterWindowMessage(LBSELCHSTRING);
_afxMsgSHAREVI = ::RegisterWindowMessage(SHAREVISTRING);
_afxMsgFILEOK = ::RegisterWindowMessage(FILEOKSTRING);
_afxMsgCOLOROK = ::RegisterWindowMessage(COLOROKSTRING);
_afxMsgHELP = ::RegisterWindowMessage(HELPMSGSTRING);
_afxMsgSETRGB = ::RegisterWindowMessage(SETRGBSTRING);
*/
XFileDialog* pDlg = DYNAMIC_DOWNCAST(XFileDialog, CWnd::FromHandlePermanent(hWnd));
if (pDlg != NULL)
return pDlg->OnInitDialog();
else
return 1;
}
return 0;
}
BEGIN_MESSAGE_MAP(XFileDialog, CWnd)
END_MESSAGE_MAP()
XFileDialog::XFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
DWORD dwFlags, LPCTSTR lpszFilter, LPCTSTR lpszInitFolder, CWnd* pParentWnd) :
CWnd()
{
m_szFileName[0] = '\0';
m_szFileTitle[0] = '\0';
m_bOpenFileDialog = bOpenFileDialog;
m_pParentWnd = NULL;
m_hWndTop = NULL;
memset(&m_ofn, 0, sizeof(OPENFILENAME)); // initialize structure to 0/NULL
m_ofn.Flags |= dwFlags | OFN_ENABLETEMPLATE |OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
m_ofn.lpstrTitle = _T("图像文件预览对话框");
m_ofn.lpstrInitialDir = lpszInitFolder;
m_ofn.lStructSize = sizeof(OPENFILENAME);
m_ofn.lpstrFile = m_szFileName;
m_ofn.nMaxFile = _countof(m_szFileName);
m_ofn.lpstrDefExt = lpszDefExt;
m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
m_ofn.nMaxFileTitle = _countof(m_szFileTitle);
if(dwFlags & OFN_ENABLETEMPLATE)
m_ofn.Flags &= ~OFN_ENABLESIZING;
m_ofn.hInstance = AfxGetResourceHandle();
m_ofn.lpfnHook = (LPOFNHOOKPROC)OFNHookProc;
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_IMAGEPREVIEWDLG);
// setup initial file name
if (lpszFileName != NULL)
Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE);
// Translate filter into commdlg format (lots of \0)
if (lpszFilter != NULL)
{
m_strFilter = lpszFilter;
LPTSTR pch = m_strFilter.GetBuffer(0); // modify the buffer in place
// MFC delimits with '|' not '\0'
while ((pch = _tcschr(pch, '|')) != NULL)
*pch++ = '\0';
m_ofn.lpstrFilter = m_strFilter;
// do not call ReleaseBuffer() since the string contains '\0' characters
}
}
XFileDialog::~XFileDialog()
{
}
void XFileDialog::EndDialog(int nResult)
{
ASSERT(::IsWindow(m_hWnd));
::EndDialog(m_hWnd, nResult);
}
BOOL XFileDialog::OnInitDialog()
{
// transfer data into the dialog from member variables
#if 1
if (!UpdateData(FALSE))
{
TRACE(traceAppMsg, 0, "Warning: UpdateData failed during dialog init.\n");
EndDialog(-1);
return FALSE;
}
#endif
GetDlgItem(IDC_IMAGEPREVIEW)->ModifyStyle ( SS_TYPEMASK, SS_OWNERDRAW );
return TRUE; // set focus to first one
}
void XFileDialog::DoDataExchange(CDataExchange *pDX)
{
CWnd::DoDataExchange(pDX);
DDX_Control(pDX, IDC_IMAGEPREVIEW, m_preview);
}
void XFileDialog::ProcFileChange(TCHAR* strFullName){
//如果是文件名
DWORD nFileAtts = GetFileAttributes(strFullName);
if ((FILE_ATTRIBUTE_NORMAL == nFileAtts) ||
(0 == (nFileAtts & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY )) ) ){
m_preview.SetFilename(strFullName);
} else {
//m_preview.SetFilename(NULL);
}
}
BOOL XFileDialog::OnNotify(WPARAM, LPARAM lp, LRESULT *pResult)
{
LPOFNOTIFY of = (LPOFNOTIFY) lp;
CString csTemp;
TCHAR strFileName[_MAX_PATH];
HWND hParent;
UINT nfiles;
switch (of->hdr.code)
{
case CDN_SELCHANGE:
hParent = GetParent()->GetSafeHwnd();
nfiles = CommDlg_OpenSave_GetFilePath(hParent, strFileName, _MAX_PATH);
if (nfiles > 0) {
ProcFileChange(strFileName);
//MessageBox(strFileName);
}
break;
case CDN_FOLDERCHANGE:
// Once we get this notification our old subclassing of
// the SHELL window is lost, so we have to
// subclass it again. (Changing the folder causes a
// destroy and recreate of the SHELL window).
//if (m_wndHook.GetSafeHwnd() != HWND(NULL))
// m_wndHook.UnsubclassWindow();
//m_wndHook.SubclassWindow(GetParent()->GetDlgItem(lst2)->GetSafeHwnd());
//UpdatePreview(_T(""));
break;
}
*pResult = 0;
return FALSE;
}
long XFileDialog::DoModal()
{
HWND hWndFocus = ::GetFocus();
BOOL bEnableParent = FALSE;
// allow OLE servers to disable themselves
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
pApp->EnableModeless(FALSE);
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
pThreadState->m_pAlternateWndInit = this;
//AfxHookWindowCreate(this);
HWND hWndParent = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);;
if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent))
{
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}
INT_PTR nResult = 0;
if (m_bOpenFileDialog)
nResult = GetOpenFileName(&m_ofn);
else
nResult = GetSaveFileName(&m_ofn);
if (nResult)
ASSERT(pThreadState->m_pAlternateWndInit == NULL);
// Second part of special case for file open/save dialog.
if (bEnableParent)
::EnableWindow(hWndParent, TRUE);
if (::IsWindow(hWndFocus))
::SetFocus(hWndFocus);
AfxUnhookWindowCreate(); // just in case
Detach(); // just in case
if (pApp != NULL)
pApp->EnableModeless(TRUE);
return nResult ? nResult : IDCANCEL;
}
IMPLEMENT_DYNAMIC(XFileDialog, CWnd)
// XFileDialog message handlers
ImagePreviewStatic.h其实就是一个CStatic的继承类,实现图片预览
/*
* $Header: $
*
* $History: $
*/
#pragma once
#include <atlimage.h>
// CImagePrieviewStatic
class CImagePreviewStatic : public CStatic
{
DECLARE_DYNAMIC(CImagePreviewStatic)
public:
CImagePreviewStatic();
virtual ~CImagePreviewStatic();
virtual BOOL Create();
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
void SetFilename(LPCTSTR szFilename);
protected:
WCHAR m_wsFilename[_MAX_PATH];
Image *m_img;
Graphics *m_graphics;
CImage *m_img2;
DECLARE_MESSAGE_MAP()
};
/*
* $Header: $
*
* $History: $
*/
#include "stdafx.h"
#include "ImagePreviewStatic.h"
// CImagePrieviewStatic
IMPLEMENT_DYNAMIC(CImagePreviewStatic, CStatic)
CImagePreviewStatic::CImagePreviewStatic() : CStatic()
{
m_img = (Image *) NULL;
m_graphics = (Graphics *) NULL;
m_img2 = (CImage*) NULL;
}
CImagePreviewStatic::~CImagePreviewStatic()
{
if (m_img) {
delete m_img;
}
if (m_graphics) {
delete m_graphics;
}
if (m_img2) {
delete m_img2;
}
}
BOOL CImagePreviewStatic::Create()
{
if (GetSafeHwnd() != HWND(NULL))
{
m_img = new Image(m_wsFilename);
m_graphics = new Graphics(GetSafeHwnd());
return TRUE;
}
return FALSE;
}
void CImagePreviewStatic::SetFilename(LPCTSTR szFilename)
{
#ifndef _UNICODE
USES_CONVERSION;
#endif
ASSERT(szFilename);
ASSERT(AfxIsValidString(szFilename));
TRACE("%s\n", szFilename);
#ifndef _UNICODE
wcscpy(m_wsFilename, A2W(szFilename));
#else
wcscpy(m_wsFilename, szFilename);
#endif
//delete m_img;
//m_img = new Image(m_wsFilename, FALSE);
if (m_img2) {
delete m_img2;
}
m_img2 = new CImage();
m_img2->Load(szFilename);
Invalidate();
}
void CImagePreviewStatic::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
{
Unit units;
CRect rect;
/*
if (m_img != NULL)
{
GetClientRect(&rect);
RectF destRect(REAL(rect.left), REAL(rect.top), REAL(rect.Width()), REAL(rect.Height())),
srcRect;
m_img->GetBounds(&srcRect, &units);
m_graphics->DrawImage(m_img, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, UnitPixel, NULL);
}
*/
if (m_img2 != NULL) {
HWND hWnd = GetParent()->m_hWnd;
HDC hDc = ::GetDC(hWnd);
GetWindowRect(&rect);
::ScreenToClient(hWnd, (LPPOINT)&rect);
::ScreenToClient(hWnd, (LPPOINT)(&rect) + 1);
//获取到HDC
m_img2->Draw(hDc,rect);
}
}
BEGIN_MESSAGE_MAP(CImagePreviewStatic, CStatic)
END_MESSAGE_MAP()
// CImagePrieviewStatic message handlers
其中的对话框资源
IDD_IMAGEPREVIEWDLG DIALOGEX 0, 0, 365, 177
STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
CONTROL "",IDC_IMAGEPREVIEW,"Static",SS_OWNERDRAW,7,7,351,163
END