|
디비그리드 위에 디비체크박스를 올려서 처리한다면 그리 깔끔한 결과가 나오기 힘듭니다.
이것저것 예상치 않은 동작들이 나타날 텐데, 그런 부분들을 다 처리하려면 코딩 양도 엄청 많아지고요.
보여주신 소스에서는 현재 레코드에는 디비 체크박스를 하나 올리고 나머지 로우들은 OnDrawColumnCell 이벤트에서
그리는 방식을 썼는데, 여러가지 예상치 않은 결과가 나올 것입니다. 예를 들어 디비그리드에서 현재 레코드가 아닌 다른
레코드의 체크박스 셀을 클릭하면 어떻게 나오나요? 정확히 예상하긴 힘들지만 아마 예상한 것과는 다른 황당한 결과가
나올 것입니다. 또 디비 그리드가 스크롤될 때도 체크박스를 따라서 움직여줘야 할 수도 있고, 다른 부작용들도 한두가지가
아닙니다.
제가 여러가지 방법으로 시도해봤을 때 가장 깔끔한 방식은 현재 레코드이든지 아니든지 무조건 OnDrawColumnCell
이벤트에서 처리해주고, 클릭했을 때는 OnCellClick 이벤트에서 처리해주는 것입니다. 실제 TCheckBox나 TDBCheckBox
컴포넌트는 쓰지 않고요.
다음은 제가 쓰고 있는 델파이 프로젝트의 코드를 C++빌더로 컨버팅한 것입니다.
void __fastcall TForm1::DBGrid1CellClick(TColumn *Column)
{
if(ClientDataSet1->Eof && ClientDataSet1->Bof) return;
if(Column->Title->Caption=="입력상태")
{
AnsiString NewState;
if(Column->Field->Text=="1") NewState = "2";
else NewState = "1";
ClientDataSet1->Edit();
Column->Field->Text = NewState;
ClientDataSet1->Post();
}
}
void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender,
const TRect &Rect, int DataCol, TColumn *Column, TGridDrawState State)
{
if(Column->Field!=NULL && Column->Title->Caption=="입력상태")
{
TPoint pt = Point((Rect.Left+Rect.Right) / 2 - 6, (Rect.Top+Rect.Bottom) / 2 - 6);
TRect R(pt.x, pt.y, pt.x+13, pt.y+13);
DWORD DrawState = DFCS_BUTTONCHECK;
if(Column->Field->Text=="1") DrawState = DrawState | DFCS_CHECKED;
DrawFrameControl(DBGrid1->Canvas->Handle, &R, DFC_BUTTON, DrawState);
}
}
여기서 ClientDataSet1이 디비그리드와 연결된 데이터셋입니다. 그리고 체크박스로 나오는 필드는 저희 회사 디비의 실제
값은 문자열 "1" 혹은 "2" 값입니다. 따라서 불린 형태의 값을 가지는 필드에 연결하시려면 Text가 "1"인가 2인가 여부를
검사하거나 세팅하는 부분을 AsBoolean으로 변경하시면 됩니다.
그럼...
최진호 님이 쓰신 글 :
: DB프로그램을 만들고 있는데 이해가 안되는 부분이 있어서 이렇게 물어 봅니다..
:
: DBGrid 위에 DBCheckBox 와 ADOQuery를 하나 놓고 실행 시키는 프로그램 으로
:
: DBGrid에 DBCheck box를 넣는것 입니다..델파이의 소스를 찾아서 일부를 수정했는데... 이상하게 DBCheckBox에 클릭을 하면 색깔이 바로 변하지 않고 두번 클릭해야 변화가 되고 업데이트가 가능하던데 이런 문제는 어떤식으로 처리 해야 되나요!!!!(마우스 오른쪽 버튼을 클릭하고 다시 윈쪽 버튼을 클릭해야 수정이 가능하게 DBnavigator 버튼이 변하게 됩니다.)
:
:
:
:
:
: #include <vcl.h>
: #pragma hdrstop
:
: #include "Unit1.h"
: //---------------------------------------------------------------------------
: #pragma package(smart_init)
: #pragma resource "*.dfm"
: TForm1 *Form1;
: //---------------------------------------------------------------------------
: __fastcall TForm1::TForm1(TComponent* Owner)
: : TForm(Owner)
: {
: }
: //---------------------------------------------------------------------------
:
: void __fastcall TForm1::Button1Click(TObject *Sender)
: {
: ADOQuery1->Close();
: ADOQuery1->SQL->Clear();
: ADOQuery1->SQL->Add("SELECT * FROM Articles");
: ADOQuery1->Open();
: }
: //---------------------------------------------------------------------------
:
: void __fastcall TForm1::FormCreate(TObject *Sender)
: {
: DBCheckBox1->DataSource = DataSource1;
: DBCheckBox1->DataField = "Winner";
: DBCheckBox1->Visible = False;
: DBCheckBox1->Color = DBGrid1->Color;
: DBCheckBox1->Caption = "";
: //explained later in the article
: DBCheckBox1->ValueChecked = "출고";
: DBCheckBox1->ValueUnchecked = "미출고";
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::DBGrid1DrawColumnCell(TObject *Sender,
: const TRect &Rect, int DataCol, TColumn *Column,
: TGridDrawState State)
: {
:
: const bool ISChecked[]=
: {int(DFCS_BUTTONCHECK), int(DFCS_BUTTONCHECK)||int(DFCS_CHECKED)};
: int DrawState;
: TRect DrawRect;
:
: if(State.Contains(Grids::gdFocused))
: {
: if (Column->Field->FieldName == DBCheckBox1->DataField) {
: DBCheckBox1->Left = Rect.Left + DBGrid1->Left + 27;
: DBCheckBox1->Top = Rect.Top + DBGrid1->Top+2;
: DBCheckBox1->Width = Rect.Right - Rect.Left;
: DBCheckBox1->Height = Rect.Bottom - Rect.Top;
: DBCheckBox1->Visible = true; }
:
:
: }
:
: else
: {
: if (Column->Field->FieldName == DBCheckBox1->DataField) {
: DrawRect=Rect;
: InflateRect( (RECT *)(&DrawRect),-1,-1);
: DrawState = ISChecked[Column->Field->AsBoolean];
: DBGrid1->Canvas->FillRect(Rect);
: DrawFrameControl(DBGrid1->Canvas->Handle, (RECT *)(&DrawRect),
: DFC_BUTTON, DrawState); }
: }
:
: }
: //---------------------------------------------------------------------------
: void __fastcall TForm1::DBGrid1ColExit(TObject *Sender)
: {
: if (DBGrid1->SelectedField->FieldName == DBCheckBox1->DataField)
: DBCheckBox1->Visible = false;
: }
|