Você está na página 1de 26

Acceso a MySQL desde Visual C++

Ivan Cachicatari Poma


http://www.latindevelopers.com/ivancp/ ivancp@latindevelopers.com

Versin 1.5, 23 Marzo 2007 o

El presente articulo muestra paso a paso como crear una pequea aplicacin en n o Visual C++ 6.0 con acceso a una base de datos de MySQL, utilizando librer as prove das e incluidas en las distribuciones del motor de base de datos MySQL.

Indice

1. Introduccin o 2. Preparar los datos 3. Crear el proyecto 4. Conguraciones y otros detalles 5. La conexin a MySQL o 6. Preparar el dilogo a 7. Modicar, Agregar, Eliminar datos 8. Comentarios, conclusiones, recursos , etc..

3 3 4 6 9 13 17 25

1. Introduccin o
Las diferentes alternativas que tenemos los desarrolladores para implementar aplicaciones de acceso a base de datos nos hacen pensar dos veces antes de elegir el cmo y con qu lenguaje nos conectamos a una base de datos. El mismo dilema se o e presenta al elegir el gestor de base de datos, al principio es tedioso, pero cuando uno empieza a tener conanza no duda en seguir utilizando su gestor favorito. Este tutorial aunque pequeo intenta mostrar la puerta al mundo de posin bilidades que existe al utilizar Visual C++ como lenguaje de programacin y o MySQL como gestor de datos. Les guiar paso a paso como deben construir su e primera aplicacin de acceso a base de datos con Visual C++ utilizando las libro er API escritas en C que provee MySQL. as Empezaremos alistando los datos sobre un servidor de datos MySQL ya instalado y corriendo para luego crear un proyecto en Visual C++ 6.0 basado en dialogo el cual conguraremos inicialmente para utilizas las librer API de MySQL y as nalmente escribiremos unas cuantas lineas de cdigo. o

2. Preparar los datos


Para ste tutorial prepar una tabla que en realidad es un extracto de otra tabla e e que tengo por ah sta tabla contiene datos sucientes para experimentar con , e aplicacin que vamos a desarrollar, la tabla contiene campos para almacenar datos o basicos de una empresa como RUC, Razn Social, Email, etc. El comando SQL o de creacin de la tabla y tambien los datos estan en el archivo prueba db.sql o que pueden descargar de la direccin de Internet que se indica al nal del tutorial. o Este archivo de comandos SQL deben ejecutarlo en el servidor MySQL que tengan instalado. Puede usted elegir la mejor forma de hacerlo. Le recomiendo que lo haga mediante linea de comando, es menos tedioso y mucho mas rpido: a Comando para ejecutar el archivo SQL utilizando la linea de comando: # mysql -u root < prueba_db.sql Si el usuario root necesita password: # mysql -u root -p < prueba_db.sql

Listado 1: Script de la tabla que contiene los datos en prueba db.sql 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: CREATE DATABASE prueba_db; USE prueba_db; CREATE TABLE empresas ( RUC char(11) NOT NULL, RazonSocial varchar(80), Direccion varchar(60), Email varchar(50), Web varchar(60), PRIMARY KEY (RUC), KEY RazonSocial (RazonSocial) );

3. Crear el proyecto
Posiblemente usted ya conozca el proceso de crear una aplicacin basada en diloo a go con Visual C++, si es asi entonces contine con el siguiente paso. u

Imgen 1. Dialogo de nuevo proyecto a

Bueno... procedemos a crear el proyecto mediante el AppWizard del Visual C++ 6.0, accedemos al men: File -> New presionamos la combinacin [Ctrl] u o o + [N]. Aparecer un dilogo parecido al de la Imgen 1. a a a Elegimos el tipo de proyecto MFC AppWizard (.exe), para el proyecto eleg el 4

