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

четверг, 18 июня 2020 г.

Как словить событие формы OnMove в Delphi

Я не нашел такого события OnMove для формы в Delphi XE8. Как дела обстоят в более старших версиях не знаю. Но вот как это решается для моего случая - просто добавляем обработчик сообщения WM_MOVE в форму:
procedure OnMove(var Msg: TWMMove); message WM_MOVE;

....

procedure TMyForm.OnMove(var Msg: TWMMove);
begin
  DoSomething;
end;
Сообщение WM_MOVE приходить когда пользователь схватил форму, перетащил и отпустил. Если вам нужно ловить событие во время самого движение добавьте обработчик WM_MOVING.


четверг, 29 сентября 2016 г.

Как отключить BEEP в TEdit при нажатии Enter?

Нужно просто обнулить переменную Key в обработчике OnKeyPress
procedure TfrmMain.cbxTestCaseFilterKeyPress(Sender: TObject; var Key: Char);
begin
  case Ord(Key) of
    // {Enter} Apply Filter
    13: begin
          actTestCaseFilterApply.Execute;
          Key := #0;
        end;


суббота, 18 февраля 2012 г.

Как убрать закладки у PageControl?

Уже много раз нужно было убрать у TPageControl эти закладки. Не TabSheet,  а именно сам заголовок. Мне нужно было для визарда, для формы настроек, где слева дерево, а справа страница с контролами.
Как сделать это с TPageControl сразу не понятно и поэтому как я только не изголялся - использовал и TFrame, и TNoteBook. Всё неудобно. Но как это сделать с TPageControl я долго не искал, потомучто нужно было делать срочно.
И вот настал момент, когда сказали переделать существующий PageControl, у которого около 20 страниц, на каждой из которых может быть до 20 контролов. Переделывать все это заново как-то не хотелось.
Правду люди говорят:
"Лень -  двигатель прогресса"
Нашел как это сделать. И все оказалось очень просто. И так.

  1. Кидаем на форму TPageControl.
  2. Устанавливаем  TPageControl.Style := tsButtons.
  3. Заполняем его TTabSheet-ами
  4. У каждого табшита устанавливаем TabVisible := False;
  5. Потом присваиваем TPageControl.ActivePage := TabSheet1;
В моем случае я сделал при создании формы
 pcMain.Style := tsButtons;
 for I := 0 to pcMain.PageCount-1 do
    pcMain.Pages[I].TabVisible := False;
 pcMain.ActivePage := tsBasic;

Заполнил TreeView нодами с заданными значениями SelectedIndex. Потом в TTreeView.OnChange 

procedure TfrmMain.PropTreeChange(Sender: TObject; Node: TTreeNode);
begin
  case Node.SelectedIndex of
    10  : pcMain.ActivePage := tsBasic;
    20  : pcMain.ActivePage := tsDocs;
    30,
    31  : pcMain.ActivePage := tsTextsOffer;
    32  : pcMain.ActivePage := tsTextsInfo;
...

где tsBasic и тому подобные - это TTabSheet


Вот и все

пятница, 17 февраля 2012 г.

Проблемы с наследниками TFrame

Добавил в проект фрейм  TCustomTextFrame = class (TFrame). Визуальных контролов на него не ложил. Просто добавил нужные свойства, методы, объявил абстракные...
Добавить наследника TCustomTextFrame  через File/Add New/Other/Inherited не получилось.
Добавил простой фрейм и вручную в коде поменял ему предка с TFrame на TCustomTextFrame 
TframeTextsOffer = class(TCustomTextFrame)
Всё  нормально подхватилось и заработало.

Самое интересно началось на следующий день - при открытии в дизайнтайме TframeTextsOffer вылетала ошибка, что нет такого свойства как ClientHeight. Компилялось молча, но при запуске приложения тоже ругалось на ClientHeight.

Оказалось что делфи почемуто добавляет внуку, так сказать, фрейма в *.dfm свойства ClientHeigh, ClientWidth и ещё кучу всякого. Но у фрейма такого нет. Вот и ругается.
Но простое удаление не дает результатов -  делфи при открытии TframeTextsOffer  в дизайнтайме упорно добавляет эти свойства, на которые потом сама же и ругается.

Помогло только изменение вручную в *.dfm object frameTextsOffer: TframeTextsOffer  на inherited frameTextsOffer: TframeTextsOffer.

