6 июля 2011 г.

Adobe Flash Player ActiveX + IronPython с использованием SharpDevelop

Для многих программистов это тривиальная задача но думаю для начинающих этот топик будет полезен.
Наша задача запустить приложение написанное на IronPython использующее Adobe Flash Player ActiveX c применением среды SharpDevelop.

Понадобится: SharpDevelop и любая версия .Net Framework SDK.

Нам нужно создать компонент для палитры компонентов SharpDevelop. Для этого его надо сгенерировать его с помощью утилиты aximp.exe входящей в состав Net Framework SDK. Команда для генерации довольно таки проста

aximp.exe [имя файла ActiveX]

при этом будет сгенерированно [имякласса]s.dll Ax[имякласса]s.dll. aximp.exe обычно расположена в папке C:\Program files\Microsoft.NET\SDK\*версия*\Bin\ а файл ActiveX %windir%\system32\Macromed\Flash\.

Теперь запускаем SharpDevelop и начинаем новый проект "File">"New">"Solution…", в открывшемся окне выбираем "Python">"Windows Application" указываем имя проекта и нажимаем "Create".

Переходим в режим дизайнера форм нажав кнопку "Design". Переходим к панели "Tools" и вызываем контекстное меню панели, выбираем пункт "Configure Sidebar".

В открывшемся окне добавим новую категорию для нового компонента, нажав кнопку "New", и назовем его "ActiveX". После выберем нашу новую категорию и жмем кнопку "Add Components".

В новом окне переходим во вкладку "Custom" и указываем имя на файл сгенерированный утилитой aximp.exe а именно на тот где имя файла начинается с Ax. Жмем "ok" и еше раз "ok".

Теперь бросаем в окно программы компонент "AxShockwaveFlashObjects" из палитры компонентов и устанавливаем свойство "Movie" объекта равным имени файла нашей флешки. Жмем кнопку "Run". Тут у нас может поджидать ошибка

IronPython.Runtime.UnboundNameException: global name 
'AxShockwaveFlashObjects' is not defined
   at Caller.Call
   at BuiltinFunctionCaller.Call5
   at System.Dynamic.UpdateDelegates.UpdateAndExecute7
   at IronPython.Runtime.Importer.Import
   at IronPython.Runtime.Operations.PythonOps.InitializeModule
   at PythonMain.Main

для его устранения нужно добавить в исходный код программы строку.

import AxShockwaveFlashObjects

снова жмем кнопку "Run" и видим результат

С таким же успехом можно добавить и использовать в среде SharpDevelop любой компонент ActiveX.

27 июня 2011 г.

Бесплатный компоненты для скинования Delphi приложений.

Наверняка многие задумывались как сделать написанное на Delphi приложение боле стильным.
Нужно скиновать. 10 мин поиска и вот оно http://www.alphaskins.com/ да ешё по вкуcной лицензии для xUSSR (в стиле IBExpert). На этой странице можно загрузить еше 71 бесплатный скин для вашей Delphi  программы есть скины для  как в в стиле Mac OS, Office 2010, 2007, iOS.
Дa есть один минус надо заменить стандартные элементы управления Delphi на элементы из палитры Alpha. Хотя для этого есть конвертер (я им не пользовался) .
В палитре компонентов имеется практически все элементы управления кнопки, панели, ... и элементы управления для работы с базами данных. Также есть бесплатные элементы управления от пользователей AlphaControls.
Буду рад если этот пост будет кому нибудь полезен.

21 июня 2011 г.

Новый Flash Builder 4.5.1

Обновился Flash Builder теперь 4.5.1. И весит он теперь почти в 2 раза больше.
http://www.adobe.com/go/try_flashbuilder/.
Но а я жду релиза Eclipse Indigo Это завтра.
UDP: Уже Качаю :)...

11 июня 2011 г.

Прикручиваем Adobe Flex к приложению на Delphi.



