/** * @file XTPWindowList.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "GraphicLibrary/unzip/unzip.h" #include "Common/XTPVC80Helpers.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPMarkupTheme.h" #include "Common/XTPResourceImage.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPToolTipContext.h" #include "Common/XTPMarkupRender.h" #include "Common/XTPColorManager.h" #include "Common/XTPHookManager.h" #include "Common/ScrollBar/XTPScrollBase.h" #include "Common/ScrollBar/XTPScrollBarCtrl.h" #include "Common/ScrollBar/XTPScrollable.h" #include "Common/ScrollBar/XTPScrollInfo.h" #include "Common/Hook/XTPWinEventHook.h" #include "Common/FrameShadow/XTPFrameShadowManager.h" #include "Common/XTPMaskEditT.h" #ifdef _XTP_INCLUDE_CONTROLS # include "Controls/Util/XTPControlTheme.h" # include "Controls/Edit/XTPEdit.h" #endif #ifdef _XTP_INCLUDE_TABMANAGER # include "TabManager/Includes.h" # include "TabManager/Themes/XTPTabThemeVisualStudio2010.h" # include "TabManager/Themes/XTPTabThemeVisualStudio2012.h" # include "TabManager/Themes/XTPTabThemeOffice2013.h" # include "TabManager/Themes/XTPTabThemeVisualStudio2015.h" # include "TabManager/Themes/XTPTabThemeNativeWindows10.h" # include "TabManager/Themes/XTPTabThemeNativeWindows11.h" #endif #ifdef _XTP_INCLUDE_COMMANDBARS # include "CommandBars/XTPCommandBarsDefines.h" # include "CommandBars/XTPPaintManager.h" # include "CommandBars/XTPCommandBars.h" # include "CommandBars/XTPCommandBar.h" # include "CommandBars/XTPPopupBar.h" # include "CommandBars/XTPToolBar.h" # include "CommandBars/XTPMenuBar.h" # include "CommandBars/XTPMenuTitleBar.h" # include "CommandBars/XTPControls.h" # include "CommandBars/XTPControl.h" # include "CommandBars/XTPControlButton.h" # include "CommandBars/XTPControlEdit.h" # include "CommandBars/XTPControlExt.h" # include "CommandBars/XTPMouseManager.h" # include "CommandBars/XTPShortcutManager.h" # include "CommandBars/XTPFrameWnd.h" # include "CommandBars/XTPCommandBarsIIDs.h" # include "CommandBars/XTPTabClientWnd.h" # include "CommandBars/Frame/XTPFrameHook.h" # include "CommandBars/TabClient/XTPTearOffFrame.h" #endif #include "Controls/Resource.h" #include "Controls/Util/XTPGlobal.h" #include "Controls/Util/XTPControlTheme.h" #include "Controls/Resize/XTPResizeRect.h" #include "Controls/Resize/XTPResizePoint.h" #include "Controls/Resize/XTPResize.h" #include "Controls/Resize/XTPResizeDialog.h" #include "Controls/ListBox/XTPListBox.h" #include "Controls/Dialog/XTPWindowList.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef OIC_WINLOGO # define OIC_WINLOGO 32517 #endif ///////////////////////////////////////////////////////////////////////////// // CXTPWindowList dialog CXTPWindowList::CXTPWindowList(CMDIFrameWnd* pMDIFrameWnd) { InitModalIndirect(XTPResourceManager()->LoadDialogTemplate(XTP_IDD_WINDOWLIST), pMDIFrameWnd); m_pMDIFrameWnd = pMDIFrameWnd; _ASSERTE(m_pMDIFrameWnd); m_hWndMDIClient = m_pMDIFrameWnd->m_hWndMDIClient; _ASSERTE(m_hWndMDIClient != NULL); m_hIcon = NULL; } CXTPWindowList::CXTPWindowList(HWND hWndMDIClient) { InitModalIndirect(XTPResourceManager()->LoadDialogTemplate(XTP_IDD_WINDOWLIST), 0); m_pMDIFrameWnd = NULL; m_hWndMDIClient = hWndMDIClient; _ASSERTE(m_hWndMDIClient != NULL); m_hIcon = NULL; } void CXTPWindowList::DoDataExchange(CDataExchange* pDX) { CXTPResizeDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXTPWindowList) DDX_Control(pDX, XTP_IDC_BTN_MINIMIZE, m_btnMinimize); DDX_Control(pDX, XTP_IDC_BTN_CASCADE, m_btnCascade); DDX_Control(pDX, IDOK, m_btnOk); DDX_Control(pDX, XTP_IDC_LBOX_WINDOWS, m_lboxWindows); DDX_Control(pDX, XTP_IDC_BTN_TILEVERT, m_btnTileVert); DDX_Control(pDX, XTP_IDC_BTN_TILEHORZ, m_btnTileHorz); DDX_Control(pDX, XTP_IDC_BTN_SAVE, m_btnSave); DDX_Control(pDX, XTP_IDC_BTN_CLOSEWINDOWS, m_btnClose); DDX_Control(pDX, XTP_IDC_BTN_ACTIVATE, m_btnActivate); //}}AFX_DATA_MAP } IMPLEMENT_DYNAMIC(CXTPWindowList, CXTPResizeDialog) #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPWindowList, CXTPResizeDialog) //{{AFX_MSG_MAP(CXTPWindowList) ON_LBN_SELCHANGE(XTP_IDC_LBOX_WINDOWS, OnSelchangeLBox) ON_BN_CLICKED(XTP_IDC_BTN_ACTIVATE, OnBtnActivate) ON_BN_CLICKED(XTP_IDC_BTN_SAVE, OnBtnSave) ON_BN_CLICKED(XTP_IDC_BTN_CLOSEWINDOWS, OnBtnClosewindows) ON_BN_CLICKED(XTP_IDC_BTN_TILEHORZ, OnBtnTilehorz) ON_BN_CLICKED(XTP_IDC_BTN_TILEVERT, OnBtnTilevert) ON_BN_CLICKED(XTP_IDC_BTN_CASCADE, OnBtnCascade) ON_BN_CLICKED(XTP_IDC_BTN_MINIMIZE, OnBtnMinimize) ON_WM_DRAWITEM() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" ///////////////////////////////////////////////////////////////////////////// // CXTPWindowList message handlers BOOL CXTPWindowList::OnInitDialog() { CXTPResizeDialog::OnInitDialog(); FillMDIWindowList(); SelectMDIActive(); SetEnableButtons(); // Set control resizing. SetResize(XTP_IDC_LBOX_WINDOWS, XTP_ANCHOR_TOPLEFT, XTP_ANCHOR_BOTTOMRIGHT); SetResize(XTP_IDC_BTN_ACTIVATE, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(IDOK, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_SAVE, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_CLOSEWINDOWS, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_CASCADE, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_TILEHORZ, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_TILEVERT, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); SetResize(XTP_IDC_BTN_MINIMIZE, XTP_ANCHOR_TOPRIGHT, XTP_ANCHOR_TOPRIGHT); // Load window placement LoadPlacement(_T("CXTPWindowList")); #ifdef _XTP_ACTIVEX HWND hWndParent = ::GetParent(m_hWndMDIClient); if (!m_hIcon) m_hIcon = (HICON)::SendMessage(hWndParent, WM_GETICON, ICON_SMALL, 0); if (!m_hIcon) m_hIcon = (HICON)::SendMessage(hWndParent, WM_GETICON, ICON_BIG, 0); if (!m_hIcon) m_hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr(hWndParent, GCLP_HICONSM); if (!m_hIcon) m_hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr(hWndParent, GCLP_HICON); #else if (m_hIcon == NULL && m_pMDIFrameWnd) { m_hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr(m_pMDIFrameWnd->GetSafeHwnd(), GCLP_HICONSM); } #endif // If no icon was defined, used XT icon. if (m_hIcon == NULL) { m_hIcon = AfxGetApp()->LoadOEMIcon(OIC_WINLOGO); } m_lboxWindows.SetFont(&XTPAuxData().xtpFont); SetIcon(m_hIcon, FALSE); return TRUE; } void CXTPWindowList::OnDestroy() { // Save window placement SavePlacement(_T("CXTPWindowList")); CXTPResizeDialog::OnDestroy(); } CString CXTPWindowList::GetChildWndText(HWND hWnd) const { CString strTitle = _T(""); CWnd* pWnd = CWnd::FromHandle(hWnd); // Get the window text for the frame and use it for the tab label. if (pWnd) pWnd->GetWindowText(strTitle); // If the string is empty the document's title. if (!strTitle.IsEmpty()) return strTitle; // Get a pointer to the frame window. CMDIChildWnd* pChildFrame = DYNAMIC_DOWNCAST(CMDIChildWnd, pWnd); if (!pChildFrame || !IsWindow(pChildFrame->GetSafeHwnd())) { return _T(""); } CDocument* pDocument = pChildFrame->GetActiveDocument(); if (pDocument == NULL) return _T(""); return pDocument->GetTitle(); } void CXTPWindowList::InsertMDIChild(HWND hwndMDIChildWnd) { _ASSERTE(hwndMDIChildWnd != 0); // must be valid. // Get the window text for the frame. CString strWindowText = GetChildWndText(hwndMDIChildWnd); int iIndex = m_lboxWindows.AddString(strWindowText); m_lboxWindows.SetItemDataPtr(iIndex, (LPVOID)hwndMDIChildWnd); } void CXTPWindowList::FillMDIClientWindowList(HWND hWndMDIClient) { // Retrieve the current active MDI child window. HWND hwndActiveChild = ::GetWindow(hWndMDIClient, GW_CHILD); if (hwndActiveChild != NULL) { // Get the first top-level window in the list. HWND hwndChildFrame = ::GetWindow(hwndActiveChild, GW_HWNDLAST); while (hwndChildFrame != NULL) { if (::IsWindowVisible(hwndChildFrame) && (GetWindowLong(hwndChildFrame, GWL_EXSTYLE) & WS_EX_MDICHILD)) { // Insert the tab and get the next frame on the window manager's list InsertMDIChild(hwndChildFrame); } hwndChildFrame = ::GetWindow(hwndChildFrame, GW_HWNDPREV); } } } void CXTPWindowList::FillMDIWindowList() { m_lboxWindows.ResetContent(); FillMDIClientWindowList(m_hWndMDIClient); #ifdef _XTP_INCLUDE_COMMANDBARS CXTPTabClientWnd* pTabClient = DYNAMIC_DOWNCAST(CXTPTabClientWnd, CWnd::FromHandle(m_hWndMDIClient)); if (pTabClient) { CArray tabClients; pTabClient->GetTabClients(tabClients); for (int i = 0; i < tabClients.GetSize(); i++) { if (pTabClient == tabClients.GetAt(i)) continue; FillMDIClientWindowList(tabClients.GetAt(i)->m_hWnd); } } #endif } void CXTPWindowList::SelectMDIActive() { int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { m_lboxWindows.SelItemRange(FALSE, 0, iCount - 1); HWND hWnd = (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, 0); int iItem; for (iItem = 0; iItem < iCount; iItem++) { if (hWnd == (HWND)m_lboxWindows.GetItemData(iItem)) { m_lboxWindows.SetSel(iItem); return; } } } } void CXTPWindowList::SetEnableButtons() { int iCount = m_lboxWindows.GetSelCount(); m_btnActivate.EnableWindow(iCount == 1); m_btnSave.EnableWindow(iCount > 0); m_btnClose.EnableWindow(iCount > 0); m_btnCascade.EnableWindow(iCount > 1); m_btnTileVert.EnableWindow(iCount > 1); m_btnTileHorz.EnableWindow(iCount > 1); m_btnMinimize.EnableWindow(iCount > 0); // hide buttons if menubar does not have frame button display m_btnCascade.ShowWindow(SW_SHOW); m_btnTileVert.ShowWindow(SW_SHOW); m_btnTileHorz.ShowWindow(SW_SHOW); m_btnMinimize.ShowWindow(SW_SHOW); #ifdef _XTP_ACTIVEX m_btnSave.ShowWindow(SW_HIDE); #endif } void CXTPWindowList::OnSelchangeLBox() { SetEnableButtons(); } void CXTPWindowList::OnBtnActivate() { int iIndex = m_lboxWindows.GetCurSel(); HWND hWnd = (HWND)m_lboxWindows.GetItemData(iIndex); if (hWnd != (HWND)LB_ERR) { WINDOWPLACEMENT wp; ::GetWindowPlacement(hWnd, &wp); if (wp.showCmd == SW_SHOWMINIMIZED) ::ShowWindow(hWnd, SW_RESTORE); #ifdef _XTP_INCLUDE_COMMANDBARS CXTPTabClientWnd* pTabClientWnd = DYNAMIC_DOWNCAST(CXTPTabClientWnd, CWnd::FromHandle(hWnd)->GetParent()); if (pTabClientWnd) { CXTPTearOffFrame* pTearOffFrame = DYNAMIC_DOWNCAST(CXTPTearOffFrame, pTabClientWnd->GetParentFrame()); XTP_SAFE_CALL1(pTearOffFrame, SetForegroundWindow()); ::SendMessage(pTabClientWnd->m_hWnd, WM_MDIACTIVATE, (WPARAM)hWnd, 0); } #endif ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWnd, 0); CXTPResizeDialog::OnOK(); } } void CXTPWindowList::OnBtnSave() { int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { int iItem; for (iItem = 0; iItem < iCount; iItem++) { if (m_lboxWindows.GetSel(iItem) > 0) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); if (hWnd != NULL) { CMDIChildWnd* pMDIChildWnd = (CMDIChildWnd*)CWnd::FromHandle(hWnd); if (!pMDIChildWnd) continue; CDocument* pDocument = pMDIChildWnd->GetActiveDocument(); if (pDocument != NULL) { pDocument->DoFileSave(); } } } } } FillMDIWindowList(); SelectMDIActive(); SetEnableButtons(); } void CXTPWindowList::OnBtnClosewindows() { int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { int iItem; for (iItem = 0; iItem < iCount; iItem++) { if (m_lboxWindows.GetSel(iItem) > 0) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); if (hWnd != NULL) { ::SendMessage(hWnd, WM_CLOSE, 0, 0); } } } } FillMDIWindowList(); SelectMDIActive(); SetEnableButtons(); } void CXTPWindowList::OnBtnTilehorz() { CWaitCursor wait; int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { ::LockWindowUpdate(m_hWndMDIClient); int iItem; for (iItem = iCount - 1; iItem >= 0; iItem--) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); if (m_lboxWindows.GetSel(iItem) > 0) ::ShowWindow(hWnd, SW_RESTORE); else ::ShowWindow(hWnd, SW_MINIMIZE); } ::SendMessage(m_hWndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0); ::LockWindowUpdate(NULL); } } void CXTPWindowList::OnBtnTilevert() { CWaitCursor wait; int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { ::LockWindowUpdate(m_hWndMDIClient); int iItem; for (iItem = iCount - 1; iItem >= 0; iItem--) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); if (m_lboxWindows.GetSel(iItem) > 0) ::ShowWindow(hWnd, SW_RESTORE); else ::ShowWindow(hWnd, SW_MINIMIZE); } ::SendMessage(m_hWndMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0); ::LockWindowUpdate(NULL); } } void CXTPWindowList::OnBtnCascade() { CWaitCursor wait; int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { ::LockWindowUpdate(m_hWndMDIClient); int iItem; for (iItem = iCount - 1; iItem >= 0; iItem--) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); if (m_lboxWindows.GetSel(iItem) > 0) ::ShowWindow(hWnd, SW_RESTORE); else ::ShowWindow(hWnd, SW_MINIMIZE); } ::SendMessage(m_hWndMDIClient, WM_MDICASCADE, 0, 0); ::LockWindowUpdate(NULL); } } void CXTPWindowList::OnBtnMinimize() { CWaitCursor wait; int iCount = m_lboxWindows.GetCount(); if (iCount != LB_ERR && iCount > 0) { ::LockWindowUpdate(m_hWndMDIClient); int iItem; for (iItem = iCount - 1; iItem >= 0; iItem--) { HWND hWnd = (HWND)m_lboxWindows.GetItemData(iItem); LONG lStyle = GetWindowLong(hWnd, GWL_STYLE); if (m_lboxWindows.GetSel(iItem) > 0 && (lStyle & WS_MINIMIZEBOX)) { ::ShowWindow(hWnd, SW_MINIMIZE); } } ::SendMessage(m_hWndMDIClient, WM_MDICASCADE, 0, 0); ::LockWindowUpdate(NULL); } } void CXTPWindowList::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDIS) { if (nIDCtl == XTP_IDC_LBOX_WINDOWS) { if (lpDIS->itemID == (UINT)LB_ERR) return; CDC* pDC = CDC::FromHandle(lpDIS->hDC); CRect rcItem = lpDIS->rcItem; CXTPDCSaveState dcState(pDC); CSize sizeIcon; sizeIcon.cx = ::GetSystemMetrics(SM_CXSMICON); sizeIcon.cy = ::GetSystemMetrics(SM_CYSMICON); COLORREF crText = ::GetSysColor(COLOR_WINDOWTEXT); COLORREF crBack = ::GetSysColor(COLOR_WINDOW); if (lpDIS->itemState & ODS_SELECTED) { crBack = ::GetSysColor(COLOR_HIGHLIGHT); crText = ::GetSysColor(COLOR_HIGHLIGHTTEXT); } CRect rcLabel = rcItem; rcLabel.left += sizeIcon.cx + XTP_DPI_X(3); if (lpDIS->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) pDC->FillSolidRect(rcLabel, crBack); if (lpDIS->itemAction & ODA_FOCUS) pDC->DrawFocusRect(&rcLabel); CString strBuffer; m_lboxWindows.GetText(static_cast(lpDIS->itemID), strBuffer); pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(crText); rcItem.left += sizeIcon.cx + XTP_DPI_X(4); pDC->DrawText(strBuffer, -1, &rcItem, DT_LEFT | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE); rcItem.left = lpDIS->rcItem.left; // Try to locate the icon for the MDI window by calling WM_GETICON // first, this will give us the correct icon if the user has called // SetIcon(...) for the child frame. HICON hIcon = (HICON)::SendMessage((HWND)lpDIS->itemData, WM_GETICON, ICON_SMALL, 0); if (!hIcon) hIcon = (HICON)::SendMessage((HWND)lpDIS->itemData, WM_GETICON, ICON_BIG, 0); // If the icon returned is NULL, then try using GCLP_HICONSM to get the // document icon for the child frame if (!hIcon) hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr((HWND)lpDIS->itemData, GCLP_HICONSM); if (!hIcon) hIcon = (HICON)(ULONG_PTR)::GetClassLongPtr((HWND)lpDIS->itemData, GCLP_HICON); // If no icon was found, then use the default windows logo icon. if (hIcon == NULL) { hIcon = AfxGetApp()->LoadStandardIcon(IDI_WINLOGO); } rcItem.left += XTP_DPI_X(2); ::DrawIconEx(pDC->m_hDC, rcItem.left, rcItem.top, hIcon, sizeIcon.cx, sizeIcon.cy, 0, NULL, DI_NORMAL); return; } CXTPResizeDialog::OnDrawItem(nIDCtl, lpDIS); }