Поле в классе не изменяет своего значения
Понимаю, тема звучит коряво... Просто я уже висну...
Вобщем, вот кусок кода:
TReportPage = class(TCollectionItem)
private
FLeft: integer;
FTop: integer;
FWidth: integer;
FHeight: integer;
FReportPage:TImage;
FCanvas: TCanvas;
procedure SetLeft(Value: integer);
procedure SetTop(Value: integer);
procedure SetWidth(Value: integer);
procedure SetHeight(Value: integer);
public
constructor Create(Collection: TCollection); override;
destructor Destroy; override;
property Canvas: TCanvas read FCanvas;
published
property Left: integer Read FLeft Write SetLeft;
property Top: integer Read FTop Write SetTop;
property Width: integer Read FWidth Write SetWidth;
property Height: integer Read FHeight Write SetHeight;
end;
TReportPages = class(TCollection)
private
FReport: TReport;
procedure SetItem(Index: integer; Value: TReportPage);
function GetItem(Index: integer): TReportPage;
public
function Add: TReportPage;
constructor Create(AReport: TReport);
property Items[Index: integer]: TReportPage read GetItem write SetItem; default;
end;
TReport = class(TScrollBox)
private
FReportPages: TReportPages;
function ViewPageLetter(S: TInserts; Text: TStream): TStream;
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
procedure PrintLetters(UserInfo: TIBQuery; LetterStream: TStream;
PStrukt: PPageStrukt; pFlag: PPrintPreview);
procedure PrintReport;
published
property ReportPages: TReportPages read FReportPages;
end;
const
TopLineMargin: integer = 10;
LeftLineMargin: integer = 10;
MarginBetweenPage: integer = 5;
implementation
{ TReportPage }
constructor TReportPage.Create(Collection: TCollection);
begin
inherited Create(Collection);
FReportPage:=TImage.Create(TReportPages(Collection).FReport);
FReportPage.Parent:=TReportPages(Collection).FReport;
FTop:=FReportPage.Top;
FLeft:=FReportPage.Left;
FWidth:=FReportPage.Width;
FHeight:=FReportPage.Height;
FCanvas:=TCanvas.Create;
FCanvas.Handle:=FReportPage.Canvas.Handle;
end;
destructor TReportPage.Destroy;
begin
FReportPage.Free;
inherited;
end;
procedure TReportPage.SetHeight(Value: integer);
begin
if FReportPage <> nil then
begin
FHeight:=Value;
FReportPage.Height:=Value;
end;
end;
procedure TReportPage.SetLeft(Value: integer);
begin
if FReportPage <> nil then
begin
FLeft:=Value;
FReportPage.Left:=Value;
end;
end;
procedure TReportPage.SetTop(Value: integer);
begin
if FReportPage <> nil then
begin
FTop:=Value;
FReportPage.Top:=Value;
end;
end;
procedure TReportPage.SetWidth(Value: integer);
begin
if FReportPage <> nil then
begin
FWidth:=Value;
FReportPage.Width:=FWidth;
end;
end;
Ну, млин, не знаю я в чем проблема, но тока методы SetHeight и SetWidth не меняют размера объекта FReportPage. SetTop и SetLeft же, напротив, "место дислокации" объекта меняют.
Хде копать?
ОЧЧЧЕНЬ нужна помощь. Я спекся...
и ещё момент, мелочь конечно, но не приятно
begin
if FReportPage <> nil then
begin
FTop:=Value;
FReportPage.Top:=Value;
end;
end;
procedure TReportPage.SetWidth(Value: integer);
begin
if FReportPage <> nil then
begin
FWidth:=Value;
FReportPage.Width:=FWidth;
end;
но это не ошибка, это больше для одинаковости прогграммирования неверно
В конструкторе присваиваю значение - норма.
В этом же модуле (или в другом) обращение к свойствам FReport.Left и FReport.Top - норма, к свойствам FReportPage.Height и FReportPage.Width - ничего. Размеры FReportPage, как я уже писал, не изменяются. Может, это какая-то особенность реализации TImage или TCollectionItem?
Что-то мне подсказывает, что это особенности реализации TCollection. В конструкторе TReportPage.Create присвоил значения полям FWidth и FHeight явно большие, чем мне понадобятся.
При работе со свойством Height и Width можно задавать значения меньше или равно первоначально присвоенным значениям вышеуказанных полей.
Больше, почему-то, не получается.
Интересно, млин, почему?:confused:
Дело в компоненте Image. У него размеры задаются двояко - размеры компонента, и размеры изображения в нём.
Свойство Picture->Bitmap->Width
Свойство Picture->Bitmap->Width
Вот в этом скорее всего и проблема, канва-то после создания размер не меняет и к.с. если мы уменьшаем рисунок - он просто становится меньше канвы и всё работает, а если увеличиваем - он становится больше канвы и ни чего по сути не меняется....
Исправляется относительно просто http://forum.codenet.ru/showthread.php?t=42815
Спасибо всем откликнувшимся.
Хочу задать еще один вопрос, надеюсь - последний. Он не критичный, посему отдельную тему создавать не буду.
Тот класс TReport, описанный мной в первом посте - это класс визулизации отчета для моей программы, а так же для визуализации писем нашим подписчикам.
Тело письма (точнее ШАБЛОНА письма) создается в RichEdit, там же форматируется, затем сохраняется в Blob-поле базы данных.
Сделать превьюшку для RichEdit'а не сложно, достаточно послать сообщение
То бишь таким макаром выведем содержимое RichEdit на канву (предположим метафайла).
Но мне нужно вывести на канву содержимое Blob-поля для множества записей. Напомню, что в blob-поле хранится отформатированный в RichEdit текст.
Каждое письмо выводится на отдельный "лист", за создание которого и отвечает класс TReportPage.
Можно, каэшна, из блоба текст вывести в предварительно созданный RichEdit, а далее содержимое RichEdit вывести на канву "листа", после чего освободить RichEdit, но это, млин, какой-то корявый метод.
Общая задача выглядит так - печатать произвольное кол-во писем заданного (созданного шаблона) произвольному кол-ву подписчиков.
Грубо говоря, в базе хранится шаблон письма - отформатированный текст. Я выбираю подписчиков, кому нужно написать (напечатать) письмо, выбираю шаблон, и... вуаля. Печатаются письма по заданному шаблону выбранным подписчикам.
Может, знает кто, как?.. из блоба на канву?..:o :o
Хочу продолжить по прежней теме.
Окно предварительного просмотра, описанное в первом посте, реализовано следующим образом.
Создается TScrollBox (TReport ) и в нем создаются "листы" (форматов а4, а3, letter) (TReportPage от класса TImage)
Далее эти листы в соответствии с заданным форматом бумаги растягиваются на необходимый размер. (спасибо еще раз, господа гуру)
Вот здесь снова у меня морока, но уже с расходом памяти.
При многостраничной печати (а так уж получается, что немногостраничных отчетов в программе практически нет) удается вывести на предпросмотр отчеты, где количество страниц не очень большое. Где-то в пределах 40 страниц. Если страниц нужно печатать больше, выводится сообщение о том, что недостаточно памяти.
И правда, расход памяти на 40 "страниц" определенного формата бумаги (читай - 40 "копий" растянутого TImage) - 50 метров и более.
нужно, чтобы печатать можно было какое-угодно кол-во страниц.
раз в полгода будут печатать отчет, состоящий примерно из 10-12 тыс. страниц., а в любое другое время - отчеты от одной страницы до тех же самых 10 тыс.
Сразу хочу оговориться, что после полученного ответа на первый вопрос изменил процедуры TReportPage.SetWidth и TReportPageSetHeight в вышеприведенном коде
begin
if FReportPage <> nil then
begin
FHeight:=Value;
FReportPage.Height:=FHeight;
FReportPage.Picture.Bitmap.Height:=FHeight; {коммент}
end;
end;
procedure TReportPage.SetWidth(Value: integer);
begin
if FReportPage <> nil then
begin
FWidth:=Value;
FReportPage.Width:=FWidth;
FReportPage.Picture.Bitmap.Width:=FWidth; {коммент}
end;
end;
Что интересно, если закомментировать строчки, помеченные как {коммент}, можно создавать какое угодно кол-во страниц (TImage), но тогда опять не меняется размер.
Если вместо TImage использовать предположим TPanel или компоненты, унаследованные от TGraphicControl (кроме TImage, конечно), канва этих объектов очищается, как только свернуть окно предпросмотра или любым каким-то образом "прикрыть" превью. (кстати, почему?)
Честно говоря, для меня это тупик. Дальше не знаю, куда копать. Печатать "на авось" 10 тыс. страниц без предварительного просмотра - за это премии не дадут и по головке не погладят. Очень нужна ваша помощь, господа.
Попробуй переделать логику работы отчета: при предпросмотре генерировать в виде изображения только ту страницу (или несколько страниц, которые можно просмотреть одновременно), которая видна на экране в текущий момент, поскольку одновременно просмотреть 10+K страниц вряд-ли возможно. При печати - аналогично, только там вообще по одной странице можно печатать.
Далее... Использовать TImage для растягивания страницы, ИМХО, вообще не фонтан, так как качество масштабирования у него... :( Может попробывать программно масштабировать? Ну, например, увеличивать/уменьшать размер шрифта, толщину линий, etc...
Так работает Windows. Дело в том, что копия изображения ("картинка") окна никогда не сохраняется операционной системой в памяти, поскольку таковой будет в этом случае нехватать (исключения на самом деле есть, но они предусмотрены для ускорения работы). Окна (или видимые области окон) перерисовываются по необходимости, по сообщению WM_PAINT. Windows сама решает, когда окну необходима перерисовка, и посылает ему данное сообщение (можно, конечно, запросить канву окна самостоятельно). Соответственно, когда окно свернуто, то его нет необходимости перерисовывать. Класс TCanvas у контрола Windows не является видеобуфером окна, а всего лишь предоставляет программный интерфейс к канве окна. Считать TControl.Canvas = TBitmap.Canvas ( к примеру) не совсем корректно.
Рекомендую прочитать где нибудь, как работает вся эта система. Начни с сообщения WM_PAINT, функций BeginPaint/EndPaint, GetDC/ReleaseDC. Еще можно глянуть, как реализован класс TCanvas в исходниках.
Вы не совсем поняли.
TImage используется именно для просмотра отчета, который вообще нигде не хранится. Он при необходимости формируется программно, хватая данные из базы даных.
TImage - это страница, на которой я "рисую" отчет. Но отчеты большие, мне нужно создать столько страниц, сколько нужно для визуализации всего отчета. А это от одной - до 10-12 тыс.
Проблема в том, что когда генерируется отчет, создается страница (TImage), потом другая, третья,..., n-ная. Когда n>40-50, вылетает ошибка. "Все, млин, память закончилась".
Собсно, можно юзать имеющиеся компоненты для отчета, просто написав всю прогу от начала до конца, переписав почти половину компонентов, хочется сделать самому.
От TImage решил отказаться, придется "поднатаскаться" по WMPaint и "писать" отчет на канве менее ресурсоемкого графикконтрола.
Спасибо.
Я имел в виду, что нет необходимости формировать изображение (TImage) всех страниц отчета одновременно, посколько на экране в текущий момент времени видно не более 1 - 4 страниц. Вот для них и формируй изображения. Потом для следующих 4 и т.д. Проблема с памятью решится.
Но девчонки, что привыкли работать с офисом, им же непривычно будет.
Неа... я решил пойти другим путем. Более сложным, но более верным.
PS. Посмотреть бы, как это реализовано в генераторах отчетов...