Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Getparent?

Iniciado por Ipis, 22 de Octubre de 2003, 06:40:46 PM

« anterior - próximo »

Ipis

 
Tengo una aplicación MDI y al pulsar un botón de la barra de herramienta del marco principal ejecuto "ShellExecute" para iniciar un nuevo programa llamado(Matlab,por si os suena de algo)

No me da error y funciona perfectamente,pero no consigo integarlo en el área cliente:al maximizarlo o minimizarlo no se queda dentro de mi marco principal

He probado con GetParent(),GetParentFrame() e incluso estoy probando con SetWindowPlacement()(que,por cierto,me da problemas al inicializar el miembro ptMaxPosition) pero no debo hacerlo bien porque el programa se sigue ejecutando independientemente...... a lo mejor es que ShellExecute no es la función apropiada para ello  :blink:

Por favor,si a alguien se le ocurre una idea..... (uoh) a mí ya se me están acabando

Gracias  

Zaelsius

 En vez de GetParent() deberías usar la contraria.. ¿no?


The SetParent function changes the parent window of the specified child window.

Syntax

HWND SetParent(      
   HWND hWndChild,
   HWND hWndNewParent
);



hWndNewParent es el handle de tu aplicación. Para obtener hWndChild utiliza la función FindWindow():

HWND FindWindow(      
   LPCTSTR lpClassName,
   LPCTSTR lpWindowName
);


Como lpWindowName podría variar(tal vez no, pero no siempre podría llamarse la ventana "Matlab", a lo mejor otra versión se llama "Matlab 5" o algo así), es mejor que averigües el valor de lpClassName con la herramienta Spy++(incluida con Visual Studio).

PD: Conozco er Matlab ;)

Ipis

 Pos mira tú por donde...yo usaba GetParent para obtener
el handle de mi marco principal y pasárselo a ShellExecute,pero
voy a probar lo que dices  :rolleyes:

Por cierto,es el primer foro en el que alguien conoce "er Matlab"(claro que es el primer foro "decente" que me encuentro  :D )

Gracias..... :P


Ipis

 Jo,que no sale!!!! (nooo)  (nooo)

Ya no pueo más,no veo dónde falla(aunque a lo mejor sería más rápido buscar lo que está bien...si es que hay algo) Para colmo el Spy++ no me funciona(se me abre la pantalla y enseguida se cierra)

Este es mi código,por si sirve de algo:[CODE]

 m_hwnd = ::FindWindow("matlab",NULL);  
  ::SetParent(m_hwnd,NULL);
  (ShellExecute(m_hwnd,NULL,"matlab.exe",NULL,"C:\MatlaBR11\bin\",SW_SHOW));

Ni con estas consigo que er dichoso programa se quede dentro de mi aplicación  (grrr)

Zaelsius

 Tienes varios fallos gordos... debería ser algo como ésto:



HWND hwnd = ::FindWindow(NULL,"Matlab");
::SetParent(hwnd,m_hwnd);
(ShellExecute(m_hwnd,NULL,"matlab.exe",NULL,"C:\MatlaBR11\bin\",SW_SHOW));



Eso suponiendo que el dato miembro m_hwnd ya lo has inicializado a su valor correcto anteriormente(si es una clase de MFC no tienes que tocarlo!)

Y por supuesto comprobar tb el valor devuelto por FindWindow, no sea que matlab no se esté ejecutando o no encuentre la ventana por ese nombre.

Ipis

 Siento la ausencia,pero tenía problemas técnicos para conectarme....

Verás,las dobles barras "\" las tuve que poner para que VC++ me reconociera el carácter \,porque si no me sale el siguiente warning:

[ C:\Erika\Tutorial_C++\PDI\MainFrm.cpp(124) : warning C4129: 'M' : unrecognized character escape sequence]

El resto del código....jo,así no me extraña que no me salga;si es que no doy una.El caso es que tampoco da resultado,pero creo que es porque no sé muy bien cómo conseguir el ID de la ventana marco principal

Perdona mi ignorancia,pero qué significa eso que si es de MFC no tengo que tocarlo??De dónde saco su valor?

Otra cosilla....existe otra forma de verificar el valor de FindWindow sin usar Spy++??Es que no me funciona bien

Asias...... :D  

Zaelsius

 Supongo que sabrás que en MFC, todo está organizado en clases. Una parte de  tu aplicación estará derivada de CWnd, que es una clase que encapsula una ventana de WIndows.

La notación m_* denota que esa variable es una variable "miembro" de la clase, y en este caso m_hwnd ya deberia contener el handle adecuado del marco principal de tu aplicación.

Respecto a FindWindow().. pues en teoría, pasándole el nombre que aparece en la barra de título de la ventana de Matlab, deberia funcionar. Para obtener lpClassName hay varias opciones: o utilizas Spy++(raro que no te funcione) o un programa similar, o bien utilizas la Api win32 para preguntar una vez tengas el hwnd.

Mira, si no te importa, enviame el proyecto(quitale la basurilla temporal antes, como los .ncb y tal) al e-mail(zsgames(at)hotmail.com), a ver si lo hago funcionar(probaré con el Matlab tb). Que ya me pica la curiosidad de meter una ventana dentro de otra  :P  

Repoker

Cita de: "Ipis"Por cierto,es el primer foro en el que alguien conoce "er Matlab"

Bufff.. pues no nos han dado de castañas a nosotros en la universidad con el MATLAB XDDDd

Lo mejor: 30 licencias para 1000 estudiantes; si hay clase de física y quieres usarlo desde otra aula te dice que no hay licencias disponibles XDDDDDD

sés

 
Cita de: "Ipis"Verás,las dobles barras "\" las tuve que poner para que VC++ me reconociera el carácter \...
Puedes utilizar la otra barra ('/') y quitarte de problemas... y ahorrar en teclas... y gastar menos dedo :P
Soy indeciso... ¿o no?

Ipis

 
CitarPuedes utilizar la otra barra ('/') y quitarte de problemas... y ahorrar en teclas... y gastar menos dedo

O sea,que si quiero poner la siguiente dirección:

C:\Erika\Tutorial_C++\PDI\MainFrm.cpp(124)

Para que VC++ la reconozca me basta con:

C:/Erika/Tutorial_C++/PDI/MainFrm.cpp(124)

No sé si te he entendido mu bien,lo que quieres decir es que es lo mismo "\" que "/" ??? Si es que VC++ está lleno de sorpresas....... (uoh)  

sés

 No es lo mismo pero, para trabajar con ficheros, da igual "C:\\algo.txt" que "C:/algo.txt"
Soy indeciso... ¿o no?

Zaelsius

 Volviendo al tema...

Código que funciona.. aunque no es muy óptimo:


CMainFrame::OnMatlab()
{

if(SUCCEEDED(ShellExecute(m_hParentHWND,NULL,"MATLAB.EXE",NULL,"G:\\Ua\\MATLAB\\BIN\\",SW_SHOW)))
{
HWND hwnd;

// Esperar a que la aplicación se inicialice y se cree su ventana
while(!(hwnd = ::FindWindow(NULL,"Matlab command window")));
 
::SetParent(hwnd,m_hParentHWND);

}

}


Para hacerlo bien, hay que ejecutar un código similar en un hilo aparte, y añadir un límite de tiempo de espera.

Una vez tengas hwnd, puedes obtener el lpClassName de Matlab con la función GetClassName()

int GetClassName(
 HWND hWnd,           // handle to window
 LPTSTR lpClassName,  // class name
 int nMaxCount        // size of class name buffer
);


Utilizar lpClassName en vez de lpszWindowName en FindWindow() es más seguro y menos propenso a errores.

Para lanzar el proceso en un hilo aparte tienes que crear una clase derivada de CWinThread. Mira la sección "CWinThread overview" en la documentación para más información.

Ipis

 Un par de cosillas:

1.- A mí el código no me funciona,se ejecuta Matlab correctamente,pero al maximizar o minimizar el programa no se acopla a mi ventana marco principal(exactamente como al principio)  (nooo)

Para comprobar si FindWindow() funcionaba correctamente se me ocurrio
cambiar el título de la ventana una vez saliera del while.Sé que no es nada eficiente,pero para el caso......


  if(!(hwnd= ::FindWindow(NULL,"Matlab command window")))
    AfxMessageBox("Error-ventana no encontrada", MB_OK);
   
  else  ::SetWindowText(hwnd, "Por fin!!!!");
 


El caso es que al ejecutarlo pasa lo de siempre,y el título de la ventana no cambia y no me aparece ningún mensaje de error,pero cuando lo depuro y ejecuto paso a paso....el título cambia!!!! Aunque no su comportamiento.....os lo juro,me estoy poniendo de los nervios  (grrr)

2. - He estado "investigando" sobre  la clase CWinThread y,si no he entendido mal,lo que me permite es crear un hilo o tarea que pertenezca a mi programa,pero....si yo lo que quiero es ejecutar Matlab dentro de mi programa de forma que éste sea su "dueño", no me basta con ShellExecute o CreateProcess....o sí??

Otra posibilidad serían componentes Ole ..... o eso creo  :blink: ¿Estoy en lo cierto?

Gracias a todos.Saludos.

Zaelsius

 A mi sí que me funciona... amo a vé, voy a ser plasta por si algún paso se te hubiese escapado :rolleyes:  :

Este bucle tiene un sentido:


// Esperar a que la aplicación se inicialice y se cree su ventana
while(!(hwnd = ::FindWindow(NULL,"Matlab command window")));


... y es que cuando tu ejecutas una aplicación, su ventana no se crea automáticamente. Esto es, tras llamar a ShellExecute, el proceso de Matlab puede que ya esté corriendo o no(pq se ejecuta asíncronamente) y su ventanta probablemente aun no esté creada ni inicializada. Por eso el bucle llama a FindWindow() hasta que aparezca la ventana de Matlab.

Esto tiene un problema, y es que si pones mal el 2º parámetro de FindWindow() tu aplicación nunca encontrará la ventana y se colgará.
Y si MatLab tarda 15segundos en arrancar(por ejemplo) pues durante 15segundos tu aplicación no responderá.. pq seguirá en el bucle.

Para evitar esa espera bloqueante... lo ideal es hacer esa espera en un hilo de ejecución paralelo, para que el usuario pueda seguir utilizando tu aplicación mientras carga MatLab. De esta manera tb sería muy fácil añadir un límite de tiempo a ese hilo, para que si a los 15(p.ej) segundos no ha cargado el programa.. finalizar el hilo y mostrar un mensaje de error.


Cuando depuras la aplicación.. lo único que puede pasar es que al ir paso a paso le das tiempo a Matlab para cargarse..  :huh:

Ipis

 Jo,si es que no me entero.... :( Siento ser tan plasta,pero me urge conseguirlo(aparte de que ya es por satisfacción propia ;-D)

Citar
Para evitar esa espera bloqueante... lo ideal es hacer esa espera en un hilo de ejecución paralelo, para que el usuario pueda seguir utilizando tu aplicación mientras carga MatLab.

Veamos,lo primero es que no tengo muy claro qué ejecutar en el hilo:si la aplicación paralela de Matlab o la espera.Es que todos los ejemplos de hilos que he visto no se ejecutan dentro del programa principal(como si fuera una ventana hija,que es lo que quiero yo)

Tampoco sé cuándo ejecutar el hilo(al pulsar el botón de la barra de herramientas correspondiente a Matlab o dentro de la función CMainFrame::OnMatlab() )

Agradecería un poco más de explicación sobre los hilos(o alguna recomendación de algún tutorial o algo),porque con la documentación de VC++ sólo no me aclaro (asco)

Siento mucho la lata que estoy dando con el temita este,pero llevo.....ya ni me acuerdo el tiempo que llevo intentándolo.....Gracias por vuestra paciencia y amabilidad  :D    






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.