Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Колонка CheckBox'ов в StringGrid'e


Страницы:   1 2

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.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо