Esempio n. 1
0
Size Grid::Measure(const Size availableSize) {
    RebuildCellDataIfNeeded();

    Size borderSize(GetBorderAndPaddingSize(cachedStyle));

    Cell* cell;
    Control* el;
    for (Grid::CellData& d : els) {
        cell = GetCell(d.row, d.col);
        cell->desiredSize.Width = 0;
        cell->desiredSize.Height = 0;
        el = d.el;
        if (!el->IsVisible())
            continue;

        // calculate max dx of each column (dx of widest cell in the row)
        //  and max dy of each row (dy of tallest cell in the column)
        el->Measure(availableSize);

        // TODO: take cell's border and padding into account

        cell->desiredSize = el->DesiredSize();
        // if a cell spans multiple columns, we don't count its size here
        if (d.colSpan == 1) {
            if (cell->desiredSize.Width > maxColWidth[d.col])
                maxColWidth[d.col] = cell->desiredSize.Width;
        }
        if (cell->desiredSize.Height > maxRowHeight[d.row])
            maxRowHeight[d.row] = cell->desiredSize.Height;
    }

    // account for cells with colSpan > 1. If cell.dx > total dx
    // of columns it spans, we widen the columns by equally
    // re-distributing the difference among columns
    for (Grid::CellData& d : els) {
        if (d.colSpan == 1)
            continue;
        cell = GetCell(d.row, d.col);

        int totalDx = 0;
        for (int i = d.col; i < d.col + d.colSpan; i++) {
            totalDx += maxColWidth[i];
        }
        int diff = cell->desiredSize.Width - totalDx;
        if (diff > 0) {
            int diffPerCol = diff / d.colSpan;
            int rest = diff % d.colSpan;
            // note: we could try to redistribute rest for ideal sizing instead of
            // over-sizing but not sure if that would matter in practice
            if (rest > 0)
                diffPerCol += 1;
            CrashIf(diffPerCol * d.colSpan < diff);
            for (int i = d.col; i < d.col + d.colSpan; i++) {
                maxColWidth[i] += diffPerCol;
            }
        }
    }

    int desiredWidth = 0;
    int desiredHeight = 0;
    for (int row = 0; row < rows; row++) {
        desiredHeight += maxRowHeight[row];
    }
    for (int col = 0; col < cols; col++) {
        desiredWidth += maxColWidth[col];
    }
    // TODO: what to do if desired size is more than availableSize?
    desiredSize.Width = desiredWidth + borderSize.Width;
    desiredSize.Height = desiredHeight + borderSize.Height;
    return desiredSize;
}
void CBitmapControl::Paint(HDC hDC, const UiRect& rcPaint)
{
	try
	{
		if( !::IntersectRect( &m_rcPaint, &rcPaint, &m_rcItem ) ) 
			return;
		Control::Paint(hDC, rcPaint);
		//paint bitmap
		if (width_ * height_ > 0)
		{
			int item_w = m_rcItem.right-m_rcItem.left;
			int item_h = m_rcItem.bottom-m_rcItem.top;
			int item_x = m_rcItem.left;
			int item_y = m_rcItem.top;
			int source_w = width_;
			int source_h = height_;
			if (source_w > 0 && source_h > 0 && parent_wnd_)
			{
				//居中
				item_x += (item_w - source_w) / 2;
				item_y += (item_h - source_h) / 2;
				UiRect rcClient;
				::GetClientRect(parent_wnd_->GetHWND(), &rcClient);
				int width = rcClient.right - rcClient.left;
				int height = rcClient.bottom - rcClient.top;

				//计算实际绘制区域坐标
				int draw_x = max(rcPaint.left, item_x);
				draw_x = max(m_rcItem.left, draw_x);
				int draw_y = max(rcPaint.top, item_y);
				draw_y = max(m_rcItem.top, draw_y);
				int draw_h = min(rcPaint.bottom - draw_y, min(item_y + source_h, m_rcItem.bottom) - draw_y);
				draw_h = max(draw_h, 0);
				int src_x = draw_x - item_x;
				int src_y = draw_y - item_y;
				int src_w = min(rcPaint.right - draw_x, min(item_x + source_w, m_rcItem.right) - draw_x);
				src_w = max(src_w, 0);

				int dest_byte_width = width * 4;
				int src_byte_width = source_w * 4;
				int paint_byte_width = src_w * 4;
				char* dest_data = (char*)parent_wnd_->GetBits();
				int bottom = height - draw_y - 1;
				dest_data += bottom * dest_byte_width + draw_x * 4;
				char* src_data = (char*)data_.c_str();
				src_data += src_y * src_byte_width + src_x * 4;
				for (int i = 0; i < draw_h; ++i)
				{
					memcpy(dest_data, src_data, paint_byte_width);
					dest_data -= dest_byte_width;
					src_data += src_byte_width;
				}
			}
		}
		//绘制子控件
		for( auto it = m_items.begin(); it != m_items.end(); it++ )
		{
			Control* pControl = *it;
			if( !pControl->IsVisible() ) continue;
			UiRect controlPos = pControl->GetPos();
			if( !::IntersectRect( &m_rcPaint, &rcPaint, &controlPos ) ) continue;
			pControl->AlphaPaint( hDC, rcPaint );
		}
	}
	catch (...)
	{
		throw "CBitmapControl::DoPaint";
	}
}