Показаны сообщения с ярлыком Delphi XE3. Показать все сообщения
Показаны сообщения с ярлыком Delphi XE3. Показать все сообщения

четверг, 16 октября 2014 г.

Dialog Wizard в Delphi

Задался вопросом создания "мастера" для чего нибудь.

Наш мастер должен иметь страницу приветствия, финиша и разные прочие страницы.

Страница приветствия

Рабочая страница

Итак, что мы делаем. На форму кидаем TopPanel (TPanel), pcWizard (TPageControl), Bevel1 (TBevel) и ActionList. Для начала разберемся с верхней панелью. Я поместил там lblCaption и lblHint (TLabel), а также картинку.
В pcWizard создаем 3 закладки: tsWelcome, tsFinish, tsPage1. Первые две будут очень похожие, даже одинаковые, только текст будет разный. На них помещает текст приветствия и какую-нибудь подходящую картинку. Картинка желательно большего размера по высоте.
В ActionList создаем 3 события (Action): acNext, acBack, acCancelDone.
В TBevel размещаем 3 кнопки: "Назад", "Далее", "Отмена". И присваиваем им соответствующие события из ActionList.
На странице tsPage1 для демонстрации разместим один CheckBox. Переход далее будет осуществляться только если он отмечен.

Ну вот и все с дизайном. Переходим к коду.

При старте нашей формы нам нужно убрать шапки с закладок. В FormCreate напишем.

type
  TDialogWizard = class(TForm)
   .....
  public  
    procedure CheckWhenPageActive;
...
 end;

procedure TDialogWizard.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to pcWizard.PageCount - 1 do
    pcWizard.Pages[i].TabVisible := False;
  pcWizard.ActivePage := tsWelcome;
  CheckWhenPageActive;
end;

Здесь мы скрыли все заголовки со страниц, установили стартовую и запустили процедуру CheckWhenPageActive. Она отвечает за отображение верхней панели, текста на ней и отображение кнопок навигации. Вот ее код:

var
  DialogWizard: TDialogWizard;
  PNextPage, PPrevPage: ^TTabSheet;

.....

procedure TDialogWizard.CheckWhenPageActive;
var
  PPage : ^TTabSheet;
begin
  PPage := @(pcWizard.ActivePage);
  if PPage^ = tsWelcome then
    begin
      TopPanel.Visible := false;
      PNextPage := @tsPage1;
      PPrevPage := nil;
    end;

  if PPage^ = tsFinish then
    begin
      TopPanel.Visible := false;
      PNextPage := nil;
      PPrevPage := nil;
      acCancelDone.Caption := 'Готово';
    end;

  if PPage^ = tsPage1 then
    begin
      TopPanel.Visible := true;
      PNextPage := @tsFinish;
      PPrevPage := nil;
      lblCaption.Caption := '';
      lblHint.Caption := '';
    end;

  acNext.Visible := PNextPage <> nil;
  acBack.Visible := PPrevPage <> nil;
end;

В процедуре проверяем какая страница активна. Для каждой страницы нам необходимо указать предыдущую страницу и следующую (указатели PNextPage, PPrevPage: ^TTabSheet). Можно было бы и просто менять с помощью SelectNextPage, но тогда их надо в дизайнере отсортировать по очередности. А если надо пропустить? Я решил указывать это для каждой страницы. Если какая-либо ссылка не указана, то и соответствующая кнопка не будет видна. Например: tsWelcome - видна кнопка далее, следующая страница tsPage1. А у tsPage1, появилась возможность отображать заголовок и комментарий к странице. TopPanel.Visible := true - говорит, о том, что верхняя панель будет показана.

Итак мы знаем какая страница будет следующей. Начинаем обрабатывать переход.

procedure TDialogWizard.acNextExecute(Sender: TObject);
begin
  if AllowChangePage then
   begin
    pcWizard.ActivePage := PNextPage^;
    CheckWhenPageActive;
   end;
