KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Валентин Озеров - Советы по Delphi. Версия 1.0.6

Валентин Озеров - Советы по Delphi. Версия 1.0.6

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн "Валентин Озеров - Советы по Delphi. Версия 1.0.6". Жанр: Программирование издательство неизвестно, год неизвестен.
Перейти на страницу:

end;

TNotebook

Операция по заполнению элементами управления компонента TNotebook почти такая же, как и в TTabbedNotebook – разница лишь в типе класса – TPage вместо TTabPage. Тем не менее, если вы заглянете в DELPHIDOCEXTCTRLS.INT, декларацию класса TPage вы там не найдете. По неизвестной причине Borland не включил определение TPage и в DOC-файлы, поставляемые с Delphi. Декларация TPage в EXTCTRLS.PAS (можно найти в библиотеке VCL-исходников), правда, расположена в интерфейсной части модуля. Мы восполним пропущенную информацию о классе TPage:

TPage = class(TCustomControl)

private

 procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;

protected

 procedure ReadState(Reader: TReader); override;

 procedure Paint; override;

public

 constructor Create(AOwner: TComponent); override;

published

 property Caption;

 property Height stored False;

 property TabOrder stored False;

 property Visible stored False;

 property Width stored False;

end;

Теперь, по аналогии с вышеприведенной процедурой, попробуем добавить кнопку на TNotebook. Все, что мы должны сделать – заменить "TTabbedNotebook" на "TNotebook" и "TTabPage" на "TPage". Вот что должно получиться:

{ Данная процедура добавляет кнопку в случайной позиции на }

{ текущей странице данного TNotebook.                      }

procedure AddButton(Notebook1: TNotebook);

var

 page: TPage;

 button: TButton;

begin

 with Notebook1 do page:= TPage(Pages.Objects[PageIndex]);

 button:= TButton.Create(page);

 try

  with button do begin

   Parent:= page;

   Left:= Random(page.ClientWidth – Width);

   Top:= Random(page.ClientHeight – Height);

  end;

 except

  button.Free;

 end;

end;

Остальное не менее просто!

Недоступная закладка в компоненте Tabbednotebook

Есть ли возможность в компоненте Tabbednotebook сделать какую-либо страницу недоступной? То есть не позволять пользователю щелкать на ней и видеть ее содержимое?

Да, такая возможность существует. Самый простой путь – удалить страницу, например так:

with TabbedNotebook do Pages.Delete(PageIndex);

и снова включить ее (при необходимости), перегрузив форму.

Блокировка (а не удаление) немного мудренее, поскольку необходима организация цикла в процедуре создания формы, присваивающая имена закладкам компонента TabbedNotebook. Например так:

J:= 0;

with TabbedNotebook do for I:= 0 to ComponentCount - 1 do if Components[I].ClassName = 'TTabButton' then begin

 Components[I].Name:= ValidIdentifier(TTabbedNotebook(Components[I].Owner).Pages[J]) + 'Tab';

 Inc(J);

end;

где ValidIdentifier ValidIdentifier – функция, которая возвращает правильный Pascal-идентификатор, производный от строки 'Tab':

function ValidIdentifier(theString: str63): str63;

{--------------------------------------------------------}

{ Конвертирует строку в правильный Pascal-идентификатор, }

{ удаляя все неправильные символы и добавляя символ '_', }

{ если первый символ – цифра                             }

{--------------------------------------------------------}

var

 I, Len: Integer;

begin

 Len:= Length(theString);

 for I:= Len downto 1 do if not (theString[I] in LettersUnderscoreAndDigits) then Delete(theString, I, 1);

 if not (theString[1] in LettersAndUnderscore) then theString:= '_' + theString;

 ValidIdentifier:= theString;

end; {ValidIdentifier}

Затем мы можем сделать закладку компонента TabbedNotebook недоступной:

with TabbedNotebook  do begin

 TabIdent:= ValidIdentifier(Pages[PageIndex]) + 'Tab';

 TControl(FindComponent(TabIdent)).Enabled:= False;

 { Переключаемся на первую доступную страницу: }

 for I:= 0 to Pages.Count – 1 do begin

  TabIdent:= ValidIdentifier(Pages[I]) + 'Tab';

  if TControl(FindComponent(TabIdent)).Enabled then begin

   PageIndex:= I;

   Exit;

  end;

 end; {for}

end; {with TabbedNotebook}

следующий код восстанавливает доступность страницы:

with TabbedNotebook do for I:= 0 to Pages.Count - 1 do begin

 TabIdent:= ValidIdentifier(Pages[I]) + 'Tab';

 if not TControl(FindComponent(TabIdent)).Enabled:= True;

end; {for}

Table

Создание компонента TTable без формы

Решение 1

Действительно, любой компонент можно создать и без (вне) формы или любого другого дочернего компонента. Для этого я использую параметр nil:

