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[]; // 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 ;
_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 ;
} return ;
} 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';
m_szFileTitle[] = '\0';
m_bOpenFileDialog = bOpenFileDialog; m_pParentWnd = NULL;
m_hWndTop = NULL; memset(&m_ofn, , 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(); // 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, , "Warning: UpdateData failed during dialog init.\n");
EndDialog(-);
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) ||
( == (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 > ) {
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 = ;
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 = ; 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) + );
//获取到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