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;
Delphi7 - 隔行改變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;
Delphi5用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 (RectDataCol 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 (RectDataCol 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 (RectDataColColumnState);
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 (RectDataColColumnState); 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 (RectDataColColumnState);
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 (RectDataColColumnState);
上述6種方法分別就數據網格控件的列和行的色彩進行了設置,讀者可以根據自己的需要設置特效。該程序在Delphi5中測試通過。
點擊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;
去掉DbGrid的自動添加功能
關鍵詞:DbGrid
移動到最后一條記錄時再按一下“下”就會追加一條記錄,如果去掉這項功能
procedure TForm1.DataSource1Change(Sender: TObject; Field: TField); begin if TDataSource(Sender).DataSet.Eof then TDataSource(Sender).DataSet.Cancel; end;
DBGrid不支持鼠標的上下移動的解決代碼
自己捕捉WM_MOUSEWHEEL消息處理
private OldGridWnd : TWndMethod; procedure NewGridWnd (var Message : TMessage); public procedure TForm1.NewGridWnd(var Message: TMessage); var IsNeg : Boolean; begin if Message.Msg = WM_MOUSEWHEEL then begin IsNeg := Short(Message.WParamHi) < 0; if IsNeg then DBGrid1.DataSource.DataSet.MoveBy(1) else DBGrid1.DataSource.DataSet.MoveBy(-1) end else OldGridWnd(Message); end; procedure TForm1.FormCreate(Sender: TObject); begin OldGridWnd := DBGrid1.WindowProc ; DBGrid1.WindowProc := NewGridWnd; end;
dbgrid中移動焦點到指定的行和列
dbgrid是從TCustomGrid繼承下來的,它有col與row屬性,只不過是protected的,不能直接訪問,要處理一下,可以這樣:
TDrawGrid(dbgrid1).row:=row; TDrawGrid(dbgrid1).col:=col; dbgrid1.setfocus;
就可以看到效果了。
1 這個方法是絕對有問題的,它會引起DBGrid內部的混亂,因為DBGrid無法定位當前紀錄,如果DBGrid只讀也就罷了(只讀還是會出向一些問題,比如原本只能單選的紀錄現在可以出現多選等等,你可以自己去試試),如果DBGrid可編輯那問題就可大了,因為當前紀錄的關系,你更改的數據字段很可能不是你想象中的
2 我常用的解決辦法是將上程序改為(隨便設置col是安全的,沒有一點問題)
Query1.first; TDrawGrid(dbgrid1).col:=1; dbgrid1.setfocus;
這就讓焦點移到第一行第一列當中
如何使DBGRID網格的顏色隨此格中的數據值的變化而變化?
在做界面的時候,有時候為了突出顯示數據的各個特性(如過大或者過小等),需要通過改變字體或者顏色,本文就是針對這個情況進行的說明。
如何使DBGRID網格的顏色隨此格中的數據值的變化而變化。如<60的網格為紅色?
Delphi中數據控制構件DBGrid是用來反映數據表的最重要、也是最常用的構件。在應用程序中,如果以彩色的方式來顯示DBGrid,將會增加其可視性,尤其在顯示一些重要的或者是需要警示的數據時,可以改變這些數據所在的行或列的前景和背景的顏色。
DBGrid屬性DefaultDrawing是用來控制Cell(網格)的繪制。若DefaultDrawing的缺省設置為True,意思是Delphi使用DBGrid的缺省繪制方法來制作網格和其中所包含的數據,數據是按與特定列相連接的Tfield構件的DisplayFormat或EditFormat特性來繪制的;若將DBGrid的DefaultDrawing特性設置成False,Delphi就不繪制網格或其內容,必須自行在TDBGrid的OnDrawDataCell事件中提供自己的繪制例程(自畫功能)。
在這里將用到DBGrid的一個重要屬性:畫布Canvas,很多構件都有這一屬性。Canvas代表了當前被顯示DBGrid的表面,你如果把另行定義的顯示內容和風格指定給DBGrid對象的Canvas,DBGrid對象會把Canvas屬性值在屏幕上顯示出來。具體應用時,涉及到Canvas的Brush屬性和FillRect方法及TextOut方法。Brush屬性規定了DBGrid.Canvas顯示的圖像、顏色、風格以及訪問Windows GDI 對象句柄,FillRect方法使用當前Brush屬性填充矩形區域,方法TextOut輸出Canvas的文本內容。
以下用一個例子來詳細地說明如何顯示彩色的DBGrid。在例子中首先要有一個DBGrid構件,其次有一個用來產生彩色篩選條件的SpinEdit構件,另外還有ColorGrid構件供自由選擇數據單元的前景和背景的顏色。
1.建立名為ColorDBGrid的Project,在其窗體Form1中依次放入所需構件,並設置屬性為相應值,具體如下所列:
Table1 DatabaseName: DBDEMOS TableName: EMPLOYEE.DB Active: True; DataSource1 DataSet: Table1 DBGrid1 DataSource1: DataSource1 DefaultDrawing: False SpinEdit1 Increment:200 Value: 20000 ColorGrid1 GridOrdering: go16*1
2.為DBGrid1構件OnDrawDataCell事件編寫響應程序:
//這里編寫的程序是<60的網格為紅色的情況,其他的可以照此類推 procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;Field: TField; State: TGridDrawState); begin if Table1.Fieldbyname(′Salary′).value<=SpinEdit1.value then DBGrid1.Canvas.Brush.Color:=ColorGrid1.ForeGroundColor else DBGrid1.Canvas.Brush.Color:=ColorGrid1.BackGroundColor; DBGrid1.Canvas.FillRect(Rect); DBGrid1.Canvas.TextOut(Rect.left+2,Rect.top+2,Field.AsString); end;
這個過程的作用是當SpinEdit1給定的條件得以滿足時,如′salary′變量低於或等於SpinEdit1.Value時,DBGrid1記錄以ColorGrid1的前景顏色來顯示,否則以ColorGrid1的背景顏色來顯示。然后調用DBGrid的Canvas的填充過程FillRect和文本輸出過程重新繪制DBGrid的畫面。
3.為SpinEdit1構件的OnChange事件編寫響應代碼:
procedure TForm1.SpinEdit1Change(Sender: TObject); begin DBGrid1.refresh; //刷新是必須的,一定要刷新哦 end;
當SpinEdit1構件的值有所改變時,重新刷新DBGrid1。
4.為ColorGrid1的OnChange事件編寫響應代碼:
procedure TForm1.ColorGrid1Change(Sender: TObject); begin DBGrid1.refresh; //刷新是必須的,一定要刷新哦 end;
當ColorGrid1的值有所改變時,即鼠標的右鍵或左鍵單擊ColorGrid1重新刷新DBGrid1。
5.為Form1窗體(主窗體)的OnCreate事件編寫響應代碼:
procedure TForm1.FormCreate(Sender: TObject); begin ColorGrid1.ForeGroundIndex:=9; ColorGrid1.BackGroundIndex:=15; end;
在主窗創建時,將ColorGrid1的初值設定前景為灰色,背景為白色,也即DBGrid的字體顏色為灰色,背景顏色為白色。
6.現在,可以對ColorDBGrid程序進行編譯和運行了。當用鼠標的左鍵或右鍵單擊ColorGrid1時,DBGrid的字體和背景顏色將隨之變化。
在本文中,只是簡單展示了以彩色方式顯示DBGrid的原理,當然,還可以增加程序的復雜性,使其實用化。同樣道理,也可以將這個方法擴展到其他擁有Canvas屬性的構件中,讓應用程序的用戶界面更加友好。
判斷Grid是否有滾動條?
這是一個小技巧,如果為了風格的統一的話,還是不要用了。:)
。。。
if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_VSCROLL) <> 0 then ShowMessage(\'Vertical scrollbar is visible!\'); if (GetWindowlong(Stringgrid1.Handle, GWL_STYLE) and WS_HSCROLL) <> 0 then ShowMessage(\'Horizontal scrollbar is visible!\');
兩個Grid的同步滾動
在實際制作一個項目當中,有時候需要幾個grid一起同步滾動以減少用戶的操作量。希望下面那段代碼對您有一定的參考價值。
{1.} unit SyncStringGrid; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids; type TSyncKind = (skBoth, skVScroll, skHScroll); TSyncStringGrid = class(TStringGrid) private FInSync: Boolean; FsyncGrid: TSyncStringGrid; FSyncKind: TSyncKind; { Private declarations } procedure WMVScroll(var Msg: TMessage); message WM_VSCROLL; procedure WMHScroll(var Msg: TMessage); message WM_HSCROLL; protected { Protected declarations } public { Public declarations } procedure DoSync(Msg, wParam: Integer; lParam: Longint); virtual; published { Published declarations } property SyncGrid: TSyncStringGrid read FSyncGrid write FSyncGrid; property SyncKind: TSyncKind read FSyncKind write FSyncKind default skBoth; end; procedure Register; implementation procedure Register; begin RegisterComponents(\ 'Samples\', [TSyncStringGrid]); end; procedure TSyncStringGrid.WMVScroll(var Msg: TMessage); begin if not FInSync and Assigned(FSyncGrid) and (FSyncKind in [skBoth, skVScroll]) then FSyncGrid.DoSync(WM_VSCROLL, Msg.wParam, Msg.lParam); inherited; end; procedure TSyncStringGrid.WMHScroll(var Msg: TMessage); begin if not FInSync and Assigned(FSyncGrid) and (FSyncKind in [skBoth, skHScroll]) then FSyncGrid.DoSync(WM_HSCROLL, Msg.wParam, Msg.lParam); inherited; end; procedure TSyncStringGrid.DoSync(Msg, wParam: Integer; lParam: Longint); begin FInSync := True; Perform(Msg, wParam, lParam); FinSync := False; end; end. {****************************************} {2.} private OldGridProc1, OldGridProc2: TWndMethod; procedure Grid1WindowProc(var Message: TMessage); procedure Grid2WindowProc(var Message: TMessage); public {...} procedure TForm1.Grid1WindowProc(var Message: TMessage); begin OldGridProc1(Message); if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or Message.msg = WM_Mousewheel)) then begin OldGridProc2(Message); end; end; procedure TForm1.Grid2WindowProc(var Message: TMessage); begin OldGridProc2(Message); if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or (Message.msg = WM_Mousewheel)) then begin OldGridProc1(Message); end; end; procedure TForm1.FormCreate(Sender: TObject); begin OldGridProc1 := StringGrid1.WindowProc; OldGridProc2 := StringGrid2.WindowProc; StringGrid1.WindowProc := Grid1WindowProc; StringGrid2.WindowProc := Grid2WindowProc;
在Delphi中隨意控制DBGrid 每一行的顏色簡易方法
Delphi中使用 DBGrid 控件時,每一列都能按需要隨意地改變顏色,但要改變每一行的顏色卻很難,那么在不重新制作新控制件的情況下,有沒有好的辦法讓DBGrid按照用戶自己要求隨意改變每一行顏色的?答案是有,下面介紹一種簡單的方法。
要改變DBGrid每一行的顏色,只要在ONDrawColumnCell事件中設定要改變顏色的行的條件,並指定DBGrid的Canvas.Brush.color屬性並且把Canvas.pen.mode屬性設成pmmask,再調用DBGrid 的DefaultDrawColumnCell方法即可。注意在改變這兩個屬性前要先保護好原來的Canvas.Brush.color 屬性的值,調節器用完成 DefaultDrawColumnCell 方法后要把原屬性值改回,現以 Delphi\\demos\\db\\clientmd 目錄下的演示程序 clintproj.dpr 為例子,做簡單說明,下面是對程序中的柵格 MemberGrid 的合條件的整行進行變色,變成黑體背景黃色的,其它不合條件的行的顏色為正常字體,白色背景,只在 DrawColumnCelL 事件中設條件其它的不變,如下:
procedure TClientForm.MemberGridDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var oldcolor:tcolor; oldpm:tpenmode; begin if DM.ProjectTEAM_LEADER.Value = DM.Emp_ProjEMP_NO.Value then {設定變色的行的條件} MemberGrid.Canvas.Font.Style := [fsBold]; MemberGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State); {上面是演示程序的原內容,以下是增加部分} if DM.ProjectTEAM_LEADER.Value =DM.Emp_ProjEMP_NO.Value then {設定變色的行的條件} begin oldpm:= MemberGrid.Canvas.pen.mode; oldcolor:= MemberGrid.Canvas.Brush.color; MemberGrid.Canvas.Brush.color:=clyellow; MemberGrid.Canvas.pen.mode:=pmmask; MemberGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State); MemberGrid.Canvas.Brush.color:=oldcolor; MemberGrid.Canvas.pen.mode:=oldpm; end; end;
感覺上這個方法和前面的幾個顏色控制方法的原理是一樣的,都是通過ONDrawColumnCell事件來實現變色醒目美化的功能。:)
如何在DBGrid中能支持多項記錄的選擇
這份文檔來自國外,粗略看了一下,很有用,推薦給大家學習使用。
【Question】: How to do multi-selecting records in TDBGrid? When you add [dgMultiSelect] to the Options property of a DBGrid, you give yourself the ability to select multiple records within the grid. The records you select are represented as bookmarks and are stored in the SelectedRows property. The SelectedRows property is an object of type TBookmarkList. The properties and methods are described below. // property SelectedRows: TBookmarkList read FBookmarks; // TBookmarkList = class // public {* The Clear method will free all the selected records within the DBGrid *} // procedure Clear; {* The Delete method will delete all the selected rows from the dataset *} // procedure Delete; {* The Find method determines whether a bookmark is in the selected list. *} // function Find(const Item: TBookmarkStr; // var Index: Integer): Boolean; {* The IndexOf method returns the index of the bookmark within the Items property. *} // function IndexOf(const Item: TBookmarkStr): Integer; {* The Refresh method returns a boolean value to notify whether any orphans were dropped (deleted) during the time the record has been selected in the grid. The refresh method can be used to update the selected list to minimize the possibility of accessing a deleted record. *} // function Refresh: Boolean; True = orphans found {* The Count property returns the number of currently selected items in the DBGrid *} // property Count: Integer read GetCount; {* The CurrentRowSelected property returns a boolean value and determines whether the current row is selected or not. *} // property CurrentRowSelected: Boolean // read GetCurrentRowSelected // write SetCurrentRowSelected; {* The Items property is a TStringList of TBookmarkStr *} // property Items[Index: Integer]: TBookmarkStr // read GetItem; default; // end; unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables; type TForm1 = class(TForm) Table1: TTable; DBGrid1: TDBGrid; Count: TButton; Selected: TButton; Clear: TButton; Delete: TButton; Select: TButton; GetBookMark: TButton; Find: TButton; FreeBookmark: TButton; DataSource1: TDataSource; procedure CountClick(Sender: TObject); procedure SelectedClick(Sender: TObject); procedure ClearClick(Sender: TObject); procedure DeleteClick(Sender: TObject); procedure SelectClick(Sender: TObject); procedure GetBookMarkClick(Sender: TObject); procedure FindClick(Sender: TObject); procedure FreeBookmarkClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; Bookmark1: TBookmark; z: Integer; implementation {$R *.DFM} //Example of the Count property procedure TForm1.CountClick(Sender: TObject); begin if DBgrid1.SelectedRows.Count > 0 then begin showmessage(inttostr(DBgrid1.SelectedRows.Count)); end; end; //Example of the CurrentRowSelected property procedure TForm1.SelectedClick(Sender: TObject); begin if DBgrid1.SelectedRows.CurrentRowSelected then showmessage(\'Selected\'); end; //Example of the Clear Method procedure TForm1.ClearClick(Sender: TObject); begin dbgrid1.SelectedRows.Clear; end; //Example of the Delete Method procedure TForm1.DeleteClick(Sender: TObject); begin DBgrid1.SelectedRows.Delete; end; {* This example iterates through the selected rows of the grid and displays the second field of the dataset. The Method DisableControls is used so that the DBGrid will not update when the dataset is changed. The last position of the dataset is saved as a TBookmark. The IndexOf method is called to check whether or not the bookmark is still existent. The decision of using the IndexOf method rather than the Refresh method should be determined by the specific application. *} procedure TForm1.SelectClick(Sender: TObject); var x: word; TempBookmark: TBookMark; begin DBGrid1.Datasource.Dataset.DisableControls; with DBgrid1.SelectedRows do if Count > 0 then begin TempBookmark:= DBGrid1.Datasource.Dataset.GetBookmark; for x:= 0 to Count - 1 do begin if IndexOf(Items[x]) > -1 then begin DBGrid1.Datasource.Dataset.Bookmark:= Items[x]; showmessage(DBGrid1.Datasource.Dataset.Fields[1].AsString); end; end; end; DBGrid1.Datasource.Dataset.GotoBookmark(TempBookmark); DBGrid1.Datasource.Dataset.FreeBookmark(TempBookmark); DBGrid1.Datasource.Dataset.EnableControls; end; {* This example allows you to set a bookmark and and then search for the bookmarked record within selected a record(s) within the DBGrid. *} //Sets a bookmark procedure TForm1.GetBookMarkClick(Sender: TObject); begin Bookmark1:= DBGrid1.Datasource.Dataset.GetBookmark; end; //Frees the bookmark procedure TForm1.FreeBookmarkClick(Sender: TObject); begin if assigned(Bookmark1) then begin DBGrid1.Datasource.Dataset.FreeBookmark(Bookmark1); Bookmark1:= nil; end; end; //Uses the Find method to locate the position of the bookmarked record within the selected list in the DBGrid procedure TForm1.FindClick(Sender: TObject); begin if assigned(Bookmark1) then begin if DBGrid1.SelectedRows.Find(TBookMarkStr(Bookmark1),z) then showmessage(inttostr(z)); end; end; end.
另外一種可以在在Delphi中隨意控制DBGrid 每一行顏色的方法
有個問題是在Delphi中使用DBGrid時,如何讓DBGrid中每一行顏色按照用戶自己的意願控
制。最初看到這個問題時,我們以為非常非常簡單,所以馬上動手准備解決它。結果卻發現不是
那么回事,傳統方法根本不能發揮作用。在電腦面前一直坐到凌晨4點,不斷地調試,幸運地是憑借平時積累的一點編程經驗,終於找到了開門的匙鑰。現將它充公,供大家享用。
1、 數據表的建立
在Delphi的工具菜單中選擇Database desktop,在數據庫DBDemos下建立一個名為
example.db的數據表。數據表的字段和內容如下:
Name Age Wage
張山 25 500
王武 57 1060
李市 30 520
劉牛 28 390
2、創建基於TDBGrid的TColoredDBGrid組件
在Delphi組件菜單中,選擇New Component,在彈出對話框中作以下設置:
Ancestor Type = TDBGrid
Class Name = TColoredDBGrid
然后單擊OK按鈕,Delphi自動完成組件基本框架的定義。增添OnDRawColoredDBGrid事件並
使它出現在Object Inspector的Events中以便在應用程序中設定改變行顏色的條件。重載
DrawCell方法,只能自己繪制單元格。不能通過在OnDrawColumnCell來設置顏色,因為在
OnDrawColumnCell改變單元格的顏色會再次觸發OnDrawColumnCell。
下面就是所創建組件的源程序 。
3、建立應用程序進行驗證。
在Delphi文件菜單中選擇New建立新的應用程序工程Project1和主窗體Form1,設置Form1的
Caption屬性為“控制DBGrid行顏色的示例”。在主窗體上添加Data Source、Table、Button和
ColoredDBGrid組件。設置各組件的屬性如下:
Table1.Database=’DBDemos’ Table1.Tablename=’example.db’ Datasource1.Dataset=Table1 ColoredDBGrid1.Datasource=DataSource1 Button1.Caption=’退出’
在ColoredDBGrid1的onDRawColoredDBGrid事件中輸入下列代碼,設定由Wage(工資)來決
定在ColoredDBGrid1各行的顏色。
procedure TForm1.ColoredDBGrid1 DRawColoredDBGrid (Sender: TObject; Field: TField; var Color: TColor; var Font: TFont); Var p : Integer; begin p := Table1.FindField(\'wage\').AsInteger; //取得當前記錄的Wage字段的值。 if (p < 500) then begin //程序將根據wage值設置各行的顏色。 Color := clGreen; Font.Style := [fsItalic]; //不僅可以改變顏色,還可以改變字體 end; if(p >= 500) And (p < 800) then Color := clRed; if(p >=800) then begin Color := clMaroon; Font.Style := [fsBold]; end; end; //用‘退出’按鈕結束程序運行。 procedure TForm1.Button1Click(Sender: TObject); begin Close; end;