我爱builder

C++Builder 程序员博客

    小弟我在做一个程序,在查询完后,在dbgrid中游标移动到该条记录并使其改变颜色,但好像只能在OnDrawColumnCell中写,只是在form显示的时候颜色可以改变。在按钮中写语句通过了,可是颜色依然不改。
      请指教一下,如何在按钮的事件中再去响应一个dbgrid的OnDrawColumnCell事件,给选中的记录改变颜色。

void __fastcall TDataMod::DBGDrawColumnCell(TObject *Sender,
      const TRect &Rect, int DataCol, TColumnEh *Column,
      Gridseh::TGridDrawState State)
{
        TDBGridEh* sgGrid = dynamic_cast <TDBGridEh*>(Sender);
        if(State.Contains(Gridseh::gdSelected) )
        {
                sgGrid->Canvas->Brush->Color =  TColor(RGB(49,106,197));
                sgGrid->Canvas->Font->Color = TColor(RGB(255,255,255));
                // sgGrid->Canvas->Font->Name = "宋体";
                // sgGrid->Canvas->Font->Size = 14;
                sgGrid->Canvas->FillRect(Rect);

        }

        else if ( Column->Field->DataSet->RecNo %2 == 0)
        {
                sgGrid->Canvas->Brush->Color =  TColor(RGB(231,240,187));
                sgGrid->Canvas->Font->Color =  TColor(RGB(10,10,10));
                //sgGrid->Canvas->Font->Name = "宋体";
              // sgGrid->Canvas->Font->Size = 14;
                sgGrid->Canvas->FillRect(Rect);
                //sgGrid->Canvas->TextOutA()
        }
        else
        {
                sgGrid->Canvas->Brush->Color =  TColor(RGB(247,255,214));
                sgGrid->Canvas->Font->Color =  TColor(RGB(10,10,10));
                //sgGrid->Canvas->Font->Name = "宋体";
                //sgGrid->Canvas->Font->Size = 14;
                sgGrid->Canvas->FillRect(Rect);
        }
        String str;
        if(Column->Field== NULL)
                str="";
        else
        {
                if(Column->DisplayFormat == "0.00")
                        str = FormatFloat("0.00",  Column->Field->AsFloat);
                else
                        str = Column->Field->AsString;

        }
        sgGrid->Canvas->Pen->Width = 1;
        sgGrid->Canvas->Pen->Style = psSolid;
        sgGrid->Canvas->Pen->Color = TColor(RGB(202, 218 ,119 ));
        sgGrid->Canvas->MoveTo(Rect.Left,Rect.Bottom);
        sgGrid->Canvas->LineTo(Rect.Right,Rect.Bottom) ;
        sgGrid->Canvas->Pen->Color = TColor(RGB(202, 218 ,119 ));
        sgGrid->Canvas->MoveTo(Rect.right,Rect.top);
        sgGrid->Canvas->LineTo(Rect.Right,Rect.Bottom);
        //sgGrid->Canvas->Rectangle(Rect);

        DrawText(sgGrid->Canvas->Handle,  str.c_str(),
                  -1,  (RECT*)&Rect,  DT_SINGLELINE  |  DT_VCENTER  |  DT_CENTER);
}

只用
if(State.Contains(Gridseh::gdSelected) )
{
    sgGrid->Canvas->Brush->Color =  TColor(RGB(49,106,197));
    sgGrid->Canvas->Font->Color = TColor(RGB(255,255,255));
    sgGrid->DefaultDrawColumnCell(Rect,DataCol,Column,State);
}
大概这样是可以的,我最近刚弄过,绝对好用,不过记不太清楚了,如果不好用再联系。

引用 3 楼 yangangs 的回复:
只用
if(State.Contains(Gridseh::gdSelected) )
{
    sgGrid->Canvas->Brush->Color =  TColor(RGB(49,106,197));
    sgGrid->Canvas->Font->Color = TColor(RGB(255,255,255));
    sgGrid->DefaultDrawColumnCell(Rect,DataCol,Column,State);
}


这个可以吧

干吗要画呢?本身就有属性的呀,设置dbRowSelect=true

