/** * @file XTPPropertyPage.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 "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/XTPDrawHelpers.h" #include "Common/XTPHookManager.h" #include "Common/XTPColorManager.h" #include "Common/XTPWinThemeWrapper.h" #include "Common/XTPResourceManager.h" #include "Common/XTPResourceImage.h" #include "Common/XTPMaskEditT.h" #include "Common/ScrollBar/XTPScrollBase.h" #include "Common/ScrollBar/XTPScrollBarCtrl.h" #include "Common/ScrollBar/XTPScrollable.h" #include "TabManager/Includes.h" #include "Controls/Util/XTPControlTheme.h" #include "Controls/Button/XTPButton.h" #include "Controls/Edit/XTPEdit.h" #include "Controls/ListBox/XTPListBox.h" #include "Controls/Util/XTPGlobal.h" #include "Controls/Resize/XTPResizeRect.h" #include "Controls/Resize/XTPResizePoint.h" #include "Controls/Resize/XTPResize.h" #include "Controls/Resize/XTPResizeDialog.h" #include "Controls/Scroll/XTPScrollBar.h" #ifdef _XTP_INCLUDE_COMMANDBARS # include "CommandBars/Resource.h" # include "CommandBars/XTPCommandBarsDefines.h" # include "CommandBars/XTPPaintManager.h" # include "CommandBars/XTPShortcutManager.h" # include "CommandBars/XTPCommandBars.h" # include "CommandBars/XTPCommandBar.h" # include "CommandBars/XTPToolBar.h" # include "CommandBars/XTPMenuBar.h" # include "CommandBars/XTPMenuTitleBar.h" # include "CommandBars/XTPControl.h" # include "CommandBars/XTPControlEdit.h" #endif #include "Controls/Dialog/XTPDialogBase.h" #include "Controls/Dialog/XTPPropertyPage.h" #include "Controls/Dialog/XTPPropertySheet.h" #include "Controls/Dialog/XTPPropertyPageNavigator.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #pragma warning(disable : 4355) // 'this' : used in base member initializer list ///////////////////////////////////////////////////////////////////////////// // CXTPPropertyPage property page IMPLEMENT_DYNCREATE(CXTPPropertyPage, CPropertyPage) CXTPPropertyPage::CXTPPropertyPage() : CPropertyPage() , CXTPResize(this, xtpResizeNoClipChildren | xtpResizeNoSizeIcon) { CommonConstruct(); } CXTPPropertyPage::CXTPPropertyPage(UINT nIDTemplate, UINT nIDCaption) : CPropertyPage(nIDTemplate, nIDCaption) , CXTPResize(this, xtpResizeNoClipChildren | xtpResizeNoSizeIcon) { CommonConstruct(); } CXTPPropertyPage::CXTPPropertyPage(LPCTSTR lpszTemplateName, UINT nIDCaption) : CPropertyPage(lpszTemplateName, nIDCaption) , CXTPResize(this, xtpResizeNoClipChildren | xtpResizeNoSizeIcon) { CommonConstruct(); } void CXTPPropertyPage::CommonConstruct() { m_pSheet = 0; m_dwData = 0; m_bModified = FALSE; m_bInsideUpdate = FALSE; m_totalDev = CSize(0, 0); m_lineDev = CXTPDrawHelpers::Dlu2Pix(5, 5); m_bCreated = FALSE; } CXTPPropertyPage::~CXTPPropertyPage() { } void CXTPPropertyPage::SetCaption(LPCTSTR lpszCaption) { m_strCaption = lpszCaption; m_psp.pszTitle = m_strCaption; m_psp.dwFlags |= PSP_USETITLE; } CString CXTPPropertyPage::GetCaption() const { return m_strCaption; } void CXTPPropertyPage::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXTPPropertyPage) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } #pragma pack(push, 1) struct DLGEXTEMPLATE { WORD dlgVer; WORD wSignature; DWORD helpID; DWORD exStyle; DWORD dwStyle; WORD cDlgItems; short x; short y; short cx; short cy; }; #pragma pack(pop) BOOL CXTPPropertyPage::LoadTemplate(HGLOBAL& hTemplate, HINSTANCE& hInst) { hTemplate = NULL; hInst = NULL; if ((m_psp.dwFlags & PSP_DLGINDIRECT) && m_psp.pResource) { CDialogTemplate dlgTemp((LPCDLGTEMPLATE)m_psp.pResource); hTemplate = dlgTemp.Detach(); hInst = XTPGetInstanceHandle(); } else { HRSRC hResource = XTPResourceManager()->FindResource(hInst, m_psp.pszTemplate, RT_DIALOG); if (!hResource) return FALSE; hTemplate = LoadResource(hInst, hResource); if (!hTemplate) return FALSE; DLGTEMPLATE* pTemplate = (DLGTEMPLATE*)LockResource(hTemplate); CDialogTemplate dlgTemp(pTemplate); UnlockResource(hTemplate); FreeResource(hTemplate); hTemplate = dlgTemp.Detach(); } return TRUE; } BOOL CXTPPropertyPage::LoadTemplate() { HGLOBAL hTemplate = NULL; HINSTANCE hInstance = NULL; if (!LoadTemplate(hTemplate, hInstance)) return FALSE; if (!hTemplate) return FALSE; DLGTEMPLATE* lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate); if (!lpDialogTemplate) return FALSE; DLGEXTEMPLATE* lpDialogExTemplate = (DLGEXTEMPLATE*)lpDialogTemplate; BOOL bDialogEx = lpDialogExTemplate->wSignature == 0xFFFF; m_lineDev = CXTPDrawHelpers::Dlu2Pix(5, 5); if ((m_psp.dwFlags & PSP_USETITLE) == 0) { WORD* lpTitle = bDialogEx ? (WORD*)(lpDialogExTemplate + 1) : (WORD*)(lpDialogTemplate + 1); if (*lpTitle == (WORD)-1) // Skip menu name string or ordinal lpTitle += 2; else while (*lpTitle++) ; if (*lpTitle == (WORD)-1) // Skip class name string or ordinal lpTitle += 2; else while (*lpTitle++) ; m_strCaption = CString((LPWSTR)lpTitle); } GlobalUnlock(hTemplate); GlobalFree(hTemplate); BOOL bResult = MeasureTemplate(m_totalDev); return bResult; } BOOL CXTPPropertyPage::MeasureTemplate(SIZE& szDlg) { BOOL bResult = FALSE; HGLOBAL hTemplate = NULL; HINSTANCE hInstance = NULL; CWnd wndDlgParent; CDialog dlgTest; szDlg.cx = 0; szDlg.cy = 0; do { if (!LoadTemplate(hTemplate, hInstance) || NULL == hTemplate) break; DLGTEMPLATE* lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate); if (NULL == lpDialogTemplate) break; DLGEXTEMPLATE* lpDialogExTemplate = (DLGEXTEMPLATE*)lpDialogTemplate; DWORD lSaveStyle; if (lpDialogExTemplate->wSignature == 0xFFFF) lSaveStyle = lpDialogExTemplate->dwStyle; else lSaveStyle = lpDialogTemplate->style; DWORD dwNewStyle = ((lSaveStyle & ~WS_VISIBLE) & (DS_LOCALEDIT | WS_CLIPCHILDREN | DS_SETFONT | DS_FIXEDSYS)) | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL; if (lpDialogExTemplate->wSignature == 0xFFFF) lpDialogExTemplate->dwStyle = dwNewStyle; else lpDialogTemplate->style = dwNewStyle; LPCTSTR lpDlgParentClassName = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), reinterpret_cast(GetStockObject(WHITE_BRUSH)), NULL); if (NULL == lpDlgParentClassName) break; if (!wndDlgParent.CreateEx(0, lpDlgParentClassName, NULL, 0, 0, 0, 0, 0, NULL, 0)) break; bResult = dlgTest.CreateIndirect(lpDialogTemplate, &wndDlgParent); if (!bResult) break; CSize sz; CXTPWindowRect rc(&dlgTest); szDlg = rc.Size(); m_totalDev = szDlg; } while (false); if (::IsWindow(dlgTest)) dlgTest.DestroyWindow(); if (::IsWindow(wndDlgParent)) wndDlgParent.DestroyWindow(); if (NULL != hTemplate) GlobalUnlock(hTemplate); if (NULL != hTemplate) GlobalFree(hTemplate); return bResult; } BOOL CXTPPropertyPage::CreatePage(CWnd* pParentWnd) { if (GetSafeHwnd()) return TRUE; HGLOBAL hTemplate = NULL; HINSTANCE hInstance = NULL; if (!LoadTemplate(hTemplate, hInstance)) return FALSE; if (!hTemplate) return FALSE; DLGTEMPLATE* lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate); if (!lpDialogTemplate) return FALSE; DLGEXTEMPLATE* lpDialogExTemplate = (DLGEXTEMPLATE*)lpDialogTemplate; DWORD lSaveStyle; if (lpDialogExTemplate->wSignature == 0xFFFF) lSaveStyle = lpDialogExTemplate->dwStyle; else lSaveStyle = lpDialogTemplate->style; DWORD dwNewStyle = (lSaveStyle & (DS_LOCALEDIT | WS_CLIPCHILDREN | DS_SETFONT | DS_FIXEDSYS)) | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL; if (lpDialogExTemplate->wSignature == 0xFFFF) lpDialogExTemplate->dwStyle = dwNewStyle; else lpDialogTemplate->style = dwNewStyle; BOOL bResult = CreateDlgIndirect(lpDialogTemplate, pParentWnd, hInstance); CSize sz; CXTPWindowRect rc(this); m_totalDev = rc.Size(); m_bCreated = TRUE; GlobalUnlock(hTemplate); GlobalFree(hTemplate); return bResult; } void CXTPPropertyPage::EndDialog(int nID) { // Normally you shouldn't call EndDialog from a page. But in case it does // happen during error situations, call CPropertySheet::EndDialog instead. CXTPPropertySheet* pParent = DYNAMIC_DOWNCAST(CXTPPropertySheet, GetParent()); if (pParent != NULL) pParent->EndDialog(nID); } void CXTPPropertyPage::SetModified(BOOL bChanged) { if (m_hWnd == NULL) // allowed for backward compatibility return; _ASSERTE(::IsWindow(m_hWnd)); _ASSERTE(GetParent() != NULL); CWnd* pParentWnd = GetParent(); if (bChanged) pParentWnd->SendMessage(PSM_CHANGED, (WPARAM)m_hWnd); else pParentWnd->SendMessage(PSM_UNCHANGED, (WPARAM)m_hWnd); } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPPropertyPage, CPropertyPage) //{{AFX_MSG_MAP(CXTPPropertyPage) ON_WM_ERASEBKGND() ON_WM_CTLCOLOR() ON_WM_SIZE() ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_MOUSEWHEEL() ON_WM_NCPAINT() ON_WM_NCCALCSIZE() //}}AFX_MSG_MAP END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" ///////////////////////////////////////////////////////////////////////////// // CXTPPropertyPage message handlers BOOL CXTPPropertyPage::OnEraseBkgnd(CDC* pDC) { HBRUSH hBrush = m_pSheet ? m_pSheet->GetNavigator()->GetPageBrush(pDC, this) : NULL; if (hBrush) { CXTPClientRect rc(this); ::FillRect(pDC->GetSafeHdc(), rc, hBrush); return TRUE; } return CPropertyPage::OnEraseBkgnd(pDC); } HBRUSH CXTPPropertyPage::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hBrush = CPropertyPage::OnCtlColor(pDC, pWnd, nCtlColor); if ((nCtlColor == CTLCOLOR_BTN || nCtlColor == CTLCOLOR_DLG || nCtlColor == CTLCOLOR_STATIC) && m_pSheet) { HBRUSH hPageBrush = m_pSheet->GetNavigator()->GetPageBrush(pDC, this); if (hPageBrush) { CXTPWindowRect rcPaint(pWnd); CXTPWindowRect rcBrush(m_hWnd); ::SetBrushOrgEx(pDC->GetSafeHdc(), rcBrush.left - rcPaint.left, rcBrush.top - rcPaint.top, NULL); ::SetBkMode(pDC->GetSafeHdc(), TRANSPARENT); return hPageBrush; } } return hBrush; } LRESULT CXTPPropertyPage::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class return CPropertyPage::WindowProc(message, wParam, lParam); } BOOL CXTPPropertyPage::OnInitDialog() { CPropertyPage::OnInitDialog(); CXTPResize::Init(); return TRUE; } void CXTPPropertyPage::AdjustResizeRect(CSize& szWindow) { CSize szMin = m_totalDev; szWindow.cx = max(szWindow.cx, szMin.cx); szWindow.cy = max(szWindow.cy, szMin.cy); } void CXTPPropertyPage::OnSize(UINT nType, int cx, int cy) { CPropertyPage::OnSize(nType, cx, cy); // UpdateBars() handles locking out recursion UpdateBars(); CXTPResize::Size(); } void CXTPPropertyPage::GetScrollBarSizes(CSize& sizeSb) { sizeSb.cx = sizeSb.cy = 0; DWORD dwStyle = GetStyle(); if (GetScrollBarCtrl(SB_VERT) == NULL) { // vert scrollbars will impact client area of this window sizeSb.cx = GetSystemMetrics(SM_CXVSCROLL); if (dwStyle & WS_BORDER) sizeSb.cx -= CX_BORDER; } if (GetScrollBarCtrl(SB_HORZ) == NULL) { // horz scrollbars will impact client area of this window sizeSb.cy = GetSystemMetrics(SM_CYHSCROLL); if (dwStyle & WS_BORDER) sizeSb.cy -= CY_BORDER; } } BOOL CXTPPropertyPage::GetTrueClientSize(CSize& size, CSize& sizeSb) // return TRUE if enough room to add scrollbars if needed { CRect rect; GetClientRect(&rect); _ASSERTE(rect.top == 0 && rect.left == 0); size.cx = rect.right; size.cy = rect.bottom; DWORD dwStyle = GetStyle(); // first get the size of the scrollbars for this window GetScrollBarSizes(sizeSb); // first calculate the size of a potential scrollbar // (scroll bar controls do not get turned on/off) if (sizeSb.cx != 0 && (dwStyle & WS_VSCROLL)) { // vert scrollbars will impact client area of this window size.cx += sizeSb.cx; // currently on - adjust now } if (sizeSb.cy != 0 && (dwStyle & WS_HSCROLL)) { // horz scrollbars will impact client area of this window size.cy += sizeSb.cy; // currently on - adjust now } // return TRUE if enough room return (size.cx > sizeSb.cx && size.cy > sizeSb.cy); } CPoint CXTPPropertyPage::GetDeviceScrollPosition() const { CPoint pt(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT)); _ASSERTE(pt.x >= 0 && pt.y >= 0); return pt; } // helper to return the state of the scrollbars without actually changing // the state of the scrollbars void CXTPPropertyPage::GetScrollBarState(CSize sizeClient, CSize& needSb, CSize& sizeRange, CPoint& ptMove, BOOL bInsideClient) { // get scroll bar sizes (the part that is in the client area) CSize sizeSb; GetScrollBarSizes(sizeSb); // enough room to add scrollbars sizeRange = m_totalDev - sizeClient; // > 0 => need to scroll ptMove = GetDeviceScrollPosition(); // point to move to (start at current scroll pos) BOOL bNeedH = sizeRange.cx > 0; if (!bNeedH) ptMove.x = 0; // jump back to origin else if (bInsideClient) sizeRange.cy += sizeSb.cy; // need room for a scroll bar BOOL bNeedV = sizeRange.cy > 0; if (!bNeedV) ptMove.y = 0; // jump back to origin else if (bInsideClient) sizeRange.cx += sizeSb.cx; // need room for a scroll bar if (bNeedV && !bNeedH && sizeRange.cx > 0) { _ASSERTE(bInsideClient); // need a horizontal scrollbar after all bNeedH = TRUE; sizeRange.cy += sizeSb.cy; } // if current scroll position will be past the limit, scroll to limit if (sizeRange.cx > 0 && ptMove.x >= sizeRange.cx) ptMove.x = sizeRange.cx; if (sizeRange.cy > 0 && ptMove.y >= sizeRange.cy) ptMove.y = sizeRange.cy; // now update the bars as appropriate needSb.cx = bNeedH; needSb.cy = bNeedV; // needSb, sizeRange, and ptMove area now all updated } void CXTPPropertyPage::ScrollToDevicePosition(POINT ptDev) { _ASSERTE(ptDev.x >= 0); _ASSERTE(ptDev.y >= 0); // Note: ScrollToDevicePosition can and is used to scroll out-of-range // areas as far as CXTPPropertyPage is concerned -- specifically in // the print-preview code. Since OnScrollBy makes sure the range is // valid, ScrollToDevicePosition does not vector through OnScrollBy. int xOrig = GetScrollPos(SB_HORZ); SetScrollPos(SB_HORZ, ptDev.x); int yOrig = GetScrollPos(SB_VERT); SetScrollPos(SB_VERT, ptDev.y); ScrollPage(xOrig - ptDev.x, yOrig - ptDev.y); } void CXTPPropertyPage::ScrollPage(int xAmount, int yAmount) { if (xAmount == 0 && yAmount == 0) return; ScrollWindow(xAmount, yAmount); for (int i = 0; i < (int)m_arrItems.GetSize(); i++) { CXTPResizeRect& rrcWindow = m_arrItems[i]->m_rrcWindow; rrcWindow.left += static_cast(xAmount); rrcWindow.right += static_cast(xAmount); rrcWindow.top += static_cast(yAmount); rrcWindow.bottom += static_cast(yAmount); } } void CXTPPropertyPage::UpdateBars() { if (m_totalDev == CSize(0, 0) || !m_bCreated) return; // UpdateBars may cause window to be resized - ignore those resizings if (m_bInsideUpdate) return; // Do not allow recursive calls // Lock out recursion m_bInsideUpdate = TRUE; // update the horizontal to reflect reality // NOTE: turning on/off the scrollbars will cause 'OnSize' callbacks _ASSERTE(m_totalDev.cx >= 0 && m_totalDev.cy >= 0); CRect rectClient; BOOL bCalcClient = TRUE; CSize sizeClient; CSize sizeSb; // get client rect if (!GetTrueClientSize(sizeClient, sizeSb)) { // no room for scroll bars (common for zero sized elements) CRect rect; GetClientRect(&rect); if (rect.right > 0 && rect.bottom > 0) { // if entire client area is not invisible, assume we have // control over our scrollbars EnableScrollBarCtrl(SB_BOTH, FALSE); } m_bInsideUpdate = FALSE; return; } // enough room to add scrollbars CSize sizeRange; CPoint ptMove; CSize needSb; // get the current scroll bar state given the true client area GetScrollBarState(sizeClient, needSb, sizeRange, ptMove, bCalcClient); if (needSb.cx) sizeClient.cy -= sizeSb.cy; if (needSb.cy) sizeClient.cx -= sizeSb.cx; // first scroll the window as needed ScrollToDevicePosition(ptMove); // will set the scroll bar positions too // this structure needed to update the scrollbar page range SCROLLINFO info = { 0 }; info.fMask = SIF_PAGE | SIF_RANGE; info.nMin = 0; // now update the bars as appropriate EnableScrollBarCtrl(SB_HORZ, needSb.cx); if (needSb.cx) { info.nPage = XTPToUIntChecked(sizeClient.cx); info.nMax = m_totalDev.cx - 1; if (!SetScrollInfo(SB_HORZ, &info, TRUE)) SetScrollRange(SB_HORZ, 0, sizeRange.cx, TRUE); } EnableScrollBarCtrl(SB_VERT, needSb.cy); if (needSb.cy) { info.nPage = XTPToUIntChecked(sizeClient.cy); info.nMax = m_totalDev.cy - 1; if (!SetScrollInfo(SB_VERT, &info, TRUE)) SetScrollRange(SB_VERT, 0, sizeRange.cy, TRUE); } // remove recursion lockout m_bInsideUpdate = FALSE; } void CXTPPropertyPage::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg()) return; // eat it // ignore scroll bar msgs from other controls if (pScrollBar != GetScrollBarCtrl(SB_HORZ)) return; OnScroll(MAKEWORD(nSBCode, -1), nPos); } void CXTPPropertyPage::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg()) return; // eat it // ignore scroll bar msgs from other controls if (pScrollBar != GetScrollBarCtrl(SB_VERT)) return; OnScroll(MAKEWORD(-1, nSBCode), nPos); } BOOL CXTPPropertyPage::OnMouseWheel(UINT fFlags, short zDelta, CPoint point) { // we don't handle anything but scrolling just now if (fFlags & (MK_SHIFT | MK_CONTROL)) return FALSE; // we can't get out of it--perform the scroll ourselves return DoMouseWheel(fFlags, zDelta, point); } // This function isn't virtual. If you need to override it, // you really need to override OnMouseWheel() here or in // CSplitterWnd. BOOL CXTPPropertyPage::DoMouseWheel(UINT fFlags, short zDelta, CPoint point) { UNUSED_ALWAYS(point); UNUSED_ALWAYS(fFlags); // if we have a vertical scroll bar, the wheel scrolls that // if we have _only_ a horizontal scroll bar, the wheel scrolls that // otherwise, don't do any work at all DWORD dwStyle = GetStyle(); CScrollBar* pBar = GetScrollBarCtrl(SB_VERT); BOOL bHasVertBar = ((pBar != NULL) && pBar->IsWindowEnabled()) || (dwStyle & WS_VSCROLL); pBar = GetScrollBarCtrl(SB_HORZ); BOOL bHasHorzBar = ((pBar != NULL) && pBar->IsWindowEnabled()) || (dwStyle & WS_HSCROLL); if (!bHasVertBar && !bHasHorzBar) return FALSE; BOOL bResult = FALSE; UINT uWheelScrollLines = 3; if (bHasVertBar) { bResult = OnScrollBy(CSize(0, (zDelta < 0 ? 1 : -1) * m_lineDev.cy * XTPToIntChecked(uWheelScrollLines)), TRUE); } else if (bHasHorzBar) { bResult = OnScrollBy( CSize((zDelta < 0 ? 1 : -1) * m_lineDev.cy * XTPToIntChecked(uWheelScrollLines), 0), TRUE); } if (bResult) UpdateWindow(); return bResult; } BOOL CXTPPropertyPage::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) { // calc new x position int x = GetScrollPos(SB_HORZ); int xOrig = x; switch (LOBYTE(nScrollCode)) { case SB_TOP: x = 0; break; case SB_BOTTOM: x = INT_MAX; break; case SB_LINEUP: x -= m_lineDev.cx; break; case SB_LINEDOWN: x += m_lineDev.cx; break; case SB_PAGEUP: x -= CXTPClientRect(this).Width(); break; case SB_PAGEDOWN: x += CXTPClientRect(this).Width(); break; case SB_THUMBTRACK: x = XTPToIntChecked(nPos); break; } // calc new y position int y = GetScrollPos(SB_VERT); int yOrig = y; switch (HIBYTE(nScrollCode)) { case SB_TOP: y = 0; break; case SB_BOTTOM: y = INT_MAX; break; case SB_LINEUP: y -= m_lineDev.cy; break; case SB_LINEDOWN: y += m_lineDev.cy; break; case SB_PAGEUP: y -= CXTPClientRect(this).Height(); break; case SB_PAGEDOWN: y += CXTPClientRect(this).Height(); break; case SB_THUMBTRACK: y = XTPToIntChecked(nPos); break; } BOOL bResult = OnScrollBy(CSize(x - xOrig, y - yOrig), bDoScroll); if (bResult && bDoScroll) UpdateWindow(); return bResult; } BOOL CXTPPropertyPage::OnScrollBy(CSize sizeScroll, BOOL bDoScroll) { int xOrig, x; int yOrig, y; // don't scroll if there is no valid scroll range (ie. no scroll bar) CScrollBar* pBar; DWORD dwStyle = GetStyle(); pBar = GetScrollBarCtrl(SB_VERT); if ((pBar != NULL && !pBar->IsWindowEnabled()) || (pBar == NULL && !(dwStyle & WS_VSCROLL))) { // vertical scroll bar not enabled sizeScroll.cy = 0; } pBar = GetScrollBarCtrl(SB_HORZ); if ((pBar != NULL && !pBar->IsWindowEnabled()) || (pBar == NULL && !(dwStyle & WS_HSCROLL))) { // horizontal scroll bar not enabled sizeScroll.cx = 0; } // adjust current x position xOrig = x = GetScrollPos(SB_HORZ); int xMax = GetScrollLimit(SB_HORZ); x += sizeScroll.cx; if (x < 0) x = 0; else if (x > xMax) x = xMax; // adjust current y position yOrig = y = GetScrollPos(SB_VERT); int yMax = GetScrollLimit(SB_VERT); y += sizeScroll.cy; if (y < 0) y = 0; else if (y > yMax) y = yMax; // did anything change? if (x == xOrig && y == yOrig) return FALSE; if (bDoScroll) { // do scroll and update scroll positions ScrollPage(-(x - xOrig), -(y - yOrig)); if (x != xOrig) SetScrollPos(SB_HORZ, x); if (y != yOrig) SetScrollPos(SB_VERT, y); } return TRUE; } void CXTPPropertyPage::OnNcPaint() { Default(); if (!m_pSheet) return; CWindowDC dc(this); CXTPWindowRect rcPage(this); rcPage.OffsetRect(-rcPage.TopLeft()); COLORREF clrListBoxBack = RGB(0, 0, 0); COLORREF clrListBoxBorder = RGB(0, 0, 0); BOOL bThemeEnabled = m_pSheet->GetNavigator()->GetTheme() != xtpControlThemeDefault ? TRUE : FALSE; if (bThemeEnabled) { clrListBoxBack = XTPIniColor(_T("Controls.ListBox"), _T("Back"), GetXtremeColor(COLOR_WINDOW)); clrListBoxBorder = XTPIniColor(_T("Controls.ListBox"), _T("Border"), GetXtremeColor(COLOR_WINDOWFRAME)); } if (m_pSheet->GetPageBorderStyle() == xtpPageBorderFrame) { BOOL bFrame = FALSE; CXTPWinThemeWrapper wrpTreeView; wrpTreeView.OpenThemeData(NULL, L"LISTBOX"); if (wrpTreeView.IsAppThemeActive()) { COLORREF clr; if (SUCCEEDED(wrpTreeView.GetThemeColor(0, 0, TMT_BORDERCOLOR, &clr))) { dc.Draw3dRect(rcPage, bThemeEnabled ? clrListBoxBorder : clr, bThemeEnabled ? clrListBoxBorder : clr); rcPage.DeflateRect(1, 1); dc.Draw3dRect(rcPage, bThemeEnabled ? clrListBoxBack : GetXtremeColor(COLOR_WINDOW), bThemeEnabled ? clrListBoxBack : GetXtremeColor(COLOR_WINDOW)); rcPage.DeflateRect(1, 1); bFrame = TRUE; } } if (!bFrame) { dc.DrawEdge(rcPage, EDGE_SUNKEN, BF_RECT); rcPage.DeflateRect(2, 2); } } else if (m_pSheet->GetPageBorderStyle() == xtpPageBorderBottomLine) { dc.FillSolidRect(rcPage.left, rcPage.bottom - 2, rcPage.Width(), 1, bThemeEnabled ? clrListBoxBack : GetXtremeColor(COLOR_BTNSHADOW)); dc.FillSolidRect(rcPage.left, rcPage.bottom - 1, rcPage.Width(), 1, bThemeEnabled ? clrListBoxBorder : GetXtremeColor(COLOR_BTNHIGHLIGHT)); rcPage.DeflateRect(0, 0, 0, 2); } if ((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) == (WS_HSCROLL | WS_VSCROLL)) { CRect rcSizeIcon(rcPage.right - GetSystemMetrics(SM_CXVSCROLL), rcPage.bottom - GetSystemMetrics(SM_CYHSCROLL), rcPage.right, rcPage.bottom); HBRUSH hBrush = m_pSheet->GetNavigator()->GetPageBrush(&dc, this); if (hBrush) { CXTPClientRect rc(this); ::FillRect(dc, rcSizeIcon, hBrush); } else { dc.FillSolidRect(rcSizeIcon, GetXtremeColor(COLOR_3DFACE)); } } } void CXTPPropertyPage::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) { if (!m_pSheet) { CPropertyPage::OnNcCalcSize(bCalcValidRects, lpncsp); return; } if (m_pSheet->GetPageBorderStyle() == xtpPageBorderFrame) { RECT& rc = lpncsp->rgrc[0]; rc.left += 2; rc.top += 2; rc.right -= 2; rc.bottom -= 2; } if (m_pSheet->GetPageBorderStyle() == xtpPageBorderBottomLine) { lpncsp->rgrc[0].bottom -= 2; } CWnd::OnNcCalcSize(bCalcValidRects, lpncsp); } void CXTPPropertyPage::OnChildSetFocus(HWND hWndFocus) { if ((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) == 0) return; CWnd* pWnd = CWnd::FromHandle(hWndFocus); if (!pWnd) return; CRect rc; pWnd->GetWindowRect(rc); ScreenToClient(rc); CXTPClientRect rcClient(this); CSize szScroll(0, 0); if (rc.bottom > rcClient.bottom) szScroll.cy = rc.bottom - rcClient.bottom; if (rc.top - szScroll.cy < rcClient.top) szScroll.cy = rc.top - rcClient.top; if (rc.right > rcClient.right) szScroll.cx = rc.right - rcClient.right; if (rc.left - szScroll.cx < rcClient.left) szScroll.cx = rc.left - rcClient.left; if (szScroll != CSize(0, 0)) { OnScrollBy(szScroll, TRUE); } } ////////////////////////////////////////////////////////////////////////// // CXTPPropertyPageCaption CXTPPropertyPageStaticCaption::CXTPPropertyPageStaticCaption(){ }; #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPPropertyPageStaticCaption, CWnd) ON_WM_PAINT() ON_WM_ERASEBKGND() END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" BOOL CXTPPropertyPageStaticCaption::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; } void CXTPPropertyPageStaticCaption::OnPaint() { CPaintDC dcPaint(this); CXTPBufferDC dc(dcPaint); CXTPClientRect rc(this); dc.FillSolidRect(rc, RGB(221, 231, 238)); dc.FillSolidRect(rc.left, rc.bottom - 1, rc.Width(), 1, RGB(197, 197, 197)); rc.DeflateRect(XTP_DPI_X(7), 0); CString strText; GetWindowText(strText); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(RGB(0, 21, 110)); CXTPFontDC font(&dc, &XTPAuxData().xtpFontBold); dc.DrawText(strText, rc, DT_VCENTER | DT_SINGLELINE); } void CXTPPropertyPage::UpdatePage(void) { // By default do nothing }