¡Dar Una Buena Imagen! Parte 2 - Delphi Básico

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Delphi Bsico

SELECCION DE CONTENIDO (2003-2013)

THE EMBARCADERO MVP PROGRAM

DELPHISPANO

FB DELPHI SOLIDARIO

MAPA

LEGAL

Dar una buena imagen! Parte 2


Salvador marzo 25, 2013 Advertencia, Artculos, Cdigo, DataSnap, Delphi, Entrada Diario, FireMonkey, LiveBindings, Uncategorized, XE3

Al da con HTML5 Builder y F.Charte

Buscar
Search this website

Categoras
Elegir categora

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
delphibasico.com/delphi/?p=3918

A cerca de m

Salvador Jover

Proyecto DelpHispano

1/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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.
Redes Sociales

PRXIMO EVENTO XE4!

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.
delphibasico.com/delphi/?p=3918

PROMOCIN XE4!

Grupo Facebook Delphi Comunidad Australiana


Australian Delphi User Group Members

Solidario
S parte del grupo de facebook ms activo de nuestra Comunidad Hispana: Delphi Solidario. Unete a nuestro esfuerzo por hacer de la
2/33

Comunidad de Brasil y Portugal

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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.

Active Delphi Fernando Rizzato: Delphi for Enterprise

Comunidad Hispana de Delphi en facebook un sitio de encuentro y productividad.

Comunidad EEUU y habla inglesa


Andy's Blog and Tools

Miembros: 384 Moderadores: 4

blog.marcocantu.com marco's tech world Delphi Insider RSS de las Felix ColibriDelphi Source Code, Technical Articles, Delphi Trainings, Delphi Consulting and Development Nick Hodges Sip from the Firehose The Hackers Corner | Complex problems have simple easy-tounderstand wrong answers nete a 1 RSS de los comentarios WordPress.org entradas

Meta
Acceder

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.

Suscrbete al blog por correo electrnico


Introduce tu correo electrnico para suscribirte a este blog y recibir notificaciones de nuevas entradas.

delphibasico.com/delphi/?p=3918

3/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

The Road to Delphi a Blog about programming

suscriptor Correo electrnico

Subscribir