end;

Функция AllowChangePage проверяет, можно ли переходить к следующей странице. Если она принимает значение TRUE, то переходим к следующей странице. Вот ее код:

type
  TDialogWizard = class(TForm)
   .....
  private
    function AllowChangePage: boolean;
    .....
end;

function TDialogWizard.AllowChangePage: boolean;
var
  PPage : ^TTabSheet;
begin
  result := true;
  PPage := @(pcWizard.ActivePage);

   if PPage^ = tsPage1 then
    begin
      result := CheckBox1.Checked;
    end;
end;

Помните на tsPage1 мы кидали CheckBox. Так вот эта функция проверяет отмечен он или нет, и либо разрешает, либо запрещает переход.

С переходом назад проще. Просто переходим назад.

procedure TDialogWizard.acBackExecute(Sender: TObject);
begin
  pcWizard.ActivePage := PPrevPage^;
  CheckWhenPageActive;
end;

Осталась кнопка "Отмена/Готово". Тут тоже все просто.

procedure TDialogWizard.acCancelDoneExecute(Sender: TObject);
begin
  if pcWizard.ActivePage <> tsFinish then
    close
  else
    begin
      // Тут что-то делаем.
      close;
    end;
end;

Если страница не последняя (tsFinish), то закрываем мастер, а нет можем выполнить отмену произведенных операций к примеру и закрыть.

Ну вот и все. Подведет итог.
Мы имеем 2 процедуры в которых отрабатывается страница:
CheckWhenPageActive - Определяем что показывать, а что нет. + Навигация.
AllowChangePage - Делаем проверку на странице.

Что-то делать в мастере можно по ходу выполнения в процедуре AllowChangePage, либо создать еще страницу, ну скажем tsProgress и делать все на ней. Но опять же в процедуре AllowChangePage. Можно организовать отмену каких-либо операций в процедуре acCancelDoneExecute.

Ну что же, удачи.

Исходник проекта DialogWizard


вторник, 23 сентября 2014 г.

Сохранение размера и позиции формы в Delphi

Часто в приложении требуется сохранить размер и положение окна (формы). Встроенной технологии в Delphi нет. В интернете можно найти различные способы хранения как в INI так и в реестре. Я предлагаю другой вариант. Использовать TPersistant.
Для удобства я поместил все в DLL.


library swpas;

{  SWPAS - Save Windows Position And Size

   Библиотека для сохранения размера и положения формы.
   24.09.2014  Кутовой Максим

   После создания формы загружаем ее размеры и положение из файла. Если его нет,
   то размеры и положение будут как при разработке приложения. После закрытия
   формы сохраняем ее размер и положения в файл. Если не указать имя файла, то
   все будет сохранено в файл <ИМЯ_ФОРМЫ>.frm

     Формат вызова процедур в программе
     procedure LoadFormPositionAndSize(AForm: TForm; APath : string = ''); external 'swpas.dll';
     procedure SaveFormPositionAndSize(AForm: TForm; APath : string = ''); external 'swpas.dll';

     procedure LFPAS(AForm: TForm; APath : string = ''); external 'swpas.dll';
     procedure SFPAS(AForm: TForm; APath : string = ''); external 'swpas.dll';


     Использование в программе:

     procedure TForm1.Button1Click(Sender: TObject);
     var
       NewForm : TForm;
     begin
      NewForm := TForm2.Create(self);
      LFPAS(NewForm);
      NewForm.ShowModal;
      SFPAS(NewForm);
      FreeAndNil(NewForm);
     end;
   }


uses
  System.SysUtils,
  System.Classes,
  VCL.Forms;

{$R *.res}

{
 ****
 ****  КЛАСС для сохранения свойств формы
 ****
}

