Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Поле в классе не изменяет своего значения

20K
29 октября 2007 года
yager84
37 / / 15.05.2007
Всем привет.
Понимаю, тема звучит коряво... Просто я уже висну...

Вобщем, вот кусок кода:
Код:
TReport = class;
    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 же, напротив, "место дислокации" объекта меняют.
Хде копать?
ОЧЧЧЕНЬ нужна помощь. Я спекся...
286
29 октября 2007 года
misha_turist
572 / / 28.11.2005
Вроде правильно всё, мож у тебя при их отображении ошибки.....

и ещё момент, мелочь конечно, но не приятно
Код:
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;

но это не ошибка, это больше для одинаковости прогграммирования неверно
20K
29 октября 2007 года
yager84
37 / / 15.05.2007
В том то и дело... Ну не знаю я почему не работает код.
В конструкторе присваиваю значение - норма.
В этом же модуле (или в другом) обращение к свойствам FReport.Left и FReport.Top - норма, к свойствам FReportPage.Height и FReportPage.Width - ничего. Размеры FReportPage, как я уже писал, не изменяются. Может, это какая-то особенность реализации TImage или TCollectionItem?
20K
29 октября 2007 года
yager84
37 / / 15.05.2007
Проблема коряво, но решена.
Что-то мне подсказывает, что это особенности реализации TCollection. В конструкторе TReportPage.Create присвоил значения полям FWidth и FHeight явно большие, чем мне понадобятся.
При работе со свойством Height и Width можно задавать значения меньше или равно первоначально присвоенным значениям вышеуказанных полей.
Больше, почему-то, не получается.
Интересно, млин, почему?:confused:
309
30 октября 2007 года
el scorpio
1.1K / / 19.09.2006
Вопрос изменяются числовые значения свойств или видимые размеры?

Дело в компоненте Image. У него размеры задаются двояко - размеры компонента, и размеры изображения в нём.
Свойство Picture->Bitmap->Width
20K
30 октября 2007 года
yager84
37 / / 15.05.2007
Изменяются числовые значения размера, точно. Видимые размеры не изменяются. Спасибо.
286
30 октября 2007 года
misha_turist
572 / / 28.11.2005
Цитата: el scorpio
Дело в компоненте Image. У него размеры задаются двояко - размеры компонента, и размеры изображения в нём.
Свойство Picture->Bitmap->Width


Вот в этом скорее всего и проблема, канва-то после создания размер не меняет и к.с. если мы уменьшаем рисунок - он просто становится меньше канвы и всё работает, а если увеличиваем - он становится больше канвы и ни чего по сути не меняется....

Исправляется относительно просто http://forum.codenet.ru/showthread.php?t=42815

20K
30 октября 2007 года
yager84
37 / / 15.05.2007
Да. Действительно...
Спасибо всем откликнувшимся.
Хочу задать еще один вопрос, надеюсь - последний. Он не критичный, посему отдельную тему создавать не буду.

Тот класс TReport, описанный мной в первом посте - это класс визулизации отчета для моей программы, а так же для визуализации писем нашим подписчикам.

Тело письма (точнее ШАБЛОНА письма) создается в RichEdit, там же форматируется, затем сохраняется в Blob-поле базы данных.

Сделать превьюшку для RichEdit'а не сложно, достаточно послать сообщение
 
Код:
sendmessage(RichEdit1.handle, em_formatrange, 1, longint(@range));


То бишь таким макаром выведем содержимое RichEdit на канву (предположим метафайла).

Но мне нужно вывести на канву содержимое Blob-поля для множества записей. Напомню, что в blob-поле хранится отформатированный в RichEdit текст.
Каждое письмо выводится на отдельный "лист", за создание которого и отвечает класс TReportPage.
Можно, каэшна, из блоба текст вывести в предварительно созданный RichEdit, а далее содержимое RichEdit вывести на канву "листа", после чего освободить RichEdit, но это, млин, какой-то корявый метод.

Общая задача выглядит так - печатать произвольное кол-во писем заданного (созданного шаблона) произвольному кол-ву подписчиков.
Грубо говоря, в базе хранится шаблон письма - отформатированный текст. Я выбираю подписчиков, кому нужно написать (напечатать) письмо, выбираю шаблон, и... вуаля. Печатаются письма по заданному шаблону выбранным подписчикам.

Может, знает кто, как?.. из блоба на канву?..:o :o
20K
07 декабря 2007 года
yager84
37 / / 15.05.2007
Здравствуйте, товарищи...
Хочу продолжить по прежней теме.

Окно предварительного просмотра, описанное в первом посте, реализовано следующим образом.

Создается TScrollBox (TReport ) и в нем создаются "листы" (форматов а4, а3, letter) (TReportPage от класса TImage)
Далее эти листы в соответствии с заданным форматом бумаги растягиваются на необходимый размер. (спасибо еще раз, господа гуру)

