2009-05-27 21 views
26

tengo un programa de Windows que tiene dos 2 ventanas en ella:Win32: Llevar una ventana de arriba

hwnd (main interface) 

hwnd2 (toplevel window, no parent, created by hwnd) 

Cuando hago doble clic en hwnd, necesito hwnd2 a aparecer y mostrar algunos datos, por lo que utilizar esta función para llevar hwnd2 hacia arriba:

BringWindowToTop(hwnd2); 

hwnd2 es llevado hacia arriba, pero hay una cosa extraña. Cuando vuelvo a hacer clic en hwnd2, hwnd (interfaz principal) aparece de nuevo automáticamente. He intentado utilizar la siguiente función para resolver este problema, pero ninguna de ellas funciona.

SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 
                    //doesn't work 

BringWindowToTop(hwnd2); //This is the function brings hwnd2 to top 

SetForegroundWindow(hwnd2); //doesn't work 

SetWindowPos(hwnd2, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 
                    //doesn't work 

SetWindowPos(hwnd2, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 
             // hwnd2 "always" on top, not what I want 

SetActiveWindow(hwnd2); // doesn't work too (for replying to Magnus Skog, thanks) 

SwitchToThisWindow(hwnd2, TRUE);// got the same problem with BringWindowToTop function 
SwitchToThisWindow(hwnd2, FALSE); 

¿Cómo puedo resolver este problema? Gracias de antemano.

(para responder a AJ, hwnd2 no tiene padres, ya que tiene que ser una ventana de nivel superior para que pueda estar delante/detrás de otras ventanas)

(hwnd2 es un reproductor multimedia que se compone de varias ventanas, una de las ventanas es para video, otros dos controles de la barra de progreso para la barra de volumen y un barra de herramientas para el panel de control)

(Hay una que podría ayudar, no importa en qué ventana haga clic hwnd2, hwnd aparece automáticamente tan rápido como "el mouse está encima de hwnd en orden Z", incluida la barra de menú y el área no cliente, etc.)

(este reproductor multimedia está escrito en Direct Show. Yo uso IVideoWindow :: put_Owner para poner la ventana de video como el propietario del video, Direct Show crea internamente una ventana de sub-video como elemento secundario de la ventana de video. A excepción de esta ventana de sub-video que no puedo ver el código fuente, no veo nada sospechoso en hwnd2.)

Encontré la razón, que es por Direct Show. Uso multithread para ejecutarlo, y luego el problema está resuelto. ¿¿Pero por qué??

Este problema se puede resolver utilizando PostMessage (en lugar de SendMessage).

+2

Cualquier motivo específico por el cual hwnd2 no tiene padres? hwnd se puede establecer como padre durante la creación. –

+0

¿Qué haces en el código de manejo del botón del mouse de hwnd2? ¿Hay algo sospechoso allí? –

+1

Entonces, ¿cómo lo resolvió usando PostMessage? –

Respuesta

6

SwitchToThisWindow funciona mejor para mí.

+15

MSDN: esta función está obsoleta y no está destinada para uso general. Se recomienda que no lo use en programas nuevos porque puede estar alterado o no disponible en versiones posteriores de Windows. –

+2

Si Microsoft dice que algo está en desuso, amigo, está desaprobado. Si todavía lo usan o no. –

4

SwitchToThisWindow() no está en desuso en absoluto.
Lo uso durante 14 años en el entorno de producción.
código fuente de Windows Ver y verá que se llama en todas partes ...

+0

No hay necesidad de llamarlo aquí, es solo para "hacer trampa". Pero en este caso, ya tenemos una ventana en primer plano, así que tenemos derecho a cambiar la ventana activa – Anders

13

Ambos funcionan muy bien:

::SetForegroundWindow(wnd) 

o

::SetWindowPos(m_hWnd,  // handle to window 
      HWND_TOPMOST, // placement-order handle 
      0,  // horizontal position 
      0,  // vertical position 
      0, // width 
      0, // height 
      SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE// window-positioning options 
      ); 

Pero recuerda que el último establece la ventana siempre parte superior.

+9

Ambos no funcionan en win10 –

+0

Podría ser un poco tarde, pero tienes que llamar a ':: SetForegroundWindow' antes de mostrar la ventana (asegúrese de actualizar la ventana también). – Cedric

-4

// ¡funciona genial!

Var 
WndHandle:HWND; 

begin 
WndHandle :=FindWindowEx(0,0,nil,'Calculator'); 
PostMessage(WndHandle,WM_SHOWWINDOW,SW_RESTORE,0); 
SetForegroundWindow(WndHandle); 
end; 
15

probar esto, se dice que viene de M $

HWND hCurWnd = ::GetForegroundWindow(); 
    DWORD dwMyID = ::GetCurrentThreadId(); 
    DWORD dwCurID = ::GetWindowThreadProcessId(hCurWnd, NULL); 
    ::AttachThreadInput(dwCurID, dwMyID, TRUE); 
    ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 
    ::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 
    ::SetForegroundWindow(m_hWnd); 
    ::AttachThreadInput(dwCurID, dwMyID, FALSE); 
    ::SetFocus(m_hWnd); 
    ::SetActiveWindow(m_hWnd); 
+0

He estado buscando esta canción y baile mágico desde hace bastante tiempo. Funciona perfectamente para mí. – ulatekh

+0

Todavía no puedo entender lo que hace, pero solo funciona –

+0

De ahí que me haya referido a él como "mágico" :-) – ulatekh

0

Después de muchos intentos y errors.I encontró siguiente solución a este problema:

SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); // restore the minimize window 
SetForegroundWindow(hwnd); 
SetActiveWindow(hwnd); 
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); 
RedrawWindow(hwnd,nil,0,RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); // redraw to prevent the window blank. 

El hwnd es sus ventanas HWND. Por favor, no solo copie y pegue. También necesita usar GetLastError para verificar el error de API después de cada llamada de API.

tengo confirmar siguiente resultado en mis win7:

  • se puede restaurar minimizar la ventana y sin retorno de error.
  • Si la ventana ya está arriba, el título de la ventana parpadeará y no aparecerá ningún error.
  • Si la ventana se ha cerrado, devolverá el error "Identificador de ventana inválido 0x578".
  • Puede llevar la ventana a la parte superior en todas las ventanas que no están en la parte superior y no devuelve ningún error. (Por ejemplo, detrás del administrador de tareas más alto)
  • No hace que la ventana sea la más alta. El usuario puede hacer otra ventana encima.
Cuestiones relacionadas