2009-05-01 22 views
12

In Windows, è possibile impostare la finestra A in modo tale che sia sempre in cima alla finestra B, ma consentire ad altre finestre di funzionare normalmente e apparire sopra entrambe, quando attive.Una finestra può essere sempre sopra solo un'altra finestra?

In altre parole, voglio una relazione genitore-figlio tra due finestre. Questo può essere fatto senza fare della finestra A un figlio della finestra B, in stile MDI? Window B non è la mia (Internet Explorer) e avvita la grafica della mia finestra A quando cerco di ottenere questo risultato con SetParent.

ho pensato di cracking con questa idea da un MSDN forum post, ma ahimè finestre A è ancora sempre in cima a tutto, non solo la finestra 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); 

E 'possibile?

+0

Purtroppo, non penso che ci sia un modo per farlo. – Charlie

risposta

0

È possibile accedere all'ordine Z delle finestre?

non riesco a ricordare l'ordine z predefinita di Windows, ma penso che sia 1. Si potrebbe essere in grado di impostare IE per un -1 e la vostra applicazione a 0.

0

Prova questo:

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

Il parametro handle della seconda finestra specifica la finestra successiva nell'ordine Z.

Nota questo in realtà non cambia le relazioni parent-child finestra - ma è possibile simularlo.

+0

Questo lo fa una volta (ma poi lo fa una sola volta senza di essa). Cliccando su IE lo si mette davanti alla mia finestra :( – Mat

3

Quando l'ordine Z (o la dimensione o la posizione) della tua finestra sta cambiando, dovrebbe ricevere un messaggio WM_WINDOWPOSCHANGING. Se si elabora quel messaggio, si ha la possibilità di modificare l'ordine Z finale (o la dimensione o la posizione) a cui viene spostata la finestra.

Per illustrare, nella routine di finestra di hWndA:

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

dovrebbe inserire hWndA dopo hWndB nella Z-ordine in qualsiasi momento la posizione cambia di hWndA.

+0

Mat non possiede la finestra genitore, quindi non può cambiare il winproc di "A", ma potrebbe funzionare un qualche tipo di hook del genitore? – Aardvark

+0

, dice di possedere A e vuole farlo sembrare un figlio di B, che non è il suo (Internet Explorer). Penso che A riceverà avviso che l'ordine z di A sta cambiando se B viene spostato in primo piano. –

+0

Sì! ! Hai fatto il mio giorno ho ottenuto quello che voglio maneggiando 'ON_WM_WINDOWPOSCHANGING()' e poi facendo 'vuoto 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

Fino a Vista, un modo per farlo sarebbe stato utilizzare SetWindowsHookEx e agganciare il gancio WH_CBT o WH_CALLWNDPROC e quindi adottare le misure appropriate quando si rileva la modifica dell'ordine Z. Tuttavia questo non funziona con Vista (per quanto posso dire da googling).

L'unica altra soluzione mi viene in mente è quello di impostare un timer per sparare ogni pochi secondi, e poi, quando si riceve un WM_TIMER, è interrogare il sistema utilizzando GetNextWindow per scoprire quale finestra è dietro la vostra. Se non è IE, quindi chiama SetWindowPos per posizionare la finestra sopra IE (presumo tu abbia un HWND per la finestra di IE che ti interessa - ricorda che possono esserci più finestre di IE).

Ciò causerà problemi se le persone cercano di portare la finestra in primo piano - tornerà a essere appena sopra IE. In questo caso, nel tuo codice potresti gestire WM_ACTIVATE e provare a cambiare l'ordine Z della finestra di IE in modo che sia sotto la tua finestra (chiama SetWindowPos per spostare la finestra di IE in modo che sia sopra la finestra che è attualmente sotto la tua finestra). Questa soluzione potrebbe essere piena di problemi poiché Windows potrebbe tentare di impedirti di fare scherzi con le finestre di un altro processo, per motivi di sicurezza. D'altra parte, i documenti MSDN per SetWindowPos non esplicitamente menzionano che non è possibile modificare le finestre di un altro processo.Tuttavia, potrebbero esserci limitazioni oscure.

Anche con questo hack timer, si sta andando ad avere effettivamente un ciclo busy-attesa nella vostra app (con i messaggi WM_TIMER frequenti) e questo è generalmente una brutta cosa da fare, soprattutto per la durata della batteria dei computer portatili ecc. (perché si impedisce alla CPU di entrare in uno stato di sospensione e così via).

Direi che non c'è un buon modo per farlo, e qualsiasi cosa che si rischia di funzionare sarà fragile e causa problemi. Consiglio vivamente di non provare a farlo. È possibile invece impostare il tuo programma in una sorta di plug-in o barra degli strumenti per IE?

NB Si noti in particolare che SetWindowsHookEx impone una penalizzazione delle prestazioni a livello di sistema se si scende lungo questa rotta.

12

La creazione di un rapporto di proprietà non è sufficiente?

SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner) 

Le finestre possono essere in processi diversi e si può chiamare da qualsiasi processo. Ciò assicurerà che la finestra secondaria sia sempre sopra la finestra del proprietario. È diverso da SetParent che crea effettivamente una relazione padre/figlio. Read through this article (dal 1993 ma ancora in gran parte corretto) per vedere la distinzione tra proprietà e genitorialità.

+0

Che funziona perfettamente. – Sebastian

+1

Il collegamento dice 'Contenuto rimosso' –

+0

[Collegamento archivio Web] (https://web.archive.org/web/20100318062734/http://msdn.microsoft.com/en-us/library/ms997562.aspx) –

1

La risposta di Maurice è il meglio di ciò che è qui ma manca un passaggio importante. Quando chiami show sulla tua finestra che vuoi come overlay, devi chiamare il metodo show che ha il parametro. Dovrai definire una classe che implementa l'interfaccia IWin32Window e creare una nuova istanza. L'unica cosa di cui l'interfaccia si preoccupa è il Gestore, quindi basta impostarlo sul manico della finestra di IE e dovrebbe funzionare abbastanza bene

0

Se la relazione genitore-figlio è fatta da solo con la funzione SetWindowPos(), il tuo desiderio può essere implementato.

Problemi correlati