nombre TestMySQL, esto automticamente crear una carpeta con todos los a a elementos necesarios, es recomendable que esta carpeta est situada en un lugar e estratgico, por un principio de orden. e En el siguiente dialogo elegimos el tipo de aplicacin Basada en dialogo (Dio alog Based). Ya que este es un proyecto cuyo objetivo es demostrar el uso de las librer API de MySQL solo crearemos un proyecto de ese tipo por que no necesias tamos todo el cdigo que genera para las otras aplicaciones, en caso de que tenga o que crear proyectos mas grandes puede escoger las otras opciones. Ver Imagen 2. Una aplicacin Dialog Based bsicamente genera tres clases: una clase derivada o a de CWinApp que ser la aplicacin propiamente dicha, otra clase derivada de a o CDialog acompaada de un formulario en blanco para dar rienda suelta a nuestra n imaginacin y otra clase derivada de CDialog que contiene informacin acerca de o o la aplicacin. o

Imgen 2. AppWizard:Creando proyecto basado en dialogo a

Los siguientes dilogos de opciones son irrelevantes a lo que necesitamos as es a que click en Finish y nos olvidamos de este asunto de una buena vez. Aparecer un a dilogo que nos informar lo que estamos generando. Click en OK y con esto a a terminamos ste Paso. e

4. Conguraciones y otros detalles


Antes de compilar el proyecto debemos asegurarnos que las conguraciones de acceso a los archivos de la librer API MySQL estn correctamente establecidas. a e Al instalar una distribucin de MySQL sobre Microsoft Windows debemos ino stalar tambin los Componentes de Desarrollo (Developer Components) espec e camente la opcin C Include Files/ Lib Files (Archivos de cabecera y librer o as). Ver Imgen 3. a

Imgen 3. Instalacin de MySQL incluyendo las librer API a o as

En una instalacin, por defecto, se instalan las librer en rutas espec o as cas:

Archivos de cabecera c:\Archivos de Programa\MySQL\MySQL Server 5.0\include Archivos de librer (.lib) con informacin para poder depurar a o c:\Archivos de Programa\MySQL\MySQL Server 5.0\lib\debug Archivos de librer (.lib) optimizados a c:\Archivos de Programa\MySQL\MySQL Server 5.0\lib\opt

La carpeta debug contiene librer para compilar nuestro proyecto en el modo as Debug y la carpeta opt contiene los archivos para el modo Release. El primer modo (Debug) nos facilita la vida en la etapa de desarrollo pudiendo detectar problemas 6

y errores para poder corregirlos. El segundo modo de compilacin se utiliza cuando o estemos seguros que no hay mas problemas y generamos un ejecutable liviano y listo para el usuario nal; aunque siempre se presenta algun maldito problema que no supimos prevenir. Nota: No es necesario que intalen el servidor de datos completo, es posible que ustedes tengan un servidor MySQL corriendo en alguna otra parte de su red. Para ello pueden copiar las carpetas indicadas arriba desde otra instalacin o o simplemente instalar slo los Developer Components o Dejemos el asunto ah sigamos con la conguracin de las rutas. Ahora con, o guraremos Visual C++ para que agregue stas rutas a su lista de carpetas de e busqueda de archivos de inclusin (Include Files). Entonces debemos acceder a la o Conguracin del Proyecto (Project Settings) y agregar la ruta que corresponde o o Ver Imgen 4. Para accede a la Conguracin del Proyecto ir a Menu: Project a -Setting o presionar la combinacin [ALT]+[F7]. o

Imgen 4. Dilogo de conguracin de rutas de inclusin a a o o

De stas carpetas utilizaremos el archivo mysql.h en nuestras futuras aplicae ciones, en ste archivo estan declaradas las funciones de conexin que nos proe o porciona MySQL para C. Al igual que en el caso anterior tambin tenemos que agregar el directorio de e librer lib. El archivo libmySQL.lib ubicado en sta carpeta nos sirve para as e enlazar nuestra aplicacin, Visual C++ se encargar de enlazar todo para proo a ducir un ejecutable. Dentro de las carpetas lib\debug y lib\opt tambien existe el archivo libmySQL.dll el cual debemos copiarlo en la misma carpeta de nuestro 7

ejecutable para que pueda correr sin problemas. Pero debemos elegir el correcto, en este caso tomaremos el de la carpeta lib\debug, por que nuestro proyecto estar congurado en el modo Debug por defecto. Ver Imgen 5. a a