Adobe Flex предоставляет весьма удобные и наглядные средства визуализации данных такие как OLAP кубы разного рода диаграммы с красивыми эффектами. Мне как то захотелось использовать такую диаграмму в своем приложении написанном на Delphi. Например.
Alternative content
Get Adobe Flash player
Конечно я знаю что Delphi имеется аналогичные компоненты но они как мне кажется в смысле дизайна более «серым»и на фоне «Flex»cовых компонентов. Попробуем встроить Flex приложение в Delphi и передать в него данные для вывода графика.
Поскольку FlashDevelop написан на C# он требует .NET Framework и JRE чтобы скомпилировать Flex приложение. Можно скачать Beta 4-ой версии или стабильную 3-ю при установке нужно отметить «Install Flex SDK» при этом установщик скачает и распакует Adobe Flex SDK. Я использовал бету.
Пишем наше Flex приложение.
Запускаем FlashDevelop. Переходим меню Project > New Project, выбираем Flex 4 Project, жмем OK. Пишем имя нашего приложения(у меня «Flex»).
Вот код нашего приложения.
<?xml version="1.0" encoding="utf-8"?>
<!-- Пример диаграммы встраиваемой в программу Delphi-->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               xmlns:s="library://ns.adobe.com/flex/spark"
               initialize="init()">

    <fx:Declarations>
        <!--Небольшой Эффект -->
        <mx:SeriesSlide id="slideIn"
                        duration="1500"
                        direction="up" />
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            import flash.external.ExternalInterface;
            import mx.collections.ArrayCollection;
            
            [Bindable]
            public var danniye:ArrayCollection = new ArrayCollection;
            
            public function fromDelphi(massiv:Array):void
            {
                //Записиваваем полученные данные в массив для Графика
                danniye = new ArrayCollection(massiv);
            }            
            //Эта функция вызывается при инициазизации флекс приложения
            public function init():void
            {
                //Регистрируем внешную функцию
                ExternalInterface.addCallback("fromDelphi", fromDelphi);
            }
        ]]>
    </fx:Script>
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
    <s:Panel title='Пример "нереального" бизнесса'>
        <s:layout>
            <s:VerticalLayout />
        </s:layout>
        <mx:ColumnChart id="myChart"
                        dataProvider="{danniye}"
                        showDataTips="true">
            <mx:horizontalAxis>
                <mx:CategoryAxis dataProvider="{danniye}"
                                 categoryField="MONTH" />
            </mx:horizontalAxis>
            <mx:series>
                <mx:ColumnSeries xField="MONTH"
                                 yField="DOHOD"
                                 displayName="Доходы"
                                 showDataEffect="slideIn" />
                <mx:ColumnSeries xField="MONTH"
                                 yField="RASHOD"
                                 displayName="Расход"
                                 showDataEffect="slideIn" />
                <mx:ColumnSeries xField="MONTH"
                                 yField="PRIB"
                                 displayName="Прибыль"
                                 showDataEffect="slideIn" />
            </mx:series>
        </mx:ColumnChart>
        <mx:Legend dataProvider="{myChart}" />
    </s:Panel>
</s:Application>
Для компиляции и запуска жмем F5.
Delphi приложение.
И так запустим Delphi и начнем новый проект. Свяжем наше приложение с базой данных. Для простоты я использовал ClientDataSet а данные беру из XML файл в формате cds-xml. Бросаем компонент форму указываем путь к XML файлу. Бросаем DataSource свойство DataSet устанавливаем равным ClientDataSet.
Теперь добавляем идем меню Component > Import Active X Control

В появившемся окне выбираем Shockwave Flash и нажимаем кнопку Install. В следующих окнах нажимаем OK и Yes.
Бросаем в окно программы компонент ShockwaveFlash из набора Active X. Добавим в uses XMLIntf, XMLDoc, StdCtrls и напишем процедуру для вызова функции которая будет находится внутри нашей флешки.
procedure TForm1.CdsToXml(datset:TDataSource; flash:TShockwaveFlash);
var i, j : integer;
    filNode, recNode, obNode, arNode, iNode, inNode:IXMLNode;
    xmldoc:TXMLDocument;
