<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>API</title><link>http://blogs.clearscreen.com/lpf/category/155.aspx</link><description>El API de Win32 sigue siendo igual de útil en VB.net</description><managingEditor>Luis Pérez Fernández</managingEditor><dc:language>es-ES</dc:language><generator>.Text Version 0.95.2004.102</generator><item><dc:creator>Luis Pérez Fernández</dc:creator><title>LineDDA</title><link>http://blogs.clearscreen.com/lpf/archive/2005/10/25/2519.aspx</link><pubDate>Tue, 25 Oct 2005 17:12:00 GMT</pubDate><guid>http://blogs.clearscreen.com/lpf/archive/2005/10/25/2519.aspx</guid><wfw:comment>http://blogs.clearscreen.com/lpf/comments/2519.aspx</wfw:comment><comments>http://blogs.clearscreen.com/lpf/archive/2005/10/25/2519.aspx#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://blogs.clearscreen.com/lpf/comments/commentRss/2519.aspx</wfw:commentRss><trackback:ping>http://blogs.clearscreen.com/lpf/services/trackbacks/2519.aspx</trackback:ping><description>&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Recientemente, para una chorradilla que estoy haciendo en casa en mis (poooocos) ratos libres, me vi en la necesidad de tener que calcular todos los puntos existentes en la línea recta que separa dos puntos cualesquiera de la pantalla.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;O sea, dado un punto de origen definido en coordenadas de pantalla (X e Y) y un punto de destino, situados ambos en cualquier sitio de la pantalla y sin que tengan que estar a la misma altura ni horizontal ni vertical, se trata de obtener toda la sucesión de puntos que separan el origen y el destino.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Vale, cosa fácil... en VB6 ya me vi en las mismas y me acordé de que hay una función del API, llamada &lt;strong&gt;LineDDA&lt;/strong&gt;, que hace precisamente eso... pues nada, la portamos al .net, ¿no? Sí, pero... hay un problemilla que en realidad no es tal hasta que lo haces la primera vez...&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;El caso es que LineDDA es una de esas curiosas funciones del API de Win32 que funcionan mediante el uso de &lt;em&gt;callbacks&lt;/em&gt;, o sea, funciones de retorno... es decir, tú llamas a LineDDA pasándole como parámetro un puntero a una función que has definido en el código, y LineDDA llama a esa función una vez por cada punto que encuentra en la línea recta que se quiere obtener.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Y como era la primera vez que me he enfrentado al caso, he tenido que dar un par de vueltecillas hasta que he encontrado la solución; es bastante fácil gracias al uso de los &lt;strong&gt;delegados&lt;/strong&gt;.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Los delegados son tipos de referencia; o sea... algo así como instancias de procedimientos que hacen referencia a otro procedimiento declarado en otra (o en la misma) clase, siempre y cuando sus argumentos y tipos devueltos sean los mismos. En el ejemplo se ve mejor y creo que se comprende bastante bien.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Para probar &lt;strong&gt;LineDDA&lt;/strong&gt;, lo mejor es crear una nueva aplicación Windows con VB.net. Una vez hecho esto, añadiremos un nuevo módulo al proyecto con este código:&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;&lt;/font&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Este es el delegado. Al instanciar un nuevo objeto de tipo LineDDACallBack, haremos&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'referencia a otra función que debe tener la misma estructura de parámetros y tipo&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'de retorno&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Delegate&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt; LineDDACallback(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; x &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; y &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, _&lt;br /&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;    ByVal&lt;/span&gt; lpData &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;

&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Esta es la declaración del API de Win32 LineDDA, adaptada a VB.net. Como se ve, uno&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'de los parámetros que le pasamos es nuestra función delegada (en realidad, un puntero&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'a la misma para que LineDDA pueda llamarla para darnos el resultado que queremos)&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Declare&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt; LineDDA &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Lib&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4"&gt;"gdi32"&lt;/span&gt; (&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; n1 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; n2 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, _&lt;br /&gt;    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; n3 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; n4 &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; lpLineDDAProc &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; LineDDACallback, _&lt;br /&gt;    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; lParam &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;Después, en &lt;strong&gt;Form1.vb&lt;/strong&gt; escribiremos el código necesario para invocar a la función:&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;&lt;/font&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Declarar estas dos variables a nivel de formulario&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Private&lt;/span&gt; m_Puntos() &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Drawing.Point
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Private&lt;/span&gt; m_NumeroPuntos &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; 0