Imgen 5. Dilogo de conguracin de librer a a o as

Cuando tengan lista una aplicacin para el usuario nal debern congurar el o a proyecto en el modo Release Lanzamiento e incluir en su distribucin el archivo o o libmySQL.dll contenido en la carpeta lib\opt. Antes de compilar deben tambin e congurar las rutas de las librer hacia la carpeta lib\opt. as

Otras conguraciones
Luego de hacer todas las tareas anteriores procedemos a establecer conguraciones adicionales: Carpeta de salida. En la pestaa General de la ventana de Conguracin n o del Proyecto ((Project Settings)) en la seccin Output les: escribir OutPut como o carpeta de salida. Esto le dice al compilador que los archivos ejecutables que produzca no los mezcle con los archivos intermedios y los bote en un directorio aparte (OutPut). Carpeta de trabajo. La carpeta de trabajo es el lugar que tendr nuestro a programa como carpeta por defecto al ejecutarlo desde el Visual C++ (Working directory). En sta carpeta debemos copiar el archivo libmySQL.dll. Por defecto e el valor de esta propiedad esta en blanco. Librer as. En la pestaa Link (de Conguracin del Proyecto) agregar el n o texto libmySQL.lib en la seccin Object/Library modules, sta se usa para decirle o e 8

a compilador que utilice librer extra al momento del la construccin nal del as o ejecutable. Este paso nos evita ver problemas al momento de enlazar el proyecto (Linker Errors).

Archivos de Cabecera
Las declaraciones de las variables y funciones de MySQL C API estan en el archivo mysql.h, debemos declarar la inclusin de ste archivo en Stdafx.h, ver o e neas deben escribirse al nal de todas las declaraciones #include listado 2. Estas l existentes.
Listado 2: Incluir archivos en Stdafx.h 1: 2: #include <afxsock.h> #include <mysql.h>

Debido a que mysql.h utiliza conexiones de Sockets es necesario tambien incluir el archivo afxsock.h antes de mysql.h para que esten disponibles los Window Sockets.

5. La conexin a MySQL o
En el Paso 2 creamos el proyecto, en el cual habr notado que se han creado tres a clases: CAboutDlg, CTestMySQLApp y CTestMySQLDlg. No tocaremos la primera clase ya que es un dialogo que no cumple otra funcin mas que informar acerca o del proyecto. En la clase CTestMySQLApp crearemos la conexin a la base de datos la que o utilizaremos en todo el proyecto, de modo que ser una conexion global. a En la clase CTestMySQLDlg realizaremos una consulta a la tabla empresas de la base de datos prueba db y lo mostraremos en resultado en el control list del dialogo. Ver Imgen 6. a Pues manos a la obra, escribiremos nuestras primeras lineas de codigo asegurando la conexin a la base de datos la cual crearemos en la clase CTestMySQLApp, o necesitaremos denir las variables y funciones como se indica en la Tabla 1. En la variable m pLinkDb, que inicialmente ser NULL (Ver Listado 4), pera manecer la conexin a MySQL que obtendremos con OpenConnection al iniciar a o la aplicacin. La funcin GetConnection nos servir para el resto de objetos de la o o a 9

Tipo Variable Funcin o Funcin o Funcin Virtual o

Tipo de dato Nombre MYSQL* m pLinkDb MYSQL* GetConnection() bool OpenConnection() int ExitInstance()

Ambito protected public protected public

Tabla 1: Variables y funciones para la clase CTestMySQLApp aplicacin que necesiten utilizar una conexion a MySQL (Dilogos, Vistas, Clases, o a etc.). Podremos acceder a la conexin desde cualquier parte a travs de la variable o e global theApp. Es por eso que la variable m pLinkDb tiene que estar protegida, para evitar utilizarla negligentemente sin que est inicializada. Ver Listado10 l e nea 14. Luego del proceso de agregar las variables y funciones de la Tabla 1. Nuestra clase CTestMySQLApp quedar como el Listado 3. a
Listado 3: Declaracin de la clase CTestMySQLApp o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: class CTestMySQLApp : public CWinApp { protected: bool OpenConnection(); MYSQL* m_pLinkDb; public: MYSQL* GetConnection(); CTestMySQLApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTestMySQLApp) public: virtual BOOL InitInstance(); virtual int ExitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CTestMySQLApp)

