.NET Tutorial 24. Cómo cambiar el «Look» a tus formularios de Windows.

¿Estás cansado del aspecto  de tus formularios?. ¿Te gustaría hacer aplicaciones "cool" o más "eye candy" y eres un virtuoso con el fotochop?

Si es así, enhorabuena, verás que con apenas 5 líneas, (si, has leído bien, 5 líneas) de código, puedes tener formularios como este:

Eso que ves en esta imagen, es un formulario sin borde:

Me.FormBorderStyle = FormBorderStyle.None

El formulario tiene un BackGroundImage que he pillado por internet (yo si que no soy un virtuoso del fotochop 😉

Luego tenemos un PictureBox con el logo de MeriStation, un par de etiquetas y un botón.

El formulario se minimiza o se cierra pulsando en el __ y en l a X respectivamente.

Además, como podrás comprobar si ejecutas este ejemplo, el formulario tiene "partes transparentes", con lo que puedes tener formularios cómo esto:

Cualquiera diría que "eso" es un formulario, eh? 😉

¿Y esto cómo co**nes se hace? O_o

Pues primero, la imagen que vas a usar a modo de "skin" para tu formulario tiene que tener un color que se usará como "color transparente". Yo he usado el color verde puro (0,255,0). De esta forma, en aquellas partes donde el "skin" sea verde puro, el formulario será "transparente".

El código de nuestro formulario será este:

Namespace Tutorial24
  Partial Public Class Form1
    Inherits Form
    Public Sub New()
      InitializeComponent()

      Me.FormBorderStyle = FormBorderStyle.None
      Me.Width = Me.BackgroundImage.Width
      Me.Height = Me.BackgroundImage.Height
      Me.TransparencyKey = Color.FromArgb(0, 255, 0)
    End Sub
  End Class
End NameSpace

Fin de la historia.

Cada vez que añadáis un nuevo control a vuestro formulario, automáticamente se añaden las definiciones de dicho control en InitializeComponent (). Además se añaden también automáticamente a vuestro código sentencias del tipo Friend WithEvents lblCerrar As System.Windows.Forms.Label

Para minimizar y cerrar este formulario, es la mar de fácil, simplemente coloca unos "labels" transparentes y sin texto en la posición donde el "skin" tiene dibujados el __ y la X.

Al tener un formulario sin borde no lo podremos "mover" con el ratón. Pero para eso también hay solución. Se "overraidea"  el procedimiento WndProc () que ya vimos en el Tutorial 18 y asunto arreglado: Tendrás un formulario que podrás mover con el ratón, que se puede minimizar y/o cerrar y que además tiene un aspecto "molón", "cool", "mega-fashion", "llámalo X" 😉

 

Saludos.
mov eax,ollydbg; Int 13h

 

Descargar proyecto .NET Tutorial 24
(207 KB. Visual Studio 2008)

 

.NET Tutorial 23. Base de datos (Parte II). Access, SQL Server y MySQL: Ejemplo práctico

Sabida la teoría es hora de pasar a la práctica. Atención, que vienen curvas!!! 😉

Hoy veremos como realizar una aplicación que podrá manejar ya bien sea una base de datos de Microsoft Access, conectarse con un SQL Server o incluso conectarse con un servidor de MySQL.

Además veremos cómo será posible "montar" un servidor de "SQL" en nuestra propia casa, aunque tengamos una dirección IP dinámica.

Pues bien, lo primero es lo primero. Cuando ejecutamos este tutorial tendremos varias posibilidades:


(pantalla de login con SQLServer)


(pantalla de login con MySQL)


(utilizar una base de datos de Access)

Una vez seleccionada la tipología, (en caso de SQLServer o MySQL se crea la base de datos de forma automática si ésta no existe) se muestra la siguiente pantalla:

Las "base de datos" es este tutorial consta únicamente de dos tablas:

  • Juegos
  • Categorias

Pulsando con el botón derecho del ratón sobre el listview de la pantalla anterior:

Si pulsáis en la cabecera de la lista podréis ordenar de forma ascendente o descendente la lista por aquel concepto.

La gestión de la tabla de categoría se realiza desde aquí:

Pulsando en el botón Categorías:

 

Lo "bueno" del asunto es que nos da igual si la base de datos es de Access,  si estamos conectados con un SQLServer o con un servidor de MySQL. La gestión de las tablas de "Juegos" y de "Categorías" es exáctamente igual independientemente de la tipología seleccionada.

Esto tiene que quedar muy claro, todos los "INSERTS", "SELECT", "UPDATE" y "DELETES" que vimos en el tutorial anterior serán los mismos, sea cual sea la tipología de base de datos seleccionada.

La gestión de las bases de datos la realiza el módulo ModADOcommon.vb (versión 1.2)

 

Utilizando ModADOcommon

Aquí podemos ver todos los miembros de este módulo:

Cómo ya sabréis, los miembros que tienen un "candado" son privados, mientras que el resto son miembros Públicos.

Lo primero que deberíamos hacer es usar un objeto de tipo sBDDStruct.

El módulo posee un objeto público de este tipo: MiBaseDeDatos
(de todos modos, vosotros podréis crear todos los objetos de tipo sBDDStruct que querráis, únicamente se ha creado el objeto MiBaseDeDatos por comodidad)

MiBaseDeDatos, en función de la tipología de la base de datos se inicializa de una formo u otra. Por ejemplo, para una base de datos de Access, se inicializaría así:

With MiBaseDeDatos
.TipoAcesso = eTipoBDD.OleDB
   With .SettingsOleDB
      .Nombre = NOMBRE_BASEDATOS & ".mdb"
      .Password = ""
      .Ruta = ""
   End With
End With

Para SQLServer, sería algo como esto:

With MiBaseDeDatos
.TipoAcesso = eTipoBDD.SQLClient
   With .SettingsSQLClient
      If cboAutenticacion.Text.EndsWith("sql server") Then
         .Autenticacion = sSQLServerAutenticacion.SQLServer
         With .CredencialesInicioSesion
            .InicioSesion = TxtInicioSesion.Text.Trim
            .Contraseña = TxtPassword.Text.Trim
         End With
      Else
         .Autenticacion = sSQLServerAutenticacion.Windows
      End If
      .Servidor = cboServidores.Text
      .NombreCatalogo = NOMBRE_BASEDATOS
   End With
End With

Esto que a priori puede parece "complicado" no lo es tanto, ya que ModADOcommon está completamente ENUMerado, por lo que a la que empieces a escribir With MiBaseDeDatos y luego escribas un punto ( . ) verás ya todos los posibles miembros de MiBaseDeDatos.

Los métodos más comunes serán estos 3:

Function CargarDataSet ( ) As DataSet

Esta función devolverá un DataSet con los datos de la consulta que se ha realizado.

Por ejemplo:

Dim ds As DataSet
Dim miSQL As String =  "SELECT nombre FROM CATEGORIAS"

ds = CargarDataSet(miSQL, MiBaseDeDatos)

En ds tendremos el DataSet de la consulta "miSQL".

Los DataSets siempre se "recorren" igual:

If ds.Tables(0).Rows.Count > 0 Then
   For i = 0 To ds.Tables(0).Rows.Count – 1
      xxxx = ds.Tables(0).Rows(i).Item("nombre")
   Next
End If

En xxxx tendremos el valor del campo "nombre" para aquel registro dentro del DataSet.

 

Function BDDExecuteReader ( ) As String

Este función devuelve un string o "nothing"  como respuesta a una instrucción SELECT.

Por ejemplo:

Dim s As String = ""
Dim miSQL As String"SELECT codigo FROM categorias WHERE nombre=’FPS’"

s = BDDExecuteReader(miSQL, MiBaseDeDatos)

s puede que sea "nothing" si no existe ninguna categoría donde el nombre sea FPS o bien, en s tendremos el valor del campo codigo donde el nombre de la categoria sea FPS.

 

Sub BDDExecuteNonQuery ( )

Este procedimiento se utilizará para ejecutar las consultas de tipo INSERT, UPDATE o DELETE

Por ejemplo:

Dim miSQL As String =  "INSERT INTO categorias (nombre) VALUES (‘FPS’)"

BDDExecuteNonQuery(miSQL, MiBaseDeDatos)

Pues como hemos visto, básicamente, con estos 3 métodos podremos controlar nuestras bases de datos.

Cómo véis, en todos estos métodos se pasa como argumento un objeto de tipo sBDDStruct, en los ejemplos anteriores era MiBaseDeDatos.
Si MiBaseDeDatos es de .Tipo = Access, aquel BDDExecuteNonQuery realizará en "INSERT" en una base de datos de Access, mientras que si es de .Tipo = SQLServer, realizará el "INSERT" en una base de datos de SQLServer.

Sin embargo, nosotros sólo hemos escrito:

BDDExecuteNonQuery(miSQL, MiBaseDeDatos)

Ya se encarga la propia función de usar unos "métodos internos" para "INSERTAR" en Access, SQLServer o incluso en MySQL.

En ModADOcommon tendremos también otros métodos bastante útiles:

GuardarQuerysEnLog = True

Con esa instrucción conseguiremos que se genere un fichero "log" (el nombre esta en NombreFicheroQuerys) con todas las sentencias de tipo "INSERT", "UPDATE" y "DELETE"

IniciarTransaccion (ByVal BDD As sBDDStruct)

Este método inicia una operacion de transacción. A groso modo las transacciones en SQL se utilizan para asegurar que una serie de sentencias SQL se han ejecutado TODAS correctamente. En caso de error, se "deshacen" automáticamente las sentencias SQL que estaban dentro de la transacción.

Function FormatoFecha ( ) As String

Esta función devolverá un string con el formato correcto para insertar una fecha en un campo "fecha" de la base de datos

Function FormatoBoolean ( ) As Object

Esta función devolverá un "object" con el formato correcto para insertar un valor booleano en un campo "booleano" de la base de datos

Function Comillas ( ) As String

Esta función devuelve un string formateado correctamente, eliminando las comillas simples en caso de que estas existan. Cuando necesitemos usar un campo "string" en cualquier consulta (ya sea SELECT, INSERT, UPDATE o DELETE) es recomendable usar la función Comillas para evitar sorpresas con textos con comillas (típico por ejemplo en nombres franceses o ingleses)

 

 

Utilizando SQL Server Management Studio Express

Cuando iniciamos este tutorial, si nos conectamos con un servidor SQLServer, lo primero que se mira es si la base de datos existe en dicho servidor (con MySQL ocurre lo mismo)

En caso de que la base de datos no exista en el servidor, se crea.

¿Cómo?

Si os fijáis, en la carpeta donde está el ejecutable hay dos ficheros:

CreateDataBase.sql
CreateTablas.sql

Estos dos ficheros no son mas que "sentencias" SQL (mas o menos largas) que crean la base de datos para este tutorial y sus correspondientes tablas.

Podéis abrirlos con el bloc de notas si queréis.

Estos dos ficheros, no están hechos "a mano". Los ha generado el Management Studio Express. (ver Tutorial 10 para mas info acerca del Management Studio Express)

Una vez que hemos creado (a "mano") nuestra base de datos desde el Management Studio Express, realizamos lo siguiente:

Al hacer esto, se crea una nueva consulta con toda la "sentencia" SQL para generar la base de datos.

Simplemente, la copiamos y la pegamos en el bloc de notas y la guardamos como CreateDataBase.sql.

Para la generación de las tablas, hacemos algo similar:

Esto nos abrirá un asistente que nos generára una "sentencia" SQL (mas o menos larga, depende de vuestra base de datos) para la generación de las tablas de aquella base de datos.

Si ahora miráis el código del tutorial 23, veréis que en el formulario FrmMain hay un método llamado CrearBaseDeDatos

Dicho método crea las bases de datos y sus correspondientes tablas en un SQLServer o en un MySQL si la base de datos no existe.

(Nota: Con MySQL se hace algo parecido con sus herramientas propias)

Aprovechando que estamos en el Management Studio Express vamos a ver cómo realizar "consultas" de forma "visual":

Para ello pulsamos aquí:

En la ventana de la consulta que aparecerá a nuestra derecha, pulsamos con el botón derecho del ratón y seleccionamos Diseñar consulta en el editor… o bien pulsamos en el icono de la barra de herramientas:

Nos aparecera un asistente y seleccionaremos las tablas que queremos incluir en nuestra consulta.

Finalmente tendremos algo como esto:


(haz click  para agrandar la imagen)

Desde esta pantalla, podemos "jugar" y modificar nuestra consulta de forma "visual"

Al pulsar el botón Aceptar, veremos que tenemos nuestra consulta:


(haz click para agrandar la imagen)

Ahora simplemente pulsa en el botón ! Ejecutar para ejecutar la consulta:

Si la consulta es correcta, puedes utilizar la "sentencia" SQL dentro de tú codigo de .NET para utilizarla en un "SELECT". Seguro que dicha sentencia no va a fallar, ni tiene errores de "sintaxis".

Puedes hacer algo parecido con cualquier sentencia de tipo "INSERT", "UPDATE" y "DELETE".

Cuando tengas "sentencias" SQL "grandes" es recomendable usar esta técnica, ya que te ahorras mas de dos horas de quebraderos de cabeza mirando por que demonios no "funciona aquella sentencia SQL".

Tal y como comenté en el Tutorial 10, el Management Studio Express es una herramienta tremendamente útil cuando se sabe utilizar.

 

 

Que comience la magia

Posiblemente todo esto está muy bien. Sin embargo lo realmente interesante cuando se tiene un SQLServer o un MySQL (u otro tipo de tipología "server") es poder que otras personas "interactúen" con nuestra base de datos, tanto si viven en Toledo, Cuenca, Sevilla o Seatle.

El mayor problema es que cómo somos de "la cofradía del puño cerrao" ( x-D ) no disponemos de un dirección IP fija. Y claro, esto es un problema.

Pues bien, vamos a ver que con un coste 0, podemos "montar" nuestro propio servidor de base de datos.
Sí, cómo lo oyes, coste 0.

Lo primero que tenemos que hacer es registarnos en www.no-ip.com

No-IP ofrece un servicio gratuito para convertir tu dirección IP dinámica en una "dirección" fija.


(haz click para agrandar la imagen)

una vez registrados, accederemos a Add a Host. Se nos mostrará una pantalla como esta:


(haz click para agrandar la imagen)

El tipo de Host tiene que ser DNS Host (A)

Nos crearemos un nombre para nuestro Host, por ejemplo ollydbg.no-ip.biz

Cuando te registras en No-IP se te descarga un cliente (No-IP DUC):

Este cliente se puede configurar para que se ejecute al iniciar Windows, o incluso mejor, que se ejecute como un "servicio de Windows". Configúralo como quieras.

Cuando se está ejecutando aparece en la barra de tareas:

Y podemos acceder a su configuración siempre que querramos:

Y voilá. con esto ya podremos hacer que desde fuera de nuestra red accedan a nuestra base de datos:

Para SQLServer, en Nombre del servidor usaremos lo siguiente:

ollydbg.no-ip.biz,puerto SQLServer

y para MySQL pues casi igual:

Con esto conseguimos, que aunque nuestra dirección IP sea dinámica (cada vez que enciendes y apagas el router tu dirección IP pública cambia) cómo ahora nos "llamamos" ollydbg.no-ip.biz, nos da igual si nuestra dirección cambia o no 😉

Obviamente, todo esto hay que hacerlo tambien en el firewall de windows, en el firewall del router, configurar el SQLServer para que acepte conexiones del exterior, configurar el puerto del SQLServer, etc.

Además, deberías crear un tipo de usuario que tenga permisos "restringidos", que no tenga acceso a las tablas "master", etc, etc.
(si quieres saber más acerca de todo esto mándame un MP, no te cortes, que no muerdo 😉

 

A fecha de hoy, podemos decir que este tutorial es el más complejo que se ha publicado en este blog (quizás más incluso que el Tutorial 8)

De todos modos, tenéis que tener en cuenta que lo explicado aquí puede ser aprovechado incluso para obtener alguna compensación económica. Existe un amplico mercado para "gestionar" aplicaciones que controlan bases de datos. El cómo, el qué y el dónde es algo que tendréis que sopesar vosotros.

 

Por último comentar algo acerca del código fuente de este tutorial:

Obviamente, si quieres probar localmente conectarte a TU SQLServer o a TU MySQL, tendrás que tener instalados SQLServer y/o MySQL en tu PC.

Además, si quiere "recompilar" el código, necesitaras incluir comoreferencia a tu proyecto la referencia MySQL.Data. Puedes encontar másinformación sobre esto en el archivo leeme.txt que está en la carpeta Dll para Referencia MySQL.Data

Links de interés:

Para SQLServer recomiendo la version SQLServer 2005 Express
El Management Studio Express 2005 lo podéis descargar de aquí.
Para MySQL recomiendo la versión MySQL 5.1 GA
Conectores de MySQL para .NET recomiendo la versión 5.2.7
Para las herramientas "visuales" de MySQL recomiendo las MySQL GUI Tools (que incluyen el MySQL Administrator 1.2, MySQL Query Browser 1.2, y  MySQL Migration Toolkit 1.1)

 

No me cansaré de repetirlo, pero el tema de la gestión de las bases de datos es bastante amplio y complejo, por lo que no os cortéis en comentar cualquier duda que tengáis!!!, el botón de comentar no muerde 😉

 

Saludos.
mov eax,ollydbg; Int 13h 

 

Descargar proyecto .NET Tutorial 23
(460 KB. Visual Studio 2008)

 

.NET Tutorial 22. Base de datos (Parte I)

Este espero que sea el primergranito de arena de una serie de tutoriales enfocados a la gestión y elmantenimiento de base de datos, ya bien sean bases de datos de Access, de SQL Server. En un futuro integraremos también MySQL.

Tal y como vimos en su día en el Tutorial 10, existen básicamente dos tipologías:

  • Arquitectura de "fichero" (por ejemplo Access)
  • Arquitectura de "servidor" (por ejemplo SQL Server, MySQL,…)

En dicho tutorial ya comentamos los pros y los contras de cada uno de estos sistemas.

Sin embargo existen una serie de conceptos que suelen ser comunes a ambos sistemas: el SQL (Structured Query Language).

El SQL por decirlo de alguna forma, en un "lenguaje de programación"con el cual se realizan diversas tareas en una base de datos,indistintamente si la base de datos es de Access, SQL Server, MySQL,etc.

Si bien es cierto que la inmensa mayoría de los motores de bases dedatos actuales soportan las "sentencias" SQL"estándar", puede quetengan particularidades puntuales.
Tampoco deberemos preocuparnos mucho por esto, ya que intentaremos en la medida de lo posible usar "sentencias" SQL "estándar".
De esta forma, dicha "sentencia" SQL, será válida tanto para una basede datos de Access, como para una base de datos de SQL Server, MySQL,etc.

IMPORTANTE: Bien, dicho esto, antesde empezar tiene que quedar claro como voy a usar las bases de datos eneste y en los sucesivos tutoriales:

NO usaré controles "bindeados" a ninguna base de datos.

Visual Basic.NET permite de alguna forma manejar las bases de datosde forma "visual" o "bindeada". Esto que a priori puede parecer unchollo y fácil de implementar (de hecho es facilísimo) a la larga daráproblemas en:

  • La implementación de la base de datos
  • Querer hacer algo "especial"

Nosotros lo que vamos a ver es como manejar la base de datos directamente.Podremos hacer con ella lo que nos de la real gana. Al final, veréisque no es tan complicado como parece o pueda parecer a priori.

Bien, visto esto, aclaremos una serie de conceptos básicos.

Normalmente una base de datos estará formada por una o más tablas.
A su vez, cada una de estas tablas estará formada por uno o mas campos.
Por último, una tabla está formada por "n" registros de campos.

Existen distintos tipos de campos. Deberíamos empezar a acostumbrarnos de utilizar el tipo correcto de campo.

Me explico. Supongamos que tenemos la tabla "Jugadores"
Supongamos que la tabla "Jugadores" tiene dos campos: "Nombre" y "Puntos"

A priori, en "Nombre" lo que meteremos será el "nombre" (Capitan Obvius 😉  del "Jugador"
Y en "Puntos" lo que meteremos serán los "puntos" del "Jugador"

El campo "Nombre" debería de ser de tipo "cadena". Y aún podríamos afinar mas.
Sisabemos que el nombre del jugador nunca será superior a 50 caracteres,podríamos definir que además de tipo "cadena" su longitud no seasuperior a 50. De esta forma "optimizamos" la base de datos

Ocurre tres cuartos de lo mismo con el campo "Puntos".
Dicho campo debería ser de tipo "numérico".
Existen distintos tipos de "números": bit, byte, word, float, real, etc.

¿Para que vamos a decir que "Puntos" es de tipo real (tropecientosbytes), cuando sabemos a ciencia cierta que los "Puntos nunca seránmayores a 9.999.999" (integer)

Sobre una base de datos, básicamente podremos hacer dos operaciones:

  • Consultas
  • Modificaciones

Con las "consultas" recuperamos información de las tablas, mientrasque con las "modificaciones" añadimos, borramos o actualizamosinformación en las tablas.

Dicho esto, tenemos que tener en cuenta que existen cuatro instrucciones básicas en el "lenguaje" SQL:

  • Selección (SELECT)
  • Inserción (INSERT)
  • Actualización (UPDATE)
  • Borrado (DELETE)

Las instrucciones de selección (SELECT) pertenecen a operaciones deconsulta, mientras que la inserción, actualización y borrado pertenecena las operaciones de modificación.

Por otro lado en la operación de selección pueden ocurrir dos cosas:

  • La consulta devuelve un conjunto de datos (a esto lo llamaremos DataSet)
  • La consulta sólamente devuelve un único valor (devuelve un campo)

Básicamente una "sentencia" en lenguaje SQL es una "cadena de texto"que le indica al motor de la base de datos que se va a realizar unaoperación de consulta o una operación de modificación.

Las "sentencias" en lenguaje SQL tienen su propia sintáxis. Existenlibros y libros y más libros sobre esto. Sería imposible recopilarlastodas en este blog. Os mostraré las más "básicas" (nada de INNER JOINS, GROUP, HAVING, UNION, etc)

SELECCIÓN

DataSet = SELECT * FROM [Jugadores]
DataSet = SELECT [nombre],[puntos] FROM [Jugadores]
DataSet = SELECT * FROM [Jugadores] ORDER BY [Nombre] DESC
Campo = SELECT [puntos] FROM [Jugadores] WHERE [Nombre] = ‘ollydbg’

Cómo véis las tres primeras sentencias devuelven un "conjunto de datos"(DataSet), mientras que la última sentencia devuelve un único campo(puntos en esta caso)

SELECT * FROM [Jugadores] se "traduce" a algo cómo:

"Seleccioname todos los campos de todos los registros de la tabla jugadores"

SELECT [nombre],[puntos] FROM [Jugadores] se "traduce" a algo cómo:

"Seleccioname el nombre y los puntos de todos los registros de la tabla jugadores"

SELECT * FROM [Jugadores] ORDER BY [Nombre] DESC se "traduce" a algo cómo:

"Seleccioname todos los campos de todos los registros de la tablajugadores, pero hazlo ordenandome el resultado por el campo nombre yademás de forma descendente"

Por último, SELECT [puntos] FROM [Jugadores] WHERE [Nombre] = ‘ollydbg’ se "traduce" a algo cómo:

"Devuelveme los puntos del jugador que tiene por nombre ollydbg"

SELECCIÓN SUMA 

campo =  SELECT SUM ([puntos]) AS TotalPuntos FROM [Jugadores] WHERE [Nombre] = ‘ollydbg’

Esta sentencia se traduce cómo: De la tabla jugadores, súmame todoslos puntos de todos los registros donde el nombre del jugador seaollydbg

Al igual que la SUMa, se puede calcular la desviación típica (AVG),que nos devuelva el valor mínimo (MIN), el valor máximo (MAX) o inclusoque nos cuente (COUNT) cuantos registros hay afectados.

 

INSERCIÓN

INSERT INTO [Jugadores]
   ([puntos]
   ,[nombre]
   ,[mapeado])
VALUES
   (100000
   ,’ollydbg’
   ,’map_lvl001′
   )

Esta sentencia SQL lo que hace es crear un nuevo registro en la tabla jugadores.
Lo que está indicando, es que en la tabla jugadores inserte un nuevo registro donde los campos serán:
campo puntos = 100000
campo nombre = ollydbg
campo mapeado = map_lvl001


ACTUALIZACIÓN

UPDATE [Jugadores]
   SET [puntos] = 999999
      ,[cambiado] = ‘True’
WHERE
   [nombre] = ‘ollydbg’ AND [mapeado] = ‘map_lvl001’
 

Esta sentencia SQL lo que hace es actualizar todos aquellosregistros de la tabla jugadores, donde el nombre del jugador seaollydbg y el mapeado sea map_lvl001. Para todos estos registros dondese cumplan estas dos condiciones, se modificará el valor del campopuntos y el campo cambiado, por los valores 999999 y Truerespectivamente.


BORRADO

DELETE FROM [Jugadores]

Esta sentencia borra todos los registros de la tabla jugadores

DELETE FROM [Jugadores] WHERE [nombre] = ‘ollydbg’

Esta sentencia borra todos los registros de la tabla jugadores donde el nombre sea ollydbg.

BORRADO con Truncado

TRUNCATE TABLE [Jugadores] 

Esta sentencia borra todos los registros de la tabla jugadores, peroademas, inicializa todos aquellos campos de tipo "autonumérico"

BORRADO de la tabla

DROP TABLE [Jugadores]

Esta sentencia  no borra los registros. Borra la TABLA de la base de datos.

 

Bueno, pues como habéis visto básicamente con las 4 intrucciones(SELECT, INSERT, UPDATE y DELETE) podremos manejar nuestra base dedatos.

Ya he dicho que de sentencias SQL hay para parar un tren. Estapágina en castellano está bastante bien por si queréis profundizar unpoco mas en el tema: http://sql.1keydata.com/es/

Yo he llegado a ver sentencias SQL de más de 2000 líneas, así que no desesperéis.

También existen lo que se denomina procedimientos almacenados. Es un tema muy intersante, pero que trataremos en sucesivos tutos.

 

Pues bien, todo lo que hemos explicado en esta entrega lo realizaremoscon módulo que vengo utilizando desde hace ya bastante tiempo.

En concreto el módulo se llama ModADOcommon.vb y lo podéis ver aqui: ModADOcommon.

Antes de que nadie se lleve las manos a la cabeza al ver todo "ese engendro" de código, ya os diré que es tremendamente simple de usar.  Todo está ENUMerado, de esta forma, usarlo es casi un juego de niños.

Además, no tenéis porque saber cual es el código interno de la función, por ejemplo CargarDataSet ( ) . Vosotros únicamente usáis la función y arreando. 😉

En las próximas entregas veremos como se usa dicho módulo.

 

Saludos.
mov eax,ollydbg; Int 13h  

Descargar ModADOcommon.vb
(34 KB. Visual Studio 2008)

 

.NET Tutorial 21. Creando interfaces amigables: AutoComboBox

Cuando desarrollamos una aplicación tenemos que intentar en la medida de lo posible "ponérselo fácil" al usuario final.
Hay una máxima: El usuario siempre es "tonto" (con cariño, eh! 😉 Pero si además si para hacer una tarea tiene que pulsar 3 botones cuando la podría hacer sin pulsar ninguno, los que somos "tontos" somos los developers 😉

Hoy vamos a ver cómo podemos facilitar la entrada de datos a nuestros queridos usuarios.

Es muy común tener aplicaciones donde se solicita al usuario que introduzca una serie de códigos: clientes, proveedores, productos, códigos de cuentas corrientes, y un sin fín de cosas que podéis imaginar.

Podemos diseñar nuestras entradas de datos de dos formas:

  • Con una caja de texto donde el usuario introduce el código
  • Con un botón que al pulsarlo nos muestra una "lista" de los posibles códigos y el usuario selecciona el código que quiere usar

Con un poco de suerte, si el usuario tiene "buena memoria" se acordará que el código TRI098_FOR2187P pertenece al producto "trigo forrajero 41%".

Cómo véis ya hay que tener una buena memoria de coj*nes. 😉

Pues bien, vamos a ver que es posible diseñar otra forma mucho más cómoda para el usuario, sin "obligarle" a tener buena o mala memoria.

El tema es utilizar un combobox en lugar de un textbox, pero con la particularidad de que "cargaremos" los posibles valores que se podrán utilizar en el combobox, de tal forma, que a medida que el usuario escriba el código se le mostrarán los posibles códigos correctos.

Cómo ya sé que me explico fatal os los enseñaré con fotos.

Supongamos que tenemos esto:

Vamos a suponer que queremos introducir "antonio"

Cuando pulso la "a" dentro del combobox, automáticamente se muestra esto:

 

Si ahora pulso la "n" se muestra esto:

y finalmente si ahora pulso la "t" se muestra esto:

Cómo véis, el usuario "no se tiene que acordar", ya que en tiempo de ejecución se le va guiando.

También podemos usar el propio combobox a modo de "lista rápida":

 

Bien, y esto…¿Cómo lo hacemos?

Pues como siempre es más simple de lo que parece.

Lo único que tendremos que hacer será tener un "array" con los items que queremos "cargar" en el combobox y utilizar estos 3 métodos:

With ComboName
   .Items.Clear()
   .Items.AddRange(miArray)

   .AutoCompleteMode = AutoCompleteMode.SuggestAppend
   .AutoCompleteSource = AutoCompleteSource.ListItems
End With

El método .Items.AddRange lo que hace es "añadir" el array miArray al combobox
Y los métodos .AutoCompleteMode y .AutoCompleteSource los pondremos cómo el código de arriba.

Y listo, con solo esas 3 líneas ya consigues el efecto que hemos visto en las imagenes anteriores.

"miArray" lo puedes llenar con y como quieras.

Imagínate que tienes un DataSet que lo rellenas con el siguiente SQL:

SELECT codigo FROM clientes ORDER BY codigo ASC

De esa forma puedes tener un combobox de "clientes" que tienes en tu base de datos.

 

Pues cómo dijo no se quien, con esto y un bizcocho, nos vemos a las ocho 😉

 

Saludos.
mov eax,ollydbg; Int 13h  

Descargar proyecto .NET Tutorial 21
(39 KB. Visual Studio 2008)

 

.NET Tutorial 20. Sólo existen 10 tipos de personas

Si al leer el título de este post has pensado "1","2","3",…,"10" enhorabuena, quizás te interese este post. Si por el contrario al leer el título de este post has pensado "2", ya sabes de que vamos a tratar aquí 😉
(por cierto, mira que hay que ser "rarito" para haber pesando "2"…muahahaha 😉

A todo esto, la frase completa es: "Sólo existen 10 tipos de personas: las que saben binario y las que no"

Posiblemente a estas alturas, lo que voy a explicar es algo que ya daba por sabido.

En nuestro quehacer diario, en el 99.999….(muchos 9 aquí) % contamos en el sistema decimal.

Sin embargo, en el mundo de la informática e ingeniería en general, existen otros sistemas de numeración, siendo los más conocidos, el sistema binario, hexadecimal, BCD y octal.

En este "tuto" haremos incapié en el sistema binario

En el sistema decimal, cualquier número puede representarse con los valores 0,1,2,3,4,5,6,7,8 y 9

En un sistema binario, cualquier número puede representarse únicamente con los valores 0 y 1

En un sistema hexadecimal cualquier número puede representarse con los valores 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E y F

Sistema Binario.

Alguno/a puede estar pensando cómo narices puede escribirse "algo" únicamente con ceros y unos.

En un sistema binario, la base es 2.

Algunos conceptos básicos:

Bit: unidad mínima de un sistema binario
Byte: Conjunto de 8 bits, cuyo valor oscila entre 0 y 255
Nibble Inferior: Conjunto de los 4 bits de la parte derecha de un Byte
Nibble Superior: Conjunto de los 4 bits de la parte izquierda de un Byte
LSB: Bit menos significativo. En un Byte esto representa el bit de la parte derecha de un Byte
MSB: Bit más significativo. En un Byte esto representa el último bit de la parte izquierda de un Byte
Word: Conjunto de 2 Bytes, es decir 16 bits.

Bien, ¿Cómo se representan los números en binario?

Supongamos que queremos representar el número 155 en binario.

————————————————-
| 128 | 64  |  32 | 16  |  8  |  4  |  2  |  1  |
| 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 |
————————————————-
|  1  |  0  |  0  |  1  |  1  |  0  |  1  |  1  |
————————————————-

En un sistema binario, el bit de menor peso vale 2^0, el siguiente 2^1, el siguiente 2^2 y así sucesivamente. Por eso según la bibliografía que consultéis, a veces el bit de menor peso se le llama Bit 0, donde un Byte tiene Bit 0, Bit 1, Bit 2…Bit 7.


Si un Bit está a 1 se computa su valor, si está a 0 no se computa su valor. En el ejemplo anterior vemos que los bits que están a 1 son:

2^7 + 2^4 + 2^3 + 2^1 + 2^0
o lo que es lo mismo:
128+16+8+2+1
que sumado es 155

Por lo tanto, 155 en binario es 10011011

Siguiendo este método puedes comprobar que 11111111 en binario es 255:

————————————————-
| 128 | 64  |  32 | 16  |  8  |  4  |  2  |  1  |
| 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 |
————————————————-
|  1  |  1  |  1  |  1  |  1  |  1  |  1  |  1  |
————————————————-

2^7 + 2^6 + 2^5 + 2^4 + 2^3 + 2^2 + 2^1 + 2^0 =
128 +
64 + 32 + 16 + 8 + 4 + 2 + 1 = 255

Existen algunos operadores "intersantes" en .NET que nos permiten trabajar directamente con bits. Estos operadores son el >> y el <<

El operador >> lo que hace es rotar los bits hacia la derecha (dividir)
Mientras que el operador << lo que hace es rotar los bits hacia la izquierda (multiplicar) 

Por ejemplo, si en .NET hacemos esto:

34 >> 1

el resultado es 17

¿Por qué 17?

Tal y como hemos dicho, el operador >> rota los bits hacia la derecha:
34 en binario se representa como:
100010
Al "rotar" los bits hacia la derecha lo que hacemos es "mover" todos los bits una posición hacia la derecha. Se "mete" un 0 por la izquierda y el LSB se pierde:
010001

010001, o lo que es lo mismo 10001 en notación decimal es 17.

Si hacemos esto:

34 >> 3

Lo que haremos es rotar 3 veces los bits hacia la derecha:

34: 100010

Si rotamos 3 veces nos queda:

000100, que en notación decimal equivale a 4

Cómo ves, los 3 bits de menor peso "se pierden"

Ocurre lo mismo con el operador <<. En este caso, los bits se rotan hacia la izquierda (añadiendo 0 a la derecha)

34 << 1

El resultado es: 68

34: 0100010
68: 1000100

Cómo véis al rotar hacia la izquierda, metemos un cero por la derecha

Todo esto se usaba "en la época de los dinosaurios" para multiplicar (<< / SHL ) por 2,4,8,16,32,64,128 o para dividir (>> / SHR ) entre 2,4,8,16,32,64,128

Estas operaciones eran (y son) muchísimo más rápidas que las multiplicaciones o divisiones "normales".


.NET
dispone de una serie de métodos para convertir a distintas notaciones:

Dim i As Integer = 33
Dim binary As String = Convert.ToString(i, 2)
Dim hex As String = Convert.ToString(i, 16)
Dim binaryToInt As Integer = Convert.ToInt32(binary, 2)
Dim hexToInt As Integer = Convert.ToInt32(hex, 16)

Cómo podéis ver, la clase Convert nos permite pasar fácilmente de una notación a otra.

Quizás al finalizar esta entrada te hayas quedado "igual". Yo considero que es "básico" saber que es un byte, un bit y como trabajar con ellos. Las casas han de comenzarse por los cimientos, y esto es realmente los "cimientos" de la programación, ya sea en .NET, en C, en Pascal, en Java, en ensamblador, en PHP, en ASP, en Phyton, etc.

 

Saludos.
mov eax,ollydbg; Int 13h

[Utilidad] OllySecrets v.2

Os presento la segunda versión del programa OllySecrets.
Con esta segunda versión, además de poder ocultar un texto dentro de una imagen, también podréis ocultar cualquier tipo de archivo dentro de una imagen. (WTF!!!, PQC!!!)

Esto quiere decir que puedes tener por ejemplo el archivo mifoto.png y "meter dentro" de esa foto, el archivo bohemian_rhapsody.mp3. Lo "bueno" del asunto es que podrás seguir abriendo mifoto.png con photoshop, Gimp, Paint.NET, etc.

Aunque lo más cachondo es lo siguiente:
Imagínate que tienes una imagen que se llama paisaje.png. Dentro de paisaje.png "escondes" el archivo bohemian_rhapsody.mp3. Y ahora coges ese archivo paisaje.png y lo "escondes" en el archivo mifoto.png.
Total…que el archivo mifoto.png tiene una imagen "escondida" y a su vez, dicha imagen escondida tiene un mp3. 

¿Qué no te lo crees?….Por favor, sigue leyendo 😉

Podréis comprobar que he variado ligeramente el interfaz del programa con respecto a la versión 1 dándole unos colores "made in meristation": 


(haz click para agrandar la imagen)

Aquí podremos ver dos cosas nuevas:

  • Al lado del nombre de la imagen que tenemos seleccionada, aparecerá una cantidad. Dicha cantidad expresa el tamaño máximo del archivo que podemos ocultar en dicha imagen. Obviamente cuanto más grande (en resolución) sea la imagen seleccionada, mayor será el tamaño del fichero que podremos meter dentro. Por contrapartida, cuanto más grande sea el tamaño del fichero que queremos meter dentro, el proceso de "ocultación" será mas lento.
  • Podéis ver que existe una casilla donde se puede seleccionar el archivo que queremos esconder. Si no queréis esconder ningún archivo en la imagen seleccionada, simplemente dejar dicha casilla en blanco.

La recuperación ya bien sea del texto oculto o del archivo oculto se realiza automáticamente cuando se selecciona una imagen:


(haz click para agrandar la imagen)

En este caso, podemos ver que la imagen seleccionada tiene un texto oculto y un archivo oculto (morning.mid).
En caso de que exista un archivo oculto, simplemente pulsa en el botón Guardar para "extraer" dicho archivo de la imagen y guardarlo en tú disco duro.

 

Finalmente, podéis acceder a la pantalla de parámetros:


(haz click para agrandar la imagen)

Se han incluído dos nuevos parámetros que no existían en la versión 1:

  • La carpeta donde se guardarán los archivos "ocultos" cuando pulses sobre el botón Guardar
  • Una opción que abrirá automáticamente la carpeta anterior cuando se guarde un archivo oculto

 

Cómo sé que hay bastante gente que aún no "entiende" que es lo que hace o deja de hacer OllySecrets os mostraré dos ejemplos que podéis descargar de internet.

Ejemplo 1:

Si os descargáis la siguiente imagen (haz click para verla a tamaño real, luego sobre la imagen haz click con el botón derecho y selecciona Guardar imagen como… Y guárdala en formato PNG en tú disco duro):

Pues bien, si utilizáis OllySecrets sobre esa imagen veréis que tiene escondida esta otra imagen:

Ejemplo 2:

Ahora descargaos la siguiente imagen, usando el mismo método que la imagen anterior:

A priori  podríais pensar que se trata de la "misma" imagen que antes, pero veréis que no es así.
Si ulizáis OllySecrets con esta imagen veréis que tiene escondida esta otra imagen:

Pues bien, si ahora volvéis a utilizar OllySecrets con la imagen "escondida" podréis comprobar que dicha imagen tiene también un texto oculto y un fichero midi, fichero que podréis abrir con Windows Media Player, por ejemplo.

Es decir, la imagen "original" de Lost tenía oculta otra imagen y a su vez dicha imagen tenía oculto un fichero midi. KE-ME-LOL!

 

Visto lo visto, ya podéis imaginaros la de cosas que podéis "esconder" en vuestras imagenes gracias a esta "¿utilidad?".

¿Quién huviése dicho que dentro de aquella imagen había un fichero *.ZIP que contenía las instrucciones de la receta "virutas de foie-gras de pato con judías verdes, trufa negra y almendra tierna marinado con vichyssoise de mejillones de roca a las finas hierbas con un toque de albahaca"?

Fans de la conspiranoia, venid a mi!!! 😉

 

Cómo siempre, espero vuestros comentarios, criticas constructivas, y/o sugerencias.

Saludos.
mov eax,ollydbg; Int 13h 

 

Descargar proyecto OllySecrets (versión 2)
(53 KB. Visual Studio 2008. NET Framework 3.5) 

 

PD: El programa necesita .NET Framework 3.5 para funcionar (incluído de serie en Vista y Windows 7)

PD 2: Para que los archivos adjuntos no se "corrompan" asegúrate que el ancho y alto de la imagen contenedora sea múltiplo de 2 (y si pueden ser múltiplos de 10 mejor aún)

.NET Tutorial 19. Usando ArrayLists

Seguramente a estas alturas, los lectores/as de este blog ya sabrán como usar Arrays, sobre todo si habéis seguido y estudiado el código fuente de los ejemplos que he ido publicando o si habéis seguido lo explicado en el .NET Tutorial 5.

Hoy os mostraré "otra" forma de manejar arrays. Dependiendo de la aplicación este "nuevo" método es tremendamente más fácil de usar que el que vimos en el Tutorial 5.

Tal y cómo hemos visto hasta ahora, los arrays los declarabamos así:

Dim miArray (20) As String

O si teniamos una estructura lo declarabamos así:

Private Structure sPersona
   Dim Nombre As String
   Dim Apellido As String
   Dim Edad As Short
End Structure

Dim miArray (20) As sPersona

Y para acceder a los elementos lo hacíamos asi:

miArray (8) . Nombre = "Irene"
miArray (8) . Apellido = "Junquera"
miArray (8). Edad = 27

La cosa se "complicaba" un poco más si teníamos arrays "redimensionables"

Bueno, todo esto lo vimos en el Tutorial 5 y creo que quedó bastante claro.

Bien, hoy vamos a ver que existe una forma mucho más fácil de realizar este tipo de contrucciones. Para ello utilizaremos los ArrayList.

Por definición un ArrayList es una "colección" de objetos de tamaño dinámico.

Al tratarse de una "colección" tendremos a disposición algunos métodos interesantes, tales como .Add, .Remove, .Sort, etc.

Supondremos que tenemos la siguiente estructura:

Private Structure sPersona
   Dim Nombre As String
    Dim Apellido As String
    Dim Edad As Short
End Structure

Y definimos nuestro "array" de "Personas" así:

Private ListaPersonas As ArrayList

Antes de "meter" cosas dentro del arraylist hay que inicializarlo, lo haremos así:

ListaPersonas = New ArrayList

Una vez inicializado el ArrayList, ya podemos trabajar con él

Añadir elementos al ArrayList

Un arraylist contiene elementos de tipo "Object", esto quiere decir que podremos "meter" en el ArrayList cualquier cosa imaginable que querramos.

En el caso de los Arryas "normales" cuando los definíamos ya estabamos indicando que ibamos a "meter" dentro del array:

Dim miArray (20) As String

miArray contiene "objetos" de tipo String

Pues bien, ¿Cómo narices meto "cosas" en un ArrayList?. Pues simple, así:

Dim itemPersona As sPersona

With itemPersona
   .Apellido = "Pedrerol"
   .Nombre = "Josep"
   .Edad = 51
End With
ListaPersonas.Add (itemPersona)

Cómo véis, me defino un "objeto" del tipo de dato que quiero añadir al ArrayList, en este caso, he definido un "objeto" itemPersona, que es de tipo sPersona. Al usar el método .Add ( itemPersona) lo que hago es "meter" ese objeto en el ArrayList.

La gracia del asunto está en que a continuación podemos hacer lo siguiente:

With itemPersona
   .Apellido = "Pulido"
   .Nombre = "Julio"
   .Edad = 51
End With
ListaPersonas.Add (itemPersona)

Al hacer esto, el arraylist tendrá 2 elementos, "Josep Pedrerol 51" y "Julio Pulido 51"

Cómo véis lo único que hay que hacer es usar el método .Add ( item ). El compilador ya se encarga internamente de hacer los "redims" y cosas "raras".

Borrar elementos del ArrayList

Pues si hemos visto que existe un método .Add ( item ) para añadir un elemento al ArrayList, podeis imaginar que también existe un método .Remove ( item ) para "quitar" ese "item" del ArrayList.

Lo "interesante" del asunto es que todos los elementos se "mueven" hacía arriba automáticamente al hacer un .Remove ( item )

Suponed que tenemos este ArrayList:

1: "pepe"
2: "juan"
3: "luis"
4: "edu"

Es decir, es un ArrayList de 4 elementos
Si ahora hacemos un .Remove ( "juan" ), el ArrayList nos quedará así:

1: "pepe"
2: "luis"
3: "edu"

Cómo véis, no hemos tenido que hacer "nada" para que el ArrayList se "ajuste" automáticamente.
Prueba de hacer esto con los Arrays ( ) "normales" y luego me cuentas (que si tener que montar un array "temporal", que si recorrer todo el array, bufff…menudo follón 😉

Pués bien, para borrar un "item" lo hacemos así:

Dim itemPersona As sPersona

With itemPersona
   .Apellido = "Roncero"
   .Nombre = "Tomás"
   .Edad = 53
End With
ListaPersonas.Remove  ( itemPersona )

Recorrer todos los elementos del ArrayList

Ahora que ya sabemos cómo añadir y borrar "items" del ArrayList quizás te interese recorrer todo el ArrayList para mostrarlos en una lista, cargarlos en un combobox, etc.

Simplemente tendremos que usar un bucle For Each:

For Each itemPersona As sPersona In ListaPersonas
Debug.Print(itemPersona.Nombre & " " & itemPersona.Apellido & ", " & itemPersona.Edad)
Next

Cómo véis es realmente simple. 😉

Ordenando los elementos del ArrayList 

Este quizás es el punto más interesante del "asunto".
Los ArrayList poseen un método llamado .Sort que hacen que ordenar un determinado ArrayList sea casí trivial.

En nuestro ejemplo podemos ordenar nuestro ArrayList por "apellidos" de forma ascendente o descendente y tambien por "edades".

Para ello procedemos así:

Dim myComparer = New clsOrdenarApellido
ListaPersonas.Sort ( myComparer )

Donde clsOrdenarApellido es una clase que implementa la interfaz IComparer

Para ordenar de forma "descendente" por apellidos, tan simple como esto:

Dim myComparer = New clsOrdenarApellido
myComparer.OrdenAscendente = False
ListaPersonas.Sort ( myComparer )

Y para ordenar por "edades", pues así:

Dim myComparer = New clsOrdenarEDAD
ListaPersonas.Sort ( myComparer )

donde en este último caso, clsOrdenarEDAD también es una clase que implementa la interfaz IComparer

Cómo véis es tremendamente fácil de usar y nos "olvidamos" de "redimensionar", saber si se empieza por el elemento 0 o por el 1, etc.

 

Aquí podéis ver el código completo del ejemplo que hemos usado para este tutorial: Código completo

Lo único que tenéis que hacer es crearos un formulario nuevo con el nombre Form1 y meter 6 Buttons con los siguientes nombres:

  • BtnAñadir
  • BtnMostrar
  • BtnBorrar
  • BtnOrderApellidoASC
  • BtnOrderApellidoDESC
  • BtnOrderEdadASC

Y "pastear" el Código completo en vuestro Form1.

Bueno, pues de momento, esto es todo

 

PD: ¿Morderá el botón de comentarios?…Tendré que preguntar a los jefazos de gamefilia 😉

Saludos.
mov eax,ollydbg; Int 13h 

 

Cómo añadir el Messenger en tu blog

Cómo habéis podido comprobar he estado realizando "reformas" en el diseño del blog. Básicamente he añadido unos bloques laterales para acceder más rápido a una serie de contenidos.

En uno de los enlaces del bloque lateral he incluido un enlace que quizás a alguien le pueda ser interesante. Se trata de una opción que permite a cualquiera que se comunique con nosotros a través de nuestra cuenta de Messenger.

Lo bueno es que funciona via "html" por lo que ni siquiera es necesario tener una cuenta de messenger para que se comuniquen con nostros.

Los pasos que hay que hacer son muy simples:

  1. Tienes que ir a esta dirección (http://settings.messenger.live.com/Applications/WebSettings.aspx) y activar la casilla que pone: Permitir que los usuarios de sitios web vean mi estado y me envíen mensajes.
  2. A continuación debes pulsar donde pone Crear HTML. Ahi seleccionas el aspecto que quieres dar a la ventana del messenger, el tamaño y el color. Una vez seleccionado eso, verás que abajo aparece un código en lenguaje HTML que será el que tienes que copiar en tu blog

"Lamentablemente" los blogs de gamefilia no permiten la etiqueta <iframe> en los bloques laterales (bueno, ni en los laterales ni en el cuerpo de los post):

Por ese motivo buscando por internet ví que blogger si que permitía el uso de la etiqueta <iframe> en sus "Gadchets".

Lo único que tuve que hacer es crear un blog alli y modificar ligeramente la plantilla por defecto, el resultado es este
(Obviamente, si no estás "en linea" no podrás "hablar").

La "ventaja" de hacer esto, es que si tú no tienes messenger (en aquel PC) puedes hablar mediante messenger con la persona que haya hecho "este invento".

Además me pareció bastante curioso. 😉

 

Saludos.
mov eax,ollydbg; Int 13h