Files
interactive/application/sp-console3/Common/PathDialog.cpp
2026-08-07 17:38:18 +09:00

426 lines
8.9 KiB
C++

#include "stdafx.h"
#include "PathDialog.h"
#include <io.h>
#include <errno.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define IDC_FOLDERTREE 0x3741
#define IDC_TITLE 0x3742
#define IDC_STATUSTEXT 0x3743
//#define IDC_NEW_EDIT_PATH 0x3744
#define IDC_NEW_EDIT_PATH 0xFFFF
// Class CDlgWnd
BEGIN_MESSAGE_MAP(CPathDialogSub, CWnd)
ON_BN_CLICKED(IDOK, OnOK)
ON_EN_CHANGE(IDC_NEW_EDIT_PATH, OnChangeEditPath)
END_MESSAGE_MAP()
void CPathDialogSub::OnOK()
{
::GetWindowText(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH), m_pdlg->m_szPathName, MAX_PATH);
if (CPathDialog::MakeSurePathExists(m_pdlg->m_szPathName) == 0) {
m_pdlg->m_bSuccess = TRUE;
::EndDialog(m_pdlg->m_hWnd, IDOK);
}
else {
::SetFocus(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH));
}
}
void CPathDialogSub::OnChangeEditPath()
{
::GetWindowText(::GetDlgItem(m_hWnd, IDC_NEW_EDIT_PATH), m_pdlg->m_szPathName, MAX_PATH);
SendMessage(BFFM_ENABLEOK, 0, _tcslen(m_pdlg->m_szPathName) > 0);
}
/////////////////////////////////////////////////////////////////////////////
// CPathDialog dialog
CPathDialog::CPathDialog(LPCTSTR pszCaption, LPCTSTR pszTitle, LPCTSTR pszInitialPath, CWnd* pParent)
{
m_dlg.m_pdlg = this;
m_hWnd = NULL;
// Get the true parent of the dialog
m_pwndParent = CWnd::GetSafeOwner(pParent);
m_pszCaption = pszCaption;
m_pszInitialPath = pszInitialPath;
memset(&m_bi, 0, sizeof(m_bi));
m_bi.hwndOwner = !m_pwndParent ? NULL : m_pwndParent->GetSafeHwnd();
m_bi.pszDisplayName = 0;
m_bi.pidlRoot = 0;
// m_bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT;
m_bi.ulFlags = BIF_NEWDIALOGSTYLE;
m_bi.lpfn = BrowseCallbackProc;
m_bi.lpszTitle = pszTitle;
// m_bi.lParam = (LPARAM)pszInitialPath;
}
/////////////////////////////////////////////////////////////////////////////
// CPathDialog message handlers
CString CPathDialog::GetPathName()
{
return m_szPathName;
}
int CALLBACK CPathDialog::BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam, LPARAM pData)
{
CPathDialog* pdlg = (CPathDialog*)pData;
switch (uMsg) {
case BFFM_INITIALIZED:
{
pdlg->m_hWnd = hwnd;
if (pdlg->m_pszCaption != NULL)
::SetWindowText(hwnd, pdlg->m_pszCaption);
VERIFY(pdlg->m_dlg.SubclassWindow(hwnd));
::ShowWindow(::GetDlgItem(hwnd, IDC_STATUSTEXT), SW_HIDE);
RECT rc;
::GetWindowRect(::GetDlgItem(hwnd, IDC_FOLDERTREE), &rc);
rc.bottom = rc.top - 2;
rc.top = rc.bottom - 23;
rc.left = rc.left + 2;
::ScreenToClient(hwnd, (LPPOINT)&rc);
::ScreenToClient(hwnd, ((LPPOINT)&rc) + 1);
HWND hwndEdit = ::CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
WS_VISIBLE | WS_CHILD | WS_TABSTOP,
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
hwnd, NULL, NULL, NULL);
::SetWindowLong(hwndEdit, GWL_ID, IDC_NEW_EDIT_PATH);
::ShowWindow(hwndEdit, SW_SHOW);
HFONT hfont = (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0);
::SendMessage(hwndEdit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
LPCTSTR lpszPath = pdlg->m_pszInitialPath;
TCHAR szPath[MAX_PATH];
if (lpszPath == NULL) {
::GetCurrentDirectory(MAX_PATH, szPath);
lpszPath = szPath;
}
if (GetFileAttributes(lpszPath) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND) {
SHGetSpecialFolderPath(hwnd, szPath, CSIDL_PERSONAL, 0);
lpszPath = szPath;
}
else
::SendMessage(hwnd,BFFM_SETSELECTION, TRUE, (LPARAM)lpszPath);
::SetWindowText(::GetDlgItem(hwnd, IDC_NEW_EDIT_PATH), lpszPath);
}
break;
case BFFM_SELCHANGED:
{
char szSelection[MAX_PATH];
// if (!::SHGetPathFromIDList((LPITEMIDLIST)lParam, szSelection) || szSelection[1]!=':') {
if (!::SHGetPathFromIDList((LPITEMIDLIST)lParam, szSelection)) {
szSelection[0] = NULL;
::SendMessage(hwnd, BFFM_ENABLEOK, 0, FALSE);
}
else {
::SendMessage(hwnd, BFFM_ENABLEOK, 0, TRUE);
}
// ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szSelection);
::SetWindowText(::GetDlgItem(hwnd, IDC_NEW_EDIT_PATH), szSelection);
break;
}
default:
break;
}
return 0;
}
int CPathDialog::DoModal()
{
TCHAR szDiaplayName[MAX_PATH];
m_bi.lpfn = BrowseCallbackProc;
m_bi.lParam = (LPARAM)this;
m_bi.pszDisplayName = szDiaplayName;
LPITEMIDLIST pidl;
LPMALLOC pmalloc;
int nRet = -1;
if (SUCCEEDED(SHGetMalloc(&pmalloc))) {
m_bSuccess = FALSE;
pidl = SHBrowseForFolder(&m_bi);
if (pidl)
pmalloc->Free(pidl);
if (m_bSuccess)
nRet = IDOK;
pmalloc->Release();
}
return nRet;
}
BOOL CPathDialog::IsValidFileName(LPCTSTR pszFileName)
{
if (pszFileName == NULL)
return FALSE;
int nLen = (int)_tcslen(pszFileName);
if (nLen <= 0)
return FALSE;
//check first char
switch (pszFileName[0]) {
case _T('.'):
case _T(' '):
case _T('\t'):
return FALSE;
}
//check last char
switch (pszFileName[nLen-1]) {
case _T('.'):
case _T(' '):
case _T('\t'):
return FALSE;
}
//check all
int i = 0;
while (pszFileName[i] != 0) {
switch (pszFileName[i]) {
case _T('\\'):
case _T('/'):
case _T(':'):
case _T('*'):
case _T('?'):
case _T('\"'):
case _T('<'):
case _T('>'):
case _T('|'):
return FALSE;
}
i++;
}
return TRUE;
}
const TCHAR c_FolderDoesNotPermission[] = _T(
"폴더 : \n"
"%s\n\n"
"에 접근할 수 없습니다. 다른 위치를 선택하십시오."
);
const TCHAR c_FolderDoesNotExist[] = _T(
"폴더 : \n"
"%s\n\n"
"가 존재하시 않습니다. 폴더를 생성하시겠습니까?"
);
const TCHAR c_szErrInvalidPath[] = _T(
"폴더 : \n"
"%s\n\n"
"가 잘못되었습니다. 다시 입력하십시오."
);
const TCHAR c_szErrCreatePath[] = _T(
"폴더 : \n"
"%s\n\n"
"를 만들 수 없습니다. 폴더이름을 확인하십시오."
);
//return -1: user break;
//return 0: no error
//return 1: lpPath is invalid
//return 2: can not create lpPath
int CPathDialog::MakeSurePathExists(LPCTSTR pszPath)
{
int nRet;
CString sMessage;
try
{
//validate path
nRet = Touch(pszPath, TRUE);
if (nRet != 0)
throw nRet;
if (_access(pszPath, 06) == 0) {
if (pszPath[0] == '\\' && pszPath[1] == '\\') {
char szFile[MAX_PATH];
if (GetTempFileName(pszPath, "she", 0, szFile) == 0) {
sMessage.Format(c_FolderDoesNotPermission, pszPath);
AfxMessageBox(sMessage, MB_ICONWARNING);
return -1;
}
DeleteFile(szFile);
}
return 0;
}
if (errno == ENOENT) {
sMessage.Format(c_FolderDoesNotExist, pszPath);
if (AfxMessageBox(sMessage, MB_YESNO | MB_ICONQUESTION) != IDYES)
return -1;
//create path
nRet = Touch(pszPath, FALSE);
if (nRet != 0)
throw nRet;
}
else if (errno == EACCES) {
char szFile[MAX_PATH];
if (!GetTempFileName(pszPath, "she", 0, szFile)) {
sMessage.Format(c_FolderDoesNotPermission, pszPath);
AfxMessageBox(sMessage, MB_ICONWARNING);
return -1;
}
DeleteFile(szFile);
}
return 0;
}
catch (int nErrCode)
{
switch (nErrCode) {
case 1:
sMessage.Format(c_szErrInvalidPath, pszPath);
break;
case 2:
default:
sMessage.Format(c_szErrCreatePath, pszPath);
break;
}
AfxMessageBox(sMessage, MB_OK | MB_ICONEXCLAMATION);
}
return nRet;
}
//return 0: no error
//return 1: lpPath is invalid
//return 2: lpPath can not be created(bValidate == FALSE)
int CPathDialog::Touch(LPCTSTR pszPath, BOOL bValidate)
{
if (pszPath == NULL)
return 1;
TCHAR szPath[MAX_PATH];
_tcscpy(szPath, pszPath);
int nLen = (int)_tcslen(szPath);
//path must be "x:\..."
/*
if ((nLen < 3)
|| ((szPath[0] < _T('A') || _T('Z') < szPath[0])
&& (szPath[0] < _T('a') || _T('z') < szPath[0])
|| (szPath[1] != _T(':')) || (szPath[2] != _T('\\'))))
*/
if (nLen == 3) {
if (!bValidate) {
if (_access(szPath, 0)!=0) {
return 2;
}
}
return 0;
}
int i = 3;
BOOL bLastOne = TRUE;
LPTSTR lpCurrentName;
while (szPath[i] != 0) {
lpCurrentName = &szPath[i];
while( (szPath[i]!=0) && (szPath[i]!=_T('\\')) )
{
i++;
}
bLastOne =(szPath[i]==0);
szPath[i] = 0;
if( !IsValidFileName(lpCurrentName) )
{
return 1;
}
if(!bValidate)
{
CreateDirectory(szPath, NULL);
if(_taccess(szPath, 0)!=0)
{
return 2;
}
}
if(bLastOne)
{
break; //it's done
}
else
{
szPath[i] = _T('\\');
}
i++;
}
return (bLastOne?0:1);
}
//return 0: ok
//return 1: error
int CPathDialog::ConcatPath(LPTSTR lpRoot, LPCTSTR lpMorePath)
{
if (lpRoot==NULL)
return 1;
int nLen = (int)_tcslen(lpRoot);
if (nLen<3)
return 1;
if (lpMorePath == NULL)
return 0;
if (nLen == 3) {
_tcscat(lpRoot, lpMorePath);
return 0;
}
_tcscat(lpRoot, _T("\\"));
_tcscat(lpRoot, lpMorePath);
return 0;
}