J'ai un programme Windows qui contient deux fenêtres:
hwnd (main interface)
hwnd2 (toplevel window, no parent, created by hwnd)
Lorsque je double-clique sur hwnd, j'ai besoin que hwnd2 apparaisse et affiche des données, donc j'utilise cette fonction pour amener hwnd2 en haut:
BringWindowToTop(hwnd2);
hwnd2 est ramené au sommet, mais il y a une chose étrange. Lorsque je clique à nouveau sur hwnd2, hwnd (interface principale) réapparaît automatiquement. J'ai essayé d'utiliser la fonction suivante pour résoudre ce problème, mais aucune d'entre elles ne fonctionne.
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);
Comment pourrais-je résoudre ce problème? Merci d'avance.
(pour répondre à aJ, hwnd2 n'a pas de parent car il doit être une fenêtre de niveau supérieur pour pouvoir être devant/derrière d'autres fenêtres)
(hwnd2 est un lecteur multimédia composé de plusieurs fenêtres, l'une des fenêtres est destinée à l'affichage vidéo, deux autres commandes de barre de suivi pour la barre de progression et la barre de volume, une commande de barre d'outils pour le panneau de commande.)
(Il y en a un qui pourrait aider, peu importe la fenêtre sur laquelle je clique sur hwnd2, hwnd apparaît automatiquement aussi longtemps que "la souris est au-dessus de hwnd dans l'ordre Z", y compris la barre de menus et la zone non client, etc.)
(Ce lecteur multimédia est écrit dans Direct Show. J'utilise IVideoWindow :: put_Owner pour mettre la fenêtre vidéo en tant que propriétaire de la vidéo, Direct Show crée en interne une fenêtre sous-vidéo en tant qu'enfant de la fenêtre vidéo. À l'exception de cette fenêtre sous-vidéo qui Je ne vois pas le code source, je ne vois rien de suspect dans hwnd2.)
J'ai trouvé la raison, à cause de Direct Show. J'utilise le multithread pour l'exécuter, puis le problème est résolu. Mais pourquoi??
Ce problème peut être résolu en utilisant PostMessage (plutôt que SendMessage).
essayez ceci , on dit qu'il vient 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);
Les deux fonctionnent très bien:
::SetForegroundWindow(wnd)
ou
::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
);
Mais rappelez-vous que le dernier définit la fenêtre toujours en haut.
SwitchToThisWindow fonctionne le mieux pour moi.
SwitchToThisWindow () n'est pas du tout obsolète.
Je l'utilise depuis 14 ans en environnement de production.
Voir le code source de Windows et vous verrez qu'il s'appelle partout ...
Après de nombreux essais et erreurs, j'ai trouvé la solution suivante à ce problème:
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);
//redraw to prevent the window blank.
RedrawWindow(hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN );
Le hwnd est votre Windows HWND. Veuillez ne pas simplement copier et coller. Vous devez également utiliser GetLastError
pour vérifier l'erreur api après chaque appel api.
J'ai confirmé le résultat suivant sur mon win7:
Avez-vous essayé SetActiveWindow ()?