引用 5 楼 jaffy 的回复:
干吗要画呢?本身就有属性的呀,设置dbRowSelect=true

哪里有这个属性啊??

引用 6 楼 xjq2003 的回复:
引用 5 楼 jaffy 的回复:
干吗要画呢?本身就有属性的呀,设置dbRowSelect=true

哪里有这个属性啊??


这是别的控件,如EHLib,CXGrid,自带的就要自已画了

行选择是dbgrid中本来就有的属性啊!

  • Filed under: C++ Builder
  • 看了多位的介绍, 我按照以下做了,想变颜色,但就是变不了. 谢谢高手.
        if(StoredProc4->RecNo%2==0 )
          {
              DBGrid1->Canvas->Brush->Color=clGrayText;
              DBGrid1->Canvas->Font->Color=clBlue;
          }
          else
          {
              DBGrid1->Canvas->Brush->Color=clAppWorkSpace;
              DBGrid1->Canvas->Font->Color=clRed;
          }
          DBGrid1->Canvas->Pen->Mode = pmMask;
          DBGrid1->Canvas->FillRect(Rect);
          DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);

    不是啊. 我想将表中的奇数行和偶数行设置成不同的颜色. 就是找不到切入点.
    DBGrid 不随StoredProc4->RecNo%2==0 变化.

    郁闷!

    if(DBGrid1->DataSource->DataSet->Active==false) return;
    if(DBGrid1->DataSource->DataSet->RecordCount <=0) return;
    if (DBGrid1->DataSource->DataSet->RecNo % 2==1)
    {
            DBGrid1->Canvas->Font->Color=clBlack;
            DBGrid1->Canvas->Brush->Color=clWindow;
    }else{
            DBGrid1->Canvas->Font->Color=clBlack;
            DBGrid1->Canvas->Brush->Color=0×00D4D4D4;  //clActiveBorder;
          }
    //================
    if(State.Contains(gdSelected))
    {
        DBGrid1->Canvas->Font->Color = clWhite;
        DBGrid1->Canvas->Brush->Color=clBlue;
    }
    DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);

    大哥, 我照你说的那样输入如下,可以运行,但颜色就是变不了. 整个报表都是第一个选项的结果. 说明程序起作用了,但偶数行没反映. 我的数据源是TStoredProc. 再帮一下. 谢谢!
        if (DBGrid1->DataSource->DataSet->RecNo % 2==1)
          {
            DBGrid1->Canvas->Font->Color=clBlack;
            DBGrid1->Canvas->Brush->Color=clWindow;
          }
          else
          {
            DBGrid1->Canvas->Font->Color=clBlack;
            DBGrid1->Canvas->Brush->Color=0×00D4D4D4;
          }

          DBGrid1->Canvas->Pen->Mode = pmMask;
          DBGrid1->Canvas->FillRect(Rect);
          DBGrid1->DefaultDrawColumnCell(Rect,DataCol,Column,State);

    发现问题了. TADOStoredProc就可以, 用TStoredProc就不行. 娘西匹!

    问题解决了
    恭喜你啊

    来学习的!

  • Filed under: C++ Builder
  • DBGrid里要是显示大于0×7FFFFFFF的数,就会出现负值,原因是它只接受有符号的整数,

    那请问下大于0×7FFFFFFF而小于0xFFFFFFFF 的数应该怎么样现在呢,我不想出现负值。

    就是怎么样让它显示全部的不符号整数。

    dataset里面的field的类型不对,找找有没有无符号数。如果是查询语句,可以在查询时转成字符串

    把数据库字段改一下,改成DECIMAL比较好

      感谢两位的关注,我把数据库字段改成largeint,还是不行,关键是在grid里写入值的时候,它是用AsInteger来接收的,而AsInteger确接受的是有符号的数.哎,难道真不能写入无符号的数.

    引用 4 楼 bingyu0914 的回复:
      感谢两位的关注,我把数据库字段改成largeint,还是不行,关键是在grid里写入值的时候,它是用AsInteger来接收的,而AsInteger确接受的是有符号的数.哎,难道真不能写入无符号的数.

    改dataset里面的field的类型为BIGINT。

    引用 5 楼 hemiya 的回复:

    改dataset里面的field的类型为BIGINT。

    首先感谢你对我的支持,我不知道你用什么数据库控件,我用的是clientdataset,它的field类型并没有BIGINT,只用

    ftLargeint,我试了下用它自己控件添加一条超过0×8FFFFFFF值的记录是可以显示正数的,但是当我给数据库添加新记录

    时用AsInteger就只能得到负数.

    换成VALUE试下

    我觉得应该是数据源的问题,你转成字符串型后存入数据库中,DBGRID显示字符串应该可以吧

    引用 6 楼 bingyu0914 的回复:
    引用 5 楼 hemiya 的回复:

    改dataset里面的field的类型为BIGINT。

    首先感谢你对我的支持,我不知道你用什么数据库控件,我用的是clientdataset,它的field类型并没有BIGINT,只用

    ftLargeint,我试了下用它自己控件添加一条超过0×8FFFFFFF值的记录是可以显示正数的,但是当我给数据库添加新记录

    时用AsInteger就只能得到负数.


    对不起啊,是我搞混了.bigint是数据库的数据类型,不是clientdataset的field类型,我也用的clientdataset,不过我用这个只是显示数据,
    添加数据的时候用的clientdataset的execute执行sql命令,不是用的clientdataset的insert函数,我用的是firebird数据库.

    调用DBGRID的自绘事件,自己把数字填进去。。。

      感谢各位,只是字符串不能象数字那样很好的排序,VALUE值也不能显示成正数,我现在用64位写进去正数,但是

    clientdataset的index排序的方法就不起作用,换成整型即使是负数显示都能进行排序,DBGRID的自绘事件的自绘事情太

    烦琐了,因为数据太多,着个难道真是一个不能实现的功能?还得请高人指点.

      谁有好的方法,给个建议撒!大家帮忙顶一下!

    固定字符串长度可以实现以上功能,感谢大家的参与.

  • Filed under: C++ Builder
  • 小虾问大虾,触发dbgrid的什么事件来把dbgrid中显示的数据导入word.在论坛中找了不少范例都一样,我点击了dbgrid的所有事件也没有找到与例子中类似的事件void __fastcall DBGrid2Word(TDBGrid *dbg, String strDocFile)…….?请教各位。

    没用过DBGrid,可以获得DBgrid里的数据,再用ole写到word里把

    用ole导出数据

    引用 3 楼 hemiya 的回复:
    用ole导出数据

    用ole导出数据速度比较慢!
    或者直接写文件的方法也可以,这样速度更快

    老妖代码中的void __fastcall DBGrid2Word(TDBGrid *dbg, String strDocFile)事件是自定义事件。
    不是DBGrid控件的系统中事件,所以你是找不到了。

    定义方法,在头文件中public部分加入以下声明:
    void __fastcall DBGrid2Word(TDBGrid *dbg, String strDocFile);

    自定义函数

  • Filed under: C++ Builder
  • 隔行显示不同色  
    void   __fastcall   TForm1::DBGrid1DrawColumnCell(TObject   *Sender,  
    const   TRect   &Rect,   int   DataCol,   TColumn   *Column,  
    TGridDrawState   State)  
    {  
        if   (State.Contains(gdSelected))  
            return;  
        if   (DBGrid1-> DataSource-> DataSet-> RecNo   %   2   ==0)  
            DBGrid1-> Canvas-> Brush-> Color   =   clRed;   //定义背景颜色  
        else  
            DBGrid1-> Canvas-> Brush-> Color   =   clBlue;   //定义背景颜色  
        DBGrid1-> DefaultDrawColumnCell(Rect,DataCol,Column,State);  
    }  
    为什么DBGrid1-> DataSource-> DataSet-> RecNo   的值总是等于-1?
     
    另外DBGrid能不能设置在编辑时不自动保存,而是在我按一个保存的按钮后再保存?因为DBGrid上有些字段是隐藏的,在保存前需要先赋值,而在编辑时,先用Query1-> Edit(),在保存按钮下的代码中用了Query1-> Post()也不保存修改或添加的记录,请问这样做对应的Query与DataSource控件的属性如何设置,那个保存按钮的代码如何写呢?  

    第二个问题
    DBGrid1-> DataSource-> DataSet-> LockType=ltBaltchOptimistisc
    保存时调用query的updatebatch()函数

    RecNo   对于   paradox   和dbf   才是有意义的,他的说明写了。

    DBGrid1-> DataSource-> DataSet-> LockType=ltBaltchOptimistisc
    程序编译时这里都会出错啊,DataSet没有LockType属性
    在程序中我把Query1-> CachedUpdates=true;Query1-> RequestLive=true;在修改时调用了Query1-> Edit()方法,修改过程同时还有添加了新记录,保存时调用了Query1-> Post()方法,但什么也保存不了啊。有什么方法可以保存呢?

    Query1-> CachedUpdates=true这样的话你试试Query1-> ApplyUpdates();  

    另外   对于BDE控件,RecNo   的值总是等于-1。

    该回复于2008-07-10 02:44:24被版主删除

    该回复于2008-07-10 02:56:32被版主删除

    学习,强烈需要

  • Filed under: C++ Builder
  • RT,在线等高手解决问题,希望贴出完整代码,本人是新手,分数不是问题,感谢!

    将其字段的checkbox设为true就会有checkbox 了

    Ehlib是第三方控件,不过做数据库编程来说已经替代默认BCB自带的DBGrid什么的控件了,属于增强版.老妖网站上有

    不要第3方控件应该怎么实现呢

    up

    引用 4 楼 wuweize 的回复:
    不要第3方控件应该怎么实现呢
    实现不了

    …不是吧

    C/C++ code
    void __fastcall TForm1::OnDrawColumnCell1(TObject *Sender, const TRect &Rect, int DataCol, TColumn *Column, TGridDrawState State) { int Select_Check[2]={DFCS_BUTTONCHECK,DFCS_BUTTONCHECK |DFCS_CHECKED} ; if (Column->Field->DataType== ftBoolean ) { TRect RecTemp; RecTemp.left = Rect.Left; RecTemp.right = Rect.Right; RecTemp.top = Rect.Top; RecTemp.bottom = Rect.Bottom; DBGrid1->Canvas->FillRect(Rect); DrawFrameControl(DBGrid1->Canvas->Handle,&RecTemp,DFC_BUTTON, Select_Check[Column->Field->AsBoolean?1:0]); } } //————————————————————————— void __fastcall TForm1::CellClick(TColumn *Column) { if (!Column->Field->DataSet->Eof) { if (Column->Field->DataType == ftBoolean ) { SaveBoolean(); } } } //————————————————————————— void __fastcall TForm1::KeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if ((Key ==VK_DOWN) && (ADOQuery1->RecNo==ADOQuery1->RecordCount)) Key=NULL; if ((Key==VK_SPACE)&& (DBGrid1->SelectedField->DataType==ftBoolean)) { SaveBoolean(); } } //————————————————————————— void __fastcall TfrmGatByRec::SaveBoolean()//这段出错,不知道格式怎么写 { DBGrid1->SelectedField->DataSet->Edit(); DBGrid1->SelectedField->AsBoolean=!DBGrid1->SelectedField->AsBoolean; DBGrid1->SelectedField->DataSet->Post(); }

    幫我看下上面代碼是實現什么功能,注釋那是出錯了,謝謝

    沒人幫忙?????????

  • Filed under: C++ Builder
  • 因为数据库中有一个文本型的Field,
    我要判断这个Field的值是否符合要求,
    没法用SQL语句来选择,
    而且数据量不是很多,
    所以想用代码一条一条地判断,
    符合的就在DBGrid中显示。
    不知有什么办法可以实现?

      怎么会没法用SQL语句判断呢?

    C/C++ code
    void __fastcall TForm1::ADOQuery1FilterRecord(TDataSet *DataSet, bool &Accept) { //这里写上你过滤的代码,比如你可以在那个‘text’类型字段中搜索某个你认为的关键的东东 搜索到了就让 Accept= true; Accept = IsIWant(….) ;// 。。 } //—————————————————————————

    谢谢jxw1987628,问题解决了。

    另外,
    hnzlk:
    我的数据库有一个Field,
    用来保存温度的,
    而如果温度传感器不接或短路时,
    这个Field里的值不是一个数值,
    而是“断线”或“短路”这样的文本,
    所以我只能把这个Field定义为文本型。
    这样的话怎么用SQL去筛选温度值大于30度而小于50度的记录呢?
    可另开帖给分。

    顶小漫
    ADOQuery1->Filtered=true;

    怎么用SQL去筛选温度值大于30度而小于50度的记录呢
    select * from 表
    where case when isnumeric(温度)=1 then cast(温度 as float) else 0 end between 30 and 50

  • Filed under: C++ Builder
  • 还没弄明白DBGrid是怎么绑定数据显示出来呢,

    拖DBGrid,TADOQuery,DataSource到界面中,
      //DBGrid数据查询
      AnsiString strdataBind;
      qryDataBind->Close();
      qryDataBind->SQL->Clear();
      strdataBind="select * from 化验数据";
      qryDataBind->SQL->Add(strdataBind);
      qryDataBind->Open();

    DBGrid中的FileName没有数据,点击了提示TADOQuery,Missing SQL property
    没有找到少设置什么了,给提示下

    没有ADOCONNECTION吧,你数据源可能都没有设置

    C/C++ code
    ADOConnection1,DBGrid,ADOQuery,DataSource 设置ADOQuery的SQL语句以及connection,并设置DataSource的dataset,并设置DBGrid的datasource,当然前提要让 ADOConnection1连上数据库,把ADOQuery的active设为true就能看到数据了。

    DataSource->DataSet设为ADOQuery
    DBGrid->DataSource设为DataSource

    这样当ADOQuery里有数据里,DBGrid就会显示了。

  • Filed under: C++ Builder
  • 在DBGrid显示数据的同时,还有一个线程在源源不断的对数据库写记录。
    一般情况下,DBGrid是能静态显示数据库数据的。但是由于数据源不断更新,请问怎么解决这样的冲突?
    现在的问题是,在有新数据进入数据表之后,DBGrid刷新成空表格。

    C/C++ code
    // 你是在其他工作线程里面刷新DBGrid ? // 还是在主线程里面刷新DBGrid ?

    引用 1 楼 Ring_Pt 的回复:
    如果刷成空表 那不是很容易?
    如果要刷新數據庫中的當前數據簡單的做法就是用個Timer控件,定時去刷

    额,谢谢,可能是我没有解释清楚
    现在的症状是刷成空表格,而我不希望,我希望他一直显示。
    而且我也不想要什么定时刷新。
    比如用户在当前情况下载入了数据的数据到DBGRID上,我期望的是,即使有数据再进入数据库,也不需要吧新数据更新在GBGRID上。就好象,娶了个老婆,当有新MM来骚扰时候,就不鸟她,做个专一的人,哈哈。
    一句话,希望DBGrid里的数据是静态的。

    引用 2 楼 jxw1987628 的回复:
    C/C++ code
    // 你是在其他工作线程里面刷新DBGrid ?

    // 还是在主线程里面刷新DBGrid ?


    主线程刷,其他线程写数据库
    谢谢你
    请按照你的思路讲下去

    C/C++ code
    // 保持静态的,那你干脆就不要用DBGrid了 // 以为DBgrid这种需要和数据集(Query等) 数据源控件(Datasource等)实时挂接 // 你换成其他的表格控件如StringGrid,这种数据就是静态的,你读取了多少,往里面 // 添加就ok了,

    记录 DataSet 的 RecNo,刷新,或者是关闭表,再重新开启表,再恢复 DataSet RecNo
    但如果你是用 DataSet 的方法直接插入数据,那么和该 DataSet 控件绑定的 DBGrid 会自动刷新,但如果是 SQL 命令插入的数据,你就只能使用记录 RecNo 的方法来保持原来的游标,或者刷新后直接将游标移动到最有一个记录 DataSet 的 Last() 方法

    引用 1 楼 Ring_Pt 的回复:
    如果刷成空表 那不是很容易?
    如果要刷新數據庫中的當前數據簡單的做法就是用個Timer控件,定時去刷

    不错啊,好方法

    不要用DBGrid,直接用StringGrid,其他线程插入一条就显示一条。

    有什么办法可以在载入过一次之后关掉DBGRID或者DATASOURCE?
    想要再次载入的时候再打开?

    请大虾帮帮忙

    引用 9 楼 wujiajia1989 的回复:
    有什么办法可以在载入过一次之后关掉DBGRID或者DATASOURCE?
    想要再次载入的时候再打开?

    修改Active属性,切换连接,还是关闭

    引用 11 楼 yuanreid 的回复:
    引用 9 楼 wujiajia1989 的回复:
    有什么办法可以在载入过一次之后关掉DBGRID或者DATASOURCE?
    想要再次载入的时候再打开?

    修改Active属性,切换连接,还是关闭


    你说的ACTIVE是指ADOQUERY的?那关闭了,还能把数据载入到DBGRID里面去呢
    又或者说,怎么判断DBGRID已经载入了数据,我把ACITIVE关了呢?

    谁帮忙解决下哈,分不够可以额外加

    不知道你的数据载入是如何做的。如果本身DBGRID的Dataset没有改变,其控件是无法得知数据源的数据是否有变更的,前面已经说过用轮询的办法。

    数据载入就是自动的载入的,链接上DATASOURCE就可以了,没有额外的操作。
    轮询是指用一个计时器定时刷新吧?
    那到了时间后,怎么让他重新载入一次数据呢?

    ado_Query->SQL->Add("select *from TAB");这样来加数据到DBGRID里去的

    “还有一个线程在源源不断的对数据库写记录”是怎么实现的?

    动态的加载数据,控件使用静态的。

    能否用一个临时表中转.
    当有新数据时对临时表操作.

    怎么判断DBGRID已经载入了数据,我把ACITIVE关了呢?
    可以看临时表是否有数据就知道 DBGRID是否已经载入了数据

    这个问题还是没有搞定。
    请大虾们帮忙。
    我把问题再阐述一遍:DBGrid显示SQL里的数据,但是由于SQL里的数据是在即时更新的,这样怎么让DBGrid也在即时变化?
    请大虾们指教。可能的话,希望说的越详细越好。

  • Filed under: C++ Builder
  • //删除多选的记录
    void __fastcall TForm1::N1Click(TObject *Sender)
    {
      for(int i=0;i <(DBGrid1->SelectedRows->Count);i++)
      {
        DBGrid1->DataSource->DataSet->Bookmark=DBGrid1->SelectedRows->Items[i];
        DBGrid1->DataSource->DataSet->Delete();
      }
    }
    但是记录已经删除了DBGrid1->SelectedRows->Count还是不变,除非重新选择记录.这样很容易出错.
    高人指点一下.

    不行,还是没有更新DBGrid1->SelectedRows->Count的值.

    把这个DBGrid的DataSource的Enabled设置成false,再恢复为true试试

    要将MultiSelect 设为True

    以上都不行,是不是BUG啊

    删除数据后
    执行 selcet * from….
    搜索出数据,显示就不会错了

    引用 5 楼 epsont507 的回复:
    以上都不行,是不是BUG啊

    不会吧

    删完了,刷新一下数据集

    你的Bookmark用来干啥的?  代码不怎么完整!

      for(int i=0;i <DBGrid1->SelectedRows->Count;i++)
      {
        DBGrid1->DataSource->DataSet->GotoBookmark((void *)fm_ch_prod->DBGrid1->SelectedRows->Items[i].c_str());  //定位 如果有的话
        DBGrid1->DataSource->DataSet->Delete();
      }

    汗…….改的不对…..

    修改版
    for(int i=0;i <DBGrid1->SelectedRows->Count;i++)
      {
        DBGrid1->DataSource->DataSet->GotoBookmark((void *)DBGrid1->SelectedRows->Items[i].c_str());  //定位 如果有的话
        DBGrid1->DataSource->DataSet->Delete();
      }

  • Filed under: C++ Builder