Не знаю насколько это правильно, но пока работает.

вторник, 24 января 2012 г.

Delphi и дескрипшены к полям MS Access

Задача: Получить коментарии (описания) полей в MS Access и сделать их хинтами к контролам.


Итак что нужно сделать
  1. Получить комментарии к полям
  2. Список Таблица.Поле=Коментарий
  3. Обновить хинты контролов.
Первое.
В DataModule делаю 


private
  FFieldsComments: TStrings;
  ...

  procedure UpdateFieldsComments;
published
  property FieldsComments: TStrings read FFieldsComments;


FFieldsComments создается в DataModuleCreate и разрушается в DataModuleDestroy.


procedure TdmMain.UpdateFieldsComments;
var
  ADODataSet: TADODataSet;
begin
  if Assigned(FFieldsComments) and ADOConnection1.Connected then
  begin
    FFieldsComments.Clear;
    ADODataSet := TADODataSet.Create(Self);
    try
      ADOConnection1.OpenSchema(siColumns, VarArrayOf([Unassigned, Unassigned, tblDeviceCharacteristics.TableName]), EmptyParam, ADODataSet);
      ADODataSet.Open;
      ADODataSet.First;
      while not ADODataSet.Eof do
      begin
        if ADODataSet.FieldByName('DESCRIPTION').AsWideString <> '' then
          FFieldsComments.Append(ADODataSet.FieldByName('TABLE_NAME').AsWideString + '.' +ADODataSet.FieldByName('COLUMN_NAME').AsWideString + '=' +ADODataSet.FieldByName('DESCRIPTION').AsWideString);
        ADODataSet.Next;
      end;
    finally
       FreeAndNil(ADODataSet)
    end;
  end;
end;



Всё делается методом OpenSchema.Самый мне непонятный параметр это второй. Туда передаю VarArrayOf(...), но я пока не нашел описания что есть что в этом масиве. Я просто подставил то что нашёл в инете и получил, что хотел. Может, если найду описание дополню статью. 
Процедуру UpdateFieldsComments вызываю в ADOConnection.OnAfterConnect.

Теперь в форме нужно обновить хинты.


procedure TfrmMain.UpdateHitnsFromDB;
var
  i: integer;
  procedure UpdateDBEditHint( AControl: TDBEdit);
  begin
    if AControl.DataSource.DataSet is TADOTable then
      AControl.Hint := dmMain.FieldsComments.Values[TADOTable(AControl.DataSource.DataSet).TableName + '.' + AControl.DataField];
  end;

  procedure UpdateDBLinkEditHint( AControl: TDBLinkEdit);
  begin
    if AControl.DataSource.DataSet is TADOTable then
      AControl.Hint := dmMain.FieldsComments.Values[TADOTable(AControl.DataSource.DataSet).TableName + '.' + AControl.DataField];
  end;

  procedure UpdateDBLookupComboBoxHint( AControl: TDBLookupComboBox);
  begin
    if AControl.DataSource.DataSet is TADOTable then
      AControl.Hint := dmMain.FieldsComments.Values[TADOTable(AControl.DataSource.DataSet).TableName + '.' + AControl.DataField];
  end;

begin
  for I := 0 to ComponentCount-1 do
    if Components[I] is TDBEdit then
      UpdateDBEditHint(Components[I] as TDBEdit)
    else if Components[I] is TDBLinkEdit then
       UpdateDBLinkEditHint(Components[I] as TDBLinkEdit)
    else if Components[I] is TDBLookupComboBox then
       UpdateDBLookupComboBoxHint(Components[I] as TDBLookupComboBox)
end;

UpdateHitnsFromDB вызываю в actConnectExecute
Вот и все.  


среда, 18 января 2012 г.

Delphi и Диалог выбора папки

Сколько себя помню у Delphi никогда не было своего компонента выбора папки типа TOpenDialog и каждый раз когда нужно было выбирать именно папку искал как это делается.
Вот теперь решил записать то что я нашел и немного переделал для себя.
Это пока функция, возможно когда-то сделаю компонент типа TOpenFolder.