Comunidad Hispana
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 desde servicio que ya vienen o introducidas TDataModule
/*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

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

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.
delphibasico.com/delphi/?p=3918

El blog de cadetill El blog de jachguate El Blog de Jhonny Surez El blog del Poli Glenn

4/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Si damos un vistazo a la unidad DataSnap.DSServer, veremos su interfaz como sigue:

Stephens La Web de Seoane

COMUNIDAD
Recursos en la Red Publicaciones Truco o trato Foros

{ $ M e t h o d I n f oO N } T D S S e r v e r M o d u l e=c l a s s ( T D S S e r v e r M o d u l e B a s e ) e n d ; { $ M e t h o d I n f oO F F }

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!

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

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
5/33

Embarcadero MVP
Adriano Santos Alan Fletcher Alan Glei Alexander Alexeev Alexander Bozhko Alister Christie Andrey Terekhov Bob Swart

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
delphibasico.com/delphi/?p=3918

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

puede ser repetitiva y tediosa, la implementacin que recrea la invocacin del mtodo EchoString se presenta como sigue:

Brian Long Bruno Fierens Caique

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
6/33

f u n c t i o nT S e r v e r M e t h o d s 1 C l i e n t . E c h o S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; b e g i n i fF E c h o S t r i n g C o m m a n d=n i lt h e n b e g i n F E c h o S t r i n g C o m m a n d: =F D B X C o n n e c t i o n . C r e a t e C o m m a n d ;

Rodrigues Carlos Henrique Agnes

F E c h o S t r i n g C o m m a n d . C o m m a n d T y p e: =T D B X C o m m a n d T y p e s . D S S e r v e r M e t h o d ; F E c h o S t r i n g C o m m a n d . T e x t: =' T S e r v e r M e t h o d s 1 . E c h o S t r i n g ' ; F E c h o S t r i n g C o m m a n d . P r e p a r e ; e n d ; F E c h o S t r i n g C o m m a n d . E x e c u t e U p d a t e ; e n d ;

Cary Jensen

Daniel Wildt

F E c h o S t r i n g C o m m a n d . P a r a m e t e r s [ 0 ] . V a l u e . S e t W i d e S t r i n g ( V a l u e ) ; Wolf Daniel R e s u l t: =F E c h o S t r i n g C o m m a n d . P a r a m e t e r s [ 1 ] . V a l u e . G e t W i d e S t r i n g ; Danny Wind

Didier Cabale Eliseo

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
delphibasico.com/delphi/?p=3918

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

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

{$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 necesite un procedimiento lo remoto habitual que es no que parmetros pero

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

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
7/33

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.

but not all the parameter types are supported. The supported types are: Boolean SmallInt Integer Int64 Single Double

Olaf Monien Pedro Bento Radek Cervinka Ray Konopka Ricardo Boaro Robert Love Salvador Jover Samuel David

delphibasico.com/delphi/?p=3918

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

AnsiString String TDBXTime TDBXDate

Uwe Raabe Victory Fernandes Vladislav Bajenov Xavier

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

TJSONValue and all descendents TDBXWideStringValue TDBXAnsiStringValue TDBXUInt8Value TDBXInt8Value TDBXInt16Value TDBXInt32Value TDBXInt64Value TDBXSingleValue TDBXDoubleValue

Martinez Zarko Gajic

Foros Hispanos
Club Delphi

Comunidad Delphiaccess

Sitio oficial y Partners

Boost C++11 Algorithms Library with the C++Builder 64-bit compiler abril 26, 2013

Danysoft

TDBXBcdValue TDBXTimeValue TDBXDateValue TDBXTimeStampValue TDBXBooleanValue TDBXReaderValue


Programa de Certificacion de Delphi Embarcadero

Programa Certificacin Delphi

delphibasico.com/delphi/?p=3918

8/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico


Basic

TDBXStreamValue Both procedure and functions are supported, as well as out and var parameters.

Niveles: 1. Delphi Certified Developer 2. Delphi Certified Master Developer

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 DBXValue TDBXAnsiStringValue TDBXAnsiCharsValue TDBXBcdValue TDBXBooleanValue TDBXDateValue TDBXDoubleValue TDBXInt16Value TDBXInt32Value TDBXInt64Value TDBXSingleValue TDBXStringValue TDBXTimeStampValue TDBXTimeValue TDBXWideCharsValue TDBXWideStringValue Collection

Estadisticas

Inicio: 08/03/2012

Connection

AnsiString Boolean Currency TDateTime TDBXDate TDBXTime Double Int64 Integer LongInt OleVariant Single SmallInt WideString

TDBXReader TParams

Estadsticas anteriores

TDBXConnection

TDataSet Delphi Bsico . 2003-2013 Connection DBXValue La fe no es la simple aceptacin TStream de unas verdades abstractas, TDBXConnectionValue sino una relacin ntima con
Cristo que nos lleva a abrir

Collection DBXValue nuestro corazn a este misterio TDBXReaderValue que se saben amadas por Dios. TDBXStreamValue
Benedicto XVI de amor y a vivir como personas

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
delphibasico.com/delphi/?p=3918 9/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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


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

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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 incluyendo los administrativos. servidor,

delphibasico.com/delphi/?p=3918

11/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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.

delphibasico.com/delphi/?p=3918

12/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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. publicados los 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. En dicho modulo estn de ejemplo mtodos

delphibasico.com/delphi/?p=3918

13/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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 la que identifica entrada. Para ello, de que parametrizamos clave primaria consulta la imagen

GetImageBanner_Intebase, que recibe en un integer la deseamos:

S e l e c tB a n n e r f r o mB a n n e r s w h e r eI D B a n n e r=: I D B a n n e r

Veamos el cdigo que hemos escrito a tal efecto:

u n i tS e r v e r M e t h o d s U n i t 1 ; i n t e r f a c e u s e sS y s t e m . S y s U t i l s ,S y s t e m . C l a s s e s ,D a t a s n a p . D S S e r v e r ,D a t a s n a p . D S A u t h , D a t a . D B X M S S Q L ,D a t a . F M T B c d ,D a t a . D B ,D a t a . S q l E x p r ,D a t a s n a p . P r o v i d e r ,D a t a . D B X J S O N , D a t a . D B X I n t e r B a s e ,V c l . D i a l o g s ; t y p e T S e r v e r M e t h o d s 1=c l a s s ( T D S S e r v e r M o d u l e )
delphibasico.com/delphi/?p=3918 14/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

d e m o s _ i n t e r b a s e :T S Q L C o n n e c t i o n ; I m a g e n e s _ I n t e r b a s e :T S Q L Q u e r y ; d s p I m a g e n e s _ I n t e r b a s e :T D a t a S e t P r o v i d e r ; I m a g e n e s _ I n t e r b a s e I D B A N N E R :T I n t e g e r F i e l d ; I m a g e n e s _ I n t e r b a s e B A N N E R :T B l o b F i e l d ; G e t I m a g e B a n n e r _ I n t e r b a s e :T S Q L Q u e r y ; d s p G e t I m a g e B a n n e r _ I n t e r b a s e :T D a t a S e t P r o v i d e r ; G e t I m a g e B a n n e r _ I n t e r b a s e B A N N E R :T B l o b F i e l d ; p r o c e d u r ed e m o s _ i n t e r b a s e B e f o r e C o n n e c t ( S e n d e r :T O b j e c t ) ; p r i v a t e {P r i v a t ed e c l a r a t i o n s} p u b l i c {P u b l i cd e c l a r a t i o n s} f u n c t i o nE c h o S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; f u n c t i o nR e v e r s e S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; f u n c t i o nG e t I m a g e n B a n n e r A s J S O N ( A I D B a n n e r :I n t e g e r ) :T J S O N A r r a y ; f u n c t i o nG e t I m a g e n B a n n e r A s S t r e a m ( A I D B a n n e r :I n t e g e r ) :T S t r e a m ;o v e r l o a d ; e n d ; i m p l e m e n t a t i o n { $ R* . d f m } u s e sS y s t e m . S t r U t i l s ,U M a i n S e r v e r ,D a t a . D B X J S O N C o m m o n ;

f u n c t i o nG e t I m a g e n B a n n e r A s S t r e a m ( A S Q L Q u e r y :T S Q L Q u e r y ;A I D B a n n e r :I n t e g e r ) :T S t r e a m ;o v e r

f u n c t i o nT S e r v e r M e t h o d s 1 . G e t I m a g e n B a n n e r A s S t r e a m ( A S Q L Q u e r y :T S Q L Q u e r y ;A I D B a n n e r :I n t e g e r ) :T v a r s t r e a m :T M e m o r y S t r e a m ; b e g i n i f( A S Q L Q u e r y . A c t i v e )t h e nA S Q L Q u e r y . C l o s e ( ) ; A S Q L Q u e r y . P a r a m B y N a m e ( ' I D B a n n e r ' ) . V a l u e: =A I D B a n n e r ; A S Q L Q u e r y . O p e n ( ) ; s t r e a m: =T M e m o r y S t r e a m . C r e a t e ; s t r e a m . W r i t e D a t a ( A S Q L Q u e r y . F i e l d B y N a m e ( ' B a n n e r ' ) . A s B y t e s , L e n g t h ( A S Q L Q u e r y . F i e l d B y N a m e ( ' B a n n e r ' ) . A s B y t e s ) ) ; / / s t r e a m . S a v e T o F i l e ( ' t e s t _ a h o r a . j p g ' ) ; s t r e a m . S e e k ( 0 ,S y s t e m . C l a s s e s . T S e e k O r i g i n . s o B e g i n n i n g ) ; A S Q L Q u e r y . C l o s e ( ) ; R e s u l t : =s t r e a m ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . G e t I m a g e n B a n n e r A s J S O N ( A I D B a n n e r :I n t e g e r ) :T J S O N A r r a y ; v a r s t r e a m :T S t r e a m ;


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

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

b e g i n s t r e a m : =G e t I m a g e n B a n n e r A s S t r e a m ( A I D B a n n e r ) ; t r y R e s u l t : =T D B X J S O N T o o l s . S t r e a m T o J S O N ( s t r e a m ,0 ,s t r e a m . S i z e ) ; f i n a l l y s t r e a m . F r e e ; e n d ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . G e t I m a g e n B a n n e r A s S t r e a m ( A I D B a n n e r :I n t e g e r ) :T S t r e a m ; b e g i n R e s u l t : =G e t I m a g e n B a n n e r A s S t r e a m ( G e t I m a g e B a n n e r _ I n t e r b a s e ,A I D B a n n e r ) ; e n d ; p r o c e d u r eT S e r v e r M e t h o d s 1 . d e m o s _ i n t e r b a s e B e f o r e C o n n e c t ( S e n d e r :T O b j e c t ) ; b e g i n d e m o s _ i n t e r b a s e . P a r a m s . V a l u e s [ ' D a t a b a s e ' ]: =M a i n S e r v e r . G e t P a t h ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . E c h o S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; b e g i n R e s u l t: =V a l u e ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . R e v e r s e S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; b e g i n R e s u l t: =S y s t e m . S t r U t i l s . R e v e r s e S t r i n g ( V a l u e ) ; e n d ; e n d .

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?

R e s u l t : =G e t I m a g e n B a n n e r A s S t r e a m ( G e t I m a g e B a n n e r _ I n t e r b a s e ,A I D B a n n e r ) ;

delphibasico.com/delphi/?p=3918

16/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Fijmonos privada,

que

la

funcin declara una

GetImagenBannerAsStream,

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

T D B X J S O N T o o l s . S t r e a m T o J S O N ()

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 sin responsabilizarme de su liberacin. Eso sucede cuando instanciamos objetos, seres inferiores 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. un prrafo de la entrada de Jim Terney. Os leo

Accessing Values
The GetStream and SetStream methods have an InstanceOwner parameter. Passing True indicates that DBX owns the

delphibasico.com/delphi/?p=3918

17/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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: Si a continuacin observamos con detenimiento los mtodos generados por el proxy para devolver el stream

f u n c t i o nT S e r v e r M e t h o d s 1 C l i e n t . G e t I m a g e n B a n n e r A s S t r e a m ( A I D B a n n e r :I n t e g e r ) :T S t r e a m ; b e g i n i fF G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d=n i lt h e n b e g i n F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d: =F D B X C o n n e c t i o n . C r e a t e C o m m a n d ; F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . C o m m a n d T y p e: =T D B X C o m m a n d T y p e s . D S S e r v e r M e t h o d ; F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . T e x t: =' T S e r v e r M e t h o d s 1 . G e t I m a g e n B a n n e r A s S t r e a m ' ; F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . P r e p a r e ; e n d ; F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . P a r a m e t e r s [ 0 ] . V a l u e . S e t I n t 3 2 ( A I D B a n n e r ) ; F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . E x e c u t e U p d a t e ; R e s u l t: =F G e t I m a g e n B a n n e r A s S t r e a m C o m m a n d . P a r a m e t e r s [ 1 ] . V a l u e . G e t S t r e a m ( F I n s t a n c e O w n e r ) ; e n d ;

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

c o n s t r u c t o rT S e r v e r M e t h o d s 1 C l i e n t . C r e a t e ( A D B X C o n n e c t i o n :T D B X C o n n e c t i o n ;A I n s t a n c e O w n e r b e g i n i n h e r i t e dC r e a t e ( A D B X C o n n e c t i o n ,A I n s t a n c e O w n e r ) ; e n d ;

En este caso, tomaba el valor True (lo veris en el interior del evento onCreate del formulario cliente,
delphibasico.com/delphi/?p=3918 18/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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, demasiado ortodoxo. Os muestro una imagen del formulario aunque esto no sea

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.

delphibasico.com/delphi/?p=3918

19/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Este es el cdigo que he escrito a tal efecto.

u n i tU M a i n C l i e n t ; i n t e r f a c e u s e s S y s t e m . S y s U t i l s ,S y s t e m . T y p e s ,S y s t e m . U I T y p e s ,S y s t e m . R t t i ,S y s t e m . C l a s s e s , S y s t e m . V a r i a n t s ,F M X . T y p e s ,F M X . C o n t r o l s ,F M X . F o r m s ,F M X . D i a l o g s , D a t a . D B X D a t a S n a p ,I P P e e r C l i e n t ,D a t a . D B X C o m m o n ,D a t a . F M T B c d ,D a t a . D B , D a t a . S q l E x p r ,F M X . O b j e c t s ,D a t a . B i n d . E n g E x t ,F m x . B i n d . D B E n g E x t , S y s t e m . B i n d i n g s . O u t p u t s ,F m x . B i n d . E d i t o r s ,D a t a . B i n d . C o m p o n e n t s , D a t a . B i n d . D B S c o p e ,D a t a s n a p . D B C l i e n t ,D a t a s n a p . D S C o n n e c t ,F M X . L a y o u t s , F m x . B i n d . N a v i g a t o r ,U P r o x y ,F M X . L i s t B o x ; t y p e T F o r m 1=c l a s s ( T F o r m ) I m a g e 1 :T I m a g e ; D a t a S n a p C O N N E C T I O N :T S Q L C o n n e c t i o n ; B a n n e r s :T C l i e n t D a t a S e t ; D S P r o v i d e r C o n n e c t i o n 1 :T D S P r o v i d e r C o n n e c t i o n ; B a n n e r s B a n n e r :T B l o b F i e l d ; B i n d S o u r c e D B 1 :T B i n d S o u r c e D B ; B i n d i n g s L i s t 1 :T B i n d i n g s L i s t ; L i n k P r o p e r t y T o F i e l d 1 :T L i n k P r o p e r t y T o F i e l d ; B i n d N a v i g a t o r 1 :T B i n d N a v i g a t o r ; b t n D a t a s e t :T B u t t o n ; b t n M e t h o d J S O N :T B u t t o n ; I m a g e 2 :T I m a g e ; L a b e l 1 :T L a b e l ; B a n n e r s I D B a n n e r :T I n t e g e r F i e l d ; L i n k P r o p e r t y T o F i e l d 2 :T L i n k P r o p e r t y T o F i e l d ; c b x S e l e c t o r :T C o m b o B o x ; I n t e r b a s e :T L i s t B o x I t e m ; b t n M e t h o d S t r e a m :T B u t t o n ; P a n e l 1 :T P a n e l ; l a b B a s e D e D a t o s :T L a b e l ; p r o c e d u r eb t n D a t a s e t C l i c k ( S e n d e r :T O b j e c t ) ; p r o c e d u r eb t n M e t h o d J S O N C l i c k ( S e n d e r :T O b j e c t ) ; p r o c e d u r eF o r m C r e a t e ( S e n d e r :T O b j e c t ) ; p r o c e d u r eF o r m D e s t r o y ( S e n d e r :T O b j e c t ) ; p r o c e d u r ec b x S e l e c t o r C h a n g e ( S e n d e r :T O b j e c t ) ; p r o c e d u r eb t n M e t h o d S t r e a m C l i c k ( S e n d e r :T O b j e c t ) ; p r i v a t e {P r i v a t ed e c l a r a t i o n s} F I n s t a n c e O w n e r:B o o l e a n ; F S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; f u n c t i o nG e t S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; p u b l i c {P u b l i cd e c l a r a t i o n s}
delphibasico.com/delphi/?p=3918 20/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

e n d ; v a r F o r m 1 :T F o r m 1 ; i m p l e m e n t a t i o n { $ R* . f m x } u s e sD a t a . D B X J S O N C o m m o n ; p r o c e d u r eT F o r m 1 . b t n D a t a s e t C l i c k ( S e n d e r :T O b j e c t ) ; b e g i n B a n n e r s . O p e n ; e n d ; p r o c e d u r eT F o r m 1 . b t n M e t h o d J S O N C l i c k ( S e n d e r :T O b j e c t ) ; v a r f S t r e a m :T M e m o r y S t r e a m ; i :I n t e g e r ; b e g i n i fB a n n e r s . I s E m p t yt h e n r a i s eE x c e p t i o n . C r e a t e ( ' D e b e sa b r i rp r i m e r oe ld a t a s e t ' ) ; t r y i : =B a n n e r s I D B a n n e r . A s I n t e g e r ; f S t r e a m : =T M e m o r y S t r e a m . C r e a t e ( ) ; c a s ec b x S e l e c t o r . I t e m I n d e xo f 0 :b e g i n / / f S t r e a m . S a v e T o F i l e ( ' . . \ . . \ . . \ t e s t _ i n t e r b a s e _ j a s o n _ f m x . j p g ' ) ; e n d ; e n d ; I m a g e 2 . B i t m a p . L o a d F r o m S t r e a m ( f S t r e a m ) ; f i n a l l y f S t r e a m . F r e e ; e n d ; e n d ; p r o c e d u r eT F o r m 1 . b t n M e t h o d S t r e a m C l i c k ( S e n d e r :T O b j e c t ) ; v a r f S t r e a m :T M e m o r y S t r e a m ; i :I n t e g e r ; b e g i n i fB a n n e r s . I s E m p t yt h e n r a i s eE x c e p t i o n . C r e a t e ( ' D e b e sa b r i rp r i m e r oe ld a t a s e t ' ) ; t r y i : =B a n n e r s I D B a n n e r . A s I n t e g e r ; f S t r e a m : =T M e m o r y S t r e a m . C r e a t e ( ) ; c a s ec b x S e l e c t o r . I t e m I n d e xo f 0 :b e g i n f S t r e a m . L o a d F r o m S t r e a m ( G e t S e r v e r M e t h o d s 1 C l i e n t . G e t I m a g e n B a n n e r A s S t r e a m ( i ) ) ;


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

f S t r e a m . L o a d F r o m S t r e a m ( T D B X J S O N T o o l s . J S O N T o S t r e a m ( G e t S e r v e r M e t h o d s 1 C l i e n t . G e t I m a g e

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

/ / f S t r e a m . S a v e T o F i l e ( ' . . \ . . \ . . \ t e s t _ i n t e r b a s e _ s t r e a m _ f m x . j p g ' ) ; e n d ; e n d ; I m a g e 2 . B i t m a p . L o a d F r o m S t r e a m ( f S t r e a m ) ; f i n a l l y f S t r e a m . F r e e ; e n d ; e n d ; p r o c e d u r eT F o r m 1 . c b x S e l e c t o r C h a n g e ( S e n d e r :T O b j e c t ) ; b e g i n B a n n e r s . C l o s e ; c a s ec b x S e l e c t o r . I t e m I n d e xo f 0 :B a n n e r s . P r o v i d e r N a m e : =' d s p I m a g e n e s _ I n t e r b a s e ' ; e n d ; e n d ; p r o c e d u r eT F o r m 1 . F o r m C r e a t e ( S e n d e r :T O b j e c t ) ; b e g i n F I n s t a n c e O w n e r: =T r u e ; e n d ; p r o c e d u r eT F o r m 1 . F o r m D e s t r o y ( S e n d e r :T O b j e c t ) ; b e g i n F S e r v e r M e t h o d s 1 C l i e n t . F r e e ; e n d ; f u n c t i o nT F o r m 1 . G e t S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; b e g i n i fF S e r v e r M e t h o d s 1 C l i e n t=n i lt h e n R e s u l t: =F S e r v e r M e t h o d s 1 C l i e n t ; e n d ; e n d .

F S e r v e r M e t h o d s 1 C l i e n t : =T S e r v e r M e t h o d s 1 C l i e n t . C r e a t e ( D a t a S n a p C O N N E C T I O N . D B X C o n n e c t i o n ,F I

Y aqu tenis algunas capturas de la aplicacin en ejecucin, con una animacin mostrando el resultado.

delphibasico.com/delphi/?p=3918

22/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

En el video se puede ver la aplicacin


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

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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

G e t S e r v e r M e t h o d s 1 C l i e n t . G e t I m a g e n B a n n e r A s S t r e a m ( 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 era as estado en e intentar asegurarme que realmente 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
delphibasico.com/delphi/?p=3918 24/33

descartar que no fuera un problema generado por mi

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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 Ni regresin idea. Es fruto algo de cambios ver en posteriores. que

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:

u n i tS e r v e r M e t h o d s U n i t 1 ; i n t e r f a c e u s e sS y s t e m . S y s U t i l s ,S y s t e m . C l a s s e s ,D a t a s n a p . D S S e r v e r ,D a t a s n a p . D S A u t h ; t y p e T S e r v e r M e t h o d s 1=c l a s s ( T D S S e r v e r M o d u l e ) p r i v a t e
delphibasico.com/delphi/?p=3918 25/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

{P r i v a t ed e c l a r a t i o n s} p u b l i c {P u b l i cd e c l a r a t i o n s} f u n c t i o nE c h o S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; f u n c t i o nR e v e r s e S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; f u n c t i o nG e t S t r e a m B y S i z e ( A S i z e B y t e s :I n t e g e r ) :T S t r e a m ; / / B yB y t e s e n d ; i m p l e m e n t a t i o n { $ R* . d f m } u s e sS y s t e m . S t r U t i l s ; f u n c t i o nT S e r v e r M e t h o d s 1 . E c h o S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; b e g i n R e s u l t: =V a l u e ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . G e t S t r e a m B y S i z e ( A S i z e B y t e s :I n t e g e r ) :T S t r e a m ; v a r f S t r e a m :T B y t e s S t r e a m ; f B y t e s :T B y t e s ; i :I n t e g e r ; b e g i n S e t L e n g t h ( f B y t e s ,A S i z e B y t e s ) ; f o ri: =0t oL e n g t h ( f B y t e s )-1d of B y t e s [ i ]: =1 ; f S t r e a m : =T B y t e s S t r e a m . C r e a t e ( f B y t e s ) ; R e s u l t : =f S t r e a m ; e n d ; f u n c t i o nT S e r v e r M e t h o d s 1 . R e v e r s e S t r i n g ( V a l u e :s t r i n g ) :s t r i n g ; b e g i n R e s u l t: =S y s t e m . S t r U t i l s . R e v e r s e S t r i n g ( V a l u e ) ; e n d ; e n d .

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.

delphibasico.com/delphi/?p=3918

26/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Este es el cdigo del cliente.

u n i tU M a i n C l i e n t _ f m x ; i n t e r f a c e u s e s S y s t e m . S y s U t i l s ,S y s t e m . T y p e s ,S y s t e m . U I T y p e s ,S y s t e m . R t t i ,S y s t e m . C l a s s e s , S y s t e m . V a r i a n t s ,F M X . T y p e s ,F M X . C o n t r o l s ,F M X . F o r m s ,F M X . D i a l o g s , D a t a . D B X D a t a S n a p ,I P P e e r C l i e n t ,D a t a . D B X C o m m o n ,F M X . O b j e c t s ,D a t a . D B , D a t a . S q l E x p r ,U P r o x y ,F M X . L a y o u t s ,F M X . M e m o ,F M X . E d i t ; t y p e T M a i n C l i e n t e F M X=c l a s s ( T F o r m ) b t n I m g 1 :T B u t t o n ; b t n I m g 2 :T B u t t o n ; D a t a S n a p C O N N E C T I O N :T S Q L C o n n e c t i o n ; I m a g e 1 :T I m a g e ; b t n T e s t :T B u t t o n ; M e m o 1 :T M e m o ; b t n C a n c e l :T B u t t o n ; n u m b o x :T E d i t ; p r o c e d u r eF o r m C r e a t e ( S e n d e r :T O b j e c t ) ; p r o c e d u r eF o r m D e s t r o y ( S e n d e r :T O b j e c t ) ; p r o c e d u r eb t n T e s t C l i c k ( S e n d e r :T O b j e c t ) ; p r o c e d u r eb t n C a n c e l C l i c k ( S e n d e r :T O b j e c t ) ; p r i v a t e {P r i v a t ed e c l a r a t i o n s} F F i n :B o o l e a n ;
delphibasico.com/delphi/?p=3918 27/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

F I n s t a n c e O w n e r:B o o l e a n ; F S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; f u n c t i o nG e t S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; p u b l i c {P u b l i cd e c l a r a t i o n s} f u n c t i o nF i n :B o o l e a n ; e n d ; v a r M a i n C l i e n t e F M X :T M a i n C l i e n t e F M X ; i m p l e m e n t a t i o n { $ R* . f m x } p r o c e d u r eT M a i n C l i e n t e F M X . b t n C a n c e l C l i c k ( S e n d e r :T O b j e c t ) ; b e g i n F F i n : =T r u e ; e n d ; p r o c e d u r eT M a i n C l i e n t e F M X . b t n T e s t C l i c k ( S e n d e r :T O b j e c t ) ; v a r f B y t e s S t r e a m :T B y t e s S t r e a m ; i , j :I n t e g e r ; s L o g :S t r i n g ; b e g i n F F i n : =F a l s e ; m e m o 1 . L i n e s . C l e a r ; f B y t e s S t r e a m : =T B y t e s S t r e a m . C r e a t e ; t r y i : =S t r T o I n t ( n u m b o x . T e x t ) ; w h i l en o tF i nd o b e g i n f B y t e s S t r e a m . L o a d F r o m S t r e a m ( G e t S e r v e r M e t h o d s 1 C l i e n t . G e t S t r e a m B y S i z e ( i ) ) ; s L o g : =' S i z e :' + I n t T o S t r ( f B y t e s S t r e a m . S i z e ) +'>' ; f o rj: =0t oL e n g t h ( f B y t e s S t r e a m . B y t e s ) 1d o s L o g : =s L o g+I n t T o S t r ( f B y t e s S t r e a m . B y t e s [ j ] ) ; m e m o 1 . L i n e s . A d d ( s L o g ) ; I n c ( i ) ; n u m b o x . T e x t : =I n t T o S t r ( i ) ; A p p l i c a t i o n . P r o c e s s M e s s a g e s ; e n d ; f i n a l l y m e m o 1 . L i n e s . S a v e T o F i l e ( ' T e s t . t x t ' ) ; f B y t e s S t r e a m . F r e e ; e n d ; e n d ; f u n c t i o nT M a i n C l i e n t e F M X . F i n :B o o l e a n ; b e g i n


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

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

R e s u l t : =F F i n ; e n d ; p r o c e d u r eT M a i n C l i e n t e F M X . F o r m C r e a t e ( S e n d e r :T O b j e c t ) ; b e g i n F I n s t a n c e O w n e r: =T r u e ; e n d ; p r o c e d u r eT M a i n C l i e n t e F M X . F o r m D e s t r o y ( S e n d e r :T O b j e c t ) ; b e g i n F S e r v e r M e t h o d s 1 C l i e n t . F r e e ; F S e r v e r M e t h o d s 1 C l i e n t : =N i l ; e n d ; f u n c t i o nT M a i n C l i e n t e F M X . G e t S e r v e r M e t h o d s 1 C l i e n t :T S e r v e r M e t h o d s 1 C l i e n t ; b e g i n i fF S e r v e r M e t h o d s 1 C l i e n t=n i lt h e n R e s u l t: =F S e r v e r M e t h o d s 1 C l i e n t ; e n d ; e n d .

F S e r v e r M e t h o d s 1 C l i e n t : =T S e r v e r M e t h o d s 1 C l i e n t . C r e a t e ( D a t a S n a p C O N N E C T I O N . D B X C o n n e c t i o n ,F I

Y finalmente, podis ver una imagen de la aplicacin en ejecucin, as como una animacin

delphibasico.com/delphi/?p=3918

29/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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
delphibasico.com/delphi/?p=3918 30/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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.

Tw ittear

Like

Send

Comprtelo:

Facebook 4 LinkedIn 1 Imprimir

Twitter 1

Google +1

Correo electrnico Ms

datasnap

Delphi

qc

XE3

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


Like 4 Tw ittear 1 0

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
delphibasico.com/delphi/?p=3918 31/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

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 *
delphibasico.com/delphi/?p=3918 32/33

16/05/13

Dar una buena imagen! Parte 2 | Delphi Bsico

Nombre

* *

Correo

electrnico Web

cinco + 1 =

Comentario

Puedes usar las siguientes etiquetas y atributos HTML: < a h r e f = " "t i t l e = " " >< a b b rt i t l e = " " >< a c r o n y mt i t l e = " " > < b >< b l o c k q u o t ec i t e = " " >< c i t e >< c o d e >< d e l d a t e t i m e = " " >< e m >< i >< qc i t e = " " >< s t r i k e >< s t r o n g >

Publicar comentario

Spam Protection by WP-SpamFree

Recibir un email con los siguientes comentarios a esta entrada. Recibir un email con cada nuevo post.

2013 Delphi Bsico

Powered by Pinboard Theme by One Designs and WordPress

delphibasico.com/delphi/?p=3918

33/33

También podría gustarte