Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Enlazar Formulario del Builder con winMain propio

Iniciado por Tarzan, 17 de Diciembre de 2007, 09:21:38 PM

« anterior - próximo »

Tarzan

Buenas tardes,

He creado una aplicación con Builder C++ 6.0... con su formulario y controles gráficos. He introducido botones, paneles, radiobuttons, etc.
Y he comprobado que el entorno Builder, con las herramientas RAD, genera un código automático para la creación de una ventana y enlazarla con el formulario inicial.

Sin embargo, a mí me gustaría poder utilizar la creación de la ventana de una forma más específica, (con un Winmain en el que registro la clase y llamo al CreateWindowEx con todos sus parámetros... También me gusta hacerlo así porque puedo acceder a la función WindowProc y controlar todos los enventos de la ventana de forma específica.

Con Builder c++, al crear una aplicación te genera automáticamente la función WinMain con 3 llamadas:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
   try
   {
        Application->Initialize();
        Application->CreateForm(__classid(TvPrincipal), &vPrincipal);
        Application->Run();


El bucle principal de la aplicación se encuentra en la función Run y cualquier línea que escriba después de esta llamada no se ejecuta.
La ventaja de utilizar este tipo de entorno es que te facilita muchas cosas. La creación de la ventana son 3 líneas de código y es muy sencillo situar componentes gráficos en el formulario sin escribir código.

El problema es que yo necesito crear la ventana desde cero y acceder a la función WindowProcedure para controlar cualquier evento de la aplicación. Pero, por otra parte, me gusta usar la herramienta RAD del Builder y poder pegar controles gráficos sin escribir código.

¿Hay alguna forma de crear un proyecto en Builder C++, usar su formulario y herramienta RAD (pinchar y arrastrar componentes gráficos al formulario generando el código automáticamente), pero CAMBIANDO esas 3 líneas del WINMAIN por un WinMain propio y más específico?

Espero haber planteado bien la pregunta.
Saludos.

swapd0

Cita de: "Tarzan"La creación de la ventana son 3 líneas de código...
No, la creacion de la ventana es la segunda linea, primero inicializa el objeto Aplicacion, despues crea la ventana, y por ultimo lanza la aplicacion. Como solo tienes una ventana, en las opciones del proyecto aparecera como ventana princial y por eso se muestra al lanzar la aplicacion.

Hace mucho que no programo con el C++ Builder pero creo recordar que puedes leer el manejador de la ventana (¿HWND?), y con el puedes bajar al cutre API de Windows.

Segun recuerde de mis pruebas de hacer una aplicacion con plugins, puedes hacer esto, y tendras dos ventanas:

Application->Initialize();
Application->CreateForm(__classid(TvPrincipal), &vPrincipal);  // una forma de crear la ventana
TvPrincipal *wnd=new TvPrincipal();
wnd->Show();  // otra forma, puede que falten parametros y que tengas que llamar a wnd->Init() o algo asi
Application->Run();


De todas formas, ¿por que no te planteas no usar el builder para todo?

Tarzan

¿No usar el Builder para todo?. Te refieres a no usarlo y hacerlo todo desde cero, no?

Podría hacerlo... al menos ya tengo preparada la estructura principal de la aplicación.

El WinMain (dónde creo la ventana y dónde tengo un bucle principal para insertar el código de la aplicación)

El WindowProcedure (función que es llamada automáticamente por el sistema y que captura cualquier evento que el usuario produzca).
Además puedo tratar estos eventos de forma independiente mediante un switch muy lógico.

El problema es que perdería el uso de la herramienta RAD (pinchar y arrastrar controles gráficos al formulario del Builder)...
Para mí es muy útil programar la interfaz gráfica así porque nunca lo he hecho desde cero.
Ahora mismo tengo creada una estrcutura de paneles, botones, edits, labels, etc... y, bueno, imagino que podría aprovechar el código y enlazarlo de alguna forma con la aplicación si la empiezo desde cero.

Lo que me dices de usar el handle (hwnd) me interesa.
Si creo una ventana nueva, como tú has hecho en el ejemplo, ¿Qué debería hacer para enlazar ese handle con el del formulario (se supone que estará dentro del objeto application)?

TvPrincipal *wnd=new TvPrincipal();

tiene que haber alguna forma de enlazar el objeto wnd con el application generado de forma automática con el proyecto Builder.
De esta forma, podría usar mi propio WinMain con el WindowProcedure y seguir usando la herramienta RAD del builder.

¿Alguien lo ha hecho antes?

Saludos.

swapd0

Cita de: "Tarzan"¿No usar el Builder para todo?. Te refieres a no usarlo y hacerlo todo desde cero, no?
Ups, queria decir usar el builder para todo.


Cita de: "Tarzan"
Lo que me dices de usar el handle (hwnd) me interesa.
Si creo una ventana nueva, como tú has hecho en el ejemplo, ¿Qué debería hacer para enlazar ese handle con el del formulario (se supone que estará dentro del objeto application)?

TvPrincipal *wnd=new TvPrincipal();

tiene que haber alguna forma de enlazar el objeto wnd con el application generado de forma automática con el proyecto Builder.
De esta forma, podría usar mi propio WinMain con el WindowProcedure y seguir usando la herramienta RAD del builder.

¿Alguien lo ha hecho antes?
Se supone que cualquier objeto que herede de TWindow tiene un HWND, que es el manejador de la ventana que usa el windows, no olvides que las VCL son unas clases montadas sobre el API del windows.

Otra solucion, ¿por que no capturas los eventos en la propia ventana creada con el builder? Asi si creas un objeto, o varios de esa ventana ella sola leeria los eventos y reaccionaria a ellos, no tendrias que hacer el WindowProcedure a mano cada vez que uses esa ventana.

Para esto podrias usar los eventos que trae cada control. Asi tendrias el codigo mas repartido, y no en un switch enorme en el WindowProcedure.

Tarzan

Hola Swapd0,

Lo que dices de usar los eventos de cada control es precisamente lo que tengo montado. Es muy útil la herramienta del Builder que te permite observar todos los eventos de cada control y tratarlos por separado.

El problema es que necesito tratar el evento OnMouseMove sobre una imagen para que cambie de color cuando el cursor está por encima. Y cuando el cursor sale, debe volver a su estado original.
Lo fácil, (cambiar la imagen cuando el cursor está encima), ya lo tengo implementado y funciona bien. Pero cuando el cursor sale fuera hay MUCHAS POSIBILIDADES. Es decir, puede ser que el usuario situe el cursor sobre otro componente o sobre un panel, o lo saque del marco de la ventana (la ventana no ocupa toda la ventana).
Tendría que llamar a la función  pintarImagenOriginal() en cada evento OnMouseMove de cada control posible. Y no sólo eso, también cuando el usuario saca el cursor de la ventana (para que no se quede la imagen coloreada sin estar el cursor encima)... Cosa que no sé hacer.

Mi idea:

Capturar las coordenadas del cursor y pintar la imagen sólo cuando el cursor está encima y despintar siempre que el cursor no esté encima (dando igual sobre que control esté o si está fuera de la ventana)

Con WindowProcedure, la etiqueta OnMouseMove: captura el código siempre que el cursor se mueve. Usando los eventos de los controles, solo se llama a uno o a otro cuando el cursor se situa sobre ellos... No sé si me estoy explicando bien...

Se me ocurre una cosa, ¿Hay alguna forma de averiguar las coordenadas de un objeto imagen?... Si puedo averiguar esto, con GetCursorPos(POINT), Si el cursor está dentro de esas coordenadas pinto y si no lo está despinto.
Usando un timer como decías en un principio...
Pero ¿Cómo averiguo las coordenadas de una imagen?... La venanta puede maximizarse, minimizarse, moverse... etc...

swapd0

Segun recuerdo los TSpeedButton y los TToolBar tocando por las propiedades puedes hacer que al pasar el raton por un boton, este aparezca con relieve, y al salir de el se que pone como antes.

Asi que si tienes instalado el Builder con los fuentes de las VCL, creo que lo mas facil es buscar en el codigo como lo hacen. Por cierto el codigo estara en  Pascal.

josette

todo FORM tiene la funcion WindowProc. Puedes intentar sobrecargarla y hacer cosas hay dentro. a ver que te parece esta solucion.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.