📄 bxfiledialog.cpp
字号:
//////////////////////////////////////////////////////////////////////////
// BXFileDialog.cpp : implementation file
//
// Windows 2000 / Office 2000 style file dialog.
//
// This WILL work on Win 95 / 98 / NT 4 / NT 5 (2000) / WinME
//
// Original code by Norm Almond []
// David Wulff [dwulff@battleaxesoftware.com]
//
// Update History:
// 07 Sep 2000 - David Wulff, Opps, I lost the previous update history.
// 08 Sep 2000 - David Wulff, Lots of changes, most significant is the
// .. addition of an optional preview panel, allowing you
// .. to preview bitmap images before opening/saving.
// 14 Oct 2000 - Joel Bernard, Provided a better CenterWindow function.
// David Wulff, Fixed memory leaks, added support for
// .. previewing non-bitmap images. (code by Wes Rogers)
// Other misc. changes.
// Anatoly Danekin, Shortcut path resolution.
// 13 Dec 2000 - David Wulff, Added Visual Studio .NET look
// 24 Mar 2001 - David Wulff, miscellaneous drawing updates
// Tak^Shoran, working sizing support for Win 98/2000
// Identified very bad flickering problem
// 31 Mar 2001 - David Wulff, Fixed resizing so it will work for dialogs
// .. with preview panels. Tidied up all of the code (it
// .. was a big mess) and added standard function headers.
// .. Removed compile-time only modification of sizing
// .. support and VS.NET style
// 27 Jul 2001 - David Wulff, now when you select a non-image file, or
// .. a folder, the preview pane is cleared. Added a
// .. handler for the CDN_TYPECHANGE message, so you can
// .. customise the OK button's drop-down menu.
// 03 Aug 2001 - David Wulff, added new functions to allow you to modify
// .. the listctrl view type during runtime.
// 04 Aug 2001 - David Wulff, only selects a sidebar button if the
// .. directory is selected. Misc changes.
//////////////////////////////////////////////////////////////////////////
// Note, all dates given in this file are in the standard UK format (D:M:Y)
#include "stdafx.h"
#include <winuser.h>
#include <dlgs.h>
#include "BXFileDialog_Priv.h"
#include "BXFileDialog.h"
#include "BXFileDialog_Res.h"
//define _USE_HTMLHELP // uncomment to have context help for the sidebar.
#define CONTROL_GAP 5 // the default 'gap' between controls
#ifdef _USE_HTMLHELP
#include <htmlhelp.h>
#pragma comment ( lib, "htmlhelp.lib" )
#pragma message (" NOTE: HTMLHelp support is included.")
#endif
#define ID_SHOW_PREVIEW 3420 // this is the ID for the "preview?" checkbox
BOOL BXFileDialog::m_bClear = FALSE;
TCHAR BXFileDialog::m_szFile[] = {"\0"};
BOOL bDotNetUI = FALSE;
#pragma warning ( disable : 4244 ) // float -> int conversion warnings
/////////////////////////////////////////////////////////////////////////////
// BXFileDialog
IMPLEMENT_DYNAMIC(BXFileDialog, CFileDialog)
BEGIN_MESSAGE_MAP(BXFileDialog, CFileDialog)
//{{AFX_MSG_MAP(BXFileDialog)
ON_WM_SIZE()
ON_WM_HELPINFO()
ON_WM_MEASUREITEM()
ON_BN_CLICKED(IDC_CHECK_PREVIEW, OnClickedPreview)
ON_BN_CLICKED(ID_SHOW_PREVIEW, OnShowPreview)
ON_WM_PAINT()
//}}AFX_MSG_MAP
ON_COMMAND(ID_BTN_HISTORY, OnHistoryClicked)
ON_COMMAND(ID_BTN_PERSONAL, OnPersonalClicked)
ON_COMMAND(ID_BTN_DESKTOP, OnDesktopClicked)
ON_COMMAND(ID_BTN_FAVORITES, OnFavoritesClicked)
ON_COMMAND(ID_BTN_WEBFOLDERS, OnWebFoldersClicked)
ON_COMMAND_RANGE(ID_START, ID_END, OnMyOk)
ON_COMMAND(IDOK, OnOk)
END_MESSAGE_MAP()
/************************************************************************/
/* BXFileDialog */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff, Norm Almond */
/* Description: Class constructor */
/* Revisions: */
/************************************************************************/
BXFileDialog::BXFileDialog(BOOL bOpenFileDialog, BOOL bPreview, BOOL bSizing,
LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
DWORD dwFlags, LPCTSTR lpszFilter,
CWnd* pParentWnd) :
CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags,
lpszFilter, pParentWnd)
{
m_IsOpen = bOpenFileDialog;
m_bShowPreview = m_bPreview = bPreview;
m_bFirst = TRUE;
m_ofn.hInstance = GetBXFileDialogDll()->hModule;
m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_WIN2K_FILEDIALOG);
m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLETEMPLATE |
OFN_ENABLEHOOK | OFN_HIDEREADONLY |
(bSizing ? OFN_ENABLESIZING : 0);
}
/************************************************************************/
/* ~BXFileDialog */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff, Norm Almond */
/* Description: Class destructor */
/* Revisions: */
/************************************************************************/
BXFileDialog::~BXFileDialog()
{
}
/************************************************************************/
/* OnInitDialog */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff, Norm Almond */
/* Description: WM_INITDIALOG handler */
/* Revisions: */
/************************************************************************/
BOOL BXFileDialog::OnInitDialog()
{
CFileDialog::OnInitDialog();
// create the imagelist and load the sidebar icons
m_IL.Create(IDB_ICONS, 32, 1, RGB(255, 0, 255));
// center this dialog on the main window
CWnd* pMainWnd = AfxGetMainWnd();
CenterWindowOnOwner(pMainWnd);
// store the width of the static control (set it via the dialog editor)
CWnd* pWndOutLookBar = GetDlgItem(IDC_OUTLOOK_BAR_PLACEHOLDER);
CRect rcOLBClient;
pWndOutLookBar->GetClientRect(rcOLBClient);
m_SBWidth = rcOLBClient.Width();
return TRUE;
}
/************************************************************************/
/* OnNotify */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff, Norm Almond */
/* Description: WM_NOTIFY handler */
/* Revisions: */
/************************************************************************/
BOOL BXFileDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
OFNOTIFY* pNotify = (OFNOTIFY*)lParam;
switch(pNotify->hdr.code)
{
case CDN_INITDONE:
{
SetActiveButton(&m_btnPersonal);
m_edtFile.SubclassDlgItem(edt1,GetParent());
OnFileTypeChange(m_ofn.nFilterIndex);
return TRUE;
}
// [DW]: Remind me why we need these again? CFileDialog already
// .. provides these handlers, so why replace them? [4/8/2001]
case CDN_SELCHANGE:
{
// the listctrl selection has changed
OnFileNameChange();
return TRUE;
}
case CDN_FOLDERCHANGE:
{
// the 'root' folder has changed
OnFolderChange();
return TRUE;
}
case CDN_TYPECHANGE:
{
// the file type/s to view has changed
OnFileTypeChange(pNotify->lpOFN->nFilterIndex);
return TRUE;
}
}
return FALSE;
}
/************************************************************************/
/* GetListCtrl */
/* */
/* Created: 03:8:2001 */
/* Author: David Wulff */
/* Description: Helper function to return the listctrl */
/* Revisions: */
/************************************************************************/
CListCtrl* BXFileDialog::GetListCtrl()
{
CListCtrl* pLCtrl;
BOOL bWin2k = FALSE;
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
::GetVersionEx(&osvi);
// TODO [DW]: Check to see which one is needed for Windows ME [3/8/2001]
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
osvi.dwMajorVersion == 5)
bWin2k = TRUE;
// ok, here's the deal: On Windows 2000, the listctrl we want is a child
// .. of another, custom, control. So, if we are running on Windows 2000,
// .. we will need to take this into account.
// THIS TOOK ME FOUR DAYS TO FIND! Dammit Microsoft - why can't you stick
// .. to your own guidelines? Thank God for Spy++!
if (bWin2k)
{
CWnd *pWnd = GetParent()->GetDlgItem(lst2);
pLCtrl = (CListCtrl*)pWnd->GetDlgItem(1);
}
else
pLCtrl = (CListCtrl*)GetParent()->GetDlgItem(lst1);
return pLCtrl;
}
/************************************************************************/
/* SetListCtrlView */
/* */
/* Created: 03:8:2001 */
/* Author: David Wulff */
/* Description: Set the listctrl style during runtime */
/* Revisions: */
/************************************************************************/
void BXFileDialog::SetListCtrlView(DWORD dwNewStyle)
{
CListCtrl* pLCtrl = GetListCtrl();
DWORD dwStyle = GetWindowLong (pLCtrl->GetSafeHwnd(), GWL_STYLE);
// TODO [DW]: LVS_REPORT doesn't work properly! [3/8/2001]
if ((dwStyle & LVS_TYPEMASK) != dwNewStyle)
SetWindowLong (pLCtrl->GetSafeHwnd(), GWL_STYLE,
(dwStyle & ~LVS_TYPEMASK) | dwNewStyle);
}
/************************************************************************/
/* GetActiveButton */
/* */
/* Created: 07:8:2001 */
/* Author: David Wulff */
/* Description: Returns a pointer to the acitve sidebar button */
/* Revisions: */
/************************************************************************/
BXSelBtn* BXFileDialog::GetActiveButton()
{
static TCHAR szPath[MAX_PATH];
LPITEMIDLIST lpIDList;
// "History"
SHGetSpecialFolderLocation(0, CSIDL_RECENT, &lpIDList);
SHGetPathFromIDList(lpIDList, szPath);
if (GetFolderPath().CompareNoCase(CString(szPath)) == 0)
return &m_btnHistory;
// "Favourites"
SHGetSpecialFolderLocation(0, CSIDL_FAVORITES, &lpIDList);
SHGetPathFromIDList(lpIDList, szPath);
if (GetFolderPath().CompareNoCase(CString(szPath)) == 0)
return &m_btnFavourites;
// "My Documents"
SHGetSpecialFolderLocation(0, CSIDL_PERSONAL, &lpIDList);
SHGetPathFromIDList(lpIDList, szPath);
if (GetFolderPath().CompareNoCase(CString(szPath)) == 0)
return &m_btnPersonal;
// "Desktop"
SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &lpIDList);
SHGetPathFromIDList(lpIDList, szPath);
if (GetFolderPath().CompareNoCase(CString(szPath)) == 0)
return &m_btnDeskTop;
// "Network Neighbourhood"
SHGetSpecialFolderLocation(0, CSIDL_NETHOOD, &lpIDList);
SHGetPathFromIDList(lpIDList, szPath);
if (GetFolderPath().CompareNoCase(CString(szPath)) == 0)
return &m_btnWebFolders;
return NULL; // we are not in a 'default' directory
}
/************************************************************************/
/* OnFileNameChange */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff */
/* Description: Called when the file name is changed or a new file is */
/* .. selected. */
/* Revisions: 27:7:2001 - David Wulff, Clears the preview panel when */
/* .. the selection changes */
/************************************************************************/
void BXFileDialog::OnFileNameChange()
{
CString strFilePath = (LPCSTR)GetPathName();
SHFILEINFO shfi;
CListCtrl* pLCtrl = GetListCtrl();
POSITION pos = pLCtrl->GetFirstSelectedItemPosition();
// we wont bother checking for multiple selections, as we can't preview
// .. mulitple files!
if (pos != NULL)
{
CString strSelName = pLCtrl->GetItemText(pLCtrl->GetNextSelectedItem(pos), 0);
// HACK [DW]: Not the best way to do this! [3/8/2001]
if (strSelName.Find(_T(".")) == -1)
{
if(m_bPreview)
m_strPreviewPath = _T("\0"); // set image file to null
InvalidateRect(PreviewRect);
return;
}
}
if (!GetFileName().IsEmpty())
{
// if we have selected a shortcut, we must resolve it first
if (SHGetFileInfo((LPCSTR)strFilePath, 0, &shfi, sizeof(shfi),
SHGFI_DISPLAYNAME | SHGFI_TYPENAME) &&
!lstrcmp(shfi.szTypeName, "Shortcut"))
{
ResolveShortcut(strFilePath);
}
if(m_bPreview)
m_strPreviewPath = strFilePath;
InvalidateRect(PreviewRect);
}
}
/************************************************************************/
/* OnFolderChange */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff */
/* Description: Called when the folder is changed */
/* Revisions: 04:8:2001 - David Wulff, only select a sidebar button */
/* .. after initialisation if the directory is selected */
/************************************************************************/
void BXFileDialog::OnFolderChange()
{
// if a 'default' directory is selected, activate the appropriate
// .. sidebar button
SetActiveButton(GetActiveButton());
}
/************************************************************************/
/* OnClickedPreview */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff */
/* Description: Called when the 'Preview' checkbox is clicked */
/* Revisions: */
/************************************************************************/
void BXFileDialog::OnClickedPreview()
{
m_bPreview = checkBox.GetCheck() == 1 ? TRUE : FALSE;
}
/************************************************************************/
/* OnPaint */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff */
/* Description: WM_PAINT handler */
/* Revisions: */
/************************************************************************/
void BXFileDialog::OnPaint()
{
CPaintDC dc(this);
// if we are drawing the image preview, draw a 3D border to simulate
// .. a preview control, and render the image within in
if (m_bShowPreview)
{
// deflate rect to include border
CRect rect(PreviewRect.left + 1, PreviewRect.top + 1,
PreviewRect.right - 1, PreviewRect.bottom - 1);
dc.Draw3dRect(&PreviewRect,::GetSysColor(COLOR_BTNSHADOW),
::GetSysColor(COLOR_BTNHILIGHT));
if(m_bPreview)
DrawImage(&dc, m_strPreviewPath, PreviewRect.CenterPoint(),
GetParent()->m_hWnd, rect);
}
// if we are using the VS.NET UI style, we must draw the sidebar
// .. border ourselves
if (!bDotNetUI)
{
CRect rcWnd;
CWnd* pWndOutLookBar = GetDlgItem(IDC_OUTLOOK_BAR_PLACEHOLDER);
pWndOutLookBar->GetWindowRect(&rcWnd);
ScreenToClient(&rcWnd);
rcWnd.top += (m_btnHeight * 5);
dc.Draw3dRect(&rcWnd, ::GetSysColor(COLOR_BTNSHADOW),
::GetSysColor(COLOR_BTNHILIGHT));
dc.FillRect(&rcWnd, &CBrush(::GetSysColor(COLOR_APPWORKSPACE)));
}
}
/************************************************************************/
/* OnHistoryClicked */
/* */
/* Created: 31:3:2001 */
/* Author: David Wulff */
/* Description: Called when the specified side bar button is clicked */
/* Revisions: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -