C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Необычный DBGrid, Создание объединяющих заголовков
** Pan-SQL
Отправлено: 03.06.2006, 10:55


Не зарегистрирован







Здравствуйте уважаемые участники форума! Подскажите, как создать объединяющие заголовки в Gride. это должно выглядеть вот так: сначала общий объединяющий заголовок, например, География, ниже заголовки столбцов, накпример, Страна, Область, Город. Очень нужно!
Заранее благодарен!
Doga
Отправлено: 03.06.2006, 13:36


Мастер участка

Группа: Участник
Сообщений: 575



Если нужен именно DB — то наверное лучше EhDbGrid из библиотеки EhLib.

А если нужен простой — то можно попробовать TRGrid, был тут такой недавно. В отличие от EhDbGridон умеет объединять ячейки любым образом.
** Pan-SQL
Отправлено: 05.06.2006, 17:57


Не зарегистрирован







Нужен именно DB. Можно как-нибудь перерисовать заголовок?
** Pan-SQL
Отправлено: 15.06.2006, 13:05


Не зарегистрирован







Я отыскал в Интернете код на Делфи он выглядит так:

объявляется массив GridTitles : : array of Boolean;

обработчик события OnDrawColumnCell:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if not GridTitles[Column.Index] then
DrawGridTitle(Column.Index);
end


Если заголовок колонки не нарисован, то нарисовать его. Процедура рисования должна определить координаты области заголовка и ее размеры и заново перерисовать эту область. Сама процедура оформлена как локальная, для того, чтобы не передавать параметры, переданные обработчику события. Для простоты заголовок делается двухстрочным, но ничего не мешает рисовать произвольное количество строк. RowCount объявлено константой и равно 2.
procedure DrawGridTitle(ColIndex : Integer);
var
Titles : array[1..RowCount] of String;
ARect : TRect; { Собственно область заголовка }
RH : Integer; { Высота области заголовка }
BlankPos : Integer; { Позиция разбиения заголовка }
begin
BlankPos := Pos(' ', Column.Title.Caption);
if BlankPos <> 0 then begin { Рисуем многострочный заголовок только для тех
колонок, у которых есть пробел в названии.
Заголовки остальных колонки DBGrid
нарисует сам. }
Titles[1] := Copy(Column.Title.Caption, 1, BlankPos-1);
Titles[2] := Copy(Column.Title.Caption, BlankPos+1,
Length(Column.Title.Caption) — BlankPos);
RH := RectHeight(Rect);
{ В прямоугольнике Rect передаются координаты текущей ячейки,
область для рисования заголовка можно получить, указывая в качестве
вертикальной координаты 0. Высота области рисования сейчас
равна высоте стандартной ячейки DBGrid, как раз на одну строку
заголовка. }
SetRect(ARect, Rect.Left, 0, Rect.Right, RH);
InflateRect(ARect, -2, -2); { Поправка на окантовку Titles }
Dec(RH, 2); { Смещение для отступа текста от края по вертикали }
with DBGrid1.Canvas do begin
Brush.Color := DBGrid1.FixedColor;
FillRect(ARect); { Залить область заголовка, стерев все, что там
нарисовано DBGrid'ом }
{ Рисование первой строки в заголовке }
ARect.Bottom := RH;
DrawText(Handle, PChar(Titles[1]), -1, ARect, DT_CENTER or DT_SINGLELINE);
{ Рисование второй строки в заголовке, предварительно сместив
область рисования вниз на размер строки. }
OffsetRect(ARect, 0, RH-2);
DrawText(Handle, PChar(Titles[2]), -1, ARect,DT_CENTER or DT_SINGLELINE);
end;
end;
GridTitles[ColIndex] := true; //Нарисовали заголовок для этой колонки
end;




Я переделал данный код с Делфи на С++:

void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{

if (!GridTitles[Column->Index])
{
AnsiString Titles[2];
TRect *rct;
int RH; // { Высота области заголовка }
int BlankPos; // { Позиция разбиения заголовка }
BlankPos = Column->Title->Caption.Pos(' ');

if (BlankPos != 0) // { Рисуем многострочный заголовок только для тех
// колонок, у которых есть пробел в названии.
// Заголовки остальных колонки DBGrid
// нарисует сам. }
{
Titles[0]=Column->Title->Caption.SubString(1,2);
Titles[1]=Column->Title->Caption.SubString(3, 7);
RH=Rect.Height();
/* { В прямоугольнике Rect передаются координаты текущей ячейки,
область для рисования заголовка можно получить, указывая в качестве
вертикальной координаты 0. Высота области рисования сейчас
равна высоте стандартной ячейки DBGrid, как раз на одну строку
заголовка. }
*/
SetRect(rct, 1, 1, 10, 10);
InflateRect(rct, -9, -9);// { Поправка на окантовку Titles }
RH=RH-1;
while (DBGrid1->Canvas)
{
Brush->Color = DBGrid1->FixedColor;
FillRect(DBGrid1->Handle, rct, (HBRUSH) (COLOR_ENDCOLORS+1));
rct->Bottom = RH;
}
DrawText( DBGrid1->Handle, "j", -1, rct, DT_CENTER || DT_SINGLELINE);
}
}
}

После запуска программы происходит исключение: Access violation at address 77E1548D in module ‘user32.dll ’. Write at address 0000004D. Подскажите, как это можно реализовать на С++. Заранее благодарен!

Doga
Отправлено: 15.06.2006, 15:27


Мастер участка

Группа: Участник
Сообщений: 575



Для указателя
CODE

TRect *rct;

память нигде не выделяется.

Но лучше сделать так:
CODE

TRect rct;
//...
SetRect(&rct, 1, 1, 10, 10);
InflateRect(&rct, -9, -9);
//...


Далее.

CODE

while (DBGrid1->Canvas)

совсем не похоже на
CODE

with DBGrid1.Canvas do


Этот отрывок кода на Паскале
CODE

with DBGrid1.Canvas do
begin
Brush.Color := DBGrid1.FixedColor;
FillRect(ARect);
ARect.Bottom := RH;
DrawText(Handle, PChar(Titles[1]), -1, ARect, DT_CENTER or DT_SINGLELINE);
OffsetRect(ARect, 0, RH-2);
DrawText(Handle, PChar(Titles[2]), -1, ARect,DT_CENTER or DT_SINGLELINE);
end;

на C++должен выглядеть так:
CODE

DBGrid1->Canvas->Brush->Color = DBGrid1->FixedColor;
DBGrid1->Canvas->FillRect(ARect);
ARect.Bottom = RH;
DrawText(DBGrid1->Canvas->Handle, Titles[1].c_str(), -1, &ARect, DT_CENTER || DT_SINGLELINE);
OffsetRect(&ARect, 0, RH-2);
DrawText(DBGrid1->Canvas->Handle, Titles[2].c_str(), -1, &ARect,DT_CENTER || DT_SINGLELINE);


Отредактировано Doga — 15/06/2006, 15:36

Вернуться в Вопросы программирования в C++Builder