在DELPHI中經常用到網格控制項(DBGrid)顯示資料,網格控制項只提供了每一行的顏色屬性,但在實際應用中我們經常希望它按某一行某一項的取值不同顯示不同的顏色,甚至在網格中的單位表格項中顯示出映像等等,下面我們以一個簡單的例子來告訴大家怎麼做。
比如我們要求如果春季有退書用紅色表示,如果秋季有退書用黃色表示
利用DBGrid自繪功能可以很容易地實現這樣的要求。使用者可以處理DBGrid的OnDrawColumnCell事件,在其中實現特殊的效果。要判 斷記錄是否滿足要求,可以使用DBGrid的DataLink屬性獲得資料,但DBGrid的DataLink屬性屬於保護成員,必須在 TCustomDBGrid的子類中調用。
type
TMyCustomDBGrid = class(TCustomDBGrid);
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
sCjts,sQjTs:String;
begin
with TMyCustomerDBGrid(Sender) do
begin
Cjts:=DataLink.Fields[5].AsString;
sQjts:=DataLink.Fields[9].AsString;
if sCjts<>‘‘ then //春季退書數量>0的用紅色顯示
Canvas.Brush.Color := clRed
else
if sQjts<>‘‘ then //秋季退書數量>0的用黃色顯示
Canvas.Brush.Color := clYellow
else
Canvas.Brush.Color:=clWhite;
Canvas.Font.Color:=clBlack;
canvas.fillrect(rect);
canvas.textout(rect.left+4,rect.top+4,Column.Field.AsString);
end;
end;
由此方法可以延伸出其它控制項的多種修飾方法,比如可以按資料項目值採用不同的顏色,可以按記錄號顯示不同的顏色。總之,靈活應用canvas、rect及bitmap等對象,可以將各種網格裝飾得絢麗多彩。
如何才能得到DBGRID的行號,而不是資料集的行號?
Edit1.Text :=inttostr(TDrawGrid(DBGrid1).Row);
在 Delphi 語言的資料庫編程中,DBGrid 是顯示資料的主要手段之一。但是 DBGrid 預設的外觀未免顯得單調和缺乏創意。其實,我們完全可以在我們的程式中通過編程來達到美化DBGrid 外觀的目的。通過編程,我們可以改變 DBGrid 的表頭、網格、網格線的前景色彩和背景色,以及相關的字型的大小和風格。
以下的樣本程式示範了對 DBGrid 各屬性的設定,使 Delphi 顯示的表格就像網頁中的表格一樣漂亮美觀。
樣本程式的運行:
在 Form1 上放置 DBGrid1、Query1、DataSource1 三個資料庫組件,設定相關的屬性,使 DBGrid1 能顯示表中的資料。然後,在 DBGrid1 的 onDrawColumnCell 事件中鍵入以下代碼,然後運行程式,就可以看到神奇的結果了。本代碼在 Windows98、Delphi5.0 環境下調試通過。
procedure TMainForm.DBGrid1DrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn;State: TGridDrawState);
var i :integer;
begin
if gdSelected in State then Exit;
//定義表頭的字型和背景顏色:
for i :=0 to (Sender as TDBGrid).Columns.Count-1 do
begin
(Sender as TDBGrid).Columns[i].Title.Font.Name :='宋體'; //字型
(Sender as TDBGrid).Columns[i].Title.Font.Size :=9; //字型大小
(Sender as TDBGrid).Columns[i].Title.Font.Color :=$000000ff; //字型顏色(紅色)
(Sender as TDBGrid).Columns[i].Title.Color :=$0000ff00; //背景色(綠色)
end;
//隔行改變網格背景色:
if Query1.RecNo mod 2 = 0 then
(Sender as TDBGrid).Canvas.Brush.Color := clInfoBk //定義背景顏色
else
(Sender as TDBGrid).Canvas.Brush.Color := RGB(191, 255, 223); //定義背景顏色
//定義網格線的顏色:
DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
with (Sender as TDBGrid).Canvas do //畫 cell 的邊框
begin
Pen.Color := $00ff0000; //定義畫筆顏色(藍色)
MoveTo(Rect.Left, Rect.Bottom); //畫筆定位
LineTo(Rect.Right, Rect.Bottom); //畫藍色的橫線
Pen.Color := $0000ff00; //定義畫筆顏色(綠色)
MoveTo(Rect.Right, Rect.Top); //畫筆定位
LineTo(Rect.Right, Rect.Bottom); //畫綠色的豎線
end;
end;
--- 隔行改變DBGrid網格顏色
在 Form1 上放置 DBGrid1、Query1、DataSource1 三個資料庫組件,設定相關的屬性,使 DBGrid1 能顯示表中的資料。然後,在 DBGrid1 的 onDrawColumnCell 事件中鍵入以下代碼,然後運行程式
代碼:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var i:integer;
begin
if gdSelected in State then Exit; //隔行改變網格背景色:
if adoQuery1.RecNo mod 2 = 0 then
(Sender as TDBGrid).Canvas.Brush.Color := clinfobk //定義背景顏色
else
(Sender as TDBGrid).Canvas.Brush.Color := RGB(191, 255, 223); //定義背景顏色
//定義網格線的顏色:
DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
with (Sender as TDBGrid).Canvas do //畫 cell 的邊框
begin
Pen.Color := $00ff0000; //定義畫筆顏色(藍色)
MoveTo(Rect.Left, Rect.Bottom); //畫筆定位
LineTo(Rect.Right, Rect.Bottom); //畫藍色的橫線
Pen.Color := clbtnface; //定義畫筆顏色(蘭色)
MoveTo(Rect.Right, Rect.Top); //畫筆定位
LineTo(Rect.Right, Rect.Bottom); //畫綠色
end;
end;
用BDE中的table1未能通過,顏色沒有隔行變化。
在Delphi的DBGrid中插入其他可視組件 Delphi提供了功能強大的 DBGrid組件,以方便進行資料庫應用程式設計。但是如果我們僅僅利用DBGrid組件,每一個獲得焦點(Grid)只是一個簡單的文本編輯框,不方便 使用者輸入資料。Delphi也提供了一些其他資料群組件來方便使用者輸入,比如DBComboBox,DBCheckBox等組件,但這些組件卻沒有 DBGrid功能強大。Delphi能不能象Visual Foxpro那樣讓DBGrid中獲得焦點網格可以是其它可視資料群組件以方便使用者呢?其實我們可以通過在DBGrid中插入其他可視組件來實現這一點。
Delphi 對DBGrid處理的內部機制,就是在網格上浮動一個組件——DBEdit組件。你輸入資料的網格其實是浮動DBEdit組件,其他未獲得焦點地方不過是 映像罷了。所以,在DBGrid中插入其他可視組件就是在網格上浮動一個可視組件。因此任何組件,包括從簡單的DbCheckBox到複雜的對話方塊,都可 以在DBGrid中插入。下面就是一個如何在DBGrid中插入DBComboBox組件的步驟,採用同樣的辦法可以插入其他組件。
1、在Delphi 4.0中建立一個項目。
2、分別拖動的Data Access組件板上DataSource、Table,Data Controls組件板上DBGrid,DBComboBox四個組件到Form1上。
3、設定各個組件的屬性如下:
rcf1對象 屬性 設定植
Form1 Caption '在DBGrid中插入SpinEdit組件樣本'
DataSource1 DataSet Table1
Table1 DatabaseName DBDEMOS
TableName 'teacher.DBF'
Active True
DBGrid1 DataSource DataSource1
DBComboBox1 DataField SEX
DataSource DataSource1
Visible False
Strings Items. '男'| '女'
注意:我在這裡用了Teacher.dbf,那是反映教職工的性別,只能是“男”或者是“女”。
4、 DrawDataCell事件是繪製儲存格,當獲得焦點網格所對應的欄位與組合框所對應的欄位一致時,移動組合框到獲得焦點的網格上,並且使組合框可視, 從而達到在DBGrid指定列上顯示DBComboBox的功能。設定DBGrid1的OnDrawDataCell事件如下:
procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect; Field: TField; State: TGridDrawState);
begin
if (gdFocused in State) then
begin
if (Field.FieldName = DBComboBox1.DataField ) then
begin
DBComboBox1.Left := Rect.Left + DBGrid1.Left;
DBComboBox1.Top := Rect.Top + DBGrid1.top;
DBComboBox1.Width := Rect.Right - Rect.Left;
DBComboBox1.Height := Rect.Bottom - Rect.Top;
DBComboBox1.Visible := True;
end;
end;
end;
5、DBGrid指定儲存格未獲得焦點時不顯示DBComboBox,設定DBGrid1的OnColExit事件如下:
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
If DBGrid1.SelectedField.FieldName = DBComboBox1.DataField then
begin
DBComboBox1.Visible := false;
end;
end;
6、 當DBGrid指定列獲得焦點時DrawDataCell事件只是繪製儲存格,並顯示DBComboBox,但是DBComboBox並沒有獲得焦點,數 據的輸入還是在儲存格上進行。在DBGrid1的KeyPress事件中調用SendMessage這個 Windows API函數將資料輸入傳輸到DBComboBox上,從而達到在DBComboBox上進行資料輸入。因此還要設定KeyPress事件如下:
procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
if (key < > chr(9)) then
begin
if (DBGrid1.SelectedField.FieldName =DBComboBox1.DataField) then
begin
DBComboBox1.SetFocus;
SendMessage(DBComboBox1.Handle,WM_Char,word(Key),0);
end;
end;
end;
程式在中文Windows 98,Delphi 4.015 下調試通過。希望本文能使你可以更加方便快捷的開發資料庫應用程式。
鎖定DBGrid左邊的列 我在使用 Delphi3 進行資料庫編程的時候,希望 DBGRID 構件在顯示資料的時候能象FoxPro 的 BROWSE 命令一樣,鎖定左邊指定的幾列不進行滾動,請問應用什麼方法來實現?
我 們知道 Delphi 的 TStringGrid 有一個屬性 FixedCols 來指定不滾動的列。雖然TDBGrid 不能直接使用這一屬性,但通過強制類型轉換也可以首先這一功能,因為這兩個類都來自 TCustomGrid 類。下面我們以 Delphi 3.0的 Demos\Db\CtrlGrid 為例來說明具體的用法。在這個例子的 TFmCtrlGrid.FormShow 過程中加入如下一行:
TStringGrid(DbGrid1).FixedCols := 2;
運行該程式,在左右移動各列時,Symbol 列不會移動。除了這種方法,也可以採用下面的方法:首先在 Form 聲明部分加上
type TMyGrid = Class(TDBGrid) end;
然後在 TFmCtrlGrid.FormShow 過程中加入:
TMyGrid(DbGrid1).FixedCols := 2;
兩者從形式上略有不同,但實質都是一樣的,我們這裡設定 FixedCols 為 2,這是因為在 DBGrid 構件最左側有個指示列,如果你將 DBGrid 的 Options 屬性的 dgIndicator 設為False,則應設定 FixedCols 為1。
使dbgrid的某幾筆資料變色 你可在 DBGrid 元件的 DrawDataCell 事件中依資料的條件性來改變格子或文字的顏色.
如 :
OnDrawDataCell(...)
begin
with TDBGrid(Sender) do
begin
if (條件) then
Canvas.TextOut(Rect.Left + 4
Rect.Top + 2
'要顯示的文字如表格的資料');
end;
而你會看到 DBGrid 的顯示資料怎麽有重疊的情況那是因為原本DBGrid要顯示的資料與 TextOut 所顯示的資料重疊
解決方案 :
在 Query 元件所加入的欄位(在元件上按右鍵會有 Add Fields...的選單)在不要顯示資料的欄位的 OnGetText 事件中有一參數設定為 False;
procedure TForm1.Query1Detail1GetText(Sender: TField; var Text: string;
DisplayText: Boolean);
begin
// 決定在 DBGrid 得知表格資料時要不要顯示所得到的資料False -> 不顯示
// 就可避免與 TextOut 的文字重疊了
DisplayText : = False;
end;
end;
如果用 Delphi 3 處理很簡單.例如:對錶中某欄位當其數值小於0時為紅字其他為黑字.
在 DBGrid.OnDrawColumnCell(...) 中:
begin
if TableField.AsInteger < 0 then
DBGrid.Canvas.Font.Color := clRed
else
DBGrid.Canvas.Font.Color := clBlack;
DBGrid.DefaultDrawColumnCell(...);
end;
這樣對 Field 指定的格式仍舊生效不必重寫。
實戰Delphi資料格色彩特效 Delphi中的資料格控制項(TDbGrid)對於顯示和編輯資料庫中大量的資料起著十分重要的作用;然而,在使用資料格控制項的同時,也往往因為表格 中大量的資料不易區分,而令操作者眼花繚亂。如何提高網格控制項的易用性,克服它的此項不足呢?本文從改變資料格的色彩配置角度,提出了一種解決辦法。
以下為資料格控制項的6種特殊效果的實現方法,至於資料格控制項與資料集如何串連的方法從略.
1. 縱向斑馬線效果:實現網格的奇數列和偶數列分別以不同的顏色顯示以區別相鄰的資料列。
file://在DbGrid的DrawColumnCell事件中編寫如下代碼:
Case DataCol Mod 2 = 0 of
True: DbGrid1.Canvas.Brush.Color:= clBlue; file://偶數列用藍色
False: DbGrid1.Canvas.Brush.Color:= clAqua; file://奇數列用淺綠色
End;
DbGrid1.Canvas.Pen.Mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
2. 縱向斑馬線,同時以紅色反白目前的儲存格效果:以反白當前選中的欄位。
file://將上述代碼修改為:
Case DataCol Mod 2 = 0 of
True: DbGrid1.Canvas.Brush.Color:= clBlue; file://偶數列用藍色
False: DbGrid1.Canvas.Brush.Color:= clAqua; file://奇數列用淺綠色
End;
If ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
If Not DbGrid1.SelectedRows.CurrentRowSelected then
DbGrid1.Canvas.Brush.Color:=clRed; file://當前選中儲存格顯示紅色
DbGrid1.Canvas.Pen.Mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
上述兩種方法突出了列的顯示效果。
3.在資料格中以紅色反白當前選中的行。
設定DbGrid控制項的Options屬性中的dgRowSelect屬性為真,Color屬性為clAqua(背景色)
在DbGrid的DrawColumnCell事件中編寫如下代碼:
if ((State = [gdSelected]) or (State=[gdSelected gdFocused])) then
DbGrid1.Canvas.Brush.color:=clRed; file://當前行以紅色顯示,其它行使用背景的淺綠色
DbGrid1.Canvas.pen.mode:=pmmask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
4.行突顯的斑馬線效果:既突出當前行,又區分不同的列(欄位)。
file://其它屬性設定同3,將上述代碼修改為:
if ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
begin
Case DataCol Mod 2 = 0 of
True : DbGrid1.Canvas.Brush.color:=clRed; file://當前選中行的偶數列顯示紅色
False: DbGrid1.Canvas.Brush.color:=clblue; file://當前選中行的奇數列顯示藍色
end;
DbGrid1.Canvas.pen.mode:=pmmask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
end;
5.橫向斑馬線, 同時以紅色突顯當前行效果。
file://其它屬性設定同3,將上述代碼修改為:
Case Table1.RecNo mod 2 = 0 of file://根據資料集的記錄號進行判斷
True : DbGrid1.Canvas.Brush.color:=clAqua; file://偶數行用淺綠色顯示
False: DbGrid1.Canvas.Brush.color:=clblue; file://奇數行用藍色表示
end;
if ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then file://選中行用紅色顯示
DbGrid1.Canvas.Brush.color:=clRed;
DbGrid1.Canvas.pen.mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
6.雙向斑馬線效果:即行間用不同色區分,同時,選中行以縱向斑馬線效果區分不同的列。
file://其它屬性設定同3,將上述代碼修改為:
Case Table1.RecNo mod 2 = 0 of file://根據資料集的記錄號進行判斷
True : DbGrid1.Canvas.Brush.color:=clAqua; file://偶數行用淺綠色顯示
False: DbGrid1.Canvas.Brush.color:= clblue; file://奇數行用藍色表示
end;
If ((State = [gdSelected]) or (State=[gdSelectedgdFocused])) then
Case DataCol mod 2 = 0 of
True : DbGrid1.Canvas.Brush.color:=clRed; file://當前選中行的偶數列用紅色
False: DbGrid1.Canvas.Brush.color:= clGreen; file://當前選中行的奇數列用綠色表示
end;
DbGrid1.Canvas.pen.mode:=pmMask;
DbGrid1.DefaultDrawColumnCell (Rect
DataCol
Column
State);
上述6種方法分別就資料格控制項的列和行的色彩進行了設定,讀者可以根據自己的需要設定特效。
點擊DBGrid的Title對查詢結果排序 關鍵詞:DBGrid 排序
欲 實現點擊DBGrid的Title對查詢結果排序,想作一個通用程式,不是一事一議,例如不能在SQL語句中增加Order by ...,因為SQL可能原來已經包含Order by ...,而且點擊另一個Title時又要另外排序,目的是想作到象資源管理員那樣隨心所欲。
procedure TFHkdata.SortQuery(Column:TColumn);
var
SqlStr,myFieldName,TempStr: string;
OrderPos: integer;
SavedParams: TParams;
begin
if not (Column.Field.FieldKind in [fkData,fkLookup]) then exit;
if Column.Field.FieldKind =fkData then
myFieldName := UpperCase(Column.Field.FieldName)
else
myFieldName := UpperCase(Column.Field.KeyFields);
while Pos(myFieldName,';')<>0 do
myFieldName := copy(myFieldName,1,Pos(myFieldName,';')-1)+ ',' + copy(myFieldName,Pos(myFieldName,';')+1,100);
with TQuery(TDBGrid(Column.Grid).DataSource.DataSet) do
begin
SqlStr := UpperCase(Sql.Text);
// if pos(myFieldName,SqlStr)=0 then exit;
if ParamCount>0 then
begin
SavedParams := TParams.Create;
SavedParams.Assign(Params);
end;
OrderPos := pos('ORDER',SqlStr);
if (OrderPos=0) or (pos(myFieldName,copy(SqlStr,OrderPos,100))=0) then
TempStr := ' Order By ' + myFieldName + ' Asc'
else if pos('ASC',SqlStr)=0 then
TempStr := ' Order By ' + myFieldName + ' Asc'
else
TempStr := ' Order By ' + myFieldName + ' Desc';
if OrderPos<>0 then SqlStr := Copy(SqlStr,1,OrderPos-1);
SqlStr := SqlStr + TempStr;
Active := False;
Sql.Clear;
Sql.Text := SqlStr;
if ParamCount>0 then
begin
Params.AssignValues(SavedParams);
SavedParams.Free;
end;
Prepare;
Open;
end;
end;