begin
try
    //создем Xml документ
    xmldoc:=TXMLDocument.Create(nil);
    xmldoc.Active:=True;

    //Главный тег
    inNode:=xmldoc.AddChild('invoke');
    xmldoc.Encoding:='windows-1251';

    inNode.Attributes['name']:='fromDelphi';        
    iNode:=inNode.AddChild('arguments');    
    arNode:=iNode.AddChild('array');
        
    with datset.DataSet do begin
    {пребираем все записи поля таблыци и взависимосьти от типа поля
    зеркалируем каждое значение в нужные теги}
    first;
        for I := 1 to RecordCount do begin
            obNode:=arNode.AddChild('property');
            obNode.Attributes['id']:=IntToStr(I-1);
            recNode:=obNode.AddChild('object');
            for j := 0 to FieldCount-1  do begin
                filNode:=recNode.AddChild('property');
                filNode.Attributes['id']:=FieldDefs.Items[j].Name;
                
                case Fields[j].DataType of
                    ftString:
                    begin
                        iNode:=filNode.AddChild('string');
                        iNode.Text:=Fields[J].Value;
                    end;
                    ftBoolean:
                    if Fields[J].AsBoolean then
                        iNode:=filNode.AddChild('true')
                    else
                        iNode:=filNode.AddChild('false');
                    ftCurrency:
                    begin
                        iNode:=filNode.AddChild('number');
                        iNode.Text:=FloatToStr(Fields[J].AsFloat);
                    end;
                    ftBCD:
                    begin
                        iNode:=filNode.AddChild('number');
                        iNode.Text:=FloatToStr(Fields[J].AsFloat);
                    end;
                    ftInteger:
                    begin
                        iNode:=filNode.AddChild('number');
                        iNode.Text:=Fields[J].Value;
                    end;
                    ftFloat:
                    begin
                        iNode:=filNode.AddChild('number');
                        iNode.Text:=Fields[J].Value;
                    end;
                    ftDate:
                    begin
                        iNode:=filNode.AddChild('string');
                        iNode.Text:=Fields[J].Value;
                    end;
                    ftDateTime:
                    begin
                        iNode:=filNode.AddChild('string');
                        iNode.Text:=Fields[J].Value;
                    end;
                    ftSmallint:
                    begin
                        iNode:=filNode.AddChild('number');
                        iNode.Text:=Fields[J].Value
                    end;
                    else iNode:=filNode.AddChild('null');
                end;
            end;
            Next;
            end;
        end;
finally
    //Вызаваем фукцию во флешке
    flash.CallFunction(inNode.XML);
    xmldoc:=nil;
end;
end;
Эта процедура будет создаст XML документ в котором будет указанно имя вызываемой функции и ее параметры. Которая будет иметь вид типа. 
<invoke name="fromDelphi">
    <arguments>
        <array>
            <property id="0">
                <object>
                    <property id="MONTH">
                        <string>Январь</string>
                    </property>
                    <property id="DOHOD">
                        <number>1500</number>
                    </property>
                    <property id="RASHOD">
                        <number>700</number>
                    </property>
                    <property id="PRIB">
                        <number>800</number>
                    </property>
                </object>
            </property>
            <property id="1">
                <object>
                    <property id="MONTH">
                        <string>Февраль</string>
                    </property>
                    <property id="DOHOD">
                        <number>2500</number>
                    </property>
                    <property id="RASHOD">
                        <number>1340</number>
                    </property>
                    <property id="PRIB">
                        <number>1160</number>
                    </property>
                </object>
            </property>
            <property id="2">
                <object>
                    <property id="MONTH">
                        <string>Март</string>
                    </property>
                    <property id="DOHOD">
                        <number>1100</number>
                    </property>
                    <property id="RASHOD">
                        <number>820</number>
                    </property>
                    <property id="PRIB">
                        <number>280</number>
                    </property>
                </object>
            </property>
    </arguments>
</invoke>
Пишем в обработчике onCreate нашей формы.
procedure TForm1.FormCreate(Sender: TObject);
begin
//Разделитель точка 
DecimalSeparator:='.';
//Указаваем путь к нашей флешки, здесь она рядом с экзешником
ShockwaveFlash1.LoadMovie(0, ExtractFilePath(Application.ExeName)+'flex.swf');
end;
Бросаем на нашу форму кнопку и вызываем процедуру приготовления XML пакета в котором указанны названия функции нашей флешки и параметры к ней.
procedure TForm1.btn1Click(Sender: TObject);
begin
ClientDataSet.Open;
CdsToXml(DataSet, ShockwaveFlash1);
end;
Компилируем Delphi приложение, находим swf файл скомпилированный на FlashDevelop и кидаем его рядом с экзешником Delphi приложения и запускаем его. Как только флешка загрузится жмем нашу единственную кнопку и радуемся результату :).

Архив с исходниками.