¿como unir las ventanas y las clases de c++?

Iniciado por luis_74, 8 Abril 2015, 20:12 PM

0 Miembros y 1 Visitante están viendo este tema.

luis_74

en los ejemplos de  la programacion de windows y c++ que encontré se crean las ventanas y controles usando funciones y variables individualmente,  me paso por la mente: si se ¿pudiera "meter" todo lo relacionado a la creacion de ventanas y controles dentro de clases c++ y tratarlos como si fuesen controles de delphi o VB? como se haria , algun tutorial ?

ivancea96

Si a lo que te refieres es a crear una clase "Ventana", con todos sus métodos, es algo que puedes hacer. Basta guardar los campos necesarios, como los HANDLE de la ventana y lo que sea.

No es difícil, pero es algo que lleva tiempo, y que ya han hecho otras librerías, como GLFW, SFML o Qt.

luis_74

sí a eso me refiero, no se me ocurre como se manejraria el bucle de mensajes desde una clase, creo que se quedaria "atascado" sin salir de la clase, tenia curiosidad por saber como lo hacen los compiladores como visualbasic y delphi , en esos lenguajes es algo invisible al usuario.

crack81

Bueno ya que hablas de Delphi, este encapsula todo su codigo a traves
de componentes

si quieres mas informacion de como funcion Delphi internamente puedes bajarte el proyecto de lazarus que es un RAD opensource basado en delphi,
bueno literalemente son algunos proyectos liberados de borland del antiguo delphi 7 + el compilador free pascal + el linkeador proporcionador por un tercero

te dejo su web en ella se encuentra el proyecto para que le puedas dar una estudiada o darte la idea como funciona

http://www.lazarus-ide.org/index.php
Si C/C++ es el padre de los lenguajes entonces ASM es dios.

eferion

#4
Cita de: luis_74 en 10 Abril 2015, 00:59 AM
sí a eso me refiero, no se me ocurre como se manejraria el bucle de mensajes desde una clase, creo que se quedaria "atascado" sin salir de la clase, tenia curiosidad por saber como lo hacen los compiladores como visualbasic y delphi , en esos lenguajes es algo invisible al usuario.

Si por "usuario" quieres decir "programador" te tengo que corregir. No es invisible al programador.

Para que tu programa pueda mostrar una interfaz gráfica necesitas que tu código se conecte con la API correspondiente del sistema operativo que se encarga de gestionar la interfaz de usuario del sistema operativo. Lo que sucede es que normalmente no trabajas directamente sobre la API del sistema operativo, sino que haces uso de una librería que alguien se ha molestado en programar, y que te permite crear interfaces gráficas de una forma más sencilla.

En el caso de Delphi, la librería gráfica es la VCL (Visual Component Library). Además, tienes la "suerte" de que esta librería la proporciona Borland por defecto junto con el IDE, pero aunque no tengas que preocuparte por cómo funciona la clase "Button" de la VCL, has de saber que siempre vas a poder crear tus propios controles gráficos... y para poder hacer eso tienes que conocer cómo funciona esta librería.

En el caso de VisualBasic, la librería gráfica es la MFC (Microsoft Foundation Class). Tienes la "suerte" de que esta librería, al igual que la de Delphi, la proporciona Microsoft por defecto junto con su IDE.

En cualquier caso, has de saber que siempre tienes la opción de trabajar directamente con la API... al fin y al cabo cualquier componente gráfico se va a acabar apoyando antes o después en dicha API.

¿Por qué estoy tan seguro de que todo pasa por la API del sistema operativo? Muy sencillo. Si cada aplicación crease su propio gestor de ventanas sería imposible que pudieses visualizar varias aplicaciones a la vez en la pantalla del ordenador. Para que esto sea posible es necesario que exista un gestor común que se encargue de decidir qué ventana está encima de otra, con qué control está interactuando el usuario en cada momento, a qué control le llega el "foco" cuando el usuario manipula el ratón, etc.

