![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Колонка CheckBox'ов в StringGrid'e
ShimON © (2005-03-12 18:48:00)Помогите, пожалуйста, реализовать сабж.
ShimON (2005-03-12 22:50:00) [1]Спасибо, я попробую
Юрий Зотов (2005-03-12 22:49:00) [2]> ShimON
Попробуйте писать компоненты. Во-первых, получите ценнейший опыт. Во-вторых, придется полазить по коду VCL (вот уж где кода более, чем достаточно). В-третьих, получите знания, которые трудно получить, если писать только прикладные программы.
ShimON (2005-03-12 22:34:00) [3]Так читаю, причем регулярно, но кода в них маловато... Может не то читаю...
Fenik (2005-03-12 22:32:00) [4]Книги читать надо.
ShimON (2005-03-12 22:17:00) [5]Сделал так, теперь буду знать, спасибо. Мне еще интересно, где этому научиться можно или это только с опытом приходит??
Юрий Зотов (2005-03-12 22:11:00) [6]> ShimON
1. Нельзя определять колонку с чекбоксами только по ее номеру - ведь юзер может и перетащить ее на другое место. Этот признак должна иметь сама колонка, независимо от своего номера - и такие признаки удобно хранить в свойстве Objects нулевой строки (если она Fixed).
2. Не надо ничего рисовать в мышином обработчике. Там надо только проставить признак того, стоит ли птичка, или нет (причем для этого тоже удобно использовать свойство Objects), а потом запросить перерисовку. Windows сама разберется, что, когда и как ей надо перерисовывать.
3. Приличная программа должна позволять юзеру переключать птички не только мышью, а еще и клавишей "пробел".
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
begin
with StringGrid1 do
for i := 0 to ColCount - 1 do
Objects[i, 0] := TObject(Odd(i))
end;
procedure TForm1.StringGrid1DrawCell(Sender: TObject;
ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
const
Flags: array[Boolean] of DWORD = (0, DFCS_CHECKED);
begin
with StringGrid1, Canvas do
begin
if gdSelected in State then
Brush.Color := clHighlight
else
Brush.Color := clWindow;
FillRect(Rect);
if (ARow >= FixedRows) and Boolean(Objects[ACol, 0]) then
begin
InflateRect(Rect, -4, -4);
DrawFrameControl(Canvas.Handle, Rect, DFC_BUTTON,
DFCS_FLAT or DFCS_BUTTONCHECK or Flags[Boolean(Objects[ACol, ARow])])
end
end
end;
procedure TForm1.StringGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
ACol, ARow: integer;
begin
if Button = mbLeft then
with StringGrid1 do
begin
MouseToCell(X, Y, ACol, ARow);
if (ACol >= FixedCols) and (ARow >= FixedRows) then
SwitchCell
end
end;
procedure TForm1.StringGrid1KeyPress(Sender: TObject;
var Key: Char);
begin
if Key = ' ' then
SwitchCell
end;
procedure TForm1.SwitchCell;
begin
with StringGrid1 do
begin
Objects[Col, Row] := TObject(not Boolean(Objects[Col, Row]));
Invalidate
end
end;
ShimON (2005-03-12 21:35:00) [7]Класс, мне нравиться! Буду учиться писать красиво и компактно!
begin...end (2005-03-12 21:31:00) [8]> ShimON © (12.03.05 21:19) [12]
const
States: array [Boolean] of Cardinal = (DFCS_BUTTONCHECK, DFCS_CHECKED);
begin
with (Sender as TStringGrid) do
begin
MouseToCell(X, Y, ACol, ARow);
if (ACol = 3) and (ARow <> 0) then
begin
if not ReportItems[ARow].InToolTip then
begin
ColInToolTip := 0;
for i := 1 to 10 do
begin
...
end
end;
ReportItems[ARow].InToolTip := not ReportItems[ARow].InToolTip;
DrawFrameControl(Canvas.Handle, CellRect(ACol, ARow), DFC_BUTTON, States[ReportItems[ARow].InToolTip])
end;
end
end.
ShimON (2005-03-12 21:23:00) [9]Всем большое спасибо, проблема решена.
Fenik (2005-03-12 21:21:00) [10]>if ReportItems[ARow].InToolTip then
> Flag:= false
> else
> Flag:= true;
Flag := not ReportItems[ARow].InToolTip; :))
или вообще
if not ReportItems[ARow].InToolTip then
begin
for i:= 1 to 10 do
begin
if ReportItems[i].InToolTip then
Inc(ColInToolTip);
if ColInToolTip >= 2 then
begin
beep;
MessageDlg('Можно показать только две строки.', mtWarning, [mbOK], 0);
exit;
end;
end;
ReportItems[ARow].InToolTip:= true;
DrawFrameControl(TStringGrid(Sender).Canvas.Handle, StringGrid1.CellRect(ACol, ARow), DFC_BUTTON, DFCS_CHECKED)
end
else
begin
ReportItems[ARow].InToolTip:= false;
DrawFrameControl(TStringGrid(Sender).Canvas.Handle, StringGrid1.CellRect(ACol, ARow), DFC_BUTTON, DFCS_BUTTONCHECK)
end;
ShimON (2005-03-12 21:19:00) [11]Все, я разобрался, суть флага в том, что если ячейка уже выбрана, то нужно просто убрать галочку, а если не выбрана, то надо проверить, что выделено не более двух ячеек и в этом случее только поставить галочку.
А ошибка в том, что надо было сделать наоборот:
if ReportItems[ARow].InToolTip then
Flag:= false
else
Flag:= true;
begin...end (2005-03-12 21:16:00) [12]> ShimON © (12.03.05 21:09) [9]
> Насчет кода, а почему он некорректкн??
Я не говорил, что он некорректен. Я сказал, что он неоптимален. Например, вот это:
> if ReportItems[ARow].InToolTip then
> Flag:= true
> else
> Flag:= false;
можно заменить на
Flag := ReportItems[ARow].InToolTip.
А строки
> ReportItems[ARow].InToolTip:= true
и
> ReportItems[ARow].InToolTip:= false
вообще не нужны.
Но всё это к обсуждаемому вопросу отношения не имеет. Что показывает отладчик - Вы выяснили причину проблемы? Или, может быть, лучше попробовать разобраться на новом (почти пустом) приложении, чтобы не запутываться?
Fenik (2005-03-12 21:15:00) [13]if ReportItems[ARow].InToolTip then
Flag:= true
else
Flag:= false;
Можно заменить на
Flag := ReportItems[ARow].InToolTip
Да и вообще, зачем этот Flag?
ShimON (2005-03-12 21:09:00) [14]Да, спасибо. именно это и сделал, но я пробывал все вернуть и так как не беребилдивал весь проект, то и результат был нулевой.
Насчет кода, а почему он некорректкн??
begin...end (2005-03-12 20:35:00) [15]> ShimON © (12.03.05 20:19) [7]
Относительно настроек компилятора - возможно, Вы отключили включение отладочной информации. Проверьте состояние галочки Project -> Options -> Compiler -> Debugging -> Debug Information - если она не установлена, то установите её и перебилдите проект (Project -> Build ...).
Приведённый код несколько неоптимален, но в целом серьёзных ошибок не видно. Сообщите о результатах работы с отладчиком.
ShimON (2005-03-12 20:19:00) [16]Спасибо, разобрался, но вот следущая проблема...
procedure TfmReport.StringGrid1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
ACol, ARow: integer;
i: byte;
ColInToolTip: byte;
Flag: boolean;
begin
StringGrid1.MouseToCell(X, Y, ACol, ARow);
if (ACol = 3) and (ARow <> 0) then
begin
if ReportItems[ARow].InToolTip then
Flag:= true
else
Flag:= false;
ColInToolTip:= 0;
if flag then
begin
for i:= 1 to 10 do
begin
if ReportItems[i].InToolTip then
Inc(ColInToolTip);
if ColInToolTip >= 2 then
begin
beep;
MessageDlg('Можно показать только две строки.', mtWarning, [mbOK], 0);
exit;
end;
end;
ReportItems[ARow].InToolTip:= true;
DrawFrameControl(TStringGrid(Sender).Canvas.Handle, StringGrid1.CellRect(ACol, ARow), DFC_BUTTON, DFCS_CHECKED)
end
else
begin
ReportItems[ARow].InToolTip:= false;
DrawFrameControl(TStringGrid(Sender).Canvas.Handle, StringGrid1.CellRect(ACol, ARow), DFC_BUTTON, DFCS_BUTTONCHECK)
end;
end;
end;
не меняется состояние и все тут, может я какое-то свойство поменял и клики не отлавливаются. Да, я еще по некой нужде покопался в настройках компилятора и линкера и у меня перестали появляться брикпоинты, то-есть появляются но он на них не останавливается (зажигает их зелеными крестиками), как мне это исправить??
Юрий Зотов (2005-03-12 20:10:00) [17]> ShimON
DefaultDrawing проверьте
begin...end (2005-03-12 20:07:00) [18]> ShimON © (12.03.05 19:20) [4]
А у меня точно такой же код работает.
ShimON (2005-03-12 19:20:00) [19]Пишу так в обработчике
procedure TfmReport.StringGrid1DrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
if ACol = 3 then
DrawFrameControl(TStringGrid(Sender).Canvas.Handle, Rect, DFC_BUTTON, DFCS_BUTTONCHECK);
end;
но эффекта ноль :( Что я делаю не так??
begin...end (2005-03-12 19:18:00) [20]> ShimON © (12.03.05 19:10) [2]
Обрабатывайте TStringGrid.OnMouseDown, проверяйте, на какой колонке кликнули (TStringGrid.MouseToCell), и, если нужно, перерисовывайте checkbox (уже в другом состоянии) с помощью той же DrawFrameControl.