type
  TSavedForm = class(TPersistent)
  private

    FHeight: Integer;
    FLeft: Integer;
    FTop: Integer;
    FWidth: Integer;

    {Установка свойств}
    procedure SetHeight(const Value: integer);
    procedure SetLeft(const Value: Integer);
    procedure SetTop(const Value: Integer);
    procedure SetWidth(const Value: integer);

    {Получение свойств}
    function GetHeight: integer;
    function GetLeft: Integer;
    function GetTop: Integer;
    function GetWidth: integer;
  public
    {Конструктор}
    constructor Create;

  published
    Property Left: Integer read GetLeft write SetLeft;
    property Top: Integer read GetTop write SetTop;
    property Width: integer read GetWidth write SetWidth;
    property Height: integer read GetHeight write SetHeight;

  end;

{ AForm }

constructor TSavedForm.Create;
begin
  inherited;
end;

function TSavedForm.GetHeight: integer;
begin
  result := FHeight;
end;

function TSavedForm.GetLeft: Integer;
begin
  result := FLeft;
end;

function TSavedForm.GetTop: Integer;
begin
  result := FTop
end;

function TSavedForm.GetWidth: integer;
begin
  result := FWidth;
end;

procedure TSavedForm.SetHeight(const Value: integer);
begin
  FHeight := Value;
end;

procedure TSavedForm.SetLeft(const Value: Integer);
begin
  FLeft := Value;
end;

procedure TSavedForm.SetTop(const Value: Integer);
begin
  FTop := Value;
end;

procedure TSavedForm.SetWidth(const Value: integer);
begin
  FWidth := Value;
end;


{
  ***
  ***  Процедуры для сохранения объекта  в файл
  ***  Можно вынести в отдельный модуль или библиотеку.
  ***
}

type
  TObjWriter = class(TWriter)
  end;
  TObjReader = class(TReader)
  end;


procedure WriteObj(obj: TPersistent; st: TStream);
begin
  with TObjWriter.Create(st, 64) do
  begin
    WriteProperties(obj);
    FlushBuffer; Free;
  end;
end;


procedure ReadObj(obj: TPersistent; st: TStream);
begin
  with TObjReader.Create(st, 1) do
  begin
    while st.Position < st.Size do
    try ReadProperty(obj); except Continue; end;
    Free;
  end;
end;


procedure SaveObjToFile(obj: TPersistent; FileName: string);
var fs: TFileStream;
begin
  try
    fs := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite);
    try
      WriteObj(obj, fs);
    finally
      fs.Free;
    end;
  except end;
end;


procedure LoadObjFromFile(obj: TPersistent; FileName: string);
var fs: TFileStream;
begin
  if FileExists(FileName) then try
    fs := TFileStream.Create(FileName, fmShareDenyWrite);
    try
      ReadObj(obj, fs);
    finally
      fs.Free;
    end;
  except end;
end;



{
 ***
 ***  Процедуры для работы
 ***
}


// Загрузка позиции и размеров формы
procedure LoadFormPositionAndSize(AForm: TForm; APath: string);
var
  F : TSavedForm;
  fn : string;
begin
  F:= TSavedForm.Create;
  if APath = '' then
    fn := ExtractFilePath(ParamStr(0)) + AForm.Name + '.frm'
  else
    fn := APAth;
  if FileExists(fn) then begin
     LoadObjFromFile(F, fn);
     AForm.Height := F.Height;
     AForm.Width := F.Width;
     AForm.Top := F.Top;
     AForm.Left := F.Left;
  end;
  FreeAndNil(F);
end;

// Сохранение позиции и размеров формы
procedure SaveFormPositionAndSize(AForm: TForm; AFileName: string);
var
  F : TSavedForm;
  fn : string;
begin
  F := TSavedForm.Create;
  F.Height :=  AForm.Height;
  F.Width :=  AForm.Width;
  F.Top :=  AForm.Top;
  F.Left :=  AForm.Left;
  if AFileName =  '' then
    fn := ExtractFilePath(ParamStr(0)) + AForm.Name + '.frm'
  else
     fn := AFileName;
  SaveObjToFile(F, fn);
  FreeAndNil(F);
end;

// Теже процедуры но с сокращенным именем.
procedure SFPAS(AForm: TForm; AFileName: string);
begin
  SaveFormPositionAndSize(AForm, AFileName);
end;

procedure LFPAS(AForm: TForm; AFileName: string);
begin
  LoadFormPositionAndSize(AForm, AFileName);
end;



exports
   SaveFormPositionAndSize, LoadFormPositionAndSize, SFPAS, LFPAS;

begin
end.

Готовую DLL можно взять здесь: swpas.dll

среда, 10 сентября 2014 г.

Раскраска элементов TreeView

Легко: обрабатывай OnCustomDrawItem, в котором и назначай цвет:
Код Delphi
1
2
3
4
5
6
7
8
9
10
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
   case Integer(Node.Data) of
      1 : Sender.Canvas.Font.Color := clRed;
      2 : Sender.Canvas.Font.Color := clBlue;
      else
         Sender.Canvas.Font.Color:= clBlack;
   end;
end;
, и добавляй свои элементы в дерево. Цвет будет зависеть от значения поля Data:
Код Delphi
1
2
3
4
5
6
7
8
9
10
11
procedure TForm1.Button1Click(Sender: TObject);
begin
   with TreeView1.Items.AddChild(nil, 'First red') do
      Data := Pointer(1);
   with TreeView1.Items.AddChild(nil, 'Second red') do
      Data := Pointer(1);
   with TreeView1.Items.AddChild(nil, 'First blue') do
      Data := Pointer(2);
   with TreeView1.Items.AddChild(nil, 'Black') do
      Data := Pointer(0);
end;
http://www.cyberforum.ru/delphi-beginners/thread728793.html

понедельник, 30 декабря 2013 г.

Сканер портов на TCPClient

Сегодня я хочу рассказать о так называемых сканерах портов. Если кто-то не в курсе, то эта специальная программа для определения открытых портов на удаленной машине.
Как это будет работать.
Программа пытается подключиться к какому-то порту из заданного диапазона. Если подключение произошло, то говорим пользователю что порт открыт, в противном же случае, говорим что нет, после переходим к следующему порту.
Практика.
Для начала нам необходимо бросить на форму следующие компоненты: 2 Label'а, 2 Edit'а, одну кнопку, компонент Memo для вывода информации о открытых (закрытых) портах, и наконец начинку нашей программы - компонент TCPClient, с закладки Internet. Измените свойство Caption у Label'ов следующим образом: Label1 - Начальный порт, Label2 - Конечный порт. Напротив каждого из Label'ов расположите Edit'ы... Надпись на кнопке можете сделать какую хотите... Итак, осталось написать лишь сам код программы... Весь код нашей программы будет состоять лишь из одного метода (процедуры). Кликните дважды на кнопке, перед вами появится окно с исходным кодом. Вот как она должна выглядеть:

procedure TForm1.Button1Click(Sender: TObject);
var
  i:Integer;
  ip:String;
begin
  ip:='127.0.0.1'; //По умолчанию сканируем себя
  if not InputQuery('Attention','Enter IP-address',ip) then exit; //Запрашиваем адрес компа.
  for i:=StrToInt(Edit1.Text) to StrToInt(Edit2.Text) do //Запускаем цикл
  begin
    TcpClient1.RemotePort:=IntToStr(i); //Устанавливаем порт
    TcpClient1.Open; //Пытаемся его открыть
    if TcpClient1.Connected then Memo1.Lines.Add(IntToStr(i)+' open'); //Если удалось, то сообщаем об этом
    TcpClient1.Close; //Закрываем порт.
  end;
end;


Вот и готов наш простейший сканер портов! Введите начальный порт, конечный порт, жмите кнопку, в появившемся окне набирайте IP-адрес жертвы и в бой.

вторник, 3 декабря 2013 г.

Необязательный параметр в процедуре (Вариант 3. Значение по умолчанию)

Иногда, Вы можете избежать потребности в перезагрузке методом OVERLOAD, давая значения конечных параметров по умолчанию. Вызывающая программа может тогда вызвать с или без этих конечных параметров.

procedure MyProc(a : Byte; b : Byte = 23);

Может быть вызвана 2-мя способами:

MyProc(15, 16);
MyProc(45); // По умолчанию b будет равно 23

Необязательный параметр в процедуре (Вариант 2. Использование Overload)

Директива Overload позволяет Вам иметь различные версии одинаково названной функции или процедуры с различными параметрами. Это полезно, когда есть множество путей, которыми код может захотеть использовать подпрограмму. Например, если подпрограмма - конструктор класса, Вы можете хотеть иметь одну версию Create, которая устанавливает значения по умолчанию, и другую, которая берет эти значения как параметры. 

Вы должны закодировать директиву Overload перед любыми другими директивами. 

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

Когда количество параметров такое же, он всегда сначала пробует удовлетворить самые простые/наименьшие типы данных - например, вышеупомянутое значение 23 удовлетворил бы параметр Byte, чемInteger параметр. 

Пример использования

function Summ(A, B: integer): integer; overload;       // Версия 1 функции Summ
begin
  result:= A+B;
end;

function Summ(A,B,C: Integer): integer; overload;  // Версия 2 функции Summ
begin
 result:=A+B+C;
end;

Function ShowSumm;
begin
  ShowMessage(Summ(5,10));      // Используется версия 1 функции Summ
  ShowMessage(Summ(3,7,12));   // используется версия 2 функции Summ
end;

Если позволяет ситуация и чтобы не писать много одинакового кода, можно модернизировать версию 1 примера.

function Summ(A, B: integer): integer; overload;       // Измененная версия 1 функции Summ
begin
  result:= Summ(A,B, 0);
end;

В данном случае, мы вызываем версию с 3-мя параметрами, передавая два числа и 0, который не влияет на сумму). Но это частный случай.

Необязательный параметр в процедуре (Вариант 1. Открытые массивы)

Рассмотрим открытые массивы, которые позволяют передавать в функцию или процедуру различное количество параметров. В качестве параметров можно передать либо открытый массив элементов одинакового типа, либо массивы констант различного типа. В приведенном ниже примере объявляется функция, которой в качестве параметра должен передаваться открытый массив целых чисел. 


function AddEmUp( A: array of integer ): integer;


В открытом массиве можно передавать переменные, константы или выражения из констант. Ниже приведен пример, который демонстрирует вызов функции AddEmUp с передачей ей нескольких различных элементов. 


const
  j = 23;
var
  i, Rez: integer;
begin
   i := 8;
   Rez := AddEmUp( [i, 20, j, 43] );
end; 


Для получения информации о фактически передаваемом массиве параметров в функции или процедуре могут использоваться функции High, Low и SizeOf. Для иллюстрации их использования ниже приведен текст функции AddEmUp, которая возвращает сумму всех переданных ей элементов массива A. 


function AddEmUp( A: array of integer ): integer;
var
   i: integer;
begin
   Result := 0;
   for i := Low(A) to High(A) do
       Inc( Result, A[i] );
end; 


Object Pascal также поддерживает тип array of const, который позволяет передавать в одном массиве данные различных типов. Синтаксис объявления функций или процедур, использующих такой массив для получения параметров, следующий: 

procedure WhatHaveIGot( A: array of const ); 


Вызвать объявленную выше функцию можно, например, с помощью такого оператора:


procedure WhatHaveIGot( ['Text', 10, 5.5, @WhatHaveIGot, 3.14, true, 'c'] ); 


При передаче функции или процедуре массива констант все передаваемые параметры компилятор неявно конвертирует в тип TVarRec. Тип данных TVarRec объявлен в модуле System следующим образом: 


