激死我...stringgrid + checkbox還是不能,why? |
尚未結案
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
procedure TMainUserGroupForm.RightGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
Var
CheckBox: TCheckBox;
Begin
With RightGrid Do
Begin
CheckBox := TCheckBox(Objects[ACol, ARow]);
If (CheckBox <> Nil) Then
Begin
CheckBox.Height := DefaultRowHeight - 1;
CheckBox.Left := CellRect(ACol, ARow).Left 5;
CheckBox.Top := CellRect(ACol, ARow).Top 1;
CheckBox.Width := CellRect(ACol, ARow).Right - CellRect(ACol, ARow).Left - 8;
End;
End;
End; Procedure TMainUserGroupForm.SetRightGrid;
Var
CheckBox: TCheckBox;
intX, intY: Integer;
Begin
RightGrid.RowCount := Length(c_FunctionName) 1;
For intX := 1 To Length(c_FunctionName) Do
Begin
If Length(RightGrid.Cells[1, intX]) = 0 Then
Begin
RightGrid.Cells[1, intX] := c_FunctionName[intX, 1]; For intY := 2 To 6 Do
Begin
If (c_FunctionName[intX, intY] = 'T') Then
Begin
With CheckBox Do
Begin
CheckBox := TCheckBox.Create(RightGrid);
Name := Format('RightGridCheckBox_%d_%d', [ intY, intX ] );
Caption := '';
Checked := False;
Visible := False;
Enabled := False;
Parent := RightGrid;
Height := RightGrid.DefaultRowHeight - 1;
Left := RightGrid.CellRect(intY, intX).Left 5;
Top := RightGrid.CellRect(intY, intX).Top 1;
Width := RightGrid.CellRect(intY, intX).Right - RightGrid.CellRect(intY, intX).Left - 8;
Show;
OnMouseDown := GridCheckBoxMouseDown; RightGrid.Objects[intY, intX] := CheckBox;
End;
End;
End;
End;
End;
End; 點解移動scorll bar時還,checkbox的value走了位...
|
william
版主 發表:66 回覆:2535 積分:3048 註冊:2002-07-11 發送簡訊給我 |
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
william
版主 發表:66 回覆:2535 積分:3048 註冊:2002-07-11 發送簡訊給我 |
|
hagar
版主 發表:143 回覆:4056 積分:4445 註冊:2002-04-14 發送簡訊給我 |
小弟試了一下, checkbox 的 value 並沒有走掉
因為數個 checkbox 重疊在一起了
只是找不到解決的方法.
可以參考 Peter Below 的範例:
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Grids; type TForm1 = class(TForm) StringGrid1: TStringGrid; procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure StringGrid1Click(Sender: TObject); procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); procedure StringGrid1KeyPress(Sender: TObject; var Key: Char); private { Private declarations } FCheck, FNoCheck: TBitmap; procedure ToggleCheckbox(acol, arow: Integer); public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} type TGridCracker = Class( TStringgrid ); procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var grid: TStringgrid; begin If not ( gdFixed In State ) and (aCol = 1) Then Begin grid:= Sender As TStringgrid; With grid.Canvas Do Begin brush.color := $E0E0E0; // checkboxes look better on a non-white background Fillrect( rect ); // listbox state is encoded by the Objects property If Assigned(grid.Objects[aCol, aRow]) Then Draw( (rect.right rect.left - FCheck.width) div 2, (rect.bottom rect.top - FCheck.height) div 2, FCheck ) Else Draw( (rect.right rect.left - FNoCheck.width) div 2, (rect.bottom rect.top - FNoCheck.height) div 2, FNoCheck ) End; End; end; procedure TForm1.FormCreate(Sender: TObject); var bmp: TBitmap; begin FCheck:= TBitmap.Create; FNoCheck:= TBitmap.Create; bmp:= TBitmap.create; try bmp.handle := LoadBitmap( 0, PChar(OBM_CHECKBOXES )); // bmp now has a 4x3 bitmap of divers state images // used by checkboxes and radiobuttons With FNoCheck Do Begin // the first subimage is the unchecked box width := bmp.width div 4; height := bmp.height div 3; canvas.copyrect( canvas.cliprect, bmp.canvas, canvas.cliprect ); End; With FCheck Do Begin // the second subimage is the checked box width := bmp.width div 4; height := bmp.height div 3; canvas.copyrect( canvas.cliprect, bmp.canvas, rect( width, 0, 2*width, height )); End; finally bmp.free end; end; procedure TForm1.FormDestroy(Sender: TObject); begin FNoCheck.Free; FCheck.Free; end; procedure TForm1.StringGrid1Click(Sender: TObject); var pt: TPoint; grid: TStringgrid; aCol, aRow: Integer; begin GetCursorPos( pt ); grid := Sender As TStringgrid; pt:= grid.ScreenToClient( pt ); grid.MouseToCell( pt.x, pt.y, aCol, aRow ); If (aCol = 1) and (aRow >= grid.fixedRows) Then Begin // click landed in a checkbox cell ToggleCheckbox( aCol, aRow ); End; end; procedure TForm1.ToggleCheckbox( acol, arow: Integer ); begin If aCol = 1 Then With TGridCracker( stringgrid1 ) Do Begin If Assigned( Objects[aCol, aRow] ) Then Objects[aCol, aRow] := Nil Else Objects[aCol, aRow] := Pointer(1); InvalidateCell( aCol, aRow ); End; end; procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); begin With Sender as TStringgrid Do If aCol = 1 Then Options := Options - [ goediting ] Else Options := Options [ goediting ]; end; procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char); begin If Key = #32 Then With Sender As Tstringgrid Do If Col = 1 Then Begin ToggleCheckbox( Col, row ); Key := #0; End; end; end.-- 悟嗎? |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
BorlandUser 你好
試試改用事件的參數Rect procedure TMainUserGroupForm.RightGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); Var CheckBox: TCheckBox; Begin With RightGrid Do Begin CheckBox := TCheckBox(Objects[ACol, ARow]); If (CheckBox <> Nil) Then Begin CheckBox.Height := DefaultRowHeight - 1; CheckBox.Left := RightGrid.Left Rect.Left 5;//CellRect(ACol, ARow).Left 5; CheckBox.Top := RightGrid.Top Rect.Top 1;//CellRect(ACol, ARow).Top 1; CheckBox.Width := Rect.Right-Rect.Left-8;//CellRect(ACol, ARow).Right - CellRect(ACol, ARow).Left - 8; End; End; End;修正一下!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 發表人 - chance36 於 2004/05/11 23:01:07 |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
BorlandUser 你好
我已修正過的仍然不行?還有一個注意事項,當StringGrid.Parent不是Form時,還要將CheckBox.Parent := StringGrid.Parent;如下 procedure TMainUserGroupForm.RightGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); Var CheckBox: TCheckBox; Begin With RightGrid Do Begin CheckBox := TCheckBox(Objects[ACol, ARow]); If (CheckBox <> Nil) Then Begin CheckBox.Parent := RightGrid.Parent; CheckBox.Height := DefaultRowHeight - 1; CheckBox.Left := RightGrid.Left Rect.Left 5;//CellRect(ACol, ARow).Left 5; CheckBox.Top := RightGrid.Top Rect.Top 1;//CellRect(ACol, ARow).Top 1; CheckBox.Width := Rect.Right-Rect.Left-8;//CellRect(ACol, ARow).Right - CellRect(ACol, ARow).Left - 8; End; End; End;若還是不行,你也要說明一下,怎麼不行?執行的狀況如何?才好判斷呀!不然就將程式上傳到[會員求助程式檔案上傳區],然後拉個連結過來,好讓大家可以深入了解問題的所在。 發表人 - chance36 於 2004/05/11 23:16:03 |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
unit MainUserGroup; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ComCtrls, Grids, FMTBcd, DB, SqlExpr; type
TMainUserGroupForm = class(TForm)
PageControl: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
StatusBar1: TStatusBar;
StringGrid1: TStringGrid;
SQLQuery1: TSQLQuery;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
private
{ Private declarations }
m_Mode: string;
m_GroupID: Integer;
procedure RefreshRightGrid;
procedure GridCheckBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
public
{ Public declarations }
end; var
MainUserGroupForm: TMainUserGroupForm; implementation {$R *.dfm} Uses DBModule, GlobalData, GlobalFunction; procedure TMainUserGroupForm.FormCreate(Sender: TObject);
begin
m_Mode := 'Ready';
RefreshRightGrid;
end; procedure TMainUserGroupForm.RefreshRightGrid;
var
I, J: Integer;
ck: TCheckBox;
begin
StringGrid1.RowCount := Length(g_FunctionName) + 1;
For I := 1 To Length(g_FunctionName) Do
Begin
If Length(StringGrid1.Cells[1, I]) = 0 Then
Begin
StringGrid1.Cells[1, I] := g_FunctionName[I, 1]; For J := 2 To 6 Do
Begin
If (g_FunctionName[I, J] = 'T') Then
Begin
ck := TCheckBox.Create(StringGrid1);
ck.Name := format('GridChkBox_%d_%d', [ J, I ] );
ck.caption := '';
ck.Checked := False;
ck.visible := False;
ck.parent := StringGrid1.Parent;
ck.Height := StringGrid1.DefaultRowHeight - 1;
ck.Left := StringGrid1.CellRect(J, I).Left + 5;
ck.Top := StringGrid1.CellRect(J, I).top + 1;
ck.Width := StringGrid1.CellRect(J, I).Right - StringGrid1.CellRect(J, I).Left - 5;
ck.Show; ck.OnMouseDown := GridCheckBoxMouseDown;
StringGrid1.Objects[J, I] := ck;
End;
End;
End;
End;
end;
procedure TMainUserGroupForm.GridCheckBoxMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
with Sender As TCheckbox do
Checked := not Checked;
end; procedure TMainUserGroupForm.StringGrid1DrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
ck:tcheckbox;
begin
ck:=tcheckbox(stringgrid1.objects[ACol,ARow]);
if(ck<>nil)then
begin
ck.Height := StringGrid1.DefaultRowHeight - 1;
ck.Left := StringGrid1.Left+Rect.Left+5;
ck.Top := StringGrid1.Left+Rect.Top+1;
ck.Width := Rect.Right-Rect.Left-5;
End;
end; Initialization
RegisterClass(TMainUserGroupForm); end. 以上是我改了的圖片,但這樣..就選不到勾選,而且顏色也變了...
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
貼上程式碼時按一下工具鈕中有[#]的按鈕,然後在〔code〕在這裏插入程式碼〔/code〕 貼出的文章才會有縮格的效果
For J := 2 To 6 Do Begin If (g_FunctionName[I, J] = 'T') Then Begin //ck := TCheckBox.Create(StringGrid1); ck := TCheckBox.Create(Self);// <------- 改成Self ck.Name := format('GridChkBox_%d_%d', [ J, I ] ); ck.caption := ''; ck.Checked := False; ck.visible := False; ck.parent := StringGrid1.Parent; ck.Height := StringGrid1.DefaultRowHeight - 1; ck.Left := StringGrid1.CellRect(J, I).Left 5; ck.Top := StringGrid1.CellRect(J, I).top 1; ck.Width := StringGrid1.CellRect(J, I).Right - StringGrid1.CellRect(J, I).Left - 5; // ck.Show; <----這行可省略 // ck.OnMouseDown := GridCheckBoxMouseDown;<---沒特殊動作可以不要 StringGrid1.Objects[J, I] := ck; End; End;[greeen]因為CheckBox 在你點下去時本來就會 沒勾變有勾 接著又在OnMouseDown事件中改變了Checked的屬性(有勾又變沒勾了)[/green] |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
procedure TMainUserGroupForm.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var ck:tcheckbox; begin ck:=tcheckbox(stringgrid1.objects[ACol,ARow]); if(ck<>nil)then begin ck.Height := StringGrid1.DefaultRowHeight - 1; ck.Left := StringGrid1.Left Rect.Left 5; ck.Top := StringGrid1.Left Rect.Top 1; ck.Width := Rect.Right-Rect.Left-5; End Else Begin // 這部份漏接了 inherited DrawCell; End; end;問題還不止這些唷!我再看看,我先洗個澡,待會再來 發表人 - chance36 於 2004/05/12 00:04:26 |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
// 答案出爐了 procedure TMainUserGroupForm.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var ck:tcheckbox; begin ck:=tcheckbox(stringgrid1.objects[ACol,ARow]); if(ck<>nil)then begin ck.Visible := True;// <--------- 加上這一行 因為Grid捲動後 通通被Disable // ck.BringToFront; // 一般沒有異常狀況 不用加 ck.Height := StringGrid1.DefaultRowHeight - 1; ck.Left := StringGrid1.Left Rect.Left 5; ck.Top := StringGrid1.Left Rect.Top 1; ck.Width := Rect.Right-Rect.Left-5; End Else Begin // 這部份漏接了 inherited ; // DrawCell; <------- 後面拿掉 End; end; 再於StringGrid的 OnTopLeftChanged事件中 ,把所有的CheckBox.Visiableyrhne 為False procedure TForm1.StringGrid1TopLeftChanged(Sender: TObject); Var r,c:Integer ; begin With TStringGrid(Sender) Do Begin For r:=FixedRows To RowCount-1 Do Begin For c := FixedCols To ColCount-1 Do Begin If objects[c,r] <> nil Then TCheckBox(objects[c,r]).Visible := False; End; End; End; end; |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
Chance36
版主 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
引言: 不過我不太明白什麼時後會觸發OnTopLeftChange ? 就是為何一定要用stringgrid.parent作為checkbox的parent呢?只用stringgrid會有何分別1.事件名稱已說明清楚啦!左上的Cell改變時,剛開始是[1,1]為左上Cell,往下捲動一列,不就變成[1,2]了嗎? 2.這問題,沒有圖形輔助,真不好說明,以Left來說明好了,假設Form 上放個Panel,又在Panel上放StringGrid,關係如下 Panel1.Parent := Form1; Panel1.Left := 10 ; Panel.Top := 10 ; StringGrid.Parent:= Panel, StringGrid.Left:=10, StringGrid.Top:= 10; 現有一個CheckBox ,對應到StringGrid.Cells[0,0]時,其左上座標是多少? CheckBox.Parent := Form時 CheckBox.Left := Panel.Left StringGrid.Left CellRect(c,r); CheckBox.Parent := Panel時 CheckBox.Left := StringGrid.Left CellRect(c,r); 若CheckBox.Parent := StringGrid時 CheckBox.Left := CellRect(c,r); 好像沒問題,畫面也正常,但是用滑鼠點看看,是不是不聽話?我也不知原因 主要是少一層關係而已,程式碼也比較乾淨,萬一StringGrid放在多層Panel又加PageControl,其中又有Panel或其他Contaner的物件中,那可就麻煩了。所以只要Parent設成與StringGrid一樣後,只要相對於StringGrid的位移算出來就一勞永逸。 發表人 - chance36 於 2004/05/12 01:23:23 |
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
BorlandUser
中階會員 發表:148 回覆:217 積分:73 註冊:2004-02-19 發送簡訊給我 |
|
jest0024
高階會員 發表:11 回覆:310 積分:224 註冊:2002-11-24 發送簡訊給我 |
用繪的方式.. //自訂繪製TCheckBox的方法 procedure DrawCheckBox(Canvas:TCanvas;Ck:TCheckBox;Const R:TRect); Const bW = 13; var tx,ty :Integer; bR :TRect; uState:Integer; begin Canvas.Brush.Style:=bsSolid; Canvas.Brush.Color:=ck.Color; Canvas.FillRect(R); Canvas.Brush.Style:=bsClear; Canvas.Font:=ck.Font; //繪製方塊 DFCS_INACTIVE(Not Enabled) DFCS_CHECKED (Checked) uState:=DFCS_BUTTONCHECK; if(Not ck.Enabled)then uState:=uState or DFCS_INACTIVE; if(ck.Checked)then uState:=uState or DFCS_CHECKED; tx:=R.Left; ty:=R.Top (R.Bottom-R.Top-bw)div 2; DrawFrameControl(Canvas.Handle,Rect(tx,ty,tx bw,ty bw),DFC_BUTTON,uState); //繪製文字 tx:=tx bw 5; ty:=R.Top (R.Bottom-R.Top-Canvas.TextHeight('A'))div 2; if(Not Ck.Enabled)then begin Canvas.Font.Color:=clWindow; Canvas.TextOut(tx 1,ty 1,ck.Caption); Canvas.Font.Color:=clGrayText; Canvas.TextOut(tx ,ty ,ck.Caption); end else Canvas.TextOut(tx,ty,ck.Caption); end; //建立CheckBox元件 procedure TForm1.FormCreate(Sender: TObject); var ck :TCheckBox; i,j:Integer; begin for j:=1 to StringGrid1.RowCount-1 do for i:=1 to StringGrid1.ColCount-1 do begin ck:=TCheckBox.Create(Self); ck.Visible:=False; ck.Parent:=StringGrid1.Parent; ck.Caption:=Format('(%d,%d)',[i,j]); ck.OnExit:=CkExit; //離開checkBox時要把checkbox隱藏 ck.Color :=StringGrid1.Color; StringGrid1.Objects[i,j]:=ck; end; end; //離開元件時,自動隱藏 procedure TForm1.CkExit(Sender:TObject); begin if Sender is TCheckBox then TCheckBox(Sender).Visible:=False; end; //表格重繪時,須以自訂方式重繪 procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var ck:TCheckBox; begin ck:=TCheckBox(StringGrid1.Objects[ACol,ARow]); if(ck<>nil)then DrawCheckBox(StringGrid1.Canvas,ck,Rect); end; //當選擇相對表格時,將相對的Ck顯示並移動焦點 procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); var ck:TCheckBox; fR:TRect; begin ck:=TCheckBox(StringGrid1.Objects[ACol,ARow]); if(ck=nil)then Exit; fR:=StringGrid1.CellRect(ACol,ARow); //將Ck放到表格相對位置 Ck.Left:=StringGrid1.Left fR.Left 2; Ck.Top :=StringGrid1.Top fR.Top 2; Ck.Width:=fR.Right-fR.Left; Ck.Height:=fR.Bottom-fR.Top; //顯示ck並將焦點移到Ck Ck.Visible:=True; Ck.Checked:=Not Ck.Checked; Ck.SetFocus; end;學而時習之不亦樂乎! 發表人 - jest0024 於 2004/05/13 00:17:24 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |