2009-05-01 26 views
12

En Windows, es posible configurar la ventana A de manera que siempre esté en la parte superior de la ventana B, pero permita que otras ventanas funcionen normalmente y que aparezcan sobre las dos, cuando estén activas.¿Puede una ventana estar siempre encima de otra ventana?

En otras palabras, quiero una relación padre-hijo entre dos ventanas. ¿Se puede hacer esto sin hacer que la ventana A sea hija de la ventana B, estilo MDI? La ventana B no es mía (Internet Explorer) y atornilla los gráficos de mi diálogo A cuando intento lograr esto con SetParent.

pensé que se había agrietado con esta idea de un MSDN forum post, pero por desgracia las ventanas A sigue siendo siempre encima de todo, no sólo la ventana B.

// Place window A on top 
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 
// Place window B underneath it 
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 

¿Es posible?

+0

Desafortunadamente, no creo que haya una manera de hacer esto. – Charlie

Respuesta

0

¿Puede acceder al orden Z de las ventanas?

No puedo recordar el valor por defecto de orden z de las ventanas, pero creo que es 1. Es posible que pueda configurar IE para un -1 y su aplicación a 0.

0

Prueba esto:

// Place window A on top of window B 
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 

El segundo parámetro del controlador de ventana especifica la siguiente ventana hacia abajo en el orden Z.

Tenga en cuenta que esto no cambia las relaciones entre padres e hijos de la ventana, pero puede simularlo.

+0

Eso lo hace una vez (pero luego lo hace una vez sin él). Al hacer clic en IE, aparece delante de mi ventana :( – Mat

3

Cuando el orden Z (o el tamaño o la posición) de su ventana está cambiando, debe recibir un mensaje de WM_WINDOWPOSCHANGING. Si procesa ese mensaje, tiene la oportunidad de modificar el orden Z final (o el tamaño o posición) al que se mueve la ventana.

Para ilustrar, en procedimiento de ventana de hWndA:

case WM_WINDOWPOSCHANGING: 
    DefWindowProc(hWnd, msg, wParam, lParam); 
    WINDOWPOS *p = (WINDOWPOS*)lParam; 
    p->hwndInsertAfter = hWndB; 
    p->flags &= ~SWP_NOZORDER; 
    return 0; 

debe insertar hWndA después hWndB en el orden Z cualquier momento los cambios de posición de hWndA.

+0

Mat no posee la ventana primaria, por lo que no puede cambiar el winproc de "A." Sin embargo, ¿tal vez funcionaría algún tipo de gancho del padre? – Aardvark

+0

En realidad , él dice que posee A y quiere hacer que parezca un hijo de B, que no es suyo (Internet Explorer). Creo que A recibirá un aviso de que el orden z de A está cambiando si B se mueve al frente. –

+0

¡Sí! ! usted ha hecho mi día tengo lo que quiero por el manejo 'ON_WM_WINDOWPOSCHANGING()' 'y luego haciendo vacío CMyFrame :: OnWindowPosChanging (WINDOWPOS * lpwndpos) { \t __super :: OnWindowPosChanging (lpwndpos); \t CMainFrame * = pMainFrame dynamic_cast (AfxGetMainWnd()); \t if (pMainFrame)) \t { \t \t lpwndpos-> hwndInsertAfter = pMainFrame-> GetSafeHwnd(); \t} } ' – sergiol

2

Hasta Vista, una manera de hacerlo habría sido utilizar SetWindowsHookEx y enganche el gancho WH_CBT o WH_CALLWNDPROC, y luego tomar las medidas apropiadas cuando se detecta el cambio orden Z. Sin embargo, esto no funciona con Vista (por lo que puedo decir de Google).

La única otra solución que se me ocurre es configurar un temporizador para disparar cada pocos segundos, y luego cuando recibe un WM_TIMER, interroga al sistema usando GetNextWindow para averiguar qué ventana está detrás del suyo. Si no es IE, llame al SetWindowPos para ubicar su ventana arriba de IE (supongo que tiene un HWND para la ventana de IE que le interesa, recuerde que puede haber varias ventanas de IE).

Esto causará problemas si las personas intentan llevar su ventana al frente - volverá a estar justo por encima de IE. En este caso, en su código puede manejar WM_ACTIVATE y tratar de cambiar el orden Z de la ventana de IE para que esté debajo de su ventana (llame al SetWindowPos para mover la ventana de IE de modo que esté encima de la ventana que está debajo de su ventana). Esta solución puede estar plagada de problemas, ya que Windows puede tratar de evitar que se meta con las ventanas de otro proceso, por razones de seguridad. Por otro lado, los documentos de MSDN para SetWindowPos no explícitamente mencionan que no puede manipular las ventanas de otro proceso.Sin embargo, puede haber limitaciones oscuras.

Incluso con este hack temporizador, vas a tener efectivamente un bucle ocupado en espera en su aplicación (con los mensajes WM_TIMER frecuentes) y esto es generalmente una mala cosahacer, especialmente para la vida de la batería de los portátiles etc. (porque evita que la CPU entre en estado de suspensión, etc.).

Yo diría que no hay una buena manera de hacerlo, y cualquier cosa con la que sea probable que trabaje será frágil y causará problemas. Recomiendo encarecidamente no intentar hacerlo. ¿Es posible convertir su programa en algún tipo de complemento o barra de herramientas para IE?

NB Tenga especialmente en cuenta que SetWindowsHookEx impone una penalización de rendimiento a nivel de todo el sistema si realiza esta ruta.

12

¿No sería útil crear una relación de propiedad?

SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner) 

Las ventanas pueden estar en diferentes procesos y puede llamarlo desde cualquier proceso. Esto asegurará que la ventana secundaria esté siempre por encima de la ventana del propietario. Esto es diferente de SetParent, que en realidad crea una relación Padre/Hijo. Read through this article (es desde 1993, pero sigue siendo en su mayoría correcta) para ver la distinción entre propiedad y crianza.

+0

Eso funciona a la perfección. – Sebastian

+1

El enlace dice 'Contenido eliminado' –

+0

[Enlace de archivo web] (https://web.archive.org/web/20100318062734/http://msdn.microsoft.com/en-us/library/ms997562.aspx) –

1

La respuesta de Maurice es lo mejor de lo que está aquí pero le falta un paso importante. Cuando llamas a show en tu ventana como la superposición, debes llamar al método show que tiene el parámetro. Tendrá que definir una clase que implemente la interfaz IWin32Window y simplemente crear una nueva instancia de eso. Lo único que le importa a la interfaz es la Manija, así que simplemente ajústelo al asa de la ventana IE y debería funcionar bastante bien

0

Si la relación padre-hijo la hace usted mismo con la función SetWindowPos(), su deseo puede ser implementado.

Cuestiones relacionadas