На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Обязательно выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Этот раздел предназначен для вопросов, посвященных разработке компонентов, а также для тестирования собственных бесплатных компонентов с открытым исходным кодом.

Здесь запрещается:
1. Размещать ссылки на какие-либо коммерческие компоненты, реализующие требуемую функциональность.
2. Обсуждать и тестировать коммерческие компоненты или компоненты с закрытым кодом.
3. Давать ссылки на сайты с исходным кодом компонентов. Все тестируемые исходные коды должы быть размещены на сайте ИСХОДНИКИ.RU.
Модераторы: Rouse_, DimaBr
  
> Отображение элементов управления в компоненте StringGrid при прокрутке списка
    При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка.
    думаю, по аналогии можно будет решить и для прокрутки вверх.

    ExpandedWrap disabled
      procedure TMBList.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
       var
        TextTop:Integer;
        TextLeft:Integer;
        iTopRow, iBottomRow: integer;
        r, r1:TRect;
      begin
        if (acol=2) then
        begin
       
         if (FParams.Items[arow{+TopRow}].FButton<>nil) then
         begin
          r:=ARect;
          r.Left:=r.left+self.left+2;
          r.right:=r.right+self.left+2;
          r.top:=r.top+self.top+2;
          r.bottom:=r.bottom+self.top+2;
       
          FParams.Items[arow{+TopRow}].FButton.BoundsRect:=r;
          FParams.Items[arow{+TopRow}].FButton.Visible:=true;
         end;
       
         if FParams.Items[arow{+TopRow}].FCheckBox<>nil then
         begin
          r:=ARect;
          r.Left:=r.left+self.left+2;
          r.right:=r.right+self.left+2;
          r.top:=r.top+self.top+2;
          r.bottom:=r.bottom+self.top+2;
       
          FParams.Items[arow{+TopRow}].FCheckBox.BoundsRect:=r;
          FParams.Items[arow{+TopRow}].FCheckBox.Visible:=true;
         end;
       
         if (FParams.Items[arow{+TopRow}].FComboBox<>nil) then
         begin
          r:=ARect;
          r.Left:=r.left+self.left+2;
          r.right:=r.right+self.left+2;
          r.top:=r.top+self.top+2;
          r.bottom:=r.bottom+self.top+2;
       
          FParams.Items[arow{+TopRow}].FComboBox.BoundsRect:=r;
          FParams.Items[arow{+TopRow}].FComboBox.Visible:=true;
         end;
        end;
       
      end;


    Побовал через CellRect, но контрол тогда исчезает раньше, т.е. в позиции через строку ниже.

    ExpandedWrap disabled
      if (FParams.Items[arow].FButton<>nil) then
         begin
          r:=ARect;
          r1:=CellRect(2, arow);
       
           if (r1.Top=0) {and (r.Bottom=0) and (r.Left=0) and (r.Right=0)} then
            FParams.Items[arow].FButton.Visible:=false
           else
            FParams.Items[arow].FButton.Visible:=true;
       
          r.Left:=r.left+self.left+2;
          r.right:=r.right+self.left+2;
          r.top:=r.top+self.top+2;
          r.bottom:=r.bottom+self.top+2;
       
          FParams.Items[arow].FButton.BoundsRect:=r;
         end;
      И что ? Вопрос где ? Проблема в чём ?

      Вы Хотите во всех ячёйках столбца нарисовать кнопку, для этого не нужно создавать тысячу кнопок. Достаточно просто рисовать.
        Цитата TechnoMag @
        При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка

        Ес-но, т.к. для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow.
        Для скрытия контролов при выходе строки из области видимости нужно юзать другое событие, например OnTopLeftChanged
        Сообщение отредактировано: leo -
          Цитата leo @
          Цитата TechnoMag @
          При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка

          Ес-но, т.к. для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow.
          Для скрытия контролов при выходе строки из области видимости нужно юзать другое событие, например OnTopLeftChanged

          как же использовать это событие, если оно даже параметров не имеет? Если его использовать в компоненте то там даже Sender'a не будет.
          Это событие вроде используется при скролинге вверх. А какое тогда событие использовать при скролинге вниз?


          Нашел вот что, если это вообще оно:
          OnTopLeftChanged
          но смущает эта строка:

          ExpandedWrap disabled
            if R.Right = R.Left then {прямоугольник ячейки невидим}


          думаю, это когда меняется ширина ячейкм, т.е. она равна 0. Но это никак не показатель видимости ячейки если она прокручена вверх/вниз.
            Цитата TechnoMag @
            думаю, это когда меняется ширина ячейкм, т.е. она равна 0. Но это никак не показатель видимости ячейки если она прокручена вверх/вниз.

            Во-первых, справку по CellRect почитай - если ячейка невидима, то возвращается пустой TRect, а раз пустой, то соотв-но и Left=Right и Top=Bottom
            Во-вторых, я имел в виду более простой\тупой\бесхитростный способ определения невидимости строки по условию (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount)
              Цитата leo @
              Во-первых, справку по CellRect почитай - если ячейка невидима, то возвращается пустой TRect, а раз пустой, то соотв-но и Left=Right и Top=Bottom
              Во-вторых, я имел в виду более простой\тупой\бесхитростный способ определения невидимости строки по условию (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount)

              Не работает. Если в верхней ячейке остается контрол, то он не исчезает. И нижние контролы присоединяются к нему, как я и говорил по принципу стека.
              Может я неправильно понял? Простите за такой код. когда будет работать оптимизирую (ИМХО).
              ExpandedWrap disabled
                procedure TMBList.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
                begin
                if (acol=2) then
                  begin
                 
                   if (FParams.Items[arow].FButton<>nil) then
                   begin
                    if (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount) then
                      FParams.Items[arow].FButton.Visible:=false
                    else  
                    begin
                    r:=ARect;
                    r.Left:=r.left+self.left+2;
                    r.right:=r.right+self.left+2;
                    r.top:=r.top+self.top+2;
                    r.bottom:=r.bottom+self.top+2;
                 
                    FParams.Items[arow].FButton.BoundsRect:=r;
                    FParams.Items[arow].FButton.Visible:=true;
                    end;
                   end;
                 
                   if FParams.Items[arow].FCheckBox<>nil then
                   begin
                    if (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount) then
                      FParams.Items[arow].FCheckBox.Visible:=false
                    else
                    begin
                    r:=ARect;
                    r.Left:=r.left+self.left+2;
                    r.right:=r.right+self.left+2;
                    r.top:=r.top+self.top+2;
                    r.bottom:=r.bottom+self.top+2;
                 
                    FParams.Items[arow].FCheckBox.BoundsRect:=r;
                    FParams.Items[arow].FCheckBox.Visible:=true;
                    end;
                   end;
                 
                   if (FParams.Items[arow].FComboBox<>nil) then
                   begin
                    if (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount) then
                      FParams.Items[arow].FComboBox.Visible:=false
                    else
                    begin
                    r:=ARect;
                    r.Left:=r.left+self.left+2;
                    r.right:=r.right+self.left+2;
                    r.top:=r.top+self.top+2;
                    r.bottom:=r.bottom+self.top+2;
                 
                    FParams.Items[arow].FComboBox.BoundsRect:=r;
                    FParams.Items[arow].FComboBox.Visible:=true;
                    end;
                 
                   end;
                  end;
                end;


              Есть еще вариант: рисовать контрол в ячейках. Но тогда, чтобы контрол нарисовался весь, нужно его делать видимым, иначе будет нарисован только закрашеный прямойгольник цвета clBtnFace. Это не удобно,т.к. наформе будут мелькания этих элементов управления при прорисовке в ячейках. Но это лучше, если решить проблему мерцания.
              ExpandedWrap disabled
                if (ACol=2) then
                       begin
                         if FParams.Items[arow].FCheckBox<>nil then
                         begin
                          FParams.Items[arow].FCheckBox.Visible:=true;
                          FParams.Items[arow].FCheckBox.BoundsRect:=ARect;
                          FParams.Items[arow].FCheckBox.PaintTo(Canvas.Handle, ARect.Left, ARect.Top);
                          FParams.Items[arow].FCheckBox.Visible:=false;
                          end;
                 
                          if FParams.Items[arow].FButton<>nil then
                         begin
                          FParams.Items[arow].FButton.Visible:=true;
                          FParams.Items[arow].FButton.BoundsRect:=ARect;
                          FParams.Items[arow].FButton.PaintTo(Canvas.Handle, ARect.Left, ARect.Top);
                          FParams.Items[arow].FButton.Visible:=false;
                          end;
                 
                          if FParams.Items[arow].FComboBox<>nil then
                         begin
                          FParams.Items[arow].FComboBox.Visible:=true;
                          FParams.Items[arow].FComboBox.BoundsRect:=ARect;
                          FParams.Items[arow].FComboBox.PaintTo(Canvas.Handle, ARect.Left, ARect.Top);
                          FParams.Items[arow].FComboBox.Visible:=false;
                          end;
                       end;
                :wacko: :wall: :crazy:
                Ты считаешь разработчиков Delphi такими же "умными" как ты, чтобы они вызывали DrawCell для невидимых ячеек ?!! Сказал же уже черным по белому
                Цитата leo @
                для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow

                Поэтому:
                1) Если DrawCell вызвана, значит ячейка видима и незачем делать никакие доп.проверки на видимость - просто меняешь BoundsRect соотв-го батона и делаешь ему Visible:=true.
                2) Когда ячейка становится невидимой, то она просто не рисуется и DrawCell для нее не вызывается. Поэтому тебе нужно кроме DrawCell задействовать еще какое-то событие, чтобы скрывать батоны, которые должны стать невидимыми. К таким событиям относится TopLeftChanged, которое вызывается при вертикальном и горизонтальным скроллинге. Поэтому тебе нужно переопределить обработчик TopLeftChanged и в нем в цикле скрывать все батоны для строк < TopRow и >= TopRow+VisibleRowCount. При этом можно тупо прогонять цикл по всем невидимым строкам (от 0 до TopRow-1), но, чтобы не тормозить скролл, лучше запоминать предыдущее значение PrevTopRow и обрабатывать только те строки, которые из видимых перешли в невидимые:
                ExpandedWrap disabled
                  type
                    TMBList = class(...)
                    protected
                      ...
                      FPrevTopRow:integer;
                      procedure TopLeftChanged;override;
                      ...
                    end;
                   
                  procedure TBMList.TopLeftChanged;
                  var
                    From,aRow:integer;
                  begin
                    if FPrevTopRow <> TopRow then
                    begin
                      if FPrevTopRow < TopRow then
                        From:=FPrevTopRow
                      else
                        From:=TopRow+VisibleRowCount;
                      for aRow:=From to From+abs(FPrevRow-TopRow)-1 do
                        with FParams.Items[aRow] do
                        begin
                          if FCheckBox <> nil then FCheckBox.Visible:=false;
                          if FButton <> nil then FButton.Visible:=false;
                          if FComboBox <> nil then FComboBox.Visible:=false;
                        end;
                      FPrevTopRow:=TopRow;
                    end;
                    inherited;
                  end;


                Добавлено
                PS: У тебя в одной строке могут одновременно быть и FCheckBox, и FButton, и FComboBox ?! Если только что-то одно, то проще сделать или вариантную запись, или просто использовать обобщенный тип TControl, чтобы не писать по 3 раза одно и то же
                Сообщение отредактировано: leo -
                  Спасибо!!! Заработало!! :D

                  Цитата
                  или просто использовать обобщенный тип TControl, чтобы не писать по 3 раза одно и то же

                  Эмм. А как?
                  Дело в том, что я создаю разные контролы в зависимости от ситуации. И назначаю им эвенты.
                  Также мне нужно будет выполнять операции над контролом, которые присущи только этому контролу. Например для ComboBox, Items.Add. :blush:
                    Цитата TechnoMag @
                    Эмм. А как?

                    Там где нужна специфика для определенного типа, там юзать проверку типа по is:
                    ExpandedWrap disabled
                      FControl:=TComboBox.Create(...);
                      ...
                      if FControl is TComboBox then
                        with TComboBox(FControl) do
                        begin
                          OnClick:=...;
                          Items.Add(...);
                        end;
                    А где, не нужна, то напрямую использовать общие св-ва TControl:
                    ExpandedWrap disabled
                      if FControl <> nil then
                      begin
                        FControl.BoundsRect:=r;
                        FControl.Visible:=true;
                      end;
                    Сообщение отредактировано: leo -
                      Все понятно. Всем спасибо за помощь! ;)
                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,9966 ]   [ 17 queries used ]   [ Generated: 25.04.24, 01:18 GMT ]