www.pudn.com > editpad_src > bcgfiledialog.cpp, change:1999-11-25,size:15719b
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This source code is a part of BCGControlBar library.
// You may use, compile or redistribute it as part of your application
// for free. You cannot redistribute it as a part of a software development
// library without the agreement of the author. If the sources are
// distributed along with the application, you should leave the original
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES on your own risk.
//
// Stas Levin <stas@iet.co.il>
//*******************************************************************************
// BCGFileDialog.cpp : implementation file
//
#include "stdafx.h"
#include "BCGFileDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
class CNewItemInfo : public CObject
{
friend class CBCGFileDialog;
CNewItemInfo (LPCTSTR lpszName, int iIconIndex)
{
m_strName = lpszName;
m_iIconIndex = iIconIndex;
}
CString m_strName;
int m_iIconIndex;
};
/////////////////////////////////////////////////////////////////////////////
// CBCGFileDialog
const int iTabCtrlId = 200;
const int iNewListCtrlId = 201;
const int iRecentListCtrlId = 202;
WNDPROC CBCGFileDialog::m_wndProc;
IMPLEMENT_DYNAMIC(CBCGFileDialog, CFileDialog)
CBCGFileDialog::CBCGFileDialog (LPCTSTR lpszCaption, BOOL bNewPage, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
CFileDialog (TRUE /*bOpenFileDialog*/, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd),
m_pImagesNew (NULL),
m_bNewPage (bNewPage),
m_strCaption (lpszCaption),
m_hIconBig (NULL),
m_hIconSmall (NULL)
{
m_iNewItemIndex = -1;
m_pBmpLogo = NULL;
CDocManager* pDocManager = AfxGetApp ()->m_pDocManager;
if (pDocManager != NULL && lpszFilter == NULL)
{
static CString strFilter;
static CString strDefault;
BOOL bFirst = TRUE;
for (POSITION pos = pDocManager->GetFirstDocTemplatePosition (); pos != NULL;)
{
CDocTemplate* pTemplate = pDocManager->GetNextDocTemplate (pos);
ASSERT_VALID (pTemplate);
CString strFilterExt, strFilterName;
if (pTemplate->GetDocString (strFilterExt, CDocTemplate::filterExt) &&
!strFilterExt.IsEmpty() &&
pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
!strFilterName.IsEmpty())
{
// a file based document template - add to filter list
ASSERT(strFilterExt[0] == '.');
if (bFirst)
{
strDefault = ((LPCTSTR)strFilterExt) + 1; // skip the '.'
m_ofn.lpstrDefExt = strDefault;
m_ofn.nFilterIndex = m_ofn.nMaxCustFilter + 1; // 1 based number
}
// add to filter
strFilter += strFilterName;
ASSERT(!strFilter.IsEmpty()); // must have a file type name
strFilter += (TCHAR)'\0'; // next string please
strFilter += (TCHAR)'*';
strFilter += strFilterExt;
strFilter += (TCHAR)'\0'; // next string please
m_ofn.nMaxCustFilter++;
}
bFirst = FALSE;
}
CString allFilter;
VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
strFilter += allFilter;
strFilter += (TCHAR)'\0'; // next string please
strFilter += _T("*.*");
strFilter += (TCHAR)'\0'; // last string
m_ofn.nMaxCustFilter++;
m_ofn.lpstrFilter = strFilter;
}
}
//***************************************************************************************
CBCGFileDialog::~CBCGFileDialog ()
{
while (!m_lstNewItems.IsEmpty ())
{
delete m_lstNewItems.RemoveHead ();
}
}
//***************************************************************************************
static CBCGFileDialog* GetBCGFileDlg (HWND hwdParent)
{
CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle (hwdParent);
ASSERT (pDlg != NULL);
CBCGFileDialog* pFD = (CBCGFileDialog*) pDlg->GetDlgItem(0);
ASSERT (pFD != NULL);
return pFD;
}
//***************************************************************************************
LRESULT CALLBACK CBCGFileDialog::WindowProcNew(HWND hwnd,UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NOTIFY:
{
CBCGFileDialog* pFD = GetBCGFileDlg (hwnd);
LPNMHDR pHdr = (LPNMHDR) lParam;
ASSERT (pHdr != NULL);
if (wParam == iTabCtrlId && pHdr->code == TCN_SELCHANGE)
{
pFD->OnTabSelchange();
}
else if ((wParam == iNewListCtrlId || wParam == iRecentListCtrlId)
&& pHdr->code == NM_DBLCLK)
{
pFD->OnItemDblClick();
}
}
break;
case WM_COMMAND:
{
if ((int) LOWORD(wParam) == IDOK)
{
CBCGFileDialog* pFD = GetBCGFileDlg (hwnd);
if (pFD->GetPage () != CBCGFileDialog::BCGFileOpen)
{
pFD->OnItemDblClick();
return 0;
}
}
}
break;
case WM_PAINT:
{
CBCGFileDialog* pFD = GetBCGFileDlg (hwnd);
pFD->CollectControls ();
if (pFD->m_pBmpLogo != NULL)
{
ASSERT_VALID (pFD->m_pBmpLogo);
CFileDialog* pDlg = (CFileDialog*)CWnd::FromHandle (hwnd);
ASSERT (pDlg != NULL);
CPaintDC dc (pDlg); // device context for painting
dc.DrawState (pFD->m_rectLogo.TopLeft (),
pFD->m_rectLogo.Size (), pFD->m_pBmpLogo,
DSS_NORMAL);
CRect rectFrame = pFD->m_rectLogo;
rectFrame.InflateRect (1, 1);
dc.Draw3dRect (rectFrame, ::GetSysColor (COLOR_3DSHADOW),
::GetSysColor (COLOR_3DLIGHT));
}
}
}
return CallWindowProc(CBCGFileDialog::m_wndProc, hwnd, message, wParam, lParam);
}
BEGIN_MESSAGE_MAP(CBCGFileDialog, CFileDialog)
//{{AFX_MSG_MAP(CBCGFileDialog)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------
// My "classic " trick - how I can access to protected
// member m_pRecentFileList?
//-----------------------------------------------------
class CBCGApp : public CWinApp
{
friend class CBCGFileDialog;
};
void CBCGFileDialog::OnInitDone()
{
const int iBorderWidth = 20;
const int iBorderHeight = 40;
CWnd* pFD = GetParent();
ASSERT (pFD != NULL);
CRect rectClient;
pFD->GetClientRect (rectClient);
int nNewDlgWidth = rectClient.Width () + iBorderWidth * 2;
int iLogoAreaHeight = 0;
if (m_pBmpLogo != NULL)
{
BITMAP bmp;
m_pBmpLogo->GetBitmap (&bmp);
m_rectLogo = CRect (CPoint ((nNewDlgWidth - bmp.bmWidth) / 2, 8),
CSize (bmp.bmWidth, bmp.bmHeight));
iLogoAreaHeight = bmp.bmHeight + 20;
}
//---------------------------
// Adjust parent window size:
//---------------------------
pFD->SetWindowPos (NULL, -1, -1, nNewDlgWidth,
rectClient.Height () + iBorderHeight * 2 + iLogoAreaHeight,
SWP_NOMOVE | SWP_NOZORDER);
//-------------------
// Move all controls:
//-------------------
CWnd* pWndChild = pFD->GetWindow (GW_CHILD);
while (pWndChild != NULL)
{
CRect rectCtl;
pWndChild->GetClientRect (rectCtl);
pWndChild->MapWindowPoints (pFD, rectCtl);
pWndChild->SetWindowPos (NULL,
rectCtl.left + iBorderWidth,
rectCtl.top + iBorderHeight + iLogoAreaHeight,
-1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
pWndChild = pWndChild->GetNextWindow ();
}
//------------------------------------------
// Create new and recent file list controls:
//------------------------------------------
CRect rectList (0, 0, 0, 0);
m_wndNewList.Create (WS_BORDER | WS_TABSTOP | WS_CHILD | LVS_ICON | LVS_SINGLESEL,
rectList, pFD, iNewListCtrlId);
m_wndNewList.ModifyStyleEx (0, WS_EX_CLIENTEDGE);
if (m_pImagesNew != NULL)
{
m_wndNewList.SetImageList (m_pImagesNew, LVSIL_NORMAL);
}
int i = 0;
for (POSITION pos = m_lstNewItems.GetHeadPosition (); pos != NULL; i ++)
{
CNewItemInfo* pInfo = (CNewItemInfo*) m_lstNewItems.GetNext (pos);
ASSERT_VALID (pInfo);
m_wndNewList.InsertItem (i, pInfo->m_strName, pInfo->m_iIconIndex);
}
m_wndRecentList.Create (WS_TABSTOP | WS_CHILD | WS_BORDER | LVS_SINGLESEL | LVS_REPORT,
rectList, pFD, iRecentListCtrlId);
m_wndRecentList.ModifyStyleEx (0, WS_EX_CLIENTEDGE);
m_ImagesRecent.Create ( ::GetSystemMetrics (SM_CXSMICON),
::GetSystemMetrics (SM_CYSMICON),
ILC_COLOR, 0, 10);
m_wndRecentList.SetImageList (&m_ImagesRecent, LVSIL_SMALL);
m_wndRecentList.InsertColumn (0, _T("File"), LVCFMT_LEFT, 100);
m_wndRecentList.InsertColumn (1, _T("Folder"));
CRecentFileList* pMRUFiles =
((CBCGApp*) AfxGetApp ())->m_pRecentFileList;
if (pMRUFiles != NULL)
{
TCHAR szCurDir [_MAX_PATH];
::GetCurrentDirectory (_MAX_PATH, szCurDir);
int nCurDir = lstrlen (szCurDir);
ASSERT (nCurDir >= 0);
szCurDir [nCurDir] = _T('\\');
szCurDir [++ nCurDir] = _T('\0');
//---------------
// Add MRU files:
//---------------
int iNumOfFiles = 0; // Actual added to menu
for (int i = 0; i pMRUFiles->GetSize (); i ++)
{
CString strFile = (*pMRUFiles) [i];
if (!strFile.IsEmpty ())
{
CString strPath;
CString strName;
int iImage = -1;
int iIndex = strFile.ReverseFind (_T('\\'));
if (iIndex != -1)
{
strPath = strFile.Left (iIndex);
strName = strFile.Mid (iIndex + 1);
}
else
{
strName = strFile;
}
SHFILEINFO sfi;
HIMAGELIST himlSmall = (HIMAGELIST) SHGetFileInfo (strFile,
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
if (himlSmall != NULL)
{
CImageList* pImages = CImageList::FromHandle (himlSmall);
ASSERT (pImages != NULL);
iImage = m_ImagesRecent.Add (pImages->ExtractIcon (sfi.iIcon));
}
iIndex = m_wndRecentList.InsertItem (iNumOfFiles ++, strName, iImage);
m_wndRecentList.SetItemText (iIndex, 1, strPath);
int iPathWidth = m_wndRecentList.GetStringWidth (strPath) + 20;
if (iPathWidth > m_wndRecentList.GetColumnWidth (1))
{
m_wndRecentList.SetColumnWidth (1, iPathWidth);
}
}
}
}
//---------------------
// Create tabs control:
//---------------------
CRect rectTabs;
pFD->GetClientRect (rectTabs);
rectTabs.DeflateRect (4, 4);
rectTabs.top += iLogoAreaHeight;
m_wndTab.Create (WS_TABSTOP | WS_CHILD | WS_VISIBLE, rectTabs, pFD, iTabCtrlId);
m_wndTab.SetFont (GetFont ());
m_wndTab.SetOwner (this);
TC_ITEM tc;
tc.mask = TCIF_TEXT;
int iPage = 0;
if (m_bNewPage)
{
tc.pszText = _T("New");
m_wndTab.InsertItem (iPage ++, &tc);
}
tc.pszText = _T("Existing");
m_wndTab.InsertItem (iPage ++, &tc);
tc.pszText = _T("Recent");
m_wndTab.InsertItem (iPage ++, &tc);
pFD->CenterWindow ();
pFD->SetWindowText (m_strCaption);
//------------------
// Set dilaog icons:
//------------------
if (m_hIconSmall != NULL)
{
pFD->SetIcon (m_hIconSmall, FALSE);
}
if (m_hIconBig != NULL)
{
pFD->SetIcon (m_hIconBig, TRUE);
}
//--------------------------
// Setup parent window proc:
//--------------------------
m_wndProc = (WNDPROC)SetWindowLong(pFD->m_hWnd, GWL_WNDPROC,
(long)CBCGFileDialog::WindowProcNew);
}
//******************************************************************************************
void CBCGFileDialog::OnTabSelchange()
{
int nPage = m_wndTab.GetCurSel();
if (!m_bNewPage)
{
nPage ++;
}
switch (nPage)
{
case 0:
m_nPage = BCGFileNew;
break;
case 1:
m_nPage = BCGFileOpen;
break;
case 2:
m_nPage = BCGFileRecent;
break;
default:
ASSERT (FALSE);
}
//---------------------
// Show/hide file list:
//---------------------
CWnd* pWnd = GetParent();
ASSERT (pWnd != NULL);
CWnd* pWndChild = pWnd->GetWindow (GW_CHILD);
while (pWndChild != NULL)
{
TCHAR szClass [256];
::GetClassName (pWndChild->GetSafeHwnd (), szClass, 255);
CString strClass = szClass;
if (strClass.CompareNoCase (_T("SHELLDLL_DefView")) == 0)
{
pWndChild->ShowWindow (m_nPage == BCGFileOpen ? SW_SHOW : SW_HIDE);
break;
}
pWndChild = pWndChild->GetNextWindow ();
}
//--------------------------
// Show/hide other controls:
//--------------------------
for (POSITION pos = m_lstFDControls.GetHeadPosition (); pos != NULL;)
{
pWnd = CWnd::FromHandle (m_lstFDControls.GetNext (pos));
ASSERT (pWnd != NULL);
pWnd->ShowWindow (m_nPage == BCGFileOpen ? SW_SHOW : SW_HIDE);
}
m_wndNewList.ShowWindow (m_nPage == BCGFileNew ? SW_SHOW : SW_HIDE);
m_wndRecentList.ShowWindow (m_nPage == BCGFileRecent ? SW_SHOW : SW_HIDE);
}
//***************************************************************************************
void CBCGFileDialog::OnItemDblClick ()
{
ASSERT (m_nPage != BCGFileOpen);
CListCtrl& list = (m_nPage == BCGFileRecent) ? m_wndRecentList : m_wndNewList;
int iSelIndex = list.GetNextItem (-1, LVNI_ALL | LVNI_SELECTED);
if (iSelIndex == -1)
{
return;
}
if (m_nPage == BCGFileRecent)
{
CString strPath = list.GetItemText (iSelIndex, 1);
CString strName = list.GetItemText (iSelIndex, 0);
if (strPath.IsEmpty ())
{
m_strRecentFilePath = strName;
}
else
{
m_strRecentFilePath = strPath;
m_strRecentFilePath += _T('\\');
m_strRecentFilePath += strName;
}
}
else
{
ASSERT (m_nPage == BCGFileNew);
m_iNewItemIndex = iSelIndex;
}
CDialog* pWnd = (CDialog*) GetParent();
ASSERT (pWnd != NULL);
pWnd->EndDialog (IDOK);
}
//****************************************************************************************
void CBCGFileDialog::CollectControls ()
{
if (!m_lstFDControls.IsEmpty ())
{
return;
}
CWnd* pWnd = GetParent();
ASSERT (pWnd != NULL);
CRect rectList (0, 0, 0, 0);
CWnd* pWndChild = pWnd->GetWindow (GW_CHILD);
while (pWndChild != NULL)
{
BOOL bIsFileList = FALSE;
UINT uiID = pWndChild->GetDlgCtrlID();
TCHAR szClass [256];
::GetClassName (pWndChild->GetSafeHwnd (), szClass, 255);
CString strClass = szClass;
CRect rectCtl;
pWndChild->GetClientRect (rectCtl);
pWndChild->MapWindowPoints (pWnd, rectCtl);
if (strClass.CompareNoCase (_T("SHELLDLL_DefView")) == 0)
{
rectList.left = rectCtl.left;
rectList.right = rectCtl.right;
rectList.bottom = rectCtl.bottom - 10;
bIsFileList = TRUE;
}
if (strClass.CompareNoCase (_T("ToolbarWindow32")) == 0)
{
rectList.top = rectCtl.top;
}
if ((((strClass.CompareNoCase (_T("BUTTON")) != 0) ||
uiID != IDOK &&
uiID != IDCANCEL &&
uiID != IDHELP) &&
pWndChild->GetStyle () & WS_VISIBLE) &&
uiID != iTabCtrlId &&
uiID != iNewListCtrlId &&
uiID != iRecentListCtrlId &&
!bIsFileList)
{
m_lstFDControls.AddTail (pWndChild->GetSafeHwnd ());
}
pWndChild = pWndChild->GetNextWindow ();
}
m_wndNewList.MoveWindow (rectList);
m_wndRecentList.MoveWindow (rectList);
OnTabSelchange();
}
//**************************************************************************************
void CBCGFileDialog::AddNewItem (LPCTSTR lpszName, int iIconIndex)
{
m_lstNewItems.AddTail (new CNewItemInfo (lpszName, iIconIndex));
}
//**************************************************************************************
void CBCGFileDialog::SetDlgIcon (HICON hIconBig, HICON hIconSmall/* = NULL*/)
{
m_hIconBig = hIconBig;
m_hIconSmall = (hIconSmall == NULL) ? m_hIconBig : hIconSmall;
}