//}}AFX_MSG DECLARE_MESSAGE_MAP() };

10

Listado 4: Constructor de la clase CTestMySQLApp 1: 2: 3: 4: CTestMySQLApp::CTestMySQLApp() { m_pLinkDb = NULL; }

La funcin OpenConnection o
Esta funcin es muy importante por que depende de sta si seguimos con el o e programa o nos salimos de l sin antes mostrar un mensaje de error. e OpenConnection debe invocarse desde InitInstance de la Aplicacin. Ya o que necesitamos que la conexin se establezca al iniciar el programa. En la o neas funcin OpenConnection es donde inicializamos la variable m pLinkDb (L o 3-4) para luego conectarnos al servidor MySQL con la funcin de la API de o neas 11,19). Si ocurre algun error devolvemos MySQL mysql real connect (L false mostrando antes el mensaje de error (L neas 21,27). Ver Listado 5.
Listado 5: Implementacin de la funcin OpenConnection o o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: bool CTestMySQLApp::OpenConnection() { m_pLinkDb = new MYSQL; mysql_init(m_pLinkDb); CString CString CString CString sHost sUser sPassword sDatabase = = = = _T("localhost"); _T("root"); _T(""); _T("prueba_db");

if (!mysql_real_connect( m_pLinkDb, sHost, sUser, sPassword, sDatabase, 3306, // Puerto de conexion NULL, // Unix socket 0)) // Otras opciones del cliente { CString strText; strText.Format("Error: %s" ,mysql_error(m_pLinkDb)); AfxMessageBox(strText); return false; }

11

29: 30:

return true; }

Usted puede guardar y obtener los parametros de conexin del lugar que guste o el registro de Windows por ejemplo, es por eso que he declarado las variables de las l neas 6-9. En la funcin InitInstance invocamos a OpenConnection pero vericamos o que el resultado sea el que esperamos, sino retornamos FALSE y asi evitamos que la aplicacin siga. Ver Listado 6. o
Listado 6: Abriendo la conexin con OpenConnection o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: BOOL CTestMySQLApp::InitInstance() { ... if (!OpenConnection()) { return FALSE; } ... }

Cuando salgamos de la aplicacin tendremos que cerrar la conexin. Al salir de o o una aplicacin basada en MFC se invoca a la funcin ExitInstance y ah es o o donde tenemos que escribir el codigo necesario para ello. Ver Listado 7.
Listado 7: Cerrando la conexin en ExitInstance o 1: 2: 3: 4: 5: 6: 7: 8: int CTestMySQLApp::ExitInstance() { if (m_pLinkDb) { mysql_close(m_pLinkDb); } return CWinApp::ExitInstance(); }

Ahora nalmente vamos a la funcin GetConnection, sta funcin nos reo e o tornar un apuntador hacia la conexin global, antes de retornar dicho apuntaa o dor debemos asegurarnos que la conexin sea valida, para ello se utiliza la macro o ASSERT(), esta macro evala el parametro, si es FALSE NULL provoca un fallo. u o o Ver Listado 8. Con esto concluimos el asunto de la conexin a la base de datos. 12

Listado 8: Implementacin de la funcin GetConnection o o 1: 2: 3: 4: 5: 6: MYSQL* CTestMySQLApp::GetConnection() { ASSERT(m_pLinkDb); return m_pLinkDb; }

6. Preparar el dilogo a
Desde la vista de recursos en la seccin Dialogs ubicar y abrir el dialogo de la o aplicacin (en nuestro caso es el dialogo que tiene el ID: IDD TESTMYSQL DIALOG) o para modicarlo. Agregarle y ubicar los controles hasta que quede como la Imagen 6. A cada uno de los controles le asignaremos un ID como la Tabla 2. En la misma tabla se indica los eventos y funciones que tambien debemos agregar a la clase CTestMySQLDlg.

Imgen 6. Formulario utilizado para la aplicacin a o

Nota: Para agregar facilmente una variable relacionada a un control: hacer doble click sobre l manteniendo presionada la tecla [CTRL], luego asignarle el nombre y e tipo de variable. El mbito de las variables y funciones sern creados automticaa a a mente por el ClassWizard. La funcin OnFind() es invocada cuando el usuario hace click sobre el boton o IDC FIND. Asu vez la funcin OnFind() invocar a LoadData() Ver Listado 9:15o a 18. Tambien tenemos que hacer una llamada a LoadData() desde la funcin o OnInitDialog(). Ver Listado 9:10.

13

Tipo Variable Variable Funcin o Funcin o

Tipo de dato Control Evento CListCtrl IDC RESULT CString IDC QUERY void void IDC FIND BN CLICKED

Nombre m report m sFilter LoadData() OnFind()

Tabla 2: Variables y funciones para la clase CTestMySQLDlg


Listado 9: Funciones de la clase CTestMySQLDlg 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: BOOL CTestMySQLDlg::OnInitDialog() { CDialog::OnInitDialog(); ... m_report.InsertColumn(0,_T("RUC"),LVCFMT_CENTER,90); m_report.InsertColumn(1,_T("Razon social"),LVCFMT_LEFT,300); LoadData(); return TRUE; } void CTestMySQLDlg::OnFind() { LoadData(); }

La funcin LoadData() se encargar de cargar los datos y los ir volcando o a a en el control IDC RESULT(Ver Listado 10:13-44), pero antes de cargarlos ensamblar una consulta SQL para ello. La consulta SQL la ejecutaremos a travs de la a e conexin global y contendr en clausula WHERE una sentencia que nos ayudar a o a a buscar registros basados en el contenido del control IDC QUERY (Ver Listado 10:511).
Listado 10: La funcin LoadData o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: void CTestMySQLDlg::LoadData() { CWaitCursor x; UpdateData(); CString sql; sql.Format("SELECT ruc,razonsocial \ FROM empresas \ WHERE razonsocial LIKE %s%%",m_sFilter);

14

12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:

if(mysql_real_query( theApp.GetConnection() ,sql ,sql.GetLength()) == 0 ) { MYSQL_RES* res; if ((res = mysql_store_result(theApp.GetConnection()))) { m_report.DeleteAllItems(); MYSQL_ROW Row; CString sRuc; // Ruc CString sRazSoc; // Razon Social int item = 0; while ((Row = mysql_fetch_row(res))) { sRuc.Format ("%s", Row[0] ? (char*) Row[0] : "NULL"); m_report.InsertItem(item,sRuc); sRazSoc.Format ("%s", Row[1] ? (char*) Row[1] : "NULL"); m_report.SetItemText(item,1,sRazSoc); item++; } mysql_free_result(res); } } else { CString strText; strText.Format("Error: %s" ,mysql_error(theApp.GetConnection())); AfxMessageBox(strText); } }

Descripcin de las funciones API de MySQL o


o mysql real query: Ejecuta una consulta SQL sobre una conexin dados pasadas como parametros, el parmetro de consulta necesita la longitud de la consulta en a caracteres.

15

int mysql_real_query( MYSQL *mysql, // enlace a la base de datos const char *query, // Consulta unsigned long length ); // Longitud de la consulta

mysql store result: Retorna todos los registros de la ultima consulta ejecutada a una estructura MYSQL RES. Retorna NULL si no hay resultados que mostrar.

MYSQL_RES *mysql_store_result(MYSQL *mysql)

mysql fetch row: Retorna el siguiente registro de una consulta, este mtodo e debe ser llamado despus de mysql store result. Retorna NULL si no hay mas e registros.

MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

mysql free result: Libera la memoria ocupada por el resultado de una consulta obtenida mediante mysql store result.

void mysql_free_result(MYSQL_RES *result)

Imgen 7. Aplicacin ejecutandose a o

16

7. Modicar, Agregar, Eliminar datos


Si bien logramos recuperar datos, stos no nos servirn de nada si no podemos e a realizar las otras operaciones: Insertar, Modicar, Eliminar. Ese va a ser el punto de esta seccin del tutorial. Basicamente tendremos que agregar tres botones o para realizar dichas operaciones en la Imagen 8 pueden apreciar los botones ya insertados.

Imgen 8. Botones adicionales al dialogo a

Antes de escribir el codigo de las instrucciones de los botones nuevos, tenemos que crear un dialogo para poder dar de alta o modicar un registro en la base de datos. En el dialogo actual slo muestra dos campos (ruc, razonsocial) pero o la tabla empresas tiene 5 (Ver Listado 1). Para ello es dilogo de la Imagen 9, a e a ste dialogo le puse el ID: IDD EMPRESA y mediante ClassWizard cre la clase e relacionada con ste: CEmpresaDlg. e La clase CEmpresaDlg debe tener las variables, eventos y funciones que se indican en la Tabla 3. Las variables de tipo CString estan elazadas a un control y pueden agregarse utilizando el procedimiento que se indica en la Nota de la Imagen 6. La variable m bIsNew nos servir como ag para saber si estamos agregando o modicando. En a la funcin LoadData() cargaremos los datos en caso de que estemos modicando. o Utilizaremos Guardar para actualizar o dar de alta un registro de la base de datos. Las funcin OnOK puede agregarse haciendo doble click en el boton con el ID: o IDOK. La funcin OnInitDialog se agrega automaticamente ubicando el mensaje o 17

Imgen 9. Diseo del dialogo para editar/agregar datos a n

Tipo Variable Variable Variable Variable Variable Variable Funcin o Funcin o Funcin o Funcin o

Tipo de dato CString CString CString CString CString bool void bool void BOOL

Control IDC RUC IDC RAZONSOCIAL IDC DIRECCION IDC EMAIL IDC WEB

Nombre m sRUC m sRazonSocial m sDireccion m sEmail m sWeb m bIsNew LoadData() Guardar() OnOK() OnInitDialog()

Ambito public public public public public public protected protected protected protected

Tabla 3: Variables y funciones para la clase CEmpresaDlg WM INITDIALOG desde la pestaa Message Maps del ClassWizard, luego de ubicar n el mensaje hacer click en Add Function. Para terminar tenemos que modicar el contructor del dialogo CEmpresaDlg para que nos acepte un parametro CString, donde le pasaremos el RUC en caso de que quisieramos modicar un registro. Luego de todas esas modicaciones, la clase CEmpresaDlg deber quedar como el Listado 11. a
Listado 11: Declaracion de la clase CEmpresaDlg 1: 2: 3: 4: 5: 6: 7: 8: class CEmpresaDlg : public CDialog { // Construction public: CEmpresaDlg(CString sRUC,CWnd* pParent = NULL); // Dialog Data //{{AFX_DATA(CEmpresaDlg)

18

9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:

enum { IDD = IDD_EMPRESA }; CString m_sRUC; CString m_sRazonSocial; CString m_sDireccion; CString m_sEmail; CString m_sWeb; //}}AFX_DATA bool m_bIsNew; // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEmpresaDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); //}}AFX_VIRTUAL // Implementation protected: bool Guardar(); void LoadData(); // Generated message map functions //{{AFX_MSG(CEmpresaDlg) virtual BOOL OnInitDialog(); virtual void OnOK(); //}}AFX_MSG DECLARE_MESSAGE_MAP() };

Constructor de la clase CEmpresaDlg


El constructor recibe como primer parametro la variable CString sRUC la a cual asignaremos a m sRUC. Esto tambien nos servir para inicializar m bIsNew. Adicionamente tenemos tambien que declarar la variable global theApp, esto para poder utilizar la conexin global a MySQL. Ver Listado 12 l o nea 1. Si esta declaracion provoca un error entonces tambin debe incluir el archivo e TestMySQL.h : #include "TestMySQL.h"
Listado 12: Constructor de la clase CEmpresaDlg 1: 2: 3: 4: 5: 6: 7: extern CTestMySQLApp theApp; CEmpresaDlg::CEmpresaDlg(CString sRUC,CWnd* pParent /*=NULL*/) : CDialog(CEmpresaDlg::IDD, pParent) { //{{AFX_DATA_INIT(CEmpresaDlg) m_sRUC = sRUC;

19

8: 9: 10: 11: 12: 13: 14: 15:

m_sRazonSocial = _T(""); m_sDireccion = _T(""); m_sEmail = _T(""); m_sWeb = _T(""); //}}AFX_DATA_INIT m_bIsNew = m_sRUC.IsEmpty() == TRUE; }

La funcin LoadData o
La funcin LoadData se parece mucho a la funcin CTestMySQLDlg::LoadData o o slo que esta vez carga un solo registro, y se asigna el valor de cada campo a la o variable que corresponde en el dilogo. Ver Listado 13. La consulta SQL que a estamos ejecutando es SELECT * FROM empresas WHERE ruc = m sRUC. En la funcin OnInitDialog invocaremos a LoadData en caso de que estemos o editando un registro. Ver Listado 13.
Listado 13: Funcines OnInitDialog y LoadData o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: BOOL CEmpresaDlg::OnInitDialog() { CDialog::OnInitDialog(); if (!m_bIsNew) { LoadData(); } return TRUE; } void CEmpresaDlg::LoadData() { CWaitCursor x; UpdateData(); CString sql; sql.Format("SELECT * FROM empresas WHERE ruc = %s",m_sRUC); if(mysql_real_query( theApp.GetConnection() ,sql ,sql.GetLength()) == 0 ) { MYSQL_RES* res; if ((res = mysql_store_result(theApp.GetConnection()))) {

20

29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53:

MYSQL_ROW Row; if((Row = mysql_fetch_row(res))) { m_sRUC = Row[0]; m_sRazonSocial = Row[1]; m_sDireccion = Row[2]; m_sEmail = Row[3]; m_sWeb = Row[4]; UpdateData(FALSE); } mysql_free_result(res); } } else { CString strText; strText.Format("Error: %s" ,mysql_error(theApp.GetConnection())); AfxMessageBox(strText); } }

La funcin Guardar o
En la funcin Guardar() ejecutar el comando SQL INSERT UPDATE segn o a o u sea el caso. En la linea 19 del Listado 14, antes de ejecutar cualquier consulta, evaluamos el valor de la variable m bIsNew. Si la consulta se ha ejecutado con xito Guardar() devolver true, y como es invocada desde OnOK el dialogo se e a cerrar devolviendo IDOK. a
Listado 14: Funcines Guardar y OnOK o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: void CEmpresaDlg::OnOK() { if (Guardar()) { CDialog::OnOK(); } } bool CEmpresaDlg::Guardar() { CWaitCursor x; UpdateData();

21

15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59:

CString sql; m_sRazonSocial.Replace("",""); if (m_bIsNew) //Nueva Empresa { sql.Format("INSERT INTO empresas \ VALUES (%s,%s,%s,%s,%s)" ,m_sRUC ,m_sRazonSocial ,m_sDireccion ,m_sEmail ,m_sWeb); } else // Modificar Empresa { sql.Format("UPDATE empresas SET RazonSocial = %s, \ Direccion = %s, Email = %s, Web = %s \ WHERE ruc = %s " ,m_sRazonSocial ,m_sDireccion ,m_sEmail ,m_sWeb ,m_sRUC); } if(mysql_real_query( theApp.GetConnection() ,sql ,sql.GetLength()) == 0 ) { return true; } else { CString strText; strText.Format("Error: %s" ,mysql_error(theApp.GetConnection())); AfxMessageBox(strText); return false; } }

Ahora si: Guardar, Modicar, Eliminar


Luego de haber hecho el trabajo sucio de hacer que el dilogo CEmpresaDlg a funcione, lo unico que nos queda es agregar las funciones correspondientes a los 22

nuevos botones de la Imagen 8. El Listado 15 muestra las tres funciones. En el caso de OnModify y OnDel es necesario comprobar que un elemento del control CListCtrl est seleccionado. Es importante que este declarada la e inclusin del archivo EmpresaDlg.h (#include .EmpresaDlg.h") en el archivo o TestMySQLDlg.cpp para poder utilizar la clase CEmpresaDlg.
Listado 15: Cdigo para guardar, modicar y eliminar o 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: void CTestMySQLDlg::OnNew() { CEmpresaDlg dlg(""); if (dlg.DoModal() == IDOK) { m_report.InsertItem(0,dlg.m_sRUC); m_report.SetItemText(0,1,dlg.m_sRazonSocial); } } void CTestMySQLDlg::OnModify() { POSITION pos = m_report.GetFirstSelectedItemPosition(); if (pos) { int item = m_report.GetNextSelectedItem(pos); CString ruc = m_report.GetItemText(item,0); CEmpresaDlg dlg(ruc); if (dlg.DoModal() == IDOK) { m_report.SetItemText(item,0,dlg.m_sRUC); m_report.SetItemText(item,1,dlg.m_sRazonSocial); } } else { MessageBox("Debe seleccionar un item de la lista"); } } void CTestMySQLDlg::OnDel() { POSITION pos = m_report.GetFirstSelectedItemPosition(); if (pos) { int item = m_report.GetNextSelectedItem(pos); CString ruc = m_report.GetItemText(item,0); CString msg = "Realmente desea Eliminar el item seleccionado?"; if (MessageBox(msg,"Eliminar",MB_YESNO|MB_ICONWARNING) == IDYES)

23

43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71:

{ CString sql; sql.Format("DELETE FROM empresas WHERE ruc = %s",ruc); if(mysql_real_query( theApp.GetConnection() ,sql ,sql.GetLength()) == 0 ) { m_report.DeleteItem(item); } else { CString strText; strText.Format("Error: %s" ,mysql_error(theApp.GetConnection())); MessageBox(strText); } } } else { MessageBox("Debe seleccionar un item de la lista"); } }

Finalmente la aplicacin correr como se ve en la Imagen 10. o a Notarn que los botones tienen un icono, es por que he utilizado la clase a CImageButton del art culo que esta ubicado en: www.latindevelopers.com/articles/vc/imagebutton/ He modicado la clase CImageButton para que acepte solo una imagen por boton. Ademas tambien le he agregado un temporizador para hacer la busqueda mas interactiva.

24

Imgen 10. Aplicacion Final corriendo a

8. Comentarios, conclusiones, recursos , etc..


Este tutorial fue elaborado inicialmente en formato Microsoft Word, luego A fue corregido y aumentado y re-elaborado en L TEX. El proyecto Visual C++ TestMySQL y el archivo prueba db.sql puede descargarlo de www.latindevelopers.com/vcpp/db/mysql api/. El archivo prueba db.sql contiene al rededor de 10,000 registros para que usted pueda experimentar. La direccin podr cambiar en los meses poso a teriores a la publicacin de ste art o e culo. Ser saludable que usted me env un correo electrnico para resolver sus a e o consultas y sugerencias o simplemente para saber como utiliza el material del atr culo. Algunas de las funciones de la librer API de MySQL posiblemente cambien a segun vaya desarrollandose el gestor de base de datos MySQL. Se recomienda al lector que est al tanto de las actualizaciones disponibles en el sitio e ocial de MySQL: www.mysql.com Generalmente las actualizaciones no son muy dramaticas por lo que si est planeando implementar una aplicacion a mas grande, es muy posible que sea compatible con versiones superiores de MySQL. En C/C++ es posible reutilizar codigo ecientemente, es lo que no hago en este tutorial. Las innumerables lineas de codigo fuente son simplicables. 25

Por citar un solo ejemplo: las consultas pueden agruparse en una funcin o generica que las ejecute. Agradezco a Rosario Bustamante por realizar las correcciones ortogrcas. a El Lenguaje de programacin Visual C++ es una marca y producto de Mio crosoft Corp. El gestor de base de datos MySQL es producido y distribuido bajo licencia GPL por MySQL AB.

26

Você também pode gostar