&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Esta es la función real a la que llamará LineDDA, suministrándonos uno a uno los&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'puntos existentes en la línea recta&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Private&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt; _lineddacbk(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; x &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; y &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;, _&lt;br /&gt;    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; lpData &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Aumentamos en 1 el nº de puntos&lt;/span&gt;
    m_NumeroPuntos += 1
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Redimensionamos el array que contiene los puntos&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ReDim&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Preserve&lt;/span&gt; m_Puntos(m_NumeroPuntos &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;-&lt;/span&gt; 1)
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Creamos un nuevo punto con la información que nos da LineDDA&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; oPunto &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;New&lt;/span&gt; System.Drawing.Point(x, y)
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Y lo añadimos al array&lt;/span&gt;
    m_Puntos(m_NumeroPuntos &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;-&lt;/span&gt; 1) &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; oPunto
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;End&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt;

&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Por fin, la función que lo hace todo...&lt;/span&gt;
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Public&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt; CalculaLinea(&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; Origen &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Drawing.Point, _&lt;br /&gt;    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;ByVal&lt;/span&gt; Destino &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Drawing.Point) &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; System.Drawing.Point()
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Declaramos e instanciamos la función de retorno de llamada (callback)&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; oCallback &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;New&lt;/span&gt; LineDDACallback(&lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;AddressOf&lt;/span&gt; _lineddacbk)
    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Como se ve, lo que hacemos es declarar una función delegada que hace referencia&lt;br /&gt;    'a nuestra función _lineddacbk&lt;/span&gt;

    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Ahora llamamos a LineDDA&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Dim&lt;/span&gt; iRes &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;As&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Integer&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;=&lt;/span&gt; LineDDA(Origen.X, Origen.Y, Destino.X, Destino.Y, _&lt;br /&gt;        oCallback, 0)

    &lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;'Y ya está. Podeis ejecutar paso a paso, vereis como la función _lineddacbk es &lt;br /&gt;    'llamada una vez por cada punto &lt;/span&gt;&lt;span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;existente en la recta que separa Origen de Destino&lt;/span&gt;
    &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Return&lt;/span&gt; m_Puntos
&lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;End&lt;/span&gt; &lt;span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"&gt;Function&lt;/span&gt;&lt;font face="Tahoma" size="2"&gt;
&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;&lt;strong&gt;Así de fácil&lt;/strong&gt;. Probadlo, es muy divertido.&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font face="Tahoma" size="2"&gt;P.S. Como muy bien me ha hecho notar &lt;a href="http://blogs.clearscreen.com/migs"&gt;Miguel Jiménez&lt;/a&gt;, es más que probable que esta función utilice internamente el &lt;a href="http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html"&gt;algoritmo de Bresenham&lt;/a&gt;.&lt;/font&gt;&lt;/p&gt;&lt;img src ="http://blogs.clearscreen.com/lpf/aggbug/2519.aspx" width = "1" height = "1" /&gt;</description><body xmlns="http://www.w3.org/1999/xhtml"><p><font face="Tahoma" size="2">Recientemente, para una chorradilla que estoy haciendo en casa en mis (poooocos) ratos libres, me vi en la necesidad de tener que calcular todos los puntos existentes en la línea recta que separa dos puntos cualesquiera de la pantalla.</font></p>
<p><font face="Tahoma" size="2">O sea, dado un punto de origen definido en coordenadas de pantalla (X e Y) y un punto de destino, situados ambos en cualquier sitio de la pantalla y sin que tengan que estar a la misma altura ni horizontal ni vertical, se trata de obtener toda la sucesión de puntos que separan el origen y el destino.</font></p>
<p><font face="Tahoma" size="2">Vale, cosa fácil... en VB6 ya me vi en las mismas y me acordé de que hay una función del API, llamada <strong>LineDDA</strong>, que hace precisamente eso... pues nada, la portamos al .net, ¿no? Sí, pero... hay un problemilla que en realidad no es tal hasta que lo haces la primera vez...</font></p>
<p><font face="Tahoma" size="2">El caso es que LineDDA es una de esas curiosas funciones del API de Win32 que funcionan mediante el uso de <em>callbacks</em>, o sea, funciones de retorno... es decir, tú llamas a LineDDA pasándole como parámetro un puntero a una función que has definido en el código, y LineDDA llama a esa función una vez por cada punto que encuentra en la línea recta que se quiere obtener.</font></p>
<p><font face="Tahoma" size="2">Y como era la primera vez que me he enfrentado al caso, he tenido que dar un par de vueltecillas hasta que he encontrado la solución; es bastante fácil gracias al uso de los <strong>delegados</strong>.</font></p>
<p><font face="Tahoma" size="2">Los delegados son tipos de referencia; o sea... algo así como instancias de procedimientos que hacen referencia a otro procedimiento declarado en otra (o en la misma) clase, siempre y cuando sus argumentos y tipos devueltos sean los mismos. En el ejemplo se ve mejor y creo que se comprende bastante bien.</font></p>
<p><font face="Tahoma" size="2">Para probar <strong>LineDDA</strong>, lo mejor es crear una nueva aplicación Windows con VB.net. Una vez hecho esto, añadiremos un nuevo módulo al proyecto con este código:</font></p>
<p><font face="Tahoma" size="2"></font></p><pre><span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Este es el delegado. Al instanciar un nuevo objeto de tipo LineDDACallBack, haremos</span>
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'referencia a otra función que debe tener la misma estructura de parámetros y tipo</span>
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'de retorno</span>
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Public</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Delegate</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span> LineDDACallback(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> x <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> y <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, _<br /></span><span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent"><span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">    ByVal</span> lpData <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>

<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Esta es la declaración del API de Win32 LineDDA, adaptada a VB.net. Como se ve, uno</span>
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'de los parámetros que le pasamos es nuestra función delegada (en realidad, un puntero</span>
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'a la misma para que LineDDA pueda llamarla para darnos el resultado que queremos)</span>
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Public</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Declare</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span> LineDDA <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Lib</span> <span style="FONT-SIZE: 11px; COLOR: #666666; FONT-FAMILY: Courier New; BACKGROUND-COLOR: #e4e4e4">"gdi32"</span> (<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> n1 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> n2 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, _<br />    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> n3 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> n4 <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> lpLineDDAProc <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> LineDDACallback, _<br />    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> lParam <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>
</span></pre>
<p></p>
<p><font face="Tahoma" size="2">Después, en <strong>Form1.vb</strong> escribiremos el código necesario para invocar a la función:</font></p>
<p><font face="Tahoma" size="2"></font></p><pre><span style="FONT-SIZE: 11px; COLOR: black; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Declarar estas dos variables a nivel de formulario</span>
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Private</span> m_Puntos() <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Drawing.Point
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Private</span> m_NumeroPuntos <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span> <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> 0

<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Esta es la función real a la que llamará LineDDA, suministrándonos uno a uno los</span>
<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'puntos existentes en la línea recta</span>
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Private</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span> _lineddacbk(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> x <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> y <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>, _<br />    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> lpData <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span>
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Aumentamos en 1 el nº de puntos</span>
    m_NumeroPuntos += 1
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Redimensionamos el array que contiene los puntos</span>
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ReDim</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Preserve</span> m_Puntos(m_NumeroPuntos <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">-</span> 1)
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Creamos un nuevo punto con la información que nos da LineDDA</span>
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> oPunto <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">New</span> System.Drawing.Point(x, y)
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Y lo añadimos al array</span>
    m_Puntos(m_NumeroPuntos <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">-</span> 1) <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> oPunto
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">End</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span>

<span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Por fin, la función que lo hace todo...</span>
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Public</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span> CalculaLinea(<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> Origen <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Drawing.Point, _<br />    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">ByVal</span> Destino <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Drawing.Point) <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> System.Drawing.Point()
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Declaramos e instanciamos la función de retorno de llamada (callback)</span>
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> oCallback <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">New</span> LineDDACallback(<span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">AddressOf</span> _lineddacbk)
    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Como se ve, lo que hacemos es declarar una función delegada que hace referencia<br />    'a nuestra función _lineddacbk</span>

    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Ahora llamamos a LineDDA</span>
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Dim</span> iRes <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">As</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Integer</span> <span style="FONT-SIZE: 11px; COLOR: red; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">=</span> LineDDA(Origen.X, Origen.Y, Destino.X, Destino.Y, _<br />        oCallback, 0)

    <span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">'Y ya está. Podeis ejecutar paso a paso, vereis como la función _lineddacbk es <br />    'llamada una vez por cada punto </span><span style="FONT-SIZE: 11px; COLOR: green; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">existente en la recta que separa Origen de Destino</span>
    <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Return</span> m_Puntos
<span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">End</span> <span style="FONT-SIZE: 11px; COLOR: blue; FONT-FAMILY: Courier New; BACKGROUND-COLOR: transparent">Function</span><font face="Tahoma" size="2">
</font></span></pre>
<p></p>
<p><font face="Tahoma" size="2"><strong>Así de fácil</strong>. Probadlo, es muy divertido.</font></p>
<p><font face="Tahoma" size="2">P.S. Como muy bien me ha hecho notar <a href="http://blogs.clearscreen.com/migs">Miguel Jiménez</a>, es más que probable que esta función utilice internamente el <a href="http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html">algoritmo de Bresenham</a>.</font></p><img src ="http://blogs.clearscreen.com/lpf/aggbug/2519.aspx" width = "1" height = "1" /></body></item></channel></rss>