FSession:= TSession.Create(nil);

FDatabase:= TDatabase.Create(nil);

FSession.SessionName:= 'DBSession'

FDatabase.Connected:= False;

FDatabase.AliasName:= Database;

FDatabase.DatabaseName:= USER_DATABASE;

FDatabase.SessionName:= FSession.SessionName;

FUserTBL:= TTable.Create(nil);

FUserTBL.DatabaseName:= FDatabase.DatabaseName;

FUserTBL.SessionName:= FSession.SessionName;

FUserTBL.TableName:= USERTBL;

FUserTBL.IndexName:= USERSpIndex;

FUserSource:= TDataSource.Create(nil);

FUserSource.DataSet:= FUserTBL;

Решение 2

Я привожу некоторый код, касающийся описываемой проблемы: он работал, когда я использовал его в большом приложении. Я не знаю специфического метода создания компонента TTable вне родителей, поэтому я пошел путем создания своего класса от TTable во время инициализации модуля. Удобство такого подхода объясняется наличием под рукой всегда готового к работе экземпляра класса, стоит всего-лишь добавить модуль к вашему приложению. Конечно, новый класс не должен иметь одиноко выглядящую процедуру со странной технологией фильтрации данных :=))), да и не помешала бы публикация нескольких событий, но этот пример призван все-го лишь продемонстрировать иной подход к решаемой задаче.

unit Unit2;


interface


uses db, DBTables, dialogs;


type fake = class(Ttable)

 procedure fakeFilterRecord(DataSet: TDataSet; var Accept: Boolean);

end;


var

 MyTable: fake;


implementation


procedure fake.fakeFilterRecord(DataSet: TDataSet; var Accept: Boolean);

begin

 showmessage('Здравствуй, Вася');

end;


Initialization

 MyTable:= fake.create(nil);

 With Mytable do begin

  DataBaseName:= 'dbdemos';

  TableName:= 'biolife';

  OnFilterRecord:= MyTable.fakeFilterRecord;

  Filtered:= true;

  active:= true;

 end;

 {проверка получением неких данных…}

 showmessage(MyTable.fields[1].asstring);


Finalization

 {Важно!  MyTable не имеет родителя, – уничтожаем объект сами, иначе память не высвобождается…}

 MyTable.free;

end.

TreeView

Ускорение работы TreeView

Представляем вашему вниманию немного переработанный компонент TreeView, работающий быстрее своего собрата из стандартной поставки Delphi. Кроме того, была добавлена возможность вывода текста узлов и пунктов в жирном начертании (были использованы методы TreeView, хотя, по идее, необходимы были свойства TreeNode. Мне показалось, что это будет удобнее).

Для сравнения:

TreeView:

128 сек. для загрузки 1000 элементов (без сортировки)*

270 сек. для сохранения 1000 элементов (4.5 минуты!!!)

HETreeView:

1.5 сек. для загрузки 1000 элементов – ускорение около 850%!!! (2.3 секунды без сортировки = stText)*

0.7 сек. для сохранения 1000 элементов – ускорение около 3850%!!!

Примечание:

• Все операции выполнялись на медленной машине 486SX 33 Mгц, 20 Mб RAM.

• Если TreeView пуст, загрузка происходит за 1.5 секунды, плюс 1.5 секунды на стирание 1000 элементов (общее время загрузки составило 3 секунды). В этих условиях стандартный компонент TTreeView показал общее время 129.5 секунд. Очистка компонента осуществлялась вызовом функции SendMessage(hwnd, TVM_DELETEITEM, 0, Longint(TVI_ROOT)).

Проведите несколько приятных минут, развлекаясь с компонентом.

unit HETreeView;

{$R-}

// Описание: Реактивный TreeView

(*

TREEVIEW:

 128 сек. для загрузки 1000 элементов (без сортировки)*

 270 сек. для сохранения 1000 элементов (4.5 минуты!!!)

HETREEVIEW:

 1.5 сек. для загрузки 1000 элементов – ускорение около 850%!!! (2.3 секунды без сортировки = stText)*

 0.7 сек. для сохранения 1000 элементов – ускорение около 3850%!!!

NOTES:

 – Все операции выполнялись на медленной машине 486SX 33 Mгц, 20 Mб RAM.

 – * Если TTreeView пуст, загрузка происходит за 1.5 секунды,

 плюс 1.5 секунды на стирание 1000 элементов (общее время загрузки составило 3 секунды).

 В этих условиях стандартный компонент TreeView показал общее время 129.5 секунд.

 Очистка компонента осуществлялась вызовом функции

 SendMessage(hwnd, TVM_DELETEITEM, 0, Longint(TVI_ROOT)).

*)

interface


uses SysUtils, Windows, Messages, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, CommCtrl, tree2vw;


type THETreeView = class(TTreeView)

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*