Вот здесь снова у меня морока, но уже с расходом памяти.
При многостраничной печати (а так уж получается, что немногостраничных отчетов в программе практически нет) удается вывести на предпросмотр отчеты, где количество страниц не очень большое. Где-то в пределах 40 страниц. Если страниц нужно печатать больше, выводится сообщение о том, что недостаточно памяти.
И правда, расход памяти на 40 "страниц" определенного формата бумаги (читай - 40 "копий" растянутого TImage) - 50 метров и более.

нужно, чтобы печатать можно было какое-угодно кол-во страниц.
раз в полгода будут печатать отчет, состоящий примерно из 10-12 тыс. страниц., а в любое другое время - отчеты от одной страницы до тех же самых 10 тыс.

Сразу хочу оговориться, что после полученного ответа на первый вопрос изменил процедуры TReportPage.SetWidth и TReportPageSetHeight в вышеприведенном коде

Код:
procedure TReportPage.SetHeight(Value: integer);
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 тыс. страниц без предварительного просмотра - за это премии не дадут и по головке не погладят. Очень нужна ваша помощь, господа.
303
10 декабря 2007 года
makbeth
1.0K / / 25.11.2004
Я вот не пойму, зачем хранить страницы отчета в памяти в виде TImage? Вроде они используются только для просмотра и при печати...
Попробуй переделать логику работы отчета: при предпросмотре генерировать в виде изображения только ту страницу (или несколько страниц, которые можно просмотреть одновременно), которая видна на экране в текущий момент, поскольку одновременно просмотреть 10+K страниц вряд-ли возможно. При печати - аналогично, только там вообще по одной странице можно печатать.
Далее... Использовать TImage для растягивания страницы, ИМХО, вообще не фонтан, так как качество масштабирования у него... :( Может попробывать программно масштабировать? Ну, например, увеличивать/уменьшать размер шрифта, толщину линий, etc...
Цитата:
Если вместо TImage использовать предположим TPanel или компоненты, унаследованные от TGraphicControl (кроме TImage, конечно), канва этих объектов очищается, как только свернуть окно предпросмотра или любым каким-то образом "прикрыть" превью. (кстати, почему?)


Так работает Windows. Дело в том, что копия изображения ("картинка") окна никогда не сохраняется операционной системой в памяти, поскольку таковой будет в этом случае нехватать (исключения на самом деле есть, но они предусмотрены для ускорения работы). Окна (или видимые области окон) перерисовываются по необходимости, по сообщению WM_PAINT. Windows сама решает, когда окну необходима перерисовка, и посылает ему данное сообщение (можно, конечно, запросить канву окна самостоятельно). Соответственно, когда окно свернуто, то его нет необходимости перерисовывать. Класс TCanvas у контрола Windows не является видеобуфером окна, а всего лишь предоставляет программный интерфейс к канве окна. Считать TControl.Canvas = TBitmap.Canvas ( к примеру) не совсем корректно.
Рекомендую прочитать где нибудь, как работает вся эта система. Начни с сообщения WM_PAINT, функций BeginPaint/EndPaint, GetDC/ReleaseDC. Еще можно глянуть, как реализован класс TCanvas в исходниках.

20K
10 декабря 2007 года
yager84
37 / / 15.05.2007
Цитата:
Я вот не пойму, зачем хранить страницы отчета в памяти в виде TImage? Вроде они используются только для просмотра и при печати...



Вы не совсем поняли.

TImage используется именно для просмотра отчета, который вообще нигде не хранится. Он при необходимости формируется программно, хватая данные из базы даных.

TImage - это страница, на которой я "рисую" отчет. Но отчеты большие, мне нужно создать столько страниц, сколько нужно для визуализации всего отчета. А это от одной - до 10-12 тыс.

Проблема в том, что когда генерируется отчет, создается страница (TImage), потом другая, третья,..., n-ная. Когда n>40-50, вылетает ошибка. "Все, млин, память закончилась".

Собсно, можно юзать имеющиеся компоненты для отчета, просто написав всю прогу от начала до конца, переписав почти половину компонентов, хочется сделать самому.
От TImage решил отказаться, придется "поднатаскаться" по WMPaint и "писать" отчет на канве менее ресурсоемкого графикконтрола.
Спасибо.

303
11 декабря 2007 года
makbeth
1.0K / / 25.11.2004
Нет... таки я правильно тебя понял ;)
Я имел в виду, что нет необходимости формировать изображение (TImage) всех страниц отчета одновременно, посколько на экране в текущий момент времени видно не более 1 - 4 страниц. Вот для них и формируй изображения. Потом для следующих 4 и т.д. Проблема с памятью решится.
20K
11 декабря 2007 года
yager84
37 / / 15.05.2007
Собсно говоря, таки нет необходимости.
Но девчонки, что привыкли работать с офисом, им же непривычно будет.
Неа... я решил пойти другим путем. Более сложным, но более верным.

PS. Посмотреть бы, как это реализовано в генераторах отчетов...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог