mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
464 lines
11 KiB
464 lines
11 KiB
// SelectFile.cpp : Implementation of CSelectFile
|
|
|
|
#include "stdafx.h"
|
|
#include "CompatUI.h"
|
|
#include "SelectFile.h"
|
|
|
|
#include "commdlg.h"
|
|
#include "cderr.h"
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSelectFile
|
|
|
|
//
|
|
// in upload.c
|
|
//
|
|
|
|
wstring StrUpCase(wstring& wstr);
|
|
|
|
|
|
|
|
STDMETHODIMP CSelectFile::get_BrowseTitle(BSTR *pVal)
|
|
{
|
|
*pVal = m_bstrTitle.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_BrowseTitle(BSTR newVal)
|
|
{
|
|
m_bstrTitle = newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_BrowseFilter(BSTR *pVal)
|
|
{
|
|
*pVal = m_bstrFilter.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_BrowseFilter(BSTR newVal)
|
|
{
|
|
m_bstrFilter = newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_BrowseInitialDirectory(BSTR *pVal)
|
|
{
|
|
*pVal = m_bstrInitialDirectory;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_BrowseInitialDirectory(BSTR newVal)
|
|
{
|
|
m_bstrInitialDirectory = newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_BrowseFlags(long *pVal)
|
|
{
|
|
*pVal = (LONG)m_dwBrowseFlags;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_BrowseFlags(long newVal)
|
|
{
|
|
m_dwBrowseFlags = (DWORD)newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_FileName(BSTR *pVal)
|
|
{
|
|
wstring sFileName;
|
|
|
|
GetFileNameFromUI(sFileName);
|
|
m_bstrFileName = sFileName.c_str();
|
|
|
|
*pVal = m_bstrFileName.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_FileName(BSTR newVal)
|
|
{
|
|
m_bstrFileName = newVal;
|
|
SetDlgItemText(IDC_EDITFILENAME, m_bstrFileName);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_ErrorCode(long *pVal)
|
|
{
|
|
*pVal = (LONG)m_dwErrorCode;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
#define MAX_BUFFER 2048
|
|
|
|
LRESULT CSelectFile::OnClickedBrowse(
|
|
WORD wNotifyCode,
|
|
WORD wID,
|
|
HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
LRESULT lRes = 0;
|
|
|
|
// TODO: Add your implementation code here
|
|
OPENFILENAME ofn;
|
|
LPTSTR pszFileName = NULL;
|
|
DWORD dwFileNameLength = 0;
|
|
DWORD dwLen;
|
|
LPTSTR pszFilter = NULL, pch;
|
|
|
|
m_dwErrorCode = 0;
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = m_hWnd;
|
|
|
|
//
|
|
// part one (straight) - title
|
|
//
|
|
ofn.lpstrTitle = (LPCTSTR)m_bstrTitle; // assumes we're unicode (and we are)
|
|
|
|
//
|
|
// recover the filename from the edit box
|
|
//
|
|
wstring sFileName;
|
|
|
|
if (GetFileNameFromUI(sFileName)) {
|
|
m_bstrFileName = sFileName.c_str();
|
|
}
|
|
|
|
//
|
|
// part two - init filename
|
|
//
|
|
dwFileNameLength = __max(MAX_BUFFER, m_bstrFileName.Length() * 2); // in characters
|
|
|
|
pszFileName = new TCHAR[dwFileNameLength * sizeof(*pszFileName)];
|
|
if (pszFileName == NULL) {
|
|
m_dwErrorCode = ERROR_OUTOFMEMORY;
|
|
goto HandleError;
|
|
}
|
|
|
|
// so we have the buffer now
|
|
//
|
|
if (m_bstrFileName.Length () > 0) {
|
|
// sanitize the filename with regard to quotes
|
|
_tcscpy(pszFileName, (LPCTSTR)m_bstrFileName); // hypocritical copy, we are unicode
|
|
} else {
|
|
// start with the contents of the text box then
|
|
*pszFileName = TEXT('\0');
|
|
}
|
|
|
|
//
|
|
// sanity check, if pszFileName ends with \ then we will get an error
|
|
//
|
|
PathRemoveBackslash(pszFileName);
|
|
|
|
ofn.lpstrFile = pszFileName;
|
|
ofn.nMaxFile = dwFileNameLength;
|
|
|
|
//
|
|
// see if we also need to process filter
|
|
//
|
|
|
|
if (m_bstrFilter.Length() > 0) {
|
|
dwLen = m_bstrFilter.Length();
|
|
|
|
pszFilter = new TCHAR[(dwLen + 2) * sizeof(*pszFilter)];
|
|
if (pszFilter == NULL) {
|
|
m_dwErrorCode = ERROR_OUTOFMEMORY;
|
|
goto HandleError;
|
|
}
|
|
|
|
RtlZeroMemory(pszFilter, (dwLen + 2) * sizeof(*pszFilter));
|
|
_tcscpy(pszFilter, m_bstrFilter);
|
|
|
|
pch = pszFilter;
|
|
while (pch) {
|
|
pch = _tcschr(pch, TEXT('|'));
|
|
if (pch) {
|
|
*pch++ = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
// now that the replacement is done -- assign the filter string
|
|
ofn.lpstrFilter = pszFilter;
|
|
}
|
|
|
|
//
|
|
// now check whether we have some in the initial directory
|
|
//
|
|
if (m_bstrInitialDirectory.Length() > 0) {
|
|
ofn.lpstrInitialDir = (LPCTSTR)m_bstrInitialDirectory;
|
|
}
|
|
|
|
//
|
|
// flags
|
|
//
|
|
|
|
if (m_dwBrowseFlags) {
|
|
ofn.Flags = m_dwBrowseFlags;
|
|
} else {
|
|
ofn.Flags = OFN_FILEMUSTEXIST|OFN_EXPLORER;
|
|
}
|
|
|
|
BOOL bRetry;
|
|
BOOL bSuccess;
|
|
|
|
do {
|
|
bRetry = FALSE;
|
|
|
|
bSuccess = GetOpenFileName(&ofn);
|
|
if (!bSuccess) {
|
|
m_dwErrorCode = CommDlgExtendedError();
|
|
if (m_dwErrorCode == FNERR_INVALIDFILENAME) {
|
|
*pszFileName = TEXT('\0');
|
|
bRetry = TRUE;
|
|
}
|
|
}
|
|
} while (bRetry);
|
|
|
|
if (!bSuccess) {
|
|
goto HandleError;
|
|
}
|
|
|
|
SetDlgItemText(IDC_EDITFILENAME, pszFileName);
|
|
|
|
m_bstrFileName = (LPCTSTR)pszFileName;
|
|
m_dwErrorCode = 0;
|
|
|
|
HandleError:
|
|
|
|
if (pszFileName != NULL) {
|
|
delete[] pszFileName;
|
|
}
|
|
|
|
if (pszFilter != NULL) {
|
|
delete[] pszFilter;
|
|
}
|
|
|
|
|
|
bHandled = TRUE;
|
|
return lRes;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSelectFile::PreTranslateAccelerator(
|
|
LPMSG pMsg,
|
|
HRESULT& hRet
|
|
)
|
|
{
|
|
HWND hWndCtl;
|
|
HWND hwndEdit = GetDlgItem(IDC_EDITFILENAME);
|
|
HWND hwndBrowse = GetDlgItem(IDC_BROWSE);
|
|
BSTR bstrFileName = NULL;
|
|
WORD wCmd = 0;
|
|
BOOL bBrowseHandled;
|
|
|
|
hRet = S_OK;
|
|
hWndCtl = ::GetFocus();
|
|
if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) {
|
|
do {
|
|
hWndCtl = ::GetParent(hWndCtl);
|
|
} while (::GetParent(hWndCtl) != m_hWnd);
|
|
}
|
|
|
|
if (pMsg->message == WM_KEYDOWN &&
|
|
(LOWORD(pMsg->wParam) == VK_RETURN ||
|
|
LOWORD(pMsg->wParam) == VK_EXECUTE)) {
|
|
if (hWndCtl == hwndEdit) {
|
|
BOOL bReturn;
|
|
wstring sFileName;
|
|
|
|
bReturn = GetFileNameFromUI(sFileName) &&
|
|
ValidateExecutableFile(sFileName.c_str(), TRUE);
|
|
if (bReturn) {
|
|
Fire_SelectionComplete();
|
|
return TRUE;
|
|
}
|
|
}
|
|
// this either was hwndBrowse or filename was not there -- open
|
|
// browse dialog then
|
|
|
|
OnClickedBrowse(BN_CLICKED, IDC_BROWSE, hwndBrowse, bBrowseHandled);
|
|
::SetFocus(hwndEdit);
|
|
}
|
|
|
|
//
|
|
// fixup external accelerators for internal controls (in this case -- edit)
|
|
//
|
|
if (m_Accel.IsAccelKey(pMsg, &wCmd) && wCmd == IDC_EDITFILENAME) {
|
|
::SetFocus(hwndEdit);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// check for external accelerators because the next call is going to eat the message
|
|
//
|
|
if (m_ExternAccel.IsAccelKey(pMsg)) { // we do not touch external accel messages
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// check whether we are tabbing out of control
|
|
//
|
|
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) {
|
|
// check whether we're tabbing out
|
|
// (perhaps the control wants to eat tab?
|
|
DWORD_PTR dwDlgCode = ::SendMessage(pMsg->hwnd, WM_GETDLGCODE, 0, 0);
|
|
if (!(dwDlgCode & DLGC_WANTTAB)) {
|
|
// control does not want a tab
|
|
// see whether it's the last control and we're tabbing out
|
|
HWND hwndFirst = GetNextDlgTabItem(NULL, FALSE); // first
|
|
HWND hwndLast = GetNextDlgTabItem(hwndFirst, TRUE);
|
|
BOOL bFirstOrLast;
|
|
if (::GetKeyState(VK_SHIFT) & 0x8000) {
|
|
// shift ?
|
|
bFirstOrLast = (hWndCtl == hwndFirst);
|
|
} else {
|
|
bFirstOrLast = (hWndCtl == hwndLast);
|
|
}
|
|
|
|
if (bFirstOrLast) {
|
|
IsDialogMessage(pMsg);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return CComCompositeControl<CSelectFile>::PreTranslateAccelerator(pMsg, hRet);
|
|
}
|
|
/*
|
|
|
|
STDMETHODIMP CSelectFile::get_Accel(BSTR *pVal)
|
|
{
|
|
CComBSTR bstr = (LPCWSTR)m_Accel;
|
|
*pVal = bstr.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_Accel(BSTR newVal)
|
|
{
|
|
m_Accel = (LPCWSTR)newVal;
|
|
return S_OK;
|
|
}
|
|
*/
|
|
STDMETHODIMP CSelectFile::get_ExternAccel(BSTR *pVal)
|
|
{
|
|
CComBSTR bstr = m_ExternAccel.GetAccelString(0).c_str();
|
|
*pVal = bstr.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_ExternAccel(BSTR newVal)
|
|
{
|
|
m_ExternAccel = (LPCWSTR)newVal;
|
|
return S_OK;
|
|
}
|
|
|
|
static TCHAR szU[] = TEXT("<U>");
|
|
static TCHAR szUC[] = TEXT("</U>");
|
|
|
|
#define szU_Len (CHARCOUNT(szU) - 1)
|
|
#define szUC_Len (CHARCOUNT(szUC) - 1)
|
|
|
|
STDMETHODIMP CSelectFile::get_BrowseBtnCaption(BSTR *pVal)
|
|
{
|
|
// TODO: Add your implementation code here
|
|
CComBSTR bstrCaption;
|
|
wstring strCaption = m_BrowseBtnCaption;
|
|
wstring::size_type nPos;
|
|
|
|
nPos = m_BrowseBtnCaption.find(TEXT('&'));
|
|
if (nPos == wstring::npos || nPos > m_BrowseBtnCaption.length() - 1) {
|
|
bstrCaption = m_BrowseBtnCaption.c_str();
|
|
} else {
|
|
bstrCaption = m_BrowseBtnCaption.substr(0, nPos).c_str();
|
|
bstrCaption += szU;
|
|
bstrCaption += m_BrowseBtnCaption[nPos+1];
|
|
bstrCaption += szUC;
|
|
if (nPos < m_BrowseBtnCaption.length() - 1) {
|
|
bstrCaption += m_BrowseBtnCaption.substr(nPos+2).c_str();
|
|
}
|
|
}
|
|
*pVal = bstrCaption.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_BrowseBtnCaption(BSTR newVal)
|
|
{
|
|
|
|
//
|
|
// form a caption from the string
|
|
//
|
|
wstring strCaption = newVal;
|
|
wstring strCaptionU = strCaption;
|
|
wstring::size_type nPosU, nPosUC;
|
|
wstring strAccel;
|
|
|
|
StrUpCase(strCaptionU);
|
|
|
|
//
|
|
// find <u> </u> pair
|
|
//
|
|
nPosU = strCaptionU.find(szU);
|
|
nPosUC = strCaptionU.find(szUC, nPosU);
|
|
if (nPosUC == wstring::npos || nPosU == wstring::npos || nPosUC < nPosU || nPosUC <= (nPosU + szU_Len)) {
|
|
goto cleanup;
|
|
}
|
|
|
|
// extract the char at the &
|
|
//
|
|
//
|
|
strAccel = strCaption.substr(nPosU + szU_Len, nPosUC - (nPosU + szU_Len));
|
|
|
|
//
|
|
// add accel please -- with command id IDC_BROWSE
|
|
//
|
|
m_Accel.SetAccel(strAccel.c_str(), IDC_BROWSE);
|
|
|
|
//
|
|
// now we (presumably) found <u>accelchar</u>
|
|
//
|
|
m_BrowseBtnCaption = strCaption.substr(0, nPosU); // up to the <U>
|
|
m_BrowseBtnCaption += TEXT('&');
|
|
m_BrowseBtnCaption += strAccel.c_str();
|
|
m_BrowseBtnCaption += strCaption.substr(nPosUC + szUC_Len); // all the rest please
|
|
|
|
if (IsWindow()) {
|
|
SetDlgItemText(IDC_BROWSE, m_BrowseBtnCaption.c_str());
|
|
}
|
|
|
|
cleanup:
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::get_AccelCmd(LONG lCmd, BSTR *pVal)
|
|
{
|
|
CComBSTR bstrVal = m_Accel.GetAccelString((WORD)lCmd).c_str();
|
|
*pVal = bstrVal.Copy();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::put_AccelCmd(LONG lCmd, BSTR newVal)
|
|
{
|
|
m_Accel.SetAccel(newVal, (WORD)lCmd);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::ClearAccel()
|
|
{
|
|
m_Accel.ClearAccel();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CSelectFile::ClearExternAccel()
|
|
{
|
|
m_ExternAccel.ClearAccel();
|
|
return S_OK;
|
|
}
|