En cuanto a cómo lo hacen con el bucle de mensajes... a ver, normalmente cuando se crea una aplicación con interfaz gráfica, se especifica una función que será la encargada de recibir todos los mensajes por parte del SO. En esta función se encapsula una secuencia de "if" para capturar todos los mensajes importantes para la aplicación. Cuando se recibe un mensaje que es reconcido por la aplicación, el código de esta función acaba llamando a un método concreto de la aplicación para que ese mensaje sea correctamente procesado.

Un ejemplo. Tienes una aplicación con dos botones (A y B), y quieres que al presionar el botón A aparezca un texto en pantalla. Entonces en el bucle de mensajes tienes que "escuchar" un mensaje de tipo "BOTON_PRESIONADO"... además, tendrás que asegurarte de que el botón presionado sea el A. Si todo lo anterior se cumple entonces el bucle de mensajes tiene que llamar a la función BotonAPresionado. Esta última función será la que muestre el mensaje por pantalla y, tras esto, la ejecución volverá al bucle de mensajes a la espera del siguiente mensaje.

#define BOTON_PRESIONADO = 0x01

#define A = 0x01
#define B = 0x02

void bucleMensajes( int mensaje, int control )
{
 if( mensaje == BOTON_PRESIONADO && control == A )
   BotonAPresionado( );
}

void BotonAPresionado( )
{
 // Mostrar mensaje en pantalla
}


El problema de trabajar a tan bajo nivel es que mantener ordenado la función del bucle de mensajes puede ser bastante complicado... las librerías gráficas te abstraen de esta parte, ya que ellas solas son capaces de configurar el bucle de mensajes en base a la configuración que tu ventana.

luis_74

Cita de: eferion en 10 Abril 2015, 08:24 AM
Si por "usuario" quieres decir "programador" te tengo que corregir. No es invisible al programador.

Para que tu programa pueda mostrar una interfaz gráfica necesitas que tu código se conecte con la API correspondiente del sistema operativo que se encarga de gestionar la interfaz de usuario del sistema operativo. Lo que sucede es que normalmente no trabajas directamente sobre la API del sistema operativo, sino que haces uso de una librería que alguien se ha molestado en programar, y que te permite crear interfaces gráficas de una forma más sencilla.

En el caso de Delphi, la librería gráfica es la VCL (Visual Component Library). Además, tienes la "suerte" de que esta librería la proporciona Borland por defecto junto con el IDE, pero aunque no tengas que preocuparte por cómo funciona la clase "Button" de la VCL, has de saber que siempre vas a poder crear tus propios controles gráficos... y para poder hacer eso tienes que conocer cómo funciona esta librería.

En el caso de VisualBasic, la librería gráfica es la MFC (Microsoft Foundation Class). Tienes la "suerte" de que esta librería, al igual que la de Delphi, la proporciona Microsoft por defecto junto con su IDE.

En cualquier caso, has de saber que siempre tienes la opción de trabajar directamente con la API... al fin y al cabo cualquier componente gráfico se va a acabar apoyando antes o después en dicha API.

¿Por qué estoy tan seguro de que todo pasa por la API del sistema operativo? Muy sencillo. Si cada aplicación crease su propio gestor de ventanas sería imposible que pudieses visualizar varias aplicaciones a la vez en la pantalla del ordenador. Para que esto sea posible es necesario que exista un gestor común que se encargue de decidir qué ventana está encima de otra, con qué control está interactuando el usuario en cada momento, a qué control le llega el "foco" cuando el usuario manipula el ratón, etc.

En cuanto a cómo lo hacen con el bucle de mensajes... a ver, normalmente cuando se crea una aplicación con interfaz gráfica, se especifica una función que será la encargada de recibir todos los mensajes por parte del SO. En esta función se encapsula una secuencia de "if" para capturar todos los mensajes importantes para la aplicación. Cuando se recibe un mensaje que es reconcido por la aplicación, el código de esta función acaba llamando a un método concreto de la aplicación para que ese mensaje sea correctamente procesado.

