Spread the love

FireMonkey — запуск на устройстве

Читать на сайте автора.

Variant := TObject.Create ?

  Думаю многие сталкивались с тем, что иногда требуется в variant передавать blob, ну или TObject. В таких языках как Java и C# все проще, элементарные типы являются объектами ну или умеют упаковываться из значимых типов в объекты. Для всех типов в языке есть базовый тип. В Delphi же, когда тип на этапе компиляции не известен единственным универсальным решением является использование variant. 
  Но не все так гладко, тип Variant предназначен только для хранения простых типов и указатель на объект в него не поместить не используя грязных хаков. Хотя сам RTL ими так и кишит. Так для хранения ftBlob в variant используется строка. 
На самом деле есть «законный»  механизм как через Variant передавать любые данные, в том числе и объекты. Для этого есть базовый класс TCustomVariantType, на основе которого можно определить свой тип который можно будет передавать как Variant, перекрыть в нем бинарные арифметические  и логические операции. Т.е. реализовать например свое сравнению и сложение для экземпляров типа. 
Но вот тут мы подходим к самому интересному, в FireMonkey появились методы по преобразованию variant к TObject и обратно:

function VarIsObject(Value: Variant): Boolean;
function ObjectToVariant(const AObject: TObject): Variant;
function VariantToObject(const Value: Variant): TObject;
Выглядит интригующе, неправда ли? 
Но что внутри?
Совершенно обычный хак, все опять сделано через строки:
function ObjectToVariant(const AObject: TObject): Variant;
begin
Result := 'vgobj' + IntToStr(Integer(Pointer(AObject)));
end;

function VariantToObject(const Value: Variant): TObject;
var
S: string;
begin
S := Value;
{$IFDEF FPCCOMP}
if (S <> '') and (Pos(WideString('vgobj'), S) = 1) then
{$ELSE}
if (S <> '') and (Pos('vgobj', S) = 1) then
{$ENDIF}
Result := TObject(Pointer(StrToInt(Copy(S, 6, 10))))
else
Result := nil;
end;

…и расположено это все не в модули System или Variants, а в Types. Никакой поддержки на уровне компилятора нет. Т.е. все еще нельзя писать так

var 
v: Variant;
begin
v := TMyClass.Create();
end;

  Почему бы Embarcadero уже не реализовать нормальную поддержку объектов в variant, ну или хотя бы сделать на основе TCustomVariantType. Непонятно. Притом, что есть и наследники от него TInvokeableVariantType и TPublishableVariantType.


  Возможно, все ради совместимости с COM Variant, не хотят далеко от него уходить и пытаются сохранить Variant для типов передающихся по значению. Или, возможно, методы VariantToObject и ObjectToVariant были реализованы Евгением Крюковым KSDev, а в Embarcadero не стали ничего переделывать, работает и на том спасибо.


Читать на сайте автора.

Чтение в FinalBuilder VersionInfo из проекта Delphi 7

  С удивлением обнаружил, что на многих форумах у коллег возникают проблемы как при автоматической сборке проекта через FinalBuilder автоматизировать изменение VersionInfo.
  Для начала внесем ясность где настройки содержаться.
  В Делфи 7 проектах для настроек используется файл .dof, в этот файл IDE сохраняет все настройки проекта. При компиляции на основе этого файла формируется .rc файл — скрипт который уже поступает на вход компилятора ресурсов, на выходе который возвращает .res файл. .res файл будет содержать VersionInfo  и информацию об иконки исполняемого файла. При компиляции dcc( Delphi Pascal Compiler) включает ресурсы в исполняемое приложение (если они указаны в модулях {$R *.res}). Некоторые настройки могут перекрываться .cfg   файлом. cfg файл создается при каждом сохранение проекта из IDE. Dcc проверяет наличие .cfg файла c именем совпадающем с названием проекта и если файл обнаружен использует настройки из него при компиляции. В своем проекте Finalbuilder’а я удаляю перед сборкой этот файл.
  Вернемся к нашим баранам, .dof файл в действительности имеет формат ini файла. А для работы с ini файлами в FinalBuilder есть действия (action)  «Read Ini File» и «Write Ini File». С помощью их мы можем прочесть любые значения из VersionInfo, Version Info Keys (и других) и записать обратно до вызова dcc.
Пример настройки действия чтения MajorVer значения. 

  Но что бы такая схема заработало неодходимо в действие Build Delphi Win32 Project на закладке Project отменить «Load Settings from project File» и «Version Info»:


В этом случае при сборке будет использоваться .dof файл.

Читать на сайте автора.

FireMonkey и разработка под Mac OS/iOS

Читать на сайте автора.

Наращивание функциональных возможностей Delphi

Читать на сайте автора.

ActionList – укрощение клавиатуры

Читать на сайте автора.

