CheckBox in DBGrid
11 отговора
327 прегледа
CheckBox in DBGrid
Как мога да поставя CheckBox в някоя клетка на DBGrid така че като кликна върху CheckBox-a той да сменя състоянието си което да речем се записва в поле от таблица.А дали не може да се използва и DBCheckBox.В книката на Марко Канту Mastering Delphi 5 има подобен пример в I-ва част стр.519 но DBCheckBox-a се показва само когато е селектирана колоната.Аз искам да стои и когато колоната не е селектирана и при кликване върху него да сменя състоянието си.
Моля ако някой добър човек може да помогне нека го направи, като му благодаря предварително
Моля ако някой добър човек може да помогне нека го направи, като му благодаря предварително
Re: CheckBox in DBGrid
Опитай да премахнеш /и разучиш какво прави/ събитието DBGridColEnter - показано е на 520 стр.
Има обаче един съществен проблем - в примера е показана работа с ЕДНА отметка. Предполагам че искаш цялата колона да показва отметки. Тогава следва забавна ескалация на проблема:
1. Първата стъпка е да се направят толкова отметки, колкото записа имаме. Това е малко глупаво, понеже записите може да са сочен брой
2. Втората стъпка е да се правят само толкова отметки, колкото се показват на екрана.
3. На трети пас се оказва, че можем да имаме повече от една колонка с отметки.
В крайна сметка, препоръчвам ти да погледнеш и изучиш един хубав пример:
[линк]
чети и дишай по-леко
Има обаче един съществен проблем - в примера е показана работа с ЕДНА отметка. Предполагам че искаш цялата колона да показва отметки. Тогава следва забавна ескалация на проблема:
1. Първата стъпка е да се направят толкова отметки, колкото записа имаме. Това е малко глупаво, понеже записите може да са сочен брой
2. Втората стъпка е да се правят само толкова отметки, колкото се показват на екрана.
3. На трети пас се оказва, че можем да имаме повече от една колонка с отметки.
В крайна сметка, препоръчвам ти да погледнеш и изучиш един хубав пример:
[линк]
чети и дишай по-леко
Re: CheckBox in DBGrid
Аз съм направил в дадена колона да се показва CheckBox във всички клетки като съм направил състоянията на CheckBox-a като Bitmap и ги прерисувам в OnDrawColumnCell в зависимост от съдържанието на поле от таблицата, т.е. ако полето е 0 рисувам UnChecked CheckBox а ако е 1 Ckecked CheckBox.
Ето и малко код само че C++(Работя със C++Builder 6.)
void __fastcall TfrmMain::DBGrid3DrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
Graphics::TBitmap *ImSel;
ImSel = new Graphics::TBitmap;
if(Column->FieldName == "Select")
{
DBGrid3->Canvas->Brush->Color = clWhite;
DBGrid3->Canvas->FillRect(Rect);
if(ADOTask->FieldByName("Select")->AsString == '0')
{
ImageList1->GetBitmap(0,ImSel);
}
else
{
ImageList1->GetBitmap(1,ImSel);
}
DBGrid3->Canvas->Draw((Rect.Left+2 + Rect.Right - ImSel->Width)/2,Rect.Top+1, ImSel);
delete ImSel;
}
}
При кликване върху клетката, т.е. върху Bitmap-a(CheckBox) се изпълнява код в събитието OnCellClick.Променя се съдържанието на полето от таблицата което съхранява състоянието на CheckBox-a,и по което поле се изрисува съответното му състояние в клетките на колоната от DBGrid-a.
Ето и съответният код:
void __fastcall TfrmMain::DBGrid3CellClick(TColumn *Column)
{
if(Column->FieldName == "Select")
{
ADOTask->Edit();
if(ADOTaskSelect->AsString == '0')
ADOTaskSelect->AsString = '1';
else
ADOTaskSelect->AsString = '0';
ADOTask->Post();
}
}
Проблема се явява когато е селецтирана дадена клетка, т.е. е във фокус и се кликне с мишката върху нея се появява истинската стойност на полето, т.е. 1 или 0 и полето изпада в състояние Edit().Като се промени фокуса на друга клетка се появява съответния CheckBox(Bitmap-a) в клетката където е била истинската стойност.
Искам когато клетката с CheckBox-a е във фокус и се кликне върху нея да се смени само състоянието а не да се показва истинската стойност.Когато клетката не е във фокус няма проблеми.Състоянието на CheckBox-a Се променя.
Е този проблем не мога да го реша от доста време насам затова го поставям във форума.
Дано някой помогне.
Ето и малко код само че C++(Работя със C++Builder 6.)
void __fastcall TfrmMain::DBGrid3DrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
Graphics::TBitmap *ImSel;
ImSel = new Graphics::TBitmap;
if(Column->FieldName == "Select")
{
DBGrid3->Canvas->Brush->Color = clWhite;
DBGrid3->Canvas->FillRect(Rect);
if(ADOTask->FieldByName("Select")->AsString == '0')
{
ImageList1->GetBitmap(0,ImSel);
}
else
{
ImageList1->GetBitmap(1,ImSel);
}
DBGrid3->Canvas->Draw((Rect.Left+2 + Rect.Right - ImSel->Width)/2,Rect.Top+1, ImSel);
delete ImSel;
}
}
При кликване върху клетката, т.е. върху Bitmap-a(CheckBox) се изпълнява код в събитието OnCellClick.Променя се съдържанието на полето от таблицата което съхранява състоянието на CheckBox-a,и по което поле се изрисува съответното му състояние в клетките на колоната от DBGrid-a.
Ето и съответният код:
void __fastcall TfrmMain::DBGrid3CellClick(TColumn *Column)
{
if(Column->FieldName == "Select")
{
ADOTask->Edit();
if(ADOTaskSelect->AsString == '0')
ADOTaskSelect->AsString = '1';
else
ADOTaskSelect->AsString = '0';
ADOTask->Post();
}
}
Проблема се явява когато е селецтирана дадена клетка, т.е. е във фокус и се кликне с мишката върху нея се появява истинската стойност на полето, т.е. 1 или 0 и полето изпада в състояние Edit().Като се промени фокуса на друга клетка се появява съответния CheckBox(Bitmap-a) в клетката където е била истинската стойност.
Искам когато клетката с CheckBox-a е във фокус и се кликне върху нея да се смени само състоянието а не да се показва истинската стойност.Когато клетката не е във фокус няма проблеми.Състоянието на CheckBox-a Се променя.
Е този проблем не мога да го реша от доста време насам затова го поставям във форума.
Дано някой помогне.
Re: CheckBox in DBGrid
Този пример (DBGridColor)е много хубав и върви на Delphi (тествах го) но във C++Builder не върви.Ще покажа малко код.
На Delphi:
procedure TformColorGrid.DBGridDrawColumnCell(Sender: TObject; const Rect: TRect;DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
Style : Integer;
if Column->FieldName = 'Remainder' then
if ADOSubMats->FieldByName('Remainder')->AsString = '0'
Style := DFCS_CHECKED;
else
Style := DFCS_BUTTONCHECK;
DrawFrameControl(TDBGrid(Sender).Canvas.Handle,Rect,DFC_BUTTON, Style);
end;
еквивалента в C++Builder:
void __fastcall TfrmMain::DBGridSubMatsDrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
int Style;
if(Column->FieldName == "Remainder")
if(ADOSubMats->FieldByName("Remainder")->AsString == '0')
Style == DFCS_CHECKED;
else
Style == DFCS_BUTTONCHECK;
DrawFrameControl(dynamic_cast<TDBGrid*>(Sender)->Canvas->Handle,Rect,DFC_BUTTON, Style);
}
Компилатора на C++Builder се оплаква със следната грешка:
Cannot convert 'const TRect to tagRECT*'
Type mismatch in parameter 2(wanted 'tagRECT*',got 'TRect')
Струвами се че описанието на типа TRect в Delphi и C++Builder e различно и не виждам начин да се оправят нещата.Какъв е тоя тип tagRECT?
За първи път се сблъсквам с проблем от този род.Дано да се намери решение.
На Delphi:
procedure TformColorGrid.DBGridDrawColumnCell(Sender: TObject; const Rect: TRect;DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
Style : Integer;
if Column->FieldName = 'Remainder' then
if ADOSubMats->FieldByName('Remainder')->AsString = '0'
Style := DFCS_CHECKED;
else
Style := DFCS_BUTTONCHECK;
DrawFrameControl(TDBGrid(Sender).Canvas.Handle,Rect,DFC_BUTTON, Style);
end;
еквивалента в C++Builder:
void __fastcall TfrmMain::DBGridSubMatsDrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
int Style;
if(Column->FieldName == "Remainder")
if(ADOSubMats->FieldByName("Remainder")->AsString == '0')
Style == DFCS_CHECKED;
else
Style == DFCS_BUTTONCHECK;
DrawFrameControl(dynamic_cast<TDBGrid*>(Sender)->Canvas->Handle,Rect,DFC_BUTTON, Style);
}
Компилатора на C++Builder се оплаква със следната грешка:
Cannot convert 'const TRect to tagRECT*'
Type mismatch in parameter 2(wanted 'tagRECT*',got 'TRect')
Струвами се че описанието на типа TRect в Delphi и C++Builder e различно и не виждам начин да се оправят нещата.Какъв е тоя тип tagRECT?
За първи път се сблъсквам с проблем от този род.Дано да се намери решение.
Re: CheckBox in DBGrid
Не знам конкретната ситуация - ама аз наскоро открих подобен проблем - в VirtualTreeView - има един event който е дефиниран кофти !!!!- случва се - и като се опитраш да завържеш събитие за него - става кофти - явно е някакво недоглеждане на компилатора на Делфи!!!!
Погледни двата кода - имам предвид в сорса - дали декларациите на събитието не се различават ?! Ако се различават - корегирай С версията - това може да е проблема - макар че от това което и пуснал - не мога да видя проблем. Всъщност -пробвай да махнеш reference оператора пред Rect в параментрите на функцията - това май е видимата разлика?!
---
Е т'ва е живот!
Погледни двата кода - имам предвид в сорса - дали декларациите на събитието не се различават ?! Ако се различават - корегирай С версията - това може да е проблема - макар че от това което и пуснал - не мога да видя проблем. Всъщност -пробвай да махнеш reference оператора пред Rect в параментрите на функцията - това май е видимата разлика?!
---
Е т'ва е живот!
Re: CheckBox in DBGrid
Работата е в това , че не е там проблема ами това явно е bug.Господата от Borland май са бързали много и са недоогледали нещо.Мисля че е необходимо да им пратим едно e-mail-че.
Re: CheckBox in DBGrid
Само, че човека не ползва борландския dbgrid ами Colour Grid ! А иначе подобен проблем не мога да установя, защото почти не ползвам C-Builder ;-))) т.е. дали има разлика между VCL библиотеките за Delphi и CBuilder- би трябвало да няма.
---
Е т'ва е живот!
---
Е т'ва е живот!
Re: CheckBox in DBGrid
До колкото аз разбирам човека ползва точно Borland-ския DBGrid а използва пример наречен Colour Grid.Относно разлика между VCL на C++Builder и Delphi няма такава , защото Builder-а ползва VCL-a на Delphi.Така, че проблема на човека си остава нерешен.
Re: CheckBox in DBGrid
Много добре си разбрал.Точно за Борландския DBGrid става въпрос.
Re: Ето решение на проблема
Приятел използваи следния код :
void __fastcall TfrmMain::DBGridSubMatsDrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
const int CtrlState[] = {DFCS_BUTTONCHECK, DFCS_CHECKED};
TRect CheckBoxRectangle;
if(Column->Field->DataType == ftBoolean)
{
this->DBGridSubMats->Canvas->FillRect(Rect);
CheckBoxRectangle.Left = Rect.Left + 1;
CheckBoxRectangle.Right = Rect.Right - 1;
CheckBoxRectangle.Top = Rect.Top + 1;
CheckBoxRectangle.Bottom = Rect.Bottom - 1;
DrawFrameControl(this->DBGridSubMats->Canvas->Handle,
&CheckBoxRectangle,
DFC_BUTTON,
CtrlState[Column->Field->AsBoolean]);
}
}
Това е решението на проблема.
void __fastcall TfrmMain::DBGridSubMatsDrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column,
TGridDrawState State)
{
const int CtrlState[] = {DFCS_BUTTONCHECK, DFCS_CHECKED};
TRect CheckBoxRectangle;
if(Column->Field->DataType == ftBoolean)
{
this->DBGridSubMats->Canvas->FillRect(Rect);
CheckBoxRectangle.Left = Rect.Left + 1;
CheckBoxRectangle.Right = Rect.Right - 1;
CheckBoxRectangle.Top = Rect.Top + 1;
CheckBoxRectangle.Bottom = Rect.Bottom - 1;
DrawFrameControl(this->DBGridSubMats->Canvas->Handle,
&CheckBoxRectangle,
DFC_BUTTON,
CtrlState[Column->Field->AsBoolean]);
}
}
Това е решението на проблема.