Un ejemplo. Tienes una aplicación con dos botones (A y B), y quieres que al presionar el botón A aparezca un texto en pantalla. Entonces en el bucle de mensajes tienes que "escuchar" un mensaje de tipo "BOTON_PRESIONADO"... además, tendrás que asegurarte de que el botón presionado sea el A. Si todo lo anterior se cumple entonces el bucle de mensajes tiene que llamar a la función BotonAPresionado. Esta última función será la que muestre el mensaje por pantalla y, tras esto, la ejecución volverá al bucle de mensajes a la espera del siguiente mensaje.

#define BOTON_PRESIONADO = 0x01

#define A = 0x01
#define B = 0x02

void bucleMensajes( int mensaje, int control )
{
  if( mensaje == BOTON_PRESIONADO && control == A )
    BotonAPresionado( );
}

void BotonAPresionado( )
{
  // Mostrar mensaje en pantalla
}


El problema de trabajar a tan bajo nivel es que mantener ordenado la función del bucle de mensajes puede ser bastante complicado... las librerías gráficas te abstraen de esta parte, ya que ellas solas son capaces de configurar el bucle de mensajes en base a la configuración que tu ventana.




sí, me equivoque , era programador.

Lo de invisible me refería justo a eso , en delphi o vbasic el programador no trabaja directamente con la pi y no necesita saber como funciona internamente los componentes, todo está encapsulado, se apoya en las librerias, solo debe programar en los eventos on_click , on_mousemove y  todo funciona de maravilla.

mi duda era como se llevaba a cabo eso de crear los componentes o esa palabrita "encapsular", porque si antes o despues se tienen q apoyar en las apis, entonces los diseñadores de esos controles tambien habran usado las apis , como "meterias" un bucle de mensajes para cada control o ventana dentro de una clase sin "atascarse", si el bucle siempre da vueltas hasta que se cierre una ventana, en que momento se ejecutaria los bucles de las demas ventanas?



class ventana
{
     
     
private:
     
    void buclemensajes()

public:


};

void ventana::bucleMensajes( int mensaje, int control )
{
    BOOL bRet;
   
    //me quedo atascado en este while de la clase y no podre salir de la clase hasta que se cierre esta ventana :P y no podre ejecutar los otros bucles
   
    while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
    {
        if (bRet == -1)
        {
           //salir
        }
        else
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

}



}


ivancea96

En vez de un while, haz que esa función la llame el programador en su propio bucle.

luis_74

:P   me quedo confuso, podrian de favor compartir algun tutorial si hubiera sobre este tema en spanish, me interesa aprenderlo, usar las clases para crear las ventanas, controles etc sería mucho más cómodo y rápido que hacerlo del modo tradicional.

ivancea96

https://github.com/LaurentGomila/SFML/tree/master/src/SFML

Ese es el source de SFML, puedes ver cosas interesantes ahí.

¿Tutorial de cómo crear una clase para crear ventanas?

Es simplemente una clase, con sus métodos y sus variables. ¿Creaste alguna vez una ventana con la API de Windows? Si lo has hecho, simplemente tienes que meter eso organizadamente en la clase. ¿El bucle de eventos? Hay muchas formas, pero tener un while 'infinito' no es una opción (Salvo que uses threads).

Cada ciclo del while, lo puedes guardar en un método de la clase. Luego simplemente el programador llama en su bucle al método.

Podría quedar así el main del programa:
Código (cpp) [Seleccionar]
int main(){
    Window w;
    w.setKeyCallback(&keyCallback);
    /* ... */
    w.create("Titulo", 800,600);
    while(w){
        w.handleEvents();
    }
}



Es un ejemplo. Puedes ponerle callbacks, o puedes guardar los eventos en una cola y devolverlos por el "handleEvents()". Hay muchas posibilidades.

En ese caso, el handleEvents() tendría dentro los TranslateMessage(), DispatchMessage(), y etc.


Simplemente, hazlo como tú veas. Pero si quieres realmente usar ventanas con clases, usa una librería como SFML. Tiene muchas funcionalidades que a ti te llevarían mucho tiempo implementar, además de que SFML está testeada, y tiene una gran comunidad.