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
posted @ 2019-06-21 11:14  日月王  阅读(936)  评论(0)    收藏  举报