PVarRec = ^TVarRec;
TVarRec = record case
  Byte of vtInteger: (VInteger: Integer; VType: Byte);
        vtBoolean: (VBoolean: Boolean);
        vtChar: (VChar: Char);
        vtExtended: (VExtended: PExtended);
        vtString: (VString: PShortString);
        vtPointer: (VPointer: Pointer);
        vtPChar: (VPChar: PChar);
        vtObject: (VObject: TObject);
        vtClass: (VClass: TClass);
        vtWideChar: (VWideChar: WideChar);
        vtPWideChar: (VPWideChar: PWideChar);
        vtAnsiString: (VAnsiString: Pointer);
        vtCurrency: (VCurrency: PCurrency);
        vtVariant: (VVariant: PVariant);
        vtInterface: (VInterface: Pointer);
        vtWideString: (VWideString: Pointer);
        vtInt64: (VInt64: PInt64);
end;


Поле VType определяет тип содержащихся в данном экземпляре записи TVarRec данных и может принимать одно из ниже приведенных значений.

const
  vtInteger = 0;
  vtBoolean = 1;
  vtChar = 2;
  vtExtended = 3;
  vtString = 4;
  vtPointer = 5;
  vtPChar = 6;
  vtObject = 7;
  vtClass = 8;
  vtWideChar = 9;
  vtPWideChar = 10;
  vtAnsiString = 11;
  vtCurrency = 12;
  vtVariant = 13;
  vtInterface = 14;
  vtWideString = 15;
  vtInt64 = 16; 


Поскольку массив констант способен передавать данные разных типов, это может вызвать определенные затруднения при создании обрабатывающей полученные параметры функции или процедуры. В качестве примера работы с таким массивом рассмотрим реализацию процедуры WhatHaveIGot, которая просматривает элементы полученного массива параметров и выводит их тип. 


procedure WhatHaveIGot( A: array of const );
var
   i: integer; TypeStr: string;
begin
   for i := Low(A) to High(A) do begin
     case A[i].VType of
          vtInteger : TypeStr := 'Integer';
          vtBoolean : TypeStr := 'Boolean';
          vtChar : TypeStr := 'Char';
          vtExtended : TypeStr := 'Extended';
          vtString : TypeStr := 'String';
          vtPointer : TypeStr := 'Pointer';
          vtPChar : TypeStr := 'PChar';
          vtObject : TypeStr := 'Object';
          vtClass : TypeStr := 'Class';
          vtWideChar : TypeStr := 'WideChar';
          vtPWideChar : TypeStr := 'PWideChar';
          vtAnsiString : TypeStr := 'AnsiString';
          vtCurrency : TypeStr := 'Currency';
          vtVariant : TypeStr := 'Variant';
          vtInterface : TypeStr := 'Interface';
          vtWideString : TypeStr := 'WideString';
          vtInt64 : TypeStr := 'Int64';
    end;
   ShowMessage( Format( 'Array item %d is a %s', [i, TypeStr] ) );
  end;
end;

Найдено на http://programmersforum.ru/

среда, 27 ноября 2013 г.

[SQLite] Подключаемся к базе данных SQLite3 (Delphi XE3 + SQLite3)

Для реализации задач, нам необходима база данных. Желательно бесплатная и простая. И выбрал я SQLite.

