void CResizableLayout::AddAnchor(HWND hWnd, CSize sizeTypeTL, CSize sizeTypeBR) { CWnd* pParent = GetResizableWnd(); // child window must be valid ASSERT(::IsWindow(hWnd)); // must be child of parent window // ASSERT(::IsChild(pParent->GetSafeHwnd(), hWnd)); // top-left anchor must be valid ASSERT(sizeTypeTL != NOANCHOR); // get control's window class CString sClassName; GetClassName(hWnd, sClassName.GetBufferSetLength(MAX_PATH), MAX_PATH); sClassName.ReleaseBuffer(); // get parent window's rect CRect rectParent; GetTotalClientRect(&rectParent); // and child control's rect CRect rectChild; ::GetWindowRect(hWnd, &rectChild); ::MapWindowPoints(NULL, pParent->m_hWnd, (LPPOINT)&rectChild, 2); // adjust position, if client area has been scrolled rectChild.OffsetRect(-rectParent.TopLeft()); // go calculate margins CSize sizeMarginTL, sizeMarginBR; if (sizeTypeBR == NOANCHOR) sizeTypeBR = sizeTypeTL; // calculate margin for the top-left corner sizeMarginTL.cx = rectChild.left - rectParent.Width() * sizeTypeTL.cx / 100; sizeMarginTL.cy = rectChild.top - rectParent.Height() * sizeTypeTL.cy / 100; // calculate margin for the bottom-right corner sizeMarginBR.cx = rectChild.right - rectParent.Width() * sizeTypeBR.cx / 100; sizeMarginBR.cy = rectChild.bottom - rectParent.Height() * sizeTypeBR.cy / 100; // prepare the structure LayoutInfo layout(hWnd, sizeTypeTL, sizeMarginTL, sizeTypeBR, sizeMarginBR, sClassName); // initialize resize properties (overridable) InitResizeProperties(layout); // must not be already there! // (this is probably due to a duplicate call to AddAnchor) POSITION pos; ASSERT(!m_mapLayout.Lookup(hWnd, pos)); // add to the list and the map pos = m_listLayout.AddTail(layout); m_mapLayout.SetAt(hWnd, pos); }
/*! * This function adds a new control to the layout manager and sets anchor * points for its top-left and bottom-right corners. * * @param hWnd Window handle to the control to be added * @param anchorTopLeft Anchor point for the top-left corner * @param anchorBottomRight Anchor point for the bottom-right corner * * @remarks Overlapping controls, like group boxes and the controls inside, * must be added from the outer controls to the inner ones, to let * the clipping routines work correctly. * * @sa AddAnchorCallback RemoveAnchor */ void CResizableLayout::AddAnchor(HWND hWnd, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight) { CWnd* pParent = GetResizableWnd(); // child window must be valid ASSERT(::IsWindow(hWnd)); // must be child of parent window ASSERT(::IsChild(pParent->GetSafeHwnd(), hWnd)); // get parent window's rect CRect rectParent; GetTotalClientRect(&rectParent); // and child control's rect CRect rectChild; ::GetWindowRect(hWnd, &rectChild); ::MapWindowPoints(NULL, pParent->m_hWnd, (LPPOINT)&rectChild, 2); // adjust position, if client area has been scrolled rectChild.OffsetRect(-rectParent.TopLeft()); // go calculate margins CSize marginTopLeft, marginBottomRight; // calculate margin for the top-left corner marginTopLeft.cx = rectChild.left - rectParent.Width() * anchorTopLeft.cx / 100; marginTopLeft.cy = rectChild.top - rectParent.Height() * anchorTopLeft.cy / 100; // calculate margin for the bottom-right corner marginBottomRight.cx = rectChild.right - rectParent.Width() * anchorBottomRight.cx / 100; marginBottomRight.cy = rectChild.bottom - rectParent.Height() * anchorBottomRight.cy / 100; // prepare the structure LAYOUTINFO layout(hWnd, anchorTopLeft, marginTopLeft, anchorBottomRight, marginBottomRight); // get control's window class GetClassName(hWnd, layout.sWndClass, MAX_PATH); // initialize resize properties (overridable) InitResizeProperties(layout); // must not be already there! // (this is probably due to a duplicate call to AddAnchor) POSITION pos; ASSERT(!m_mapLayout.Lookup(hWnd, pos)); // add to the list and the map pos = m_listLayout.AddTail(layout); m_mapLayout.SetAt(hWnd, pos); }