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() };
1 // XFileDialog.cpp : implementation file 2 // 3 4 #include "stdafx.h" 5 #include "XFileDialog.h" 6 #include "resource.h" 7 8 // XFileDialog 9 10 UINT_PTR CALLBACK OFNHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 11 12 UINT_PTR CALLBACK OFNHookProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 13 { 14 if (hWnd == NULL) 15 return 0; 16 _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); 17 if (pThreadState->m_pAlternateWndInit != NULL && CWnd::FromHandlePermanent(hWnd) == NULL) 18 { 19 ASSERT_KINDOF(XFileDialog, pThreadState->m_pAlternateWndInit); 20 pThreadState->m_pAlternateWndInit->SubclassWindow(hWnd); 21 pThreadState->m_pAlternateWndInit = NULL; 22 } 23 24 if (message == WM_INITDIALOG) 25 { 26 /* 27 _afxMsgLBSELCHANGE = ::RegisterWindowMessage(LBSELCHSTRING); 28 _afxMsgSHAREVI = ::RegisterWindowMessage(SHAREVISTRING); 29 _afxMsgFILEOK = ::RegisterWindowMessage(FILEOKSTRING); 30 _afxMsgCOLOROK = ::RegisterWindowMessage(COLOROKSTRING); 31 _afxMsgHELP = ::RegisterWindowMessage(HELPMSGSTRING); 32 _afxMsgSETRGB = ::RegisterWindowMessage(SETRGBSTRING); 33 */ 34 35 XFileDialog* pDlg = DYNAMIC_DOWNCAST(XFileDialog, CWnd::FromHandlePermanent(hWnd)); 36 if (pDlg != NULL) 37 return pDlg->OnInitDialog(); 38 else 39 return 1; 40 } 41 42 return 0; 43 } 44 45 BEGIN_MESSAGE_MAP(XFileDialog, CWnd) 46 END_MESSAGE_MAP() 47 48 XFileDialog::XFileDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, 49 DWORD dwFlags, LPCTSTR lpszFilter, LPCTSTR lpszInitFolder, CWnd* pParentWnd) : 50 CWnd() 51 { 52 m_szFileName[0] = ‘\0‘; 53 m_szFileTitle[0] = ‘\0‘; 54 m_bOpenFileDialog = bOpenFileDialog; 55 56 m_pParentWnd = NULL; 57 m_hWndTop = NULL; 58 59 memset(&m_ofn, 0, sizeof(OPENFILENAME)); // initialize structure to 0/NULL 60 61 m_ofn.Flags |= dwFlags | OFN_ENABLETEMPLATE |OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK; 62 m_ofn.lpstrTitle = _T("图像文件预览对话框"); 63 m_ofn.lpstrInitialDir = lpszInitFolder; 64 65 m_ofn.lStructSize = sizeof(OPENFILENAME); 66 m_ofn.lpstrFile = m_szFileName; 67 m_ofn.nMaxFile = _countof(m_szFileName); 68 m_ofn.lpstrDefExt = lpszDefExt; 69 m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle; 70 m_ofn.nMaxFileTitle = _countof(m_szFileTitle); 71 if(dwFlags & OFN_ENABLETEMPLATE) 72 m_ofn.Flags &= ~OFN_ENABLESIZING; 73 m_ofn.hInstance = AfxGetResourceHandle(); 74 m_ofn.lpfnHook = (LPOFNHOOKPROC)OFNHookProc; 75 m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_IMAGEPREVIEWDLG); 76 77 // setup initial file name 78 if (lpszFileName != NULL) 79 Checked::tcsncpy_s(m_szFileName, _countof(m_szFileName), lpszFileName, _TRUNCATE); 80 81 // Translate filter into commdlg format (lots of \0) 82 if (lpszFilter != NULL) 83 { 84 m_strFilter = lpszFilter; 85 LPTSTR pch = m_strFilter.GetBuffer(0); // modify the buffer in place 86 // MFC delimits with ‘|‘ not ‘\0‘ 87 while ((pch = _tcschr(pch, ‘|‘)) != NULL) 88 *pch++ = ‘\0‘; 89 m_ofn.lpstrFilter = m_strFilter; 90 // do not call ReleaseBuffer() since the string contains ‘\0‘ characters 91 } 92 } 93 94 XFileDialog::~XFileDialog() 95 { 96 } 97 98 void XFileDialog::EndDialog(int nResult) 99 { 100 ASSERT(::IsWindow(m_hWnd)); 101 102 ::EndDialog(m_hWnd, nResult); 103 } 104 105 BOOL XFileDialog::OnInitDialog() 106 { 107 // transfer data into the dialog from member variables 108 #if 1 109 if (!UpdateData(FALSE)) 110 { 111 TRACE(traceAppMsg, 0, "Warning: UpdateData failed during dialog init.\n"); 112 EndDialog(-1); 113 return FALSE; 114 } 115 #endif 116 117 GetDlgItem(IDC_IMAGEPREVIEW)->ModifyStyle ( SS_TYPEMASK, SS_OWNERDRAW ); 118 119 return TRUE; // set focus to first one 120 } 121 122 void XFileDialog::DoDataExchange(CDataExchange *pDX) 123 { 124 CWnd::DoDataExchange(pDX); 125 DDX_Control(pDX, IDC_IMAGEPREVIEW, m_preview); 126 } 127 128 void XFileDialog::ProcFileChange(TCHAR* strFullName){ 129 //如果是文件名 130 DWORD nFileAtts = GetFileAttributes(strFullName); 131 if ((FILE_ATTRIBUTE_NORMAL == nFileAtts) || 132 (0 == (nFileAtts & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY )) ) ){ 133 m_preview.SetFilename(strFullName); 134 } else { 135 //m_preview.SetFilename(NULL); 136 } 137 } 138 139 140 BOOL XFileDialog::OnNotify(WPARAM, LPARAM lp, LRESULT *pResult) 141 { 142 LPOFNOTIFY of = (LPOFNOTIFY) lp; 143 CString csTemp; 144 TCHAR strFileName[_MAX_PATH]; 145 146 HWND hParent; 147 UINT nfiles; 148 149 switch (of->hdr.code) 150 { 151 case CDN_SELCHANGE: 152 hParent = GetParent()->GetSafeHwnd(); 153 nfiles = CommDlg_OpenSave_GetFilePath(hParent, strFileName, _MAX_PATH); 154 if (nfiles > 0) { 155 ProcFileChange(strFileName); 156 //MessageBox(strFileName); 157 } 158 break; 159 160 case CDN_FOLDERCHANGE: 161 // Once we get this notification our old subclassing of 162 // the SHELL window is lost, so we have to 163 // subclass it again. (Changing the folder causes a 164 // destroy and recreate of the SHELL window). 165 //if (m_wndHook.GetSafeHwnd() != HWND(NULL)) 166 // m_wndHook.UnsubclassWindow(); 167 168 //m_wndHook.SubclassWindow(GetParent()->GetDlgItem(lst2)->GetSafeHwnd()); 169 //UpdatePreview(_T("")); 170 break; 171 } 172 173 *pResult = 0; 174 return FALSE; 175 } 176 177 long XFileDialog::DoModal() 178 { 179 HWND hWndFocus = ::GetFocus(); 180 BOOL bEnableParent = FALSE; 181 // allow OLE servers to disable themselves 182 CWinApp* pApp = AfxGetApp(); 183 if (pApp != NULL) 184 pApp->EnableModeless(FALSE); 185 186 _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); 187 pThreadState->m_pAlternateWndInit = this; 188 //AfxHookWindowCreate(this); 189 190 HWND hWndParent = CWnd::GetSafeOwner_(m_pParentWnd->GetSafeHwnd(), &m_hWndTop);; 191 if (hWndParent && hWndParent != ::GetDesktopWindow() && ::IsWindowEnabled(hWndParent)) 192 { 193 ::EnableWindow(hWndParent, FALSE); 194 bEnableParent = TRUE; 195 } 196 197 INT_PTR nResult = 0; 198 199 if (m_bOpenFileDialog) 200 nResult = GetOpenFileName(&m_ofn); 201 else 202 nResult = GetSaveFileName(&m_ofn); 203 204 if (nResult) 205 ASSERT(pThreadState->m_pAlternateWndInit == NULL); 206 207 // Second part of special case for file open/save dialog. 208 if (bEnableParent) 209 ::EnableWindow(hWndParent, TRUE); 210 if (::IsWindow(hWndFocus)) 211 ::SetFocus(hWndFocus); 212 213 AfxUnhookWindowCreate(); // just in case 214 Detach(); // just in case 215 216 if (pApp != NULL) 217 pApp->EnableModeless(TRUE); 218 219 return nResult ? nResult : IDCANCEL; 220 } 221 222 223 IMPLEMENT_DYNAMIC(XFileDialog, CWnd) 224 225 // XFileDialog message handlers
ImagePreviewStatic.h其实就是一个CStatic的继承类,实现图片预览
1 /* 2 * $Header: $ 3 * 4 * $History: $ 5 */ 6 #pragma once 7 8 #include <atlimage.h> 9 10 // CImagePrieviewStatic 11 class CImagePreviewStatic : public CStatic 12 { 13 DECLARE_DYNAMIC(CImagePreviewStatic) 14 public: 15 CImagePreviewStatic(); 16 virtual ~CImagePreviewStatic(); 17 18 virtual BOOL Create(); 19 virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 20 21 void SetFilename(LPCTSTR szFilename); 22 23 protected: 24 WCHAR m_wsFilename[_MAX_PATH]; 25 Image *m_img; 26 Graphics *m_graphics; 27 CImage *m_img2; 28 29 DECLARE_MESSAGE_MAP() 30 };
1 /* 2 * $Header: $ 3 * 4 * $History: $ 5 */ 6 #include "stdafx.h" 7 #include "ImagePreviewStatic.h" 8 9 10 // CImagePrieviewStatic 11 IMPLEMENT_DYNAMIC(CImagePreviewStatic, CStatic) 12 13 CImagePreviewStatic::CImagePreviewStatic() : CStatic() 14 { 15 m_img = (Image *) NULL; 16 m_graphics = (Graphics *) NULL; 17 m_img2 = (CImage*) NULL; 18 } 19 20 CImagePreviewStatic::~CImagePreviewStatic() 21 { 22 if (m_img) { 23 delete m_img; 24 } 25 if (m_graphics) { 26 delete m_graphics; 27 } 28 if (m_img2) { 29 delete m_img2; 30 } 31 } 32 33 BOOL CImagePreviewStatic::Create() 34 { 35 if (GetSafeHwnd() != HWND(NULL)) 36 { 37 m_img = new Image(m_wsFilename); 38 m_graphics = new Graphics(GetSafeHwnd()); 39 return TRUE; 40 } 41 42 return FALSE; 43 } 44 45 void CImagePreviewStatic::SetFilename(LPCTSTR szFilename) 46 { 47 #ifndef _UNICODE 48 USES_CONVERSION; 49 #endif 50 51 ASSERT(szFilename); 52 ASSERT(AfxIsValidString(szFilename)); 53 54 TRACE("%s\n", szFilename); 55 56 #ifndef _UNICODE 57 wcscpy(m_wsFilename, A2W(szFilename)); 58 #else 59 wcscpy(m_wsFilename, szFilename); 60 #endif 61 62 //delete m_img; 63 //m_img = new Image(m_wsFilename, FALSE); 64 if (m_img2) { 65 delete m_img2; 66 } 67 m_img2 = new CImage(); 68 m_img2->Load(szFilename); 69 70 Invalidate(); 71 } 72 73 void CImagePreviewStatic::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) 74 { 75 Unit units; 76 CRect rect; 77 78 /* 79 if (m_img != NULL) 80 { 81 GetClientRect(&rect); 82 83 RectF destRect(REAL(rect.left), REAL(rect.top), REAL(rect.Width()), REAL(rect.Height())), 84 srcRect; 85 m_img->GetBounds(&srcRect, &units); 86 m_graphics->DrawImage(m_img, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, UnitPixel, NULL); 87 } 88 */ 89 if (m_img2 != NULL) { 90 HWND hWnd = GetParent()->m_hWnd; 91 HDC hDc = ::GetDC(hWnd); 92 GetWindowRect(&rect); 93 ::ScreenToClient(hWnd, (LPPOINT)&rect); 94 ::ScreenToClient(hWnd, (LPPOINT)(&rect) + 1); 95 //获取到HDC 96 m_img2->Draw(hDc,rect); 97 } 98 } 99 100 BEGIN_MESSAGE_MAP(CImagePreviewStatic, CStatic) 101 END_MESSAGE_MAP() 102 103 // 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
原文:https://www.cnblogs.com/eaglexmw/p/11063516.html