DragonNest/Third/XTToolkitPro/Source/Controls/XTBrowseEdit.cpp
2024-12-19 09:48:26 +08:00

621 lines
14 KiB
C++

// XTBrowseEdit.cpp : implementation of the CXTBrowseEdit class.
//
// This file is a part of the XTREME CONTROLS MFC class library.
// (c)1998-2008 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Resource.h"
#include "Common/XTPVC80Helpers.h" // Visual Studio 2005 helper functions
#include "Common/XTPResourceManager.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPWinThemeWrapper.h"
#include "Common/XTPSystemHelpers.h"
#include "XTFunctions.h"
#include "XTDefines.h"
#include "XTUtil.h"
#include "XTGlobal.h"
#include "XTButton.h"
#include "XTButtonTheme.h"
#include "XTFlatComboBox.h"
#include "XTBrowseEdit.h"
#include "XTBrowseDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
const int CX_BUTTON = (::GetSystemMetrics(SM_CXHTHUMB) +
(::GetSystemMetrics(SM_CXEDGE) * 2));
/////////////////////////////////////////////////////////////////////////////
// CXTBrowseButton class
/////////////////////////////////////////////////////////////////////////////
CXTBrowseButton::CXTBrowseButton()
{
m_nBorderGap = 0;
m_nImageGap = 0;
m_dwBStyle = 0;
m_pEditWnd = NULL;
m_dwxStyle = BS_XT_SHOWFOCUS | BS_XT_WINXP_COMPAT;
m_nID = 0;
m_nMenu = 0;
m_nSubMenuIndx = 0;
SetTheme(new CXTDisabledButtonTheme);
}
CXTBrowseButton::~CXTBrowseButton()
{
}
IMPLEMENT_DYNAMIC(CXTBrowseButton, CXTButton)
BEGIN_MESSAGE_MAP(CXTBrowseButton, CXTButton)
//{{AFX_MSG_MAP(CXTBrowseButton)
ON_WM_ENABLE()
ON_CONTROL_REFLECT(BN_CLICKED, OnBtnClicked)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CXTBrowseButton::Create(CXTBrowseEdit* pEditWnd, DWORD dwBStyle, UINT nID, UINT nMenu/*= -1*/, UINT nSubMenuIndx/*= -1*/)
{
ASSERT_VALID(pEditWnd); // Must be valid
ASSERT_VALID(pEditWnd->GetParent());
// Set the pointers to the edit and edit parent windows.
m_pEditWnd = pEditWnd;
// Set the browse style and menu resource
// ID information (if any).
m_dwBStyle = dwBStyle;
m_nMenu = nMenu;
m_nSubMenuIndx = nSubMenuIndx;
CString strButtonText;
DWORD dwStyle = (m_pEditWnd->GetStyle() & WS_VISIBLE) |
WS_CHILD | WS_TABSTOP | BS_CENTER | BS_VCENTER | BS_OWNERDRAW;
if ((m_dwBStyle & BES_XT_POPUPMENU) == 0)
{
VERIFY(XTPResourceManager()->LoadString(&strButtonText, XT_IDS_DOT));
}
else
{
CImageList imageList;
imageList.Create(11, 11, ILC_COLOR8 | ILC_MASK, 0, 1);
CBitmap bmp;
VERIFY(XTPResourceManager()->LoadBitmap(&bmp, XT_IDB_SCROLL_ARW));
imageList.Add(&bmp, RGB(0xff, 0x00, 0xff));
if (imageList.GetImageCount() == 8)
{
// extract the right arrow icon from the image list.
m_hPopupIcon = imageList.ExtractIcon(4);
ASSERT(m_hPopupIcon != NULL);
// add the BS_ICON style to create flags.
dwStyle |= BS_ICON;
}
}
if (!CXTButton::Create(strButtonText, dwStyle, CRect(0, 0, 0, 0),
m_pEditWnd->GetParent(), nID))
{
TRACE0("Failed to create browse edit button.\n");
return FALSE;
}
// Set the font for this control.
if (!strButtonText.IsEmpty())
SetFont(&XTAuxData().font);
// set the arrow icon that is displayed on the button.
if (NULL != (HICON)m_hPopupIcon)
SetIcon(CSize(10, 10), m_hPopupIcon);
// Enable the button using the parent's enabled state.
EnableWindow(m_pEditWnd->IsWindowEnabled());
return TRUE;
}
void CXTBrowseButton::SetBrowseStyle(DWORD dwxStyle)
{
m_dwBStyle = dwxStyle;
if ((m_dwBStyle & BES_XT_POPUPMENU) == 0)
{
CString strButtonText;
VERIFY(XTPResourceManager()->LoadString(&strButtonText, XT_IDS_DOT));
SetWindowText(strButtonText);
}
else
{
CImageList imageList;
imageList.Create(11, 11, ILC_COLOR8 | ILC_MASK, 0, 1);
CBitmap bmp;
VERIFY(XTPResourceManager()->LoadBitmap(&bmp, XT_IDB_SCROLL_ARW));
imageList.Add(&bmp, RGB(0xff, 0x00, 0xff));
if (imageList.GetImageCount() == 8)
{
// extract the right arrow icon from the image list.
m_hPopupIcon = imageList.ExtractIcon(4);
ASSERT(m_hPopupIcon != NULL);
// add the BS_ICON style to create flags.
ModifyStyle(0, BS_ICON);
// set the arrow icon that is displayed on the button.
if (NULL != (HICON)m_hPopupIcon)
SetIcon(CSize(10, 10), m_hPopupIcon);
}
}
}
BOOL CXTBrowseButton::PreTranslateMessage(MSG* pMsg)
{
// activate if space or enter key pressed...
if (pMsg->message == WM_KEYDOWN &&
(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_SPACE))
{
OnClicked();
return TRUE; // eat message...
}
return CXTButton::PreTranslateMessage(pMsg);
}
void CXTBrowseButton::OnBtnClicked()
{
OnClicked();
}
void CXTBrowseButton::OnClicked()
{
if (m_pEditWnd)
{
m_pEditWnd->OnBrowse();
}
}
void CXTBrowseButton::OnEnable(BOOL bEnable)
{
CXTButton::OnEnable(bEnable);
Invalidate();
}
/////////////////////////////////////////////////////////////////////////////
// CXTBrowseEdit class
/////////////////////////////////////////////////////////////////////////////
CXTBrowseEdit::CXTBrowseEdit()
{
m_nGap = ::GetSystemMetrics(SM_CXEDGE);
m_dwBStyle = BES_XT_CHOOSEDIR;
m_nMenu = 0;
m_nSubMenuIndx = 0;
m_strFileName = _T("");
m_dwFlags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_EXPLORER;
m_pParentWnd = NULL;
m_pFileDialog = NULL;
m_bOpenFileDialog = TRUE;
m_bBrowsing = false;
VERIFY(XTPResourceManager()->LoadString(&m_strDefExt, XT_IDS_DEFEXT));
VERIFY(XTPResourceManager()->LoadString(&m_strFilter, XT_IDS_DEFFILT));
VERIFY(XTPResourceManager()->LoadString(&m_strTitle, XT_IDS_DEFTITLE));
}
CXTBrowseEdit::~CXTBrowseEdit()
{
}
IMPLEMENT_DYNAMIC(CXTBrowseEdit, CXTEdit)
BEGIN_MESSAGE_MAP(CXTBrowseEdit, CXTEdit)
//{{AFX_MSG_MAP(CXTBrowseEdit)
ON_WM_ENABLE()
ON_WM_SHOWWINDOW()
ON_WM_WINDOWPOSCHANGED()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CXTBrowseEdit::OnEnable(BOOL bEnable)
{
CXTEdit::OnEnable(bEnable);
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
m_btnBrowse.EnableWindow(bEnable);
Invalidate();
}
void CXTBrowseEdit::OnShowWindow(BOOL bShow, UINT nStatus)
{
CXTEdit::OnShowWindow(bShow, nStatus);
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
m_btnBrowse.ShowWindow(bShow ? SW_SHOW : SW_HIDE);
}
bool CXTBrowseEdit::Initialize(CWnd* pParentWnd, DWORD dwBStyle, UINT nMenu/*= 0*/, int nSubMenuIndx/*= 0*/)
{
if (!CXTEdit::Initialize(pParentWnd))
return false;
// only create a browse button if one was specified.
if (m_dwBStyle & (BES_XT_CHOOSEDIR | BES_XT_CHOOSEFILE | BES_XT_POPUPMENU | BES_XT_BROWSE))
{
// set browse edit style and menu indexes.
m_dwBStyle = dwBStyle;
m_nMenu = nMenu;
m_nSubMenuIndx = nSubMenuIndx;
// Create the browse button associated with the browse edit control.
if (!m_btnBrowse.Create(this, m_dwBStyle, XT_IDC_BTN_BROWSE,
m_nMenu, m_nSubMenuIndx))
{
TRACE1("Error creating browse button for ID %d.\n", GetDlgCtrlID());
return false;
}
CXTPWindowRect rcWindow(this);
rcWindow.right -= CX_BUTTON + m_nGap;
ASSERT_VALID(m_pParentWnd); // must be valid.
m_pParentWnd->ScreenToClient(&rcWindow);
// set the window position to accommodate for the browse button.
::SetWindowPos(m_hWnd, NULL, rcWindow.left, rcWindow.top,
rcWindow.Width(), rcWindow.Height(), SWP_FRAMECHANGED | SWP_NOZORDER);
// position browse button.
PositionBrowseButton();
}
return true;
}
void CXTBrowseEdit::PositionBrowseButton()
{
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
{
CXTPWindowRect rcWindow(this);
// construct the size of the browse button.
CRect rcButton;
rcButton.left = rcWindow.right + m_nGap;
rcButton.right = rcButton.left + CX_BUTTON;
rcButton.top = rcWindow.top;
rcButton.bottom = rcWindow.top + rcWindow.Height();
ASSERT_VALID(m_pParentWnd); // must be valid.
m_pParentWnd->ScreenToClient(&rcButton);
// set the window position and make sure tab order is correct.
::SetWindowPos(m_btnBrowse.m_hWnd, m_hWnd,
rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), SWP_FRAMECHANGED);
// construct the area to be updated on the parent.
CRect rcRedraw = rcWindow;
rcRedraw.right = rcButton.right;
// refresh parent window.
m_pParentWnd->InvalidateRect(&rcRedraw);
}
}
void CXTBrowseEdit::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
CXTEdit::OnWindowPosChanged(lpwndpos);
// position browse button.
PositionBrowseButton();
}
void CXTBrowseEdit::ChooseDirectory()
{
m_bBrowsing = true;
// Get the current (if any) text that is displayed in
// the edit control, this will be the initial path for the
// browse dialog to start from.
CString strPath;
GetWindowText(strPath);
if (!DIRECTORYEXISTS_S(strPath) && !m_strInitialDir.IsEmpty())
strPath = m_strInitialDir;
// Instantiate a browse for folder dialog object
CXTBrowseDialog browseDlg;
browseDlg.SetOwner(GetParent()->GetSafeHwnd());
browseDlg.SetTitle((TCHAR*)(LPCTSTR)m_strTitle);
browseDlg.SetSelPath((TCHAR*)(LPCTSTR)strPath);
if (browseDlg.DoModal() == IDOK)
{
SetWindowText(browseDlg.GetSelPath());
}
m_bBrowsing = false;
}
void CXTBrowseEdit::ChooseFile()
{
m_bBrowsing = true;
if (m_pFileDialog)
{
if (m_pFileDialog->DoModal() == IDOK)
SetWindowText(m_pFileDialog->GetPathName());
}
else
{
CFileDialog dlg(m_bOpenFileDialog, m_strDefExt, m_strFileName,
m_dwFlags, m_strFilter, m_pParentWnd);
if (!m_strInitialDir.IsEmpty())
{
dlg.m_ofn.lpstrInitialDir = (LPCTSTR)m_strInitialDir;
}
// Check to see if this is Windows 2000 or later, if so use the
// Windows 2000 version of OPENFILENAME.
if (sizeof(OPENFILENAME) < 88) if (XTOSVersionInfo()->IsWin2KOrGreater() && dlg.m_ofn.lStructSize < 88)
{
// Windows 2000 version of OPENFILENAME has three extra members,
// this was copied from newer version of commdlg.h...
struct OPENFILENAMEEX
{
void* pvReserved; // 4 bytes
DWORD dwReserved; // 4 bytes
DWORD FlagsEx; // 4 bytes
};
dlg.m_ofn.lStructSize += sizeof(OPENFILENAMEEX); // should equal an additional 12 bytes;
}
if (dlg.DoModal() == IDOK)
{
SetWindowText(dlg.GetPathName());
}
}
m_bBrowsing = false;
}
void CXTBrowseEdit::PopupMenu()
{
if (m_bBrowsing)
return;
m_bBrowsing = true;
ASSERT(m_nMenu != 0);
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
m_btnBrowse.SetState(TRUE);
CRect rect;
m_btnBrowse.GetWindowRect(&rect);
// loading a user resource.
CMenu menu;
VERIFY(XTPResourceManager()->LoadMenu(&menu, m_nMenu));
CMenu* pPopup = menu.GetSubMenu(m_nSubMenuIndx);
ASSERT(pPopup != NULL);
CWnd* pWndPopupOwner = this;
while (pWndPopupOwner->GetStyle() & WS_CHILD)
{
pWndPopupOwner = pWndPopupOwner->GetParent();
}
XTFuncContextMenu(pPopup, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
rect.right, rect.top, pWndPopupOwner, 0);
// Return the button state to normal.
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
m_btnBrowse.SetState(FALSE);
m_bBrowsing = false;
}
void CXTBrowseEdit::OnBrowse()
{
// If this is a browse directory control.
switch (m_dwBStyle & (BES_XT_CHOOSEDIR | BES_XT_CHOOSEFILE | BES_XT_POPUPMENU | BES_XT_BROWSE))
{
case BES_XT_CHOOSEDIR:
ChooseDirectory();
break;
case BES_XT_CHOOSEFILE:
ChooseFile();
break;
case BES_XT_POPUPMENU:
PopupMenu();
break;
case BES_XT_BROWSE:
GetParent()->SendMessage( WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), LBN_XT_ONBROWSE), (LPARAM)m_hWnd );
break;
}
if (::GetFocus() != m_hWnd)
{
SetSel(0, -1);
SetFocus();
}
}
/////////////////////////////////////////////////////////////////////////////
// CXTItemEdit class
/////////////////////////////////////////////////////////////////////////////
CXTItemEdit::CXTItemEdit()
{
// Initialize defaults
m_bClosePosted = false;
m_bModified = false;
m_bEscapeKey = false;
m_nGap = 0;
m_bAutoDelete = false;
m_dwBStyle = 0;
}
BOOL CXTItemEdit::Create(CWnd* pParent, const CRect& rect, CString& strWindowText, DWORD dwBStyle/*= BES_XT_CHOOSEDIR*/, bool bAutoDelete/*= true*/)
{
m_bAutoDelete = bAutoDelete;
m_dwBStyle = dwBStyle;
m_pParentWnd = pParent;
m_strWindowText = strWindowText;
// Create the edit control.
if (!CXTBrowseEdit::Create(WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
rect, pParent, XT_IDC_LBOX_EDIT))
return FALSE;
// Initialize the edit control.
if (!Initialize(pParent, dwBStyle))
return FALSE;
// Set the window text and select it.
SetWindowText(m_strWindowText);
SetSel(0, -1);
SetFocus();
return TRUE;
}
CXTItemEdit::~CXTItemEdit()
{
}
IMPLEMENT_DYNAMIC(CXTItemEdit, CXTBrowseEdit)
BEGIN_MESSAGE_MAP(CXTItemEdit, CXTBrowseEdit)
//{{AFX_MSG_MAP(CXTItemEdit)
ON_WM_KILLFOCUS()
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CXTItemEdit::OnKillFocus(CWnd* pNewWnd)
{
CXTBrowseEdit::OnKillFocus(pNewWnd);
if (!::IsWindow(m_btnBrowse.GetSafeHwnd()) || pNewWnd != &m_btnBrowse)
{
ASSERT_VALID(this);
EndLabelEdit();
}
}
void CXTItemEdit::PostNcDestroy()
{
if (m_bAutoDelete)
{
delete this;
}
}
BOOL CXTItemEdit::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
{
if ((pMsg->wParam == VK_RETURN) ||
(pMsg->wParam == VK_ESCAPE))
{
if (pMsg->wParam == VK_ESCAPE)
{
m_bEscapeKey = true;
}
EndLabelEdit();
return TRUE;
}
}
return CXTBrowseEdit::PreTranslateMessage(pMsg);
}
void CXTItemEdit::EndLabelEdit()
{
if (m_bClosePosted) return;
if (::IsWindow(m_btnBrowse.GetSafeHwnd()))
m_btnBrowse.PostMessage(WM_CLOSE);
if (::IsWindow(GetSafeHwnd()))
PostMessage(WM_CLOSE);
m_bClosePosted = true;
if (m_bModified == false)
{
CWnd* pOwner = GetOwner();
ASSERT_VALID(pOwner);
if (m_bEscapeKey == false)
{
m_bModified = true;
// get the window text and pass it on to the
// notification window...
GetWindowText(m_strWindowText);
// Notify of label edit.
pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
BEN_XT_LABELEDITEND), (LPARAM)GetSafeHwnd());
}
else
{
// Notify of label edit.
pOwner->SendMessage(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(),
BEN_XT_LABELEDITCANCEL), (LPARAM)GetSafeHwnd());
}
}
}
void CXTItemEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if ((nChar == VK_RETURN) ||
(nChar == VK_ESCAPE))
{
if (nChar == VK_ESCAPE)
m_bEscapeKey = TRUE;
EndLabelEdit();
return;
}
CXTBrowseEdit::OnChar(nChar, nRepCnt, nFlags);
}