Вы ничего не делаете неправильно, вы только что попали в ошибку в реализации сетки VCL, которая была в Delphi 4 VCL (у меня нет ни одного более раннего компакт-диска, чтобы проверить, но он мог даже быть в 16-битный Delphi VCL уже) и все еще с нами в Delphi 2009.
Оба метода для аннулирования всей строки или столбца делают это, вычисляя площадь ячеек, которая передается во внутренний метод InvalidateRect()
. Эта область всегда начинается со столбца / строки 0 и продолжается до первой полностью невидимой строки / столбца. Совершенно очевидно, что это будет правильно работать только для некроллированной клиентской области. То, что код должен делать вместо этого, становится недействительным для последнего столбца / строки и позволяет коду в помощнике InvalidateRect()
выяснить, какие ячейки действительно видны, и вычислить клиентскую область, которую необходимо аннулировать из этого.
Поскольку вы пишете свой собственный класс, вы можете легко реализовать свои собственные методы для аннулирования правильного диапазона ячеек; Я сделал то же самое много лет назад, вместе с другими методами для аннулирования нескольких столбцов, нескольких строк и целых блоков ячеек. Поскольку InvalidateRect()
является приватным (и это здорово), вам нужно использовать функцию Windows API с тем же именем и вычислить прямоугольник, который будет признан недействительным, с помощью метода CellRect()
или BoxRect()
.
Хотя InvalidateGrid()
работает для вас, это действительно своего рода кувалда - это делает недействительной всю сетку, что, я думаю, не то, что вы хотели, когда вы начали использовать InvalidateCol()
.
Для ваших экспериментов вы должны сделать циклы рисования для каждой ячейки легко видимыми. Вызывать изменение цвета фона ячеек при каждом обновлении - это простой способ убедиться, что вы действительно выполняете только минимальные перерисовки экрана. Что-то вроде
StringGrid1.Canvas.Brush.Color := RGB(Random(256), Random(256), Random(256));
StringGrid1.Canvas.FillRect(Rect);
в обработчике событий OnDrawCell
работает нормально.