Плюсы:

  1. Бесплатный и открытый исходный код
  2. Не нуждается в дополнительной настройке на клиентской машине, надо только одну DLL
  3. Очень быстрый
  4. Возможность работать в режиме только чтение и гостевого аккаунта
  5. Не записывает ни чего в реестр, и другие файлы
  6. Поддерживается стандартного SQL ( http://www.sqlite.org/lang.html )

Как я упомянул выше, для разработки и работы программы с базой данных нам нужна одна единственная sqlite3.dll. Она должна находиться в папке с программой, а так же в директории XE3 (RAD Studio\10.0\bin). Я еще добавил ее в Windows\system32.

Из компонентов Delphi нам понадобятся:
ActionList1(TActionList)
DBServer (TSQLConnection)
SQLQuery1(TSQLQuery)

Настройку компонентов можно сделать из дизайнера, а можно вручную.

Создадим процедуру инициализации соединения с БД через DBServer.

procedure InitialConnection(ASQLConnection: TSQLConnection; AFileName: string);
begin
  ASQLConnection.ConnectionName := 'SQLITECONNECTION';
  ASQLConnection.DriverName:='Sqlite';
  ASQLConnection.LoginPrompt:= false;
  ASQLConnection.Params.Values['Host']:='localhost';
  ASQLConnection.Params.Values['FailIfMissing']:='False';
  ASQLConnection.Params.Values['ColumnMetaDataSupported']:='False';
  ASQLConnection.Params.Values['Database']:=AFileName;
  ASQLConnection.Open;
end;

ASQLConnection.Open открывает базу, если файла нет, то создает. Если же в указанную папку нельзя записать, возникнет ошибка. Так как это не прямая функция, то обрабатывать ошибки будет вызывающая процедура (acDBServerExecute).

Для передачи SQL запросов используем SQLQuery1. Но перед использованием свяжем его с нашим соединением DBServer.
SQLQuery1.SQLConnection := DBServer;
Все, можно отправлять запросы. Так например нам надо создать таблицу в базе, если ее нет (первый раз открываем базу). Давно в исходниках INIFiles подсмотрел такой вид процедур, которые начинаются на MayBeХххх(). Как я понимаю, это процедуры которые может быть что-то делают. Так вот я использую такую процедуру для создания таблицы в безе. если ее нет.

procedure MayBeCreateTables(AQuery: TSQLQuery);
begin
  AQuery.SQL.Clear;
  AQuery.SQL.Text :='CREATE TABLE if not exists MyBids ( '+
                    'id INTEGER NOT NULL PRIMARY KEY,'+
                    'WellNo CHAR(10),'+
                    'Field CHAR(20),'+
                    'WellZaboy CHAR(10),'+
                    'WellDiam CHAR(10),'+
                    'WellRastvor CHAR(20),'+
                    'DateDone DATE,'+
                    'TimeDone TIME,'+
                    'DateConfirm DATE,'+
                    'TimeConfirm TIME,'+
                    'Task TEXT,'+
                    'Zakazhik TEXT,'+
                    'Predstavitel TEXT,'+
                    'Partia TEXT,'+
                    'Comment TEXT,'+
                    'DateRecieve DATE,'+
                    'TimeRecieve TIME,'+
                    'Status TEXT,'+
                    'DateChange DATE,'+
                    'TimeChange TIME'+
                    ');';
  AQuery.ExecSQL;
end;

Ключевым словом здесь является  if not exists в SQL запросе. Таким образом SQLite сам проверяет есть ли такая таблица и если нет, то создает. Спасибо ему за это.

Осталось собрать все в кучу и обработать возможные ошибки.

В ActionList добавим новое действие в категорию DB и назовем его acDBServerStart. В нем мы будем запускать наш сервер БД.

procedure TForm1.acDBServerStartExecute(Sender: TObject);
begin
  try
   InitialConnection(DBServer, 'C:\DB\bids.db');
   SQLQuery1.SQLConnection := DBServer;
   MayBeCreateTables(SQLQuery1);
 except
    on E: Exception do
    begin
      ShowMessage( StringReplace(E.Message, #13, ' ', [rfReplaceAll]);
      //raise;
    end;
  end;
end;

//raise - закоментировал, что бы не отображались ошибки. Их будем записывать в лог.

Таким образом мы настроили соединение, соединились и на случай отсутствия таблицы создали ее. Можно добавлять данные в таблицу.