О нумерации версий Delphi

  История развивается по спирали,
а пони бегает по кругу…

   Пятничные размышления, на которые натолкнуло письмо одного моего приятеля.
   Сначала разработчики Delphi нумеровали версии просто: 1, 2, 3, 4, 5, 6, 7, 8. Затем, с подачи маркетологов Microsoft перешли на нумерацию версий по годам: 2005, 2006, 2007, 2009, 2010. В 2010 году Embarcadero придумала для всех своих продуктов новый бренд — «XE». «XE» — это не «Express Edition» как у Oracle, а два понятия: «X» — гетерогенность платформы (например, доступ к различным базам данных без дополнительных затрат) и «E» — скромное «Embarcadero». Поэтому с 2010 года началась новая эра в нумерации версий Delphi: Delphi XE, Delphi XE2… Что будет дальше? А дальше:

  • Delphi XE3
  • Delphi XE4
  • Delphi XE5
  • Delphi XE6
  • Delphi XE7
  • Delphi XE8
  • Delphi XE9
  • Delphi XEA
  • Delphi XEB
  • Delphi XEC
  • Delphi XED
  • Delphi XEE

 О, XEE! Легкой перестановкой букв мы получаем название первой версии Delphi — «Delphi.EXE». Круг замкнулся… 🙂

Читать на сайте автора.

Конвертирование XLS/XLSX/XLSM в XLSB

   С появлением MS Excel 2007 на смену привычного XLS-файла пришли сразу три формата:

  • XLSX — стандартный формат файлов Excel 2007-2010 на основе XML;
  • XLSM — формат Excel 2007-2010 на основе XML с поддержкой макросов (в отличие от XLSX он позволяет сохранять код макросов MS Visual Basic для приложений (VBA) и листы макросов MS Excel 4.0 (XLM));
  • XLSB — формат двоичных файлов Excel 2007-2010 (BIFF12).

Наиболее интересным из них является формат XLSB — Excel Binary Workbook. В отличие от других форматов Excel 2007-2010, он хранит данные не в виде XML, а является двоичным. Это дает существенные преимущества при работе с большими таблицами, т.к. бинарные файлы занимают меньше места на диске и читаются/записываются быстрее.
   Ни одна из библиотек для работы с файлами Excel в Delphi не поддерживает XLSB-формат. Например, XLSReadWrite поддерживает только XLSX, а авторы TMS FlexCel вообще не могут сказать, когда у них будет поддержка формата Excel 2007 и будет ли вообще. Поэтому, что бы конвертировать файлы Excel в XLSB-формат необходимо использовать OLE:

Var
  xls: OleVariant;

Const
  // formats in Excel 2007-2010
  xlExcel12 = 50; // XLSB
  xlOpenXMLWorkbook = 51; // XLSX
  xlOpenXMLWorkbookMacroEnabled = 52; // XLSM
  xlExcel8 = 56; // XLS (export to Excel 97-2003)

Procedure XYZ.ConvertFilesToXLSB(slFiles: TStringList);
Var
  iFile: Integer;
begin
  Try
    Try
      xls := CreateOleObject(‘Excel.Application’);
      xls.DisplayAlerts := False;
      If StrToFloat(StringReplace(xls.Version, ‘.’, DecimalSeparator, [])) < 12
        then WriteToLog(‘Error! Requires Excel 2007/2010’)
        else for iFile := 0 to slFiles.Count-1 do
                ConvertToXLSB(slFiles[iFile]);
    Finally
      xls.Quit;
      xls := UnAssigned;
    End;
  Except
    on E: Exception do
      WriteToLog(E.Message);
  End;
end;

Где ConvertToXLSB:

Procedure XYZ.ConvertToXLSB(sFileName: String);
Var
  sFileNameTo: String;
begin
  sFileName := ExpandFileName(sFileName);
  sFileNameTo := ChangeFileExt(sFileName, ‘.xlsb’);
  Try
    Try
      xls.Workbooks.Open(sFileName);
      xls.ActiveWorkbook.SaveAs(Filename := sFileNameTo, FileFormat := xlExcel12);
    Finally
      xls.Workbooks.Close;
    End;
  Except
    on E: Exception do
      WriteToLog(E.Message);
  End;
end;

   Думаю, что код простой и комментировать нечего. Остановлюсь только на строке проверки версии MS Excel. xls.Version возвращает номер версии MS Excel в виде строки, где цифры разделены точкой (например, «11.0» для Excel 2003, «12.0» для Excel 2007…), поэтому, чтобы получить номер версии в виде числа его необходимо преобразовать следующим способом:

StrToFloat(StringReplace(xls.Version, ‘.’, DecimalSeparator, []))

Читать на сайте автора.

Естественная сортировка

Читать на сайте автора.

Links for 2011-08-05 [del.icio.us]

Читать на сайте автора.