И так всё эавязано на функции ShBrowseForFolder из модуля ShlObj или по новому Winapi.ShlObj.
Но множество примеров, которые я видел были без кнопки Create New Folder и без возможности установки пути по умолчанию.
И так код:
...
function SelectFolder(hWnd: HWND; const Caption: WideString; var Folder: WideString): boolean;
...
implementation
uses  ShlObj, ActiveX, Forms;
var
  DefaultPath: widestring = '';
...
//Эта функция нужна для установки пути по умолчанию
function BrowseCallbackProc(hwnd: HWND; uMsg: UINT; lParam: LPARAM; lpData: LPARAM): integer; stdcall;
begin
  Result := 0;
  if uMsg = BFFM_INITIALIZED then
    SendMessage(hwnd, BFFM_SETSELECTION, 1, LongInt(PWideChar(DefaultPath)));
end;

function SelectFolder(hWnd: HWND; const Caption: WideString; var Folder: WideString): boolean;
var
  WindowList: Pointer;
  BrowseInfo : TBrowseInfo;
  Buffer: PChar;
  RootItemIDList, ItemIDList: PItemIDList;
  ShellMalloc: IMalloc;
  IDesktopFolder: IShellFolder;
  Eaten, Flags: LongWord;
begin
  FillChar(BrowseInfo, SizeOf(BrowseInfo), 0);
  if (ShGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then
  begin
    Buffer := ShellMalloc.Alloc(MAX_PATH);
    try
      DefaultPath := Folder;
      RootItemIDList := nil;
      with BrowseInfo do
      begin
        hwndOwner := hWnd;
        pidlRoot := RootItemIDList;
        pszDisplayName := Buffer;
        lpfn := @BrowseCallbackProc;
        lpszTitle := PWideChar(Caption);
        ulFlags := BIF_RETURNONLYFSDIRS or $0040 or BIF_EDITBOX or BIF_STATUSTEXT;
      end;
      WindowList := DisableTaskWindows(0);
      try
        ItemIDList := ShBrowseForFolder(BrowseInfo);
      finally
        EnableTaskWindows(WindowList);
      end;
      Result :=  ItemIDList <> nil;
      if Result then
      begin
        ShGetPathFromIDList(ItemIDList, Buffer);
        ShellMalloc.Free(ItemIDList);
        Folder := Buffer
      end;
    finally
      ShellMalloc.Free(Buffer);
      DefaultPath := '';
    end;
  end;
end;



Теперь пример использования:
procedure TframeGeneralSettings.Button1Click(Sender: TObject);
var
  Value: WideString;
begin
  Value := edtImagesFolder.Text;
  if SelectFolder(Handle,  'Select ' + lblImagesFolder.Caption, Value) and (Value <> edtImagesFolder.Text) then
    edtImagesFolder.Text := Value;
end;




пятница, 9 декабря 2011 г.

Delphi не загружает мои компоненты

Появилась необходимость написать свой компонет потомок TCustomLabel. Написал. Может в будущем сделаю заметочку, что и как писал

Так вот. Создал пакет, создал компонент и с дефотными настройками собрал и поставил. Стало без проблем. Заменил в основном проекте все лабелы на свои.

Всё работает отлично. Настроение хорошее...

Пока делфу не перегрузил. Тут оказалось, что оно не видит мой пакетик, мою бэпээлочку. Разбираюсь. Оказалось если не указать, куда ставить пакет, то  оно его ставит в 
С:\Documents and Settings\All Users\Documents\RAD Studio\5.0\Bpl\
С:\Documents and Settings\All Users\Documents\RAD Studio\5.0\Dcp\
И при загрузке от туда не поднимает. Т.к. я буду отдавать этот компонент людям, что бы они дальше с ним работали, то я не надаюсь, что каждый додумается добавить эти папки в пути поиска.

Полез в настройки делфы и подсмотрел как она обзывает папку с собой и  в настройках пакета прописал пути Output directory и DCP output directory



Теперь пакет ставится в 
С:\Program Files\CodeGear\RAD Studio\5.0\bin\
С:\Program Files\CodeGear\RAD Studio\5.0\lib\
Может я что-то сделал не канонично. Но по крайней мере работает.

среда, 31 марта 2010 г.

Горячие клавиши Delphi


Человек, который не знает свой инструмент, что мартышка с гранатой.





ШоткатОписаниеВерсия IDE
EscapeНажате Escape во время перемещения контрола делает объектом перемещения родителя контролаDelphi 2 и выше
Shift + ClickAfter selecting control in form designer, click on it with Shift again to select top most parent FormDelphi 5  и выше
TabНа форме перемещает фокус по контролам. В Инспекторе Объектов переключает испектор в режим инктрементного поиска по названиям совйствDelphi 5  и выше
Ctrl + JОткрывает список шаблонов кодаDelphi 5  и выше
Ctrl + TУдаляет текст с позиции курсора до конца словаDelphi 5  и выше
Ctrl + EИнкрементный поискDelphi 5  и выше
Ctrl + YУдаляет текущую строкуDelphi 5  и выше
Ctrl + BВ редакторе вызывает окно буфера. The buffer window shows a list of all different tabs.Delphi 2007  и выше
Ctrl + Shift + GГенерирует новый GUID в позиции курсораDelphi 5  и выше
Ctrl + Shift + IСдвиг выделенного блока вправоDelphi 5  и выше
Ctrl + Shift + UСдвиг выделенного блока влевоDelphi 5  и выше
Ctrl + K + IСдвиг выделенного блока вправоDelphi 5  и выше
Ctrl + K + UСдвиг выделенного блока влевоDelphi 5  и выше
Ctrl + Shift + JВызов SyncEditBorland Developer Studio 2006
Ctrl + Shift + VАвтоматически объявить переменную в позиции курсораBorland Developer Studio 2006
Ctrl + Shift + YУдалить до конца строкиDelphi 5  и выше
Alt + [Соответствующая скобка впередDelphi 5  и выше
Alt + ]Соответствующая скобка назадDelphi 5  и выше
Alt + RightArrowBrowse forward (hotlink history)Delphi 6  и выше
Alt + LeftArrowBrowse backward (hotlink history)Delphi 6  и выше
Alt + UpArrowBrowse to symbol under editor cursor (invoke a hotlink and add it to the hotlink history)Borland Developer Studio 2006
F4Запустить программу до остановки в позиции курсораDelphi 2  и выше
F5Пставить/удалить точку остановаDelphi 2  и выше
F7Трассировка с входом в вызываемые процедуры и функцииDelphi 2 и выше
Shift - F7Трассировка заходя в каждую процедуру и перескакивание в каждое возникающее событиеDelphi 5 и выше
F8Трассировка без входа в вызываемые процедуры и функцииDelphi 2 и выше
Shift - F8Run until returnDelphi 5 и выше
F9Запустить программу в режиме отладкиDelphi 2 и выше
Ctrl + F2Прервать выполнение программыDelphi 5 и выше
Ctrl + F7Просмотр значений переменных и их изменениеDelphi 2005 и выше
Ctrl + F5Добавить в список переменных для просмотраDelphi 5 и выше
Ctrl + F12Список модулейDelphi 2 и выше
Alt + GПерейти к строке по номеруDelphi 2 и выше
Ctrl + O + GПерейти к строке по номеруDelphi 5 и выше
Ctrl + Shift + RСтарт\стоп записи макроDelphi 2 и выше
Ctrl + Shift + PЗапустить макроDelphi 2 и выше
Ctrl + SpacebarПоказать список методов, свойств объекта (после точки)Delphi 5 и выше
Ctrl + Shift + SpacebarПоказать список параметров функцииDelphi 5 и выше
Ctrl + EnterОткрыть файл с именем слова на котором курсор стоитDelphi 2 и выше
Ctrl + Shift + EnterНайти все ссылкиDelphi 2005 и выше
Ctrl + Shift + CЗакончить метод (если он описан – создать шаблон для реализации,если есть реализация – объявить метод)Delphi 5 и выше
Ctrl + Shift + UpArrowПереход от объявления процедуры к ее реализацииDelphi 5 и выше
Ctrl + Shift + DownArrowПереход от объявления процедуры к ее реализацииDelphi 5 и выше
Ctrl + Shift + 1 - 9Поставить\снять закладкуDelphi 2006 и выше
Ctrl + 1 - 9Перйти к закладкеDelphi 2006 и выше
Ctrl + Alt + F12Открыть список открытых файлов в правом верхнем углуBorland Developer Studio 2006
Ctrl + Alt + Mouse WheelПереход к предыдущей или следующей реализации метода в лексикографическом порядке в текущем модуле, либо в классе, который был ограничен Ctrl + Q + LBorland Developer Studio 2006
Ctrl + Alt + UpArrowПереход к предыдущей реализации метода в лексикографическом порядке в текущем модуле, либо в классе, который был ограничен Ctrl + Q + LBorland Developer Studio 2006
Ctrl + Alt + DownArrowПереход к следующей реализации метода в лексикографическом порядке в текущем модуле, либо в классе, который был ограничен Ctrl + Q + LBorland Developer Studio 2006
Ctrl + Alt + HomeПереход к лексически первой реализации метода в текущем модуле, либо в классе, который был ограничен Ctrl + Q + LBorland Developer Studio 2006
Ctrl + Alt + EndПереход к лексически последней реализации метода в текущем модуле, либо в классе, который был ограничен Ctrl + Q + LBorland Developer Studio 2006
Ctrl + Alt + PАктивировать палитру компонентов в режиме фильтра (наберите название и нажмите Enter чтобы бросить на форму)Delphi 2005 и выше
Ctrl + Alt + AВставить текущюю дату в позицию курсораsince BCB 4.0
Ctrl + /Закоментировать\раскоментировать, Ctrl + # для нордических (и возможно для других интернациональных) клавиатурDelphi 2005 и выше
Ctrl + Shift + TДобавить в список TodoDelphi 2005 и выше
Alt + F12Переключение отображения формы между тектовым и дезигн режимамиDelphi 5 и выше
Alt + F11Диалог модулейDelphi 5 и выше
Ctrl + F11Диалог открытия проектаDelphi 2005 и выше
Ctrl + Alt + F11Окно управления проектом Delphi 2005 и выше
F11Инспектор объектовDelphi 5 и выше
F12Переключение между редактором и дизайнеромDelphi 5 и выше
Alt + 0Список оконDelphi 2005 и выше
Shift + Alt + F11Окно структурыDelphi 2005 и выше
Ctrl + Shift + BВызывает непонятное окно с название "Buffer list"Delphi 5
Ctrl + Alt + BОкно точек остановаDelphi 5 и выше
Ctrl + Alt + SОкно стека вызововDelphi 5 и выше
Ctrl + Alt + WОкно просмотра трассируемых переменныхDelphi 5 и выше
Ctrl + Alt + LОкно локальных переменныDelphi 5 и выше
Ctrl + Alt + TОкно нитей (Threads)Delphi 7 и выше
Ctrl + Alt + FОкно FPUDelphi 2005(removed from Delphi 2006)
Ctrl + Alt + CОкно CPUDelphi 5 и выше
Ctrl + Alt + VОкно событий (Event)Delphi 5 и выше
Ctrl + Alt + MОкно модулейDelphi 2005 и выше
Shift + F12Окно формDelphi 5 и выше
Ctrl + Shift + AInvoke Add to uses clause(Find unit in Delphi 2006) window (Refactoring)Delphi 2005 и выше
Ctrl + Shift + F11Окно настроек проектаDelphi 2005 и выше
Ctrl + F9Компилировать проектDelphi 5 и выше
Shift + F9Собрать проектDelphi 5 и выше
Shift + F11Окно добавления в проектDelphi 5 и выше
Shift + Ctrl + F9Запустить без отладкиDelphi 2005 и выше
Ctrl + FПоискDelphi 3 и выше
Shift + Ctrl + FПоиск в файлахDelphi 3 и выше
Alt + F7/F8Предыдущий/следующий результат (для поиска в файлах и ошибок сборки)Delphi 7 и выше
Ctrl+K+EПривести выделенный текст к нижнему регистру и убрать выделениеDelphi 5 и выше
Ctrl+K+FПривести выделенный текст к верхнему регистру и убрать выделениеDelphi 5 и выше
Ctrl+K+OПривести выделенный текст к нижнему региструDelphi 5 и выше
Ctrl+K+NПривести выделенный текст к верхнему региструDelphi 5 и выше
Ctrl+O+UПереключить регистрDelphi 5 и выше
Ctrl+Shift+K+OВключить\выключить сворачивание кодаDelphi 2006 и выше
Ctrl+Shift+K+AСворачивание кода: Развернуть все блоки кодаDelphi 2006 и выше
Ctrl+Shift+K+EСворачивание кода: Свернуть все блоки кодаDelphi 2006 и выше
Ctrl+Shift+K+UСворачивание кода: Развернуть текущий блок кодаDelphi 2006 и выше
Ctrl+Shift+K+TСворачивание кода: Переключить текущий блок (expand & collapse)
Ctrl+Shift+K+RСворачивание кода: Свернуть все регионы {$region 'comment'}..{$endregion}Delphi 2006 и выше
Ctrl+Shift+K+PСворачивание кода: Свернуть вложенные процедуры
Ctrl+Shift+K+MСворачивание кода: Свернуть все методы
Ctrl+Shift+K+CСворачивание кода: Свернуть все классы
Ctrl+Shift+K+GСворачивание кода: Свернуть до главных групп [Interface/Implementation]Delphi 2006 и выше
Ctrl+Shift+K+NСворачивание кода: Свернуть Namespace/UnitDelphi 2006 и выше
Ctrl+TabПереключиться на следующий открытый файл в редактореDelphi 2006 и выше
Ctrl+Shift+TabПереключиться на передыдущий открытый файл в редактореDelphi 2006 и выше
Ctrl + K + PДиалог печати выделенногоDelphi 5 и выше
Ctrl + K + WЗаписать блок в файл (выделенный текст)Delphi 5 и выше
Ctrl + K + RПрочитать блок из файла и вставить текст в позици курсораDelphi 5 и выше
Ctrl + K + CCopies selected text at the end of the selectionDelphi 5 и выше
Ctrl + K + TВыелить слово в позиции курсораDelphi 5 и выше
Ctrl + O + LВыделить текущую  строкуDelphi 5 и выше
Ctrl + Q + LToggles between limiting the Ctrl+Alt navigation shortcuts to the current class, or limiting it to the current unitBorland Developer Studio 2006
Ctrl + Q + WПерейти на следующий елемен в окне сообщенийDelphi 5 и выше
Ctrl + F6Переключиться между исходником (.cpp) и заголовком (.h)BDS 2006 и выше, C++ Builder personality
Оригинал тут

Тестировал на Delphi 2007. Некоторые вещи не работали. Некотрые не понял так и оставил в английском варианте. Если вы найдете ошибки, неточности и т.п. пишите. 
Доделаем до конца.

понедельник, 1 марта 2010 г.

Надоело __history в Delphi?

Пишу проект на Delphi 2007. Через некоторое время заметил что папка с проектом начала ненормально раздуваться.

Присмотревшись нашел там новую папку __history, содержимое которой напомнило мне некое подобие системы управления версиями. Но я уже привык пользоваться subversion и этот новый прибамбас просто раздражает. Поначалу я просто ее грохал. Потом мне это надоело и решил найти где это отключается.

Покопавшись нашел 
Tools->Options->Editor Options->Create backup files

Снимаем галочку и радуемся.

вторник, 16 февраля 2010 г.

GExperts: Отладка на другой машине

GExperts это отличный помощник разработчика в Delphi.
В нем есть отличная функция SendDebug, с помощью которой вы сможете выводить отладочную информацию в отдельное окно, которое имеет свою иконку в SystemTray. Для этого в коде не нужно придумывать никаких конструкций - GExperts все делает сам. Он добавляет в список модулей модуль DebugIntf а в код вставляет такую конструкцию
{IFOPTD+} SendDebug(''); {ENDIF}
Так что, когда отладили просто выключаем опцию D и просто перекомпилируйте и все.
Однако у меня возникла ситуация, когда у себя все отладил - вроде работает. Отдал заказчику, а у него что-то не работает. Если просто перекомпилировать программу с опцией D и отдать заказчику, то она не заработает, а будет выкидывать всевозможные ошибки.
Поэтому немного покопавшись решил эту проблему следующим способом.
Поместил папку к моей программе следующие файлы:

  1. C:\Program Files\GExperts for Delphi 2007\GExpertsDebugWindow.exe *

  2. C:\Windows\rtl100.bpl **

  3. C:\Windows\vcl100.bpl **

  4. C:\Windows\vclx100.bpl **
* Путь может отличатся если вы указали его вручную или у вас другая версия Delphi и соответственно GExperts.
** Номер в имени файла это версия Delphi. Так что если у вас не Delphi 2007, то у вас другой номер. Просто поищите в папке Windows файлы rtl*.bpl, vcl*.bpl и vclx*.bpl

Заархивировал папку и отправил клиенту.
Вот и всё