¡Dar una buena imagen! Parte 2 _ Delphi Básico

download ¡Dar una buena imagen! Parte 2 _ Delphi Básico

of 33

Transcript of ¡Dar una buena imagen! Parte 2 _ Delphi Básico

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 1/33

    Delphi Bsico

    Dar una buena imagen!

    Parte 2

    Salvador marzo 25, 2013 Advertencia,

    Artculos, Cdigo, DataSnap, Delphi, Entrada Diario, FireMonkey,

    LiveBindings, Uncategorized, XE3

    Si os parece bien, recapitulamos: Comentaba al

    finalizar la entrada anterior, Dar una buena imagen!

    Parte 1, que estbamos en condiciones de proseguir,

    toda vez que habamos generado una base de datos y

    almacenado algunas imgenes en ella, que era uno de

    los requisitos que poda demandar el hecho de

    habernos planteado devolver una imagen a travs de

    nuestro servidor de DataSnap. No es que realmente

    nos hiciera falta explcitamente contar con una base

    de datos, pero recordando lo compartido en aquellas

    lineas, me pareca un poco mas didctico a efectos

    Al da con HTML5 Builder

    y F.Charte

    Buscar

    Search this website

    CategorasElegir categora

    A cerca de

    m

    Salvador Jover Proyecto

    DelpHispano

    SELECCION DE CONTENIDO (2003-2013) THE EMBARCADERO MVP PROGRAM

    DELPHISPANO FB DELPHI SOLIDARIO MAPA LEGAL

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 2/33

    del blog y de las reflexiones que motivara su

    contenido. Por otro lado, hacer el cambio, y sustituir

    este origen por el de un fichero grfico, era sencillo y

    bastaba cambiar un par de lineas. As pues, y

    resumiendo, tomamos la decisin de guardar la

    imagen en la base de datos en un campo cuyo tipo de

    dato es adecuado a su contenido, habitualmente

    binario, en lugar de conservar la ruta donde ste est

    ubicado, y creamos una pequea utilidad para

    alimentar y gestionar la tabla de imgenes.

    Menciones a mtodos en DataSnap

    Sera bueno que nos detuviramos por un momento,

    antes de seguir adelante, y dedicramos unas lineas a

    hablar, o reflexionar, sobre los mtodos en DataSnap,

    que no siempre existieron tal y como ahora los

    entendemos, y que fueron una muy buena aportacin

    tras la llegada de Embarcadero y aplicar cambios

    importantes y profundos en esta tecnologa.

    Los mtodos remotos fueron uno de esos cambios

    importantes. En la docwiki de Embarcadero existe

    bastante informacin, -aunque nunca sea suficiente-,

    y de hecho, he buscado, para que pudieran quedar

    reflejados en esta segunda parte, algunos enlaces que

    nos puedan ayudar, de forma que nos permitan

    introducir el tema. Concretamente, el enlace principal

    que lo abre, Developing DataSnap Applicatins, que

    es uno de esos enlaces que es bueno tener a mano ya

    que, adems de los apuntes hacia las distintas

    referencias al tema de la docwiki, se enumeran una

    buena cantidad de recursos externos, enlazados

    desde vdeos, cdigo fuente y artculos tcnicos.

    Tambin tengo anotados por su utilidad, el enlace

    que abre el tema propiamente de los

    mtodos Exposing DataSnap Server Methods, y el que

    hace referencia y enumera los distintos tipos de datos

    que se soportan dentro del marco de

    DBExpress Data.DBXCommon.TDBXDataTypes.

    Redes Sociales

    PROMOCIN

    XE4!

    Comunidad

    Australiana

    Australian

    Delphi User

    Group

    Members

    Comunidad

    de Brasil y

    Portugal

    PRXIMO

    EVENTO

    XE4!

    Grupo

    Facebook

    Delphi

    SolidarioS parte del

    grupo de

    facebook ms

    activo de

    nuestra

    Comunidad

    Hispana:

    Delphi

    Solidario.

    Unete a

    nuestro

    esfuerzo por

    hacer de la

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 3/33

    Sin embargo, si nos referimos en concreto a la

    informacin sobre el uso de parmetros de tipo

    TStream, Jim Tierney dej escritos varios artculos

    imprescindibles, en los que se aborda el tema con

    bastante detalle. Uno de estos enlaces es DataSnap

    Server Method Stream Parameters, cuya lectura es

    necesaria, as como revisar el cdigo fuente que

    enlaza

    desde http://cc.embarcadero.com/item/26854.

    En la parte tercera de esta serie de artculos, al final

    de la misma, intentar recopilar todos los enlaces que

    me sea posible encontrar y que os puedan ser

    necesarios e interesantes. De hecho, durante los dos

    aos anteriores y este, se incrementa la

    documentacin tcnica con la aportacin de algunos

    artculos de compaeros de nuestra comunidad, que

    han ido introduciendo en la red las distintas reas de

    conocimiento de datasnap, aportando su granito de

    arena. Por supuesto, gran parte de esa posible

    lista sern recursos de habla inglesa.

    Consideraciones previas a tener en cuenta

    Todos tenemos una idea intuitiva de qu es

    un mtodo remoto expuesto por el servidor de

    DataSnap, porque a fin de cuentas, no dejan de ser

    nada distinto de los mtodos que habitualmente

    expone una clase. DataSnap, nos permite as, desde

    una aplicacin cliente, invocar mtodos que se

    ejecutan en otra aplicacin que acta como un

    servicio y que atiende o queda a la escucha de estas

    peticiones, bien a travs del protocolo http o https,

    bien a travs de tcp/ip. Bsicamente es eso.

    A menudo y de forma corporativa, hemos conocido

    esta imagen que resume y ofrece una vista amplia de

    DataSnap.

    Active Delphi

    Fernando

    Rizzato: Delphi

    for Enterprise

    Comunidad

    EEUU y

    habla

    inglesa

    Andy's Blog

    and Tools

    blog.marcocantu.com

    marco's tech

    world

    Delphi Insider

    Felix Colibri-

    Delphi Source

    Code,

    Technical

    Articles, Delphi

    Trainings,

    Delphi

    Consulting

    and

    Development

    Nick Hodges

    Sip from the

    Firehose

    The Hackers

    Corner |

    Complex

    problems

    have simple

    easy-to-

    understand

    wrong

    answers

    Comunidad

    Hispana de

    Delphi en

    facebook un

    sitio de

    encuentro y

    productividad.

    Miembros: 384

    Moderadores:

    4

    Meta

    Acceder

    RSS de las

    entradas

    RSS de los

    comentarios

    WordPress.org

    Suscrbete

    al blog por

    correo

    electrnicoIntroduce tu

    correo

    electrnico

    para

    suscribirte a

    este blog y

    recibir

    notificaciones

    de nuevas

    entradas.

    nete a 1

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 4/33

    Permitid me que deje algunas ideas en el aire, aun a

    costa de simplificar.

    Dejado aparte todas aquellas clases que colaboran en

    la parte digamos propia de la estructura del servicio

    (las que crean propiamente el servicio como tal, fijan

    y configuran los distintos canales, abriendo o

    cerrando comunicaciones, etc.), quizs la primera

    consideracin que se me ocurre para ayudaros en esa

    primera toma de contacto, es resaltar que solo van a

    poder exponer mtodos remotos las clases

    descendientes TDataModule y TDSServerModule, as

    como cualquier descendiente de TPersistent, pero

    esta ultima opcin requerira de vuestra parte un

    esfuerzo adicional ya que os obligara a implementar

    las capacidades de servicio que ya vienen

    introducidas desde TDataModule o

    TDSServerModule. No parece lo mas habitual, por lo

    que, a efectos prcticos, consideraremos que vuestra

    atencin se va a centrar realmente en estas dos

    clases, que son las que usareis en vuestro da a da.

    La segunda idea es que un TDSServerModule es un

    descendiente de la clase TDataModule y por lo tanto,

    extiende la clase y la funcionalidad de

    sta. Bsicamente la diferencia que os guiar en la

    necesidad de hacer uso de una u otra ser, que

    vuestro modulo de datos en el servidor deba exportar

    datasets hacia el cliente. En ese caso, para que sean

    visibles estos datasets y podais conectarlos a travs

    del driver de datasnap, el contendor ser la clase

    TDSServerModule.

    The Road to

    Delphi a

    Blog about

    programming

    Comunidad

    Hispana

    /*Prog*/

    Delphi-Neftal

    /*finProg*/

    Andreano

    Lanusse

    Making Things

    Happen

    Aprendiendo

    Firemonkey

    Blog de Carlos

    G

    Daniel Luyo

    Daniel Magin

    Delphi en

    Movimiento

    Delphi Live

    Delphi Magic

    Delphi y

    FastReport

    El blog de

    cadetill

    El blog de

    jachguate

    El Blog de

    Jhonny Surez

    El blog del Poli

    Glenn

    suscriptor

    Correo electrnico

    Subscribir

    Comentarios

    recientes

    Jose E Leyva

    en Dieciocho

    aos de

    Delphi y un

    largo camino

    por andar

    Salvador en

    Dar una

    buena

    imagen! Parte

    2

    GustavoSV en

    Dar una

    buena

    imagen! Parte

    2

    Al Gonzlez en

    Dieciocho

    aos de

    Delphi y un

    largo camino

    por andar

    Eliseo

    Gonzalez

    Nieto en

    Dieciocho

    aos de

    Delphi y un

    largo camino

    por andar

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 5/33

    Si damos un vistazo a la unidad DataSnap.DSServer,

    veremos su interfaz como sigue:

    {$MethodInfo ON}

    TDSServerModule = class(TDSServerModuleBase)

    end;

    {$MethodInfo OFF}

    Esto enlaza con algo que nos comentaba desde la

    lectura de la ayuda en linea, cuando se nos dice que

    es necesario aplicar la directiva {$MethodInfo} para

    que los mtodos sean visibles desde la clase

    TDataModule. Esta directiva, {$MethodInfo

    on/off} trabaja conjuntamente con la que ayuda a

    nuestro compilador a generar informacin RTTI (Run

    Time Type Library) de clase, {$TYPEINFO ON/OFF},

    haciendo necesario que ambas estn activas en el

    estado de la clase. De hecho, cuando nos dicen que

    los descendientes de TPersistent van a poder

    exponer mtodos remotos es porque esta clase -

    TPersistent- activa la informacin de tipos y por lo

    tanto es una posible candidata en el nivel mas

    elevado de esa jerarqua, cuyos descendientes van a

    heredar tambin dicho estado. La directiva

    {$TYPEINFO} es equivalente a {$M+}.

    Podemos entender el papel de la RTTI, si

    consideramos que precisamente, la generacin de

    esta metadata adicional en el servidor, ayudar al

    sistema a descubrir los mtodos a travs de una

    cadena de texto literal enviada en el mensaje

    compartido entre la aplicacion cliente y

    la aplicacin servidor, cadena de texto que representa

    la clase y el mtodo a invocar por el servidor. Si

    repasamos, por ejemplo, las lineas

    generadas automticamente en la unidad proxy, que

    es una plantilla que se crea a peticin del usuario con

    la informacin de los mtodos que descubre el

    servidor en el contexto de la aplicacin cliente, para

    facilitarnos no tener que mantener esta tarea que

    Stephens

    La Web de

    Seoane

    Legin Delphi

    Luis Felipe

    Gonzlez

    Torres

    Embarcadero

    MVP

    Puro Cdigo

    Blog de Jos

    Castillo

    Rescatando a

    Delphi

    Software: de

    Mexico para el

    mundo

    Waooo

    Delphi!

    Embarcadero

    MVP

    Adriano

    Santos

    Alan Fletcher

    Alan Glei

    Alexander

    Alexeev

    Alexander

    Bozhko

    Alister Christie

    Andrey

    Terekhov

    Bob Swart

    COMUNIDAD

    Recursos en la

    Red

    Publicaciones

    Truco o

    trato

    Foros

    Stackoverflow

    en espaol

    Embarcadero

    Uso del

    componente

    TListView en

    nuestras

    aplicaciones

    mviles mayo

    16, 2013 Jos

    Prez

    Le Dev du

    Jeudi Episode

    11 mayo 16,

    2013 tlaborde

    Ven a verme

    en Ciudad de

    Mxico y

    Guadalajara

    mayo 16, 2013

    Anders Ohlsson

    RAD Studio

    XE4 Whats

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 6/33

    puede ser repetitiva y tediosa, la implementacin que

    recrea la invocacin del mtodo EchoString se

    presenta como sigue:

    function TServerMethods1Client.EchoString(Value: string): string;

    begin

    if FEchoStringCommand = nil then

    begin

    FEchoStringCommand := FDBXConnection.CreateCommand;

    FEchoStringCommand.CommandType := TDBXCommandTypes.DSServerMethod;

    FEchoStringCommand.Text := 'TServerMethods1.EchoString';

    FEchoStringCommand.Prepare;

    end;

    FEchoStringCommand.Parameters[0].Value.SetWideString(Value);

    FEchoStringCommand.ExecuteUpdate;

    Result := FEchoStringCommand.Parameters[1].Value.GetWideString;

    end;

    He incluido en negrita la cadena que identifica

    el mtodo a invocar. Dicha cadena representa la clase

    que contiene el mtodo y su nombre. De no existir

    esa informacin adicional extra, asociada a la clase,

    no seriamos capaz de encontrar ni los actores ni las

    acciones. En agosto del 2007 compartimos una

    entrada en el blog que os puede ayudar a entender

    este punto: La Granja y en la que precisamente

    vemos como invocar un mtodo en la clase a travs

    de su nombre. Creo recordar

    que hacamos trotar graciosamente a la clase

    TCaballo, adems de otras tropelias como alimentarle

    o permitir que relinche. La RTTI se nos presenta a

    varios niveles: desde un nivel mnimo que hace que

    una instancia sea capaz de reconocerse en una clase,

    que podramos llamar autoconciencia , hasta un

    nivel ms extendido que permite a la clase describirse

    y reconocerse en toda la funcionalidad que el

    desarrollador de la misma autorice a conocer y

    describir. Las zonas publicadas (published) de la clase,

    forman parte de esas zonas que generan informacin

    extendida y metadata adicional que la RTTI ya recoga

    con la directiva {$M+}. Al activar la directiva

    Brian Long

    Bruno Fierens

    Caique

    Rodrigues

    Carlos

    Henrique

    Agnes

    Cary Jensen

    Daniel Wildt

    Daniel Wolf

    Danny Wind

    Didier Cabale

    Eliseo

    Gonzalez

    Felix Colibri

    Filip Lagrou

    Francois Piette

    Germn

    Estvez Ruiz

    Guinther Pauli

    Jim McKeeth

    Jose Castillo

    Juan Antonio

    Castillo

    Kelyn Pena

    Lachlan

    Gemmell

    Luciano

    Pimenta

    Luis Alfonso

    Rey

    new in the IDE

    (X) Info.plist

    mayo 16, 2013

    Jose Leon

    Getting

    TWebBrowser

    on iOS to

    zoom mayo

    15, 2013

    Anders Ohlsson

    Report do

    Delphi Tour

    Multi-Device:

    Porto Alegre

    mayo 15, 2013

    Fernando

    Rizzato

    Delphi for iOS

    in Zagreb,

    Croatia mayo

    15, 2013 Pawel

    Glowacki

    iOS app dev

    with Delphi

    XE4 and

    FireMonkey 3

    is a quantum

    leap beyond

    XE2 mayo

    14, 2013 David

    Intersimone

    Report do

    Delphi Tour

    Multi-Device:

    Florianpolis

    mayo 14, 2013

    Fernando

    Rizzato

    RAD Studio

    XE4 Whats

    new in the IDE

    (IX) Misc

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 7/33

    {$MethodInfo} ayudamos a que la zona publica de la

    clase genere tambin esa informacin extra de tipos

    que de otra forma no se generara.

    La tercera idea, en la que me gustara incidir es que

    una gran parte de los mtodos, se nos

    presentan ntimamente ligados a la informacin de

    tipos. Es decir, podemos encontrar la necesidad de

    ejecutar un procedimiento remoto que no

    necesite parmetros pero lo habitual es que

    existan parmetros de entrada y un tipo de retorno,

    en el caso de las funciones. As que en este punto nos

    podemos hacer la pregunta que este compaero me

    hacia entre lineas: Que tipo de dato necesito declarar

    como retorno de mi funcin, para exportar la

    imagen? Y si necesito una fecha? Puedo retornar un

    tipo propio de la logica de mi aplicacin, como por

    ejemplo una instancia de la clase TCliente?

    La respuesta a estas preguntas, la encontramos en los

    enlaces que compartamos en las lineas superiores de

    la entrada. En el primero de ellos, encontramos lo

    que buscamos: No todos lo tipos son soportados

    como parmetros.

    Luis Felipe

    Gonzlez T.

    Magnus Flysjo

    Marcelo

    Nogueira

    Marcelo

    Varela

    Marco Cantu

    Marco Santn

    Marcos

    Antonio

    Moreira

    Marcos P.

    Gomes

    Martin Strohal

    Mike Sutton

    Newton

    Gaucho

    Nick Hodges |

    A man's got to

    know his

    limitations

    Nirav Kaku

    Olaf Monien

    Pedro Bento

    Radek

    Cervinka

    Ray Konopka

    Ricardo Boaro

    Robert Love

    Salvador Jover

    Samuel David

    Changes mayo

    14, 2013 Jose

    Leon

    EDN

    Visual

    Video: Using

    the iOS

    TWebBrowser

    Component in

    Delphi -

    iOS_WebBrowser

    Code Snippet

    mayo 12, 2013

    Video: Using

    IBLite in

    Delphi iOS

    Apps mayo 10,

    2013

    Video: iOS

    SendCancelNotifications

    in Delphi

    mayo 8, 2013

    Video: Using

    iOS

    AudioRecPlay

    in Delphi to

    Record and

    Play Back

    Sounds mayo

    6, 2013

    Video: Using

    iOS Location

    Services in

    Delphi apps

    mayo 4, 2013

    Video: Using

    the iOS

    DatePicker in

    Delphi

    applications

    but not all the parameter types are

    supported. The supported types are:Boolean

    SmallInt Integer Int64 Single Double

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 8/33

    Uwe Raabe

    Victory

    Fernandes

    Vladislav

    Bajenov

    Xavier

    Martinez

    Zarko Gajic

    Foros

    Hispanos

    Club Delphi

    Comunidad

    Delphiaccess

    Sitio

    oficial y

    Partners

    Danysoft

    Embarcadero

    with

    TCalendarEdit

    mayo 2, 2013

    Get Set Up for

    Delphi XE4 iOS

    Development

    abril 30, 2013

    Video: Build

    Your First

    Multi-Device

    Delphi App

    abril 28, 2013

    Building a C++

    multi-tier

    master/detail

    Customer and

    Sales

    database

    application

    abril 26, 2013

    Using the

    Boost C++11

    Algorithms

    Library with

    the C++Builder

    64-bit

    compiler abril

    26, 2013

    Programa Certificacin

    Delphi

    Programa de Certificacion de

    Delphi

    AnsiString

    String TDBXTime TDBXDate TJSONValue and all descendents TDBXWideStringValue TDBXAnsiStringValue TDBXUInt8Value TDBXInt8Value TDBXInt16Value TDBXInt32Value TDBXInt64Value TDBXSingleValue TDBXDoubleValue TDBXBcdValue TDBXTimeValue TDBXDateValue TDBXTimeStampValue TDBXBooleanValue TDBXReaderValue

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 9/33

    En la entrada de Jim Tierney

    los encontris clasificados y agrupados de una forma

    mas clara, incluyendo algunos que no se mencionan

    explicitamente en la lista.

    Basic Basic DBXValue Collection Connection

    AnsiString

    Boolean

    Currency

    TDateTime

    TDBXDate

    TDBXTime

    Double

    Int64

    Integer

    LongInt

    OleVariant

    Single

    SmallInt

    WideString

    TDBXAnsiStringValue

    TDBXAnsiCharsValue

    TDBXBcdValue

    TDBXBooleanValue

    TDBXDateValue

    TDBXDoubleValue

    TDBXInt16Value

    TDBXInt32Value

    TDBXInt64Value

    TDBXSingleValue

    TDBXStringValue

    TDBXTimeStampValue

    TDBXTimeValue

    TDBXWideCharsValue

    TDBXWideStringValue

    TDBXReader

    TDataSet

    TParams

    TStream

    Collection DBXValue

    TDBXReaderValue

    TDBXStreamValue

    TDBXConnection

    Connection DBXValue

    TDBXConnectionValue

    Por lo tanto, ahora s estamos en posicin de

    responder a las preguntas que nos formulbamos.

    No existe un parmetro que identifique directamente

    a una instancia de TImage o de la clase TBitmap. Sin

    embargo, genricamente nos podemos apoyar en el

    uso de una clase como TStream que permite

    manipular esta informacin como una secuencia de

    bytes, optando por cualquiera de los descendientes

    Niveles:

    1. Delphi Certified Developer

    2. Delphi Certified Master

    Developer

    Estadisticas

    Inicio: 08/03/2012

    Estadsticas anteriores

    Delphi Bsico . 2003-2013

    La fe no es la simple aceptacin

    de unas verdades abstractas,

    sino una relacin ntima con

    Cristo que nos lleva a abrir

    nuestro corazn a este misterio

    de amor y a vivir como personas

    que se saben amadas por Dios.

    Benedicto XVI

    TDBXStreamValue

    Both procedure and functions aresupported, as well as out and varparameters.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 10/33

    que veamos apropiado para el contenido real.

    Tambin ahora estamos en condiciones de entender

    porque en el ejemplo del Restaurante, Luis Alfonso

    Rey se puede apoyar en la clase TDataSet como

    retorno de una de las funciones que su servidor

    exportaba. Recordad que el cdigo fuente de esta

    demo que sirvi en la exposicin durante las ultimas

    presentaciones del partner espaol se encuentra a

    vuestra disposicin en el link de la entrada

    inmediatamente anterior a esta.

    Primer paso: Nuestro servidor de datasnap

    Aunque sea repetitivo, he incluido las capturas de los

    primeros pasos, para que aquellos que se inician no

    tengan que tirar de imaginacin o memoria.

    Lo primero de todo, vamos a crear la aplicacin que

    va a dar el servicio, nuestro servidor de datasnap. Va

    a ser un servidor bsico, basado en tcp/ip y no

    expondr sus servicios a travs de http.

    Accedemos al men FILE -> NEW -> OTHER ->

    DataSnapServer. Seleccionamos la opcin DataSnap

    Server entre las tres disponibles.

    Una vez en ese punto, accederemos a un wizard que

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 11/33

    nos va a permitir configurar el servidor. He

    seleccionado la opcin VCL Forms Application ya que

    no va a ser un servicio integrado en el sistema ni un

    proyecto de tipo consola sino que ser una aplicacin

    monda y lironda.

    La siguiente parada ser para determinar como va a

    ser el servidor. Nuestro wizard necesita conocer

    como va a ser ese servidor, que capa de transporte de

    datos va a usar, si existirn filtros, si es una

    comunicacin segura y si adems, deseamos que

    incluya los mtodos de ejemplo que se aaden de

    ayuda. En el caso del servidor bsico se incluyen

    los mtodos EchoString y ReverseString, por defecto

    pero para servidores de tipo Rest, el sistema incluye

    adicionalmente un test en formato html capaz de

    evaluar los mtodos que exporta el servidor,

    incluyendo los administrativos.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 12/33

    En el siguiente paso, vamos a poder hacer un test al

    puerto 211, que es el que por defecto asigna

    DataSnap.

    Y finalmente, seleccionamos de que clase heredar la

    creada por nosotros para albergar los

    distintos mtodos que exportar el servidor. Yo he

    elegido TDSServerModule ya que, en este caso

    concreto, s voy a incluir al menos un dataset. Existir

    un componente TSQLQuery que he llamado

    Imagenes_Interbase con el fin de que se pueda

    recorrer el contenido de la tabla.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 13/33

    Al finalizar el wizard, se habr creado el proyecto en

    el que existirn varias unidades, que representan

    respectivamente el formulario de la aplicacin, el

    mdulo que contiene los componentes que generan y

    configuran la estructura del servicio y un modulo

    adicional que el sistema por defecto denomina

    ServerMethodsUnit1, conteniendo la clase que va a

    exponer los servicios. En dicho modulo estn

    publicados los mtodos de ejemplo

    que mencionbamos.

    Dejadme que escriba unas lineas de cdigo.

    Dad le un vistazo al formulario, tal y como queda tras

    aadir los componentes y comentamos.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 14/33

    Nuestro TDSserverModule, es muy sencillo y contiene

    un query para recorrer la tabla y que sea el usuario

    desde la aplicacin cliente quien pueda seleccionar

    cual de las imgenes quiere que sea devuelta por

    el mtodo remoto, y un segundo query que

    efectivamente la devolver mediante el mtodo

    adecuado, apoyndose en el indice de esa imagen

    como parmetro de entrada. Para ello,

    parametrizamos la consulta de

    GetImageBanner_Intebase, que recibe en un integer la

    clave primaria que identifica la imagen que

    deseamos:

    Select Banner

    from Banners

    where IDBanner = :IDBanner

    Veamos el cdigo que hemos escrito a tal efecto:

    unit ServerMethodsUnit1;

    interface

    uses System.SysUtils, System.Classes, Datasnap.DSServer, Datasnap.DSAuth,

    Data.DBXMSSQL, Data.FMTBcd, Data.DB, Data.SqlExpr, Datasnap.Provider, Data.DBXJSON,

    Data.DBXInterBase, Vcl.Dialogs;

    type

    TServerMethods1 = class(TDSServerModule)

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 15/33

    demos_interbase: TSQLConnection;

    Imagenes_Interbase: TSQLQuery;

    dspImagenes_Interbase: TDataSetProvider;

    Imagenes_InterbaseIDBANNER: TIntegerField;

    Imagenes_InterbaseBANNER: TBlobField;

    GetImageBanner_Interbase: TSQLQuery;

    dspGetImageBanner_Interbase: TDataSetProvider;

    GetImageBanner_InterbaseBANNER: TBlobField;

    procedure demos_interbaseBeforeConnect(Sender: TObject);

    private

    { Private declarations }

    function GetImagenBannerAsStream(ASQLQuery: TSQLQuery; AIDBanner: Integer): TStream; overload;

    public

    { Public declarations }

    function EchoString(Value: string): string;

    function ReverseString(Value: string): string;

    function GetImagenBannerAsJSON(AIDBanner: Integer): TJSONArray;

    function GetImagenBannerAsStream(AIDBanner: Integer): TStream; overload;

    end;

    implementation

    {$R *.dfm}

    uses System.StrUtils, UMainServer, Data.DBXJSONCommon;

    function TServerMethods1.GetImagenBannerAsStream(ASQLQuery: TSQLQuery; AIDBanner: Integer): TStream;

    var

    stream: TMemoryStream;

    begin

    if (ASQLQuery.Active) then ASQLQuery.Close();

    ASQLQuery.ParamByName('IDBanner').Value := AIDBanner;

    ASQLQuery.Open();

    stream := TMemoryStream.Create;

    stream.WriteData(ASQLQuery.FieldByName('Banner').AsBytes,

    Length(ASQLQuery.FieldByName('Banner').AsBytes));

    //stream.SaveToFile('test_ahora.jpg');

    stream.Seek(0, System.Classes.TSeekOrigin.soBeginning);

    ASQLQuery.Close();

    Result:= stream;

    end;

    function TServerMethods1.GetImagenBannerAsJSON(AIDBanner: Integer): TJSONArray;

    var

    stream: TStream;

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 16/33

    begin

    stream:= GetImagenBannerAsStream(AIDBanner);

    try

    Result:= TDBXJSONTools.StreamToJSON(stream, 0, stream.Size);

    finally

    stream.Free;

    end;

    end;

    function TServerMethods1.GetImagenBannerAsStream(AIDBanner: Integer): TStream;

    begin

    Result:= GetImagenBannerAsStream(GetImageBanner_Interbase, AIDBanner);

    end;

    procedure TServerMethods1.demos_interbaseBeforeConnect(Sender: TObject);

    begin

    demos_interbase.Params.Values['Database'] := MainServer.GetPath;

    end;

    function TServerMethods1.EchoString(Value: string): string;

    begin

    Result := Value;

    end;

    function TServerMethods1.ReverseString(Value: string): string;

    begin

    Result := System.StrUtils.ReverseString(Value);

    end;

    end.

    La pregunta mas interesante que yo me hara en

    vuestro caso, a la vista de la inspeccin ocular del

    cdigo, podra ser:

    Cuando escribimos una asignacin al valor de retorno

    de la funcin, como el que podemos ver en la linea

    inmediatamente inferior, qu sucede con la reserva

    de memoria que se ha hecho para gestionar el

    contenido del stream a devolver?

    Result:= GetImagenBannerAsStream(GetImageBanner_Interbase, AIDBanner);

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 17/33

    Fijmonos que la funcin

    privada, GetImagenBannerAsStream, declara una

    variable local de tipo TMemoryStream que va a ser

    instanciada cuando devolvemos un TStream, sin que

    por ningn lado se gestione que sta sea liberada. Sin

    embargo, al escribir la funcin que retornar esa

    misma imagen en el interior de una estructura del

    tipo TJSONArray, si que puedo liberar la memoria, ya

    que esa memoria asociada a la instancia del stream

    no forma parte del retorno sino que el mtodo de

    clase

    TDBXJSONTools.StreamToJSON( )

    hace su propia reserva para la estructura TJSONArray

    y copia en ella el stream. Una de las cosas que

    aprend, al dar mis primeros pasos en el entorno, es

    que cada palo aguantaba su propia vela y que si

    en algn momento he gestionado la reserva de

    memoria por el motivo que sea, debo

    responsabilizarme de su liberacin. Eso sucede

    cuando instanciamos objetos, seres inferiores sin

    padre que les cobije. Tener un propietario, es

    una garanta que se responsabilizara de lo que suceda

    con esa criatura. Los componentes tienen esos

    privilegios as como sus descendientes. Gente con

    suerte!

    Sin embargo para un TStream o cualquiera de sus

    multiples caras, el sistema encuentra una solucin

    pactada. El parmetro InstanceOwner, de tipo

    boolean, media en el dilema abierto. Os leo

    un prrafo de la entrada de Jim Terney.

    Accessing Values

    The GetStream and SetStream methods

    have an InstanceOwner parameter.

    Passing True indicates that DBX owns the

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 18/33

    Si a continuacin observamos con detenimiento

    los mtodos generados por el proxy para devolver el

    stream

    function TServerMethods1Client.GetImagenBannerAsStream(AIDBanner: Integer): TStream;

    begin

    if FGetImagenBannerAsStreamCommand = nil then

    begin

    FGetImagenBannerAsStreamCommand := FDBXConnection.CreateCommand;

    FGetImagenBannerAsStreamCommand.CommandType := TDBXCommandTypes.DSServerMethod;

    FGetImagenBannerAsStreamCommand.Text := 'TServerMethods1.GetImagenBannerAsStream';

    FGetImagenBannerAsStreamCommand.Prepare;

    end;

    FGetImagenBannerAsStreamCommand.Parameters[0].Value.SetInt32(AIDBanner);

    FGetImagenBannerAsStreamCommand.ExecuteUpdate;

    Result := FGetImagenBannerAsStreamCommand.Parameters[1].Value.GetStream(FInstanceOwner);

    end;

    La definicin del parmetro FInstanceOwner en

    GetStream( ) es la que establece como se va a liberar

    la memoria reservada previamente, de forma que no

    existan problemas derivados de su no liberacin.

    FInstanceOwner se estableca con un valor en el

    mismo constructor de la clase que va a exponer

    los mtodos

    constructor TServerMethods1Client.Create(ADBXConnection: TDBXConnection; AInstanceOwner

    begin

    inherited Create(ADBXConnection, AInstanceOwner);

    end;

    En este caso, tomaba el valor True (lo veris en el

    interior del evento onCreate del formulario cliente,

    stream and will free it. Passing False

    indicates that the caller owns the stream.

    To control how the generated proxy

    classes call SetStream and GetStream,

    there is an AInstanceOwner parameter

    on the proxy class constructor:

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 19/33

    que usar el proxy). Es lgico que sea el cliente el que

    decida qu hacer con esa memoria y al asignar True

    lo que implica es que sea el propio sistema el que se

    encargue de liberar esa memoria y por lo tanto, no

    tendremos que hacer una llamada explicita para ello.

    Cuando no sea necesaria esa informacin, en una

    llamada posterior, el sistema podr decidir si libera la

    instancia antes de obtener un nueva invocacin.

    Segundo paso: Nuestra aplicacin cliente.

    Para hacer la aplicacin cliente, no vamos a crear

    mas que un formulario, aunque esto no sea

    demasiado ortodoxo.

    Os muestro una imagen del formulario

    que tambin es muy bsico y sencillo. El usario

    pulsar el boton Abrir DataSet y podr elegir una de

    las imagenes en el componente TImage inferior.

    Luego, al pulsar uno de los dos botones de la parte

    derecha, se ejecutara uno de los dos mtodos a los

    que alude.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 20/33

    Este es el cdigo que he escrito a tal efecto.

    unit UMainClient;

    interface

    uses

    System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,

    System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,

    Data.DBXDataSnap, IPPeerClient, Data.DBXCommon, Data.FMTBcd, Data.DB,

    Data.SqlExpr, FMX.Objects, Data.Bind.EngExt, Fmx.Bind.DBEngExt,

    System.Bindings.Outputs, Fmx.Bind.Editors, Data.Bind.Components,

    Data.Bind.DBScope, Datasnap.DBClient, Datasnap.DSConnect, FMX.Layouts,

    Fmx.Bind.Navigator, UProxy, FMX.ListBox;

    type

    TForm1 = class(TForm)

    Image1: TImage;

    DataSnapCONNECTION: TSQLConnection;

    Banners: TClientDataSet;

    DSProviderConnection1: TDSProviderConnection;

    BannersBanner: TBlobField;

    BindSourceDB1: TBindSourceDB;

    BindingsList1: TBindingsList;

    LinkPropertyToField1: TLinkPropertyToField;

    BindNavigator1: TBindNavigator;

    btnDataset: TButton;

    btnMethodJSON: TButton;

    Image2: TImage;

    Label1: TLabel;

    BannersIDBanner: TIntegerField;

    LinkPropertyToField2: TLinkPropertyToField;

    cbxSelector: TComboBox;

    Interbase: TListBoxItem;

    btnMethodStream: TButton;

    Panel1: TPanel;

    labBaseDeDatos: TLabel;

    procedure btnDatasetClick(Sender: TObject);

    procedure btnMethodJSONClick(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

    procedure cbxSelectorChange(Sender: TObject);

    procedure btnMethodStreamClick(Sender: TObject);

    private

    { Private declarations }

    FInstanceOwner : Boolean;

    FServerMethods1Client: TServerMethods1Client;

    function GetServerMethods1Client: TServerMethods1Client;

    public

    { Public declarations }

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 21/33

    end;

    var

    Form1: TForm1;

    implementation

    {$R *.fmx}

    uses Data.DBXJSONCommon;

    procedure TForm1.btnDatasetClick(Sender: TObject);

    begin

    Banners.Open;

    end;

    procedure TForm1.btnMethodJSONClick(Sender: TObject);

    var

    fStream: TMemoryStream;

    i: Integer;

    begin

    if Banners.IsEmpty then

    raise Exception.Create('Debes abrir primero el dataset');

    try

    i:= BannersIDBanner.AsInteger;

    fStream:= TMemoryStream.Create();

    case cbxSelector.ItemIndex of

    0: begin

    fStream.LoadFromStream(TDBXJSONTools.JSONToStream(GetServerMethods1Client.GetImagenBannerAsJSON(i)));

    //fStream.SaveToFile('..\..\..\test_interbase_jason_fmx.jpg');

    end;

    end;

    Image2.Bitmap.LoadFromStream(fStream);

    finally

    fStream.Free;

    end;

    end;

    procedure TForm1.btnMethodStreamClick(Sender: TObject);

    var

    fStream: TMemoryStream;

    i: Integer;

    begin

    if Banners.IsEmpty then

    raise Exception.Create('Debes abrir primero el dataset');

    try

    i:= BannersIDBanner.AsInteger;

    fStream:= TMemoryStream.Create();

    case cbxSelector.ItemIndex of

    0: begin

    fStream.LoadFromStream(GetServerMethods1Client.GetImagenBannerAsStream(i));

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 22/33

    //fStream.SaveToFile('..\..\..\test_interbase_stream_fmx.jpg');

    end;

    end;

    Image2.Bitmap.LoadFromStream(fStream);

    finally

    fStream.Free;

    end;

    end;

    procedure TForm1.cbxSelectorChange(Sender: TObject);

    begin

    Banners.Close;

    case cbxSelector.ItemIndex of

    0: Banners.ProviderName:= 'dspImagenes_Interbase';

    end;

    end;

    procedure TForm1.FormCreate(Sender: TObject);

    begin

    FInstanceOwner := True;

    end;

    procedure TForm1.FormDestroy(Sender: TObject);

    begin

    FServerMethods1Client.Free;

    end;

    function TForm1.GetServerMethods1Client: TServerMethods1Client;

    begin

    if FServerMethods1Client = nil then

    FServerMethods1Client:= TServerMethods1Client.Create(DataSnapCONNECTION.DBXConnection, FInstanceOwner);

    Result := FServerMethods1Client;

    end;

    end.

    Y aqu tenis algunas capturas de la aplicacin en

    ejecucin, con una animacin mostrando el

    resultado.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 23/33

    En el video se puede ver la aplicacin

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 24/33

    ejecutandose

    Conclusin y comentarios adicionales

    A tenor de lo visto, ambos mtodos funcionan

    correctamente y conseguimos cargar sin problemas

    tanto desde un valor de retorno con un tipo TStream,

    como considerar un valor de tipo TJSONArray.

    En imgenes pequeas ambos trabajan

    correctamente.

    Ahora bien, mientras montaba el ejemplo para

    compartirlo con este compaero en un correo

    privado, me encontr que generaba un error si la

    imagen era de un tamao mediano o grande desde

    GetServerMethods1Client.GetImagenBannerAsStream(i)

    donde emerge el error que mostraba la animacin:

    Out of memory while expanding memory stream.

    TJSON array funcionaba correctamente en cualquier

    caso.

    As que os podis imaginar que parte de tiempo de

    demora de todas estas lineas ha estado en

    asegurarme que realmente era as e intentar

    descartar que no fuera un problema generado por mi

    propio cdigo.

    Yo creo que nosotros, como MVPs, o como personas

    comprometidas con la Comunidad, no podemos

    ocultar que exista un error puesto que no sera moral

    ni actuaria en conciencia. Mas al contrario, requiere

    de nosotros la responsabilidad de que perdamos un

    poco de nuestro tiempo intentando averiguar que lo

    produce, si es que realmente al final es producido por

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 25/33

    alguna linea de la librera y no de nuestro desarrollo.

    Creo que es un buen signo de salud de la Comunidad

    y por ello, he aadido unas lineas para intentar

    capturar la naturaleza del problema y con

    mi psimo ingls, intentar subirlo a QC para que se

    pueda solucionar. Quizs ya est documentado.

    Quizs sea una regresin fruto de cambios

    posteriores. Ni idea. Es algo que ver en

    los prximos das.

    Podis descargar el cdigo fuente demo_parte2 y

    si deseis seguir la lectura, voy a incluir algo de

    cdigo para analizarlo.

    Podemos aislar el problema?

    Creo que podemos olvidarnos por un momento de

    que el contenido de un TStream sea grfico o que

    tenga otra naturaleza. Por eso, se me ocurre invocar

    una funcin que devuelva un tamao en relacin de

    un parmetro de entrada, entero, que lo fije.

    La funcin GetStreamBySize( ) devolver un TStream

    de un tamao de ASizeBytes, de tipo Integer. Su

    implementacin es sencilla. Fijamos el tamao de una

    matriz de Bytes en funcin ASizeBytes y

    sobrescribimos con un numero cualquiera cada byte.

    Yo he usado un 1. Y finalmente devolvemos la

    instancia de la clase TBytesStream que es creada en

    base al tamao de la matriz de bytes.

    Este es el cdigo del servidor:

    unit ServerMethodsUnit1;

    interface

    uses System.SysUtils, System.Classes, Datasnap.DSServer, Datasnap.DSAuth;

    type

    TServerMethods1 = class(TDSServerModule)

    private

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 26/33

    { Private declarations }

    public

    { Public declarations }

    function EchoString(Value: string): string;

    function ReverseString(Value: string): string;

    function GetStreamBySize(ASizeBytes: Integer): TStream; //By Bytes

    end;

    implementation

    {$R *.dfm}

    uses System.StrUtils;

    function TServerMethods1.EchoString(Value: string): string;

    begin

    Result := Value;

    end;

    function TServerMethods1.GetStreamBySize(ASizeBytes: Integer): TStream;

    var

    fStream: TBytesStream;

    fBytes: TBytes;

    i: Integer;

    begin

    SetLength(fBytes, ASizeBytes);

    for i := 0 to Length(fBytes) - 1 do fBytes[i] := 1;

    fStream:= TBytesStream.Create(fBytes);

    Result:= fStream;

    end;

    function TServerMethods1.ReverseString(Value: string): string;

    begin

    Result := System.StrUtils.ReverseString(Value);

    end;

    end.

    El formulario cliente consta de un par de botones y

    una casilla de texto que nos permite probar con

    distintos tamaos. Tambin generamos un log del

    resultado, devuelto en las lneas del componente

    TMemo.

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 27/33

    Este es el cdigo del cliente.

    unit UMainClient_fmx;

    interface

    uses

    System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,

    System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,

    Data.DBXDataSnap, IPPeerClient, Data.DBXCommon, FMX.Objects, Data.DB,

    Data.SqlExpr, UProxy, FMX.Layouts, FMX.Memo, FMX.Edit;

    type

    TMainClienteFMX = class(TForm)

    btnImg1: TButton;

    btnImg2: TButton;

    DataSnapCONNECTION: TSQLConnection;

    Image1: TImage;

    btnTest: TButton;

    Memo1: TMemo;

    btnCancel: TButton;

    numbox: TEdit;

    procedure FormCreate(Sender: TObject);

    procedure FormDestroy(Sender: TObject);

    procedure btnTestClick(Sender: TObject);

    procedure btnCancelClick(Sender: TObject);

    private

    { Private declarations }

    FFin: Boolean;

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 28/33

    FInstanceOwner : Boolean;

    FServerMethods1Client: TServerMethods1Client;

    function GetServerMethods1Client: TServerMethods1Client;

    public

    { Public declarations }

    function Fin: Boolean;

    end;

    var

    MainClienteFMX: TMainClienteFMX;

    implementation

    {$R *.fmx}

    procedure TMainClienteFMX.btnCancelClick(Sender: TObject);

    begin

    FFin:= True;

    end;

    procedure TMainClienteFMX.btnTestClick(Sender: TObject);

    var

    fBytesStream: TBytesStream;

    i,j: Integer;

    sLog: String;

    begin

    FFin:= False;

    memo1.Lines.Clear;

    fBytesStream:= TBytesStream.Create;

    try

    i:= StrToInt(numbox.Text);

    while not Fin do

    begin

    fBytesStream.LoadFromStream(GetServerMethods1Client.GetStreamBySize(i));

    sLog:= 'Size: '+IntToStr(fBytesStream.Size)+ ' -> ';

    for j := 0 to Length(fBytesStream.Bytes)-1 do

    sLog:= sLog + IntToStr(fBytesStream.Bytes[j]);

    memo1.Lines.Add(sLog);

    Inc(i);

    numbox.Text:= IntToStr(i);

    Application.ProcessMessages;

    end;

    finally

    memo1.Lines.SaveToFile('Test.txt');

    fBytesStream.Free;

    end;

    end;

    function TMainClienteFMX.Fin: Boolean;

    begin

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 29/33

    Result:= FFin;

    end;

    procedure TMainClienteFMX.FormCreate(Sender: TObject);

    begin

    FInstanceOwner := True;

    end;

    procedure TMainClienteFMX.FormDestroy(Sender: TObject);

    begin

    FServerMethods1Client.Free;

    FServerMethods1Client:= Nil;

    end;

    function TMainClienteFMX.GetServerMethods1Client: TServerMethods1Client;

    begin

    if FServerMethods1Client = nil then

    FServerMethods1Client:= TServerMethods1Client.Create(DataSnapCONNECTION.DBXConnection, FInstanceOwner);

    Result := FServerMethods1Client;

    end;

    end.

    Y finalmente, podis ver una imagen de la aplicacin

    en ejecucin, as como una animacin

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 30/33

    Podis ver el test ejecutndose

    Descargar cdigo fuente Test Stream

    Conclusiones del Test

    Creo entender que la funcin rompe o genera el error

    cuando el tamao a devolver es superior o igual a

    30717 bytes, aunque sinceramente no he podido

    averiguar la razn. Hasta ese tamao funciona

    correctamente.

    Haciendo algunos puntos de parada intuyo que

    la gestin de memoria no es capaz de alojar el buffer

    que contiene el stream pero no estoy seguro por lo

    que intentar en los prximos das comentarlo en QC

    y buscar si existe o se documentacin algn error

    similar.

    Sin embargo, tambin quiero decir y dejar constancia

    que el ejemplo que nos muestra Jim Tierney aplicado

    sobre XE3 funciona correctamente, y precisamente

    testea tambin la devolucin de los mtodos remotos

    que retorna un valor de tipo TStream, aunque no

    exactamente igual. En el cdigo que l comparte,

    retorna una instancia TFileStream que contiene el log

    de resultados del test. Su ejemplo es muy bueno y

    complejo y me ha llevado algo de tiempo entenderlo,

    y quizs por eso no he acabado de ver qu le

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 31/33

    Comprtelo:

    TwittearTwittear 1 0

    diferencia de este que ahora yo he

    expuesto. Quizs sea simplemente un error mio y me

    alegrara que fuera as.

    Espero que haya sido didctica esta segunda parte y

    que os pueda servir de algo todos estos comentarios.

    Hasta esa tercera parte que en teora cerrara la serie.

    Un saludo a todos.

    TwittearTwittear 1

    Did you like this article? Share it with your friends!

    2 Responses to "Dar una buena imagen!

    Parte 2"

    GustavoSV dice:

    marzo 26, 2013 a las 7:46 pm

    Salvador muy didctica tu explicacin, tienes

    vena de maestro !

    Es un ejemplo muy prctico e interesante, hay algo que no

    0

    Like 4 Send

    Facebook 4 Twitter 1 Google +1

    LinkedIn 1 Correo electrnico

    Imprimir Ms

    datasnap Delphi qc XE3

    Like 4

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 32/33

    entiendo y es el por qu la redefinicin del mtodo

    GetImagenBannerAsStream tanto en la seccin private como

    public ?

    Son esas cosas de la OOP que no he podido masticar bien

    Responder

    Salvador dice:

    marzo 26, 2013 a las 9:07 pm

    Hola Gustavo,

    me alegra que te haya gustado. +1

    Respecto al metodo, queda en la parte privada porque no

    quera que el servidor lo expusiera a la clase cliente. El

    compilador es capaz de distinguir por los parmetros que

    recibe cuando debe invocar a uno u otro. Pero ciertamente, si

    hubieras cambiado la firma del mtodo privado no hubiera

    cambiado el resultado.As queda mas misterioso jajaja

    Inicialmente, exista en el ejemplo 2 bases de datos (sqlserver e

    internase) y con el selector podas cambiar de una base a otra

    ejecutando el mtodo. Luego, a medida que avanzaba en la

    escritura de la entrada, fui cambiando el cdigo para

    simplificarlo y que no quedara muy lioso, limpindolo, pero

    algunos detalles quedaron y ya no los rectifique. Un ejemplo

    de eso es el combobox, que no tiene demasiado sentido pero

    realmente tampoco afecta, ni para mal ni para bien.

    Un saludo,

    Salvador

    Responder

    Deja un comentario

    Tu direccin de correo electrnico no ser publicada. Los campos

    necesarios estn marcados *

  • 16/05/13 Dar una buena imagen! Parte 2 | Delphi Bsico

    delphibasico.com/delphi/?p=3918 33/33

    2013 Delphi Bsico Powered by Pinboard Theme by One Designs and

    WordPress

    cinco + 1 =

    Puedes usar las siguientes etiquetas y atributos HTML:

    Publicar comentario

    Spam Protection by WP-SpamFree

    Recibir un email con los siguientes comentarios a esta

    entrada.

    Recibir un email con cada nuevo post.

    Nombre *

    Correo

    electrnico

    *

    Web

    Comentario