Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.220.154.41] |
|
Сообщ.
#1
,
|
|
|
При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка.
думаю, по аналогии можно будет решить и для прокрутки вверх. 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, но контрол тогда исчезает раньше, т.е. в позиции через строку ниже. 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; |
Сообщ.
#2
,
|
|
|
И что ? Вопрос где ? Проблема в чём ?
Вы Хотите во всех ячёйках столбца нарисовать кнопку, для этого не нужно создавать тысячу кнопок. Достаточно просто рисовать. |
Сообщ.
#3
,
|
|
|
Цитата TechnoMag @ При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка Ес-но, т.к. для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow. Для скрытия контролов при выходе строки из области видимости нужно юзать другое событие, например OnTopLeftChanged |
Сообщ.
#4
,
|
|
|
Цитата leo @ Цитата TechnoMag @ При прокрутке StringGrid вниз, все компоненты находящиеся в ячейках столбца не исчезают, если достигли верхней границы, а какбы скапливаются по принципу стэка в ячейках вверху списка Ес-но, т.к. для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow. Для скрытия контролов при выходе строки из области видимости нужно юзать другое событие, например OnTopLeftChanged как же использовать это событие, если оно даже параметров не имеет? Если его использовать в компоненте то там даже Sender'a не будет. Это событие вроде используется при скролинге вверх. А какое тогда событие использовать при скролинге вниз? Нашел вот что, если это вообще оно: OnTopLeftChanged но смущает эта строка: if R.Right = R.Left then {прямоугольник ячейки невидим} думаю, это когда меняется ширина ячейкм, т.е. она равна 0. Но это никак не показатель видимости ячейки если она прокручена вверх/вниз. |
Сообщ.
#5
,
|
|
|
Цитата TechnoMag @ думаю, это когда меняется ширина ячейкм, т.е. она равна 0. Но это никак не показатель видимости ячейки если она прокручена вверх/вниз. Во-первых, справку по CellRect почитай - если ячейка невидима, то возвращается пустой TRect, а раз пустой, то соотв-но и Left=Right и Top=Bottom Во-вторых, я имел в виду более простой\тупой\бесхитростный способ определения невидимости строки по условию (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount) |
Сообщ.
#6
,
|
|
|
Цитата leo @ Во-первых, справку по CellRect почитай - если ячейка невидима, то возвращается пустой TRect, а раз пустой, то соотв-но и Left=Right и Top=Bottom Во-вторых, я имел в виду более простой\тупой\бесхитростный способ определения невидимости строки по условию (aRow < TopRow) or (aRow >= TopRow+VisibleRowCount) Не работает. Если в верхней ячейке остается контрол, то он не исчезает. И нижние контролы присоединяются к нему, как я и говорил по принципу стека. Может я неправильно понял? Простите за такой код. когда будет работать оптимизирую (ИМХО). 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. Это не удобно,т.к. наформе будут мелькания этих элементов управления при прорисовке в ячейках. Но это лучше, если решить проблему мерцания. 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; |
Сообщ.
#7
,
|
|
|
Ты считаешь разработчиков Delphi такими же "умными" как ты, чтобы они вызывали DrawCell для невидимых ячеек ?!! Сказал же уже черным по белому Цитата leo @ для невидимых ячеек DrawCell просто не вызывается, поэтому твои "батоны" и подвисают в месте последнего вызова DrawCell для данного ARow Поэтому: 1) Если DrawCell вызвана, значит ячейка видима и незачем делать никакие доп.проверки на видимость - просто меняешь BoundsRect соотв-го батона и делаешь ему Visible:=true. 2) Когда ячейка становится невидимой, то она просто не рисуется и DrawCell для нее не вызывается. Поэтому тебе нужно кроме DrawCell задействовать еще какое-то событие, чтобы скрывать батоны, которые должны стать невидимыми. К таким событиям относится TopLeftChanged, которое вызывается при вертикальном и горизонтальным скроллинге. Поэтому тебе нужно переопределить обработчик TopLeftChanged и в нем в цикле скрывать все батоны для строк < TopRow и >= TopRow+VisibleRowCount. При этом можно тупо прогонять цикл по всем невидимым строкам (от 0 до TopRow-1), но, чтобы не тормозить скролл, лучше запоминать предыдущее значение PrevTopRow и обрабатывать только те строки, которые из видимых перешли в невидимые: 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 раза одно и то же |
Сообщ.
#8
,
|
|
|
Спасибо!!! Заработало!!
Цитата или просто использовать обобщенный тип TControl, чтобы не писать по 3 раза одно и то же Эмм. А как? Дело в том, что я создаю разные контролы в зависимости от ситуации. И назначаю им эвенты. Также мне нужно будет выполнять операции над контролом, которые присущи только этому контролу. Например для ComboBox, Items.Add. |
Сообщ.
#9
,
|
|
|
Цитата TechnoMag @ Эмм. А как? Там где нужна специфика для определенного типа, там юзать проверку типа по is: FControl:=TComboBox.Create(...); ... if FControl is TComboBox then with TComboBox(FControl) do begin OnClick:=...; Items.Add(...); end; if FControl <> nil then begin FControl.BoundsRect:=r; FControl.Visible:=true; end; |
Сообщ.
#10
,
|
|
|
Все понятно. Всем спасибо за помощь!
|