Beispiel #1
0
//////////////////
// Get min/max info. 
//
void CWinMgr::GetMinMaxInfo(CWnd* pWnd, SIZEINFO& szi) {
	OnGetSizeInfo(szi, m_map, pWnd);  // get size info
	if (!pWnd->m_hWnd)					 // window not created ==> done
		return;

	// Add extra space for frame/dialog screen junk.
	DWORD dwStyle = pWnd->GetStyle();
	DWORD dwExStyle = pWnd->GetExStyle();
	if (dwStyle & WS_VISIBLE) {
		SIZE& szMin = szi.szMin; // ref!
		if (!(dwStyle & WS_CHILD)) {
			if (dwStyle & WS_CAPTION)
				szMin.cy += GetSystemMetrics(SM_CYCAPTION);
			if (::GetMenu(pWnd->m_hWnd))
				szMin.cy += GetSystemMetrics(SM_CYMENU);
		}
		if (dwStyle & WS_THICKFRAME) {
			szMin.cx += 2*GetSystemMetrics(SM_CXSIZEFRAME);
			szMin.cy += 2*GetSystemMetrics(SM_CYSIZEFRAME);
		} else if (dwStyle & WS_BORDER) {
			szMin.cx += 2*GetSystemMetrics(SM_CXBORDER);
			szMin.cy += 2*GetSystemMetrics(SM_CYBORDER);
		}
		if (dwExStyle & WS_EX_CLIENTEDGE) {
			szMin.cx += 2*GetSystemMetrics(SM_CXEDGE);
			szMin.cy += 2*GetSystemMetrics(SM_CYEDGE);
		}
	}
}
Beispiel #2
0
//////////////////
// Adjust the size of a single entry upwards to its desired size.
// Decrement hwRemaining by amount increased.
//
void
CWinMgr::AdjustSize(WINRECT* wrc, BOOL bRow,
	int& hwRemaining, HWND hWnd)
{
	SIZEINFO szi;
	OnGetSizeInfo(szi, wrc, hWnd);
	int hw = bRow ? szi.szDesired.cy : szi.szDesired.cx; // desired ht or wid
	if (wrc->Type() == WRCT_REST) {
		// for REST type, use all remaining space
		RECT& rc = wrc->GetRect();
		hw = hwRemaining + (bRow ? RectHeight(rc) : RectWidth(rc));
	}

	// Now hw is the desired height or width, and the current size of the
	// entry is the min size. So adjust the size upwards, and decrement
	// hwRemaining appropriately. This is a little confusing, but necessary so
	// each entry gets its min size.
	//
	int hwCurrent = wrc->GetHeightOrWidth(bRow); // current size
	int hwExtra = hw - hwCurrent;						// amount extra
	hwExtra = min(max(hwExtra, 0), hwRemaining);	// truncate
	hw = hwCurrent + hwExtra;							// new height-or-width
	wrc->SetHeightOrWidth(hw, bRow);				// set...
	hwRemaining -= hwExtra;								// and adjust remaining
}
Beispiel #3
0
//////////////////
// Get size information for a single entry (WINRECT). Returns size info in
// the SIZEINFO argument. For a group, calculate size info as aggregate of
// subentries.
//
void CWinMgr::OnGetSizeInfo(SIZEINFO& szi, WINRECT* wrc, CWnd* pWnd) {
	szi.szMin = SIZEZERO;				// default min size = zero
	szi.szMax = SIZEMAX;					// default max size = infinite
	szi.szDesired = wrc->GetRect().Size();	// default desired size = current 

	if (wrc->IsGroup()) {
		// For groups, calculate min, max, desired size as aggregate of children
		szi.szDesired = SIZEZERO;
		BOOL bRow = wrc->IsRowGroup();

		CWinGroupIterator it;
		for (it=wrc; it; it.Next()) {
			WINRECT* wrc2 = it;
			SIZEINFO szi2;
			OnGetSizeInfo(szi2, wrc2, pWnd);
			if (bRow) {
				szi.szMin.cx = max(szi.szMin.cx, szi2.szMin.cx);
				szi.szMin.cy += szi2.szMin.cy;
				szi.szMax.cx = min(szi.szMax.cx, szi2.szMax.cx);
				szi.szMax.cy = min(szi.szMax.cy + szi2.szMax.cy, _INFINITY);
				szi.szDesired.cx = max(szi.szDesired.cx, szi2.szDesired.cx);
				szi.szDesired.cy += szi2.szDesired.cy;

			} else {
				szi.szMin.cx += szi2.szMin.cx;
				szi.szMin.cy = max(szi.szMin.cy, szi2.szMin.cy);
				szi.szMax.cx = min(szi.szMax.cx + szi2.szMax.cx, _INFINITY);
				szi.szMax.cy = min(szi.szMax.cy, szi2.szMax.cy);
				szi.szDesired.cx += szi2.szDesired.cx;
				szi.szDesired.cy = max(szi.szDesired.cy, szi2.szDesired.cy);
			}
		}

		// Add margins. 
		int w2,h2;
		wrc->GetMargins(w2,h2);			// get margins
		w2<<=1; h2<<=1;					// double
		szi.szMin.cx += max(0,w2);		// negative margins ==> don't include in min
		szi.szMin.cy += max(0,h2);		// ditto
		szi.szDesired.cx += abs(w2);	// for desired size, use abs vallue
		szi.szDesired.cy += abs(h2);	// ditto

	} else {
		// not a group
		WINRECT* parent = wrc->Parent();
		ASSERT(parent);
		CRect& rcParent = parent->GetRect();
		BOOL bRow = parent->IsRowGroup();
		int hw, hwMin, hwTotal, pct;

		switch (wrc->Type()) {
		case WRCT_FIXED:
			hw = hwMin = wrc->GetParam();	 // ht/wid is parameter
			if (hw<0) {							 // if fixed val is negative:
				hw = -hw;						 // use absolute val for desired..
				hwMin = 0;						 // ..and zero for minimum
			}
			if (bRow) {
				szi.szMax.cy = szi.szDesired.cy = hw;
				szi.szMin.cy = hwMin;
			} else {
				szi.szMax.cx = szi.szDesired.cx = hw;
				szi.szMin.cx = hwMin;
			}
			break;

		case WRCT_PCT:
			pct = wrc->GetParam();
			ASSERT(0<pct && pct<100);
			hwTotal = bRow ? rcParent.Height() : rcParent.Width();
			hw = (hwTotal * pct) / 100;
			szi.szDesired = bRow ? CSize(rcParent.Width(), hw) :
				CSize(hw, rcParent.Height());
			break;

		case WRCT_TOFIT:
			if (wrc->HasToFitSize()) {
				szi.szDesired = wrc->GetToFitSize();
			}
			break;

		case WRCT_REST:
			break;

		default:
			ASSERT(FALSE);
		}

		// If the entry is a window, send message to get min/max/tofit size.
		// Only set tofit size if type is TOFIT.
		//
		if (wrc->IsWindow() && pWnd) {
			CWnd* pChild = pWnd->GetDlgItem(wrc->GetID());
			if (pChild) {
				if (!pChild->IsWindowVisible() && pWnd->IsWindowVisible()) {
					// parent visible but child not ==> tofit size is zero
					// important so hidden windows use no space
					szi.szDesired = SIZEZERO;
				} else {
					szi.szAvail = rcParent.Size();
					SendGetSizeInfo(szi, pWnd, wrc->GetID());
				}
			}
		}
		szi.szDesired = maxsize(minsize(szi.szDesired,szi.szMax), szi.szMin);
	}
}
Beispiel #4
0
//////////////////
// Calculate size/positions for a row or column group This is the main
// algorithm. If a window is given, it's used to get the min/max size and
// desired size for TOFIT types.
//
void CWinMgr::CalcGroup(WINRECT* pGroup, CWnd* pWnd) {
	// If this bombs, most likely the first entry in your map is not a group!
	ASSERT(pGroup && pGroup->IsGroup());
	ASSERT(pWnd);

	// adjust total avail by margins
	CRect rcTotal = pGroup->GetRect();
	int w,h;
	if (pGroup->GetMargins(w,h)) {
		w = min(abs(w), rcTotal.Width()/2);
		h = min(abs(h), rcTotal.Height()/2);
		rcTotal.DeflateRect(w,h);
	}
	
	BOOL bRow = pGroup->IsRowGroup();		 // Is this a row group?

	// Running height or width: start with total
	int hwRemaining = bRow ? rcTotal.Height() : rcTotal.Width();

	// First, set all rects to their minimum sizes.
	// This ensures that each rect gets its min size.
	CWinGroupIterator it;
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		SIZEINFO szi;
		OnGetSizeInfo(szi, wrc, pWnd);
		int hwMin = bRow ? szi.szMin.cy : szi.szMin.cx;
		hwMin = min(hwMin, hwRemaining);		// truncate
		wrc->SetHeightOrWidth(hwMin, bRow);	// set
		hwRemaining -= hwMin;					// decrement remaining height/width
		ASSERT(hwRemaining>=0);
	}

	// Now adjust all rects upward to desired size. Save REST rect for last.
	WINRECT* pRestRect = NULL;
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		if (wrc->Type()==WRCT_REST) {
			ASSERT(pRestRect==NULL);		 // can only be one REST rect!
			pRestRect = wrc;					 // remember it
		} else {
			AdjustSize(wrc, bRow, hwRemaining, pWnd);
		}
	}
	ASSERT(hwRemaining>=0);

	// Adjust REST rect if any
	if (pRestRect) {
		AdjustSize(pRestRect, bRow, hwRemaining, pWnd);
		ASSERT(hwRemaining==0);
	}

	// All the sizes of the entries have been calculated, including
	// groups (but not their children). Now move all the rects so they're
	// adjacent to one another, without altering sizes.
	PositionRects(pGroup, rcTotal, bRow);

	// Finally, descend recursively into each subgroup.
	for (it=pGroup; it; it.Next()) {
		WINRECT* wrc = it;
		if (wrc->IsGroup())
			CalcGroup(wrc, pWnd); // recurse!
	}
}