MAINTENIR UNE FENÊTRE NON MODALE AU PREMIER PLAN AVEC L'API SETWINDOWPOS EN 2 LI

Tilois Messages postés 721 Date d'inscription dimanche 10 juin 2001 Statut Membre Dernière intervention 27 mars 2011 - 24 juil. 2004 à 10:25
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 - 22 févr. 2012 à 08:19
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/24809-maintenir-une-fenetre-non-modale-au-premier-plan-avec-l-api-setwindowpos-en-2-lignes-de-code

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
22 févr. 2012 à 08:19
Je pense a un subclassing de la fenetre a mettre en topMostquand wParam true, ta fenetre est en train d'etre activée> SWP_TOPMOST
quand wParam true, une fenetre d'une autre application est en train d'etre activée> SWP_NOTOPMOST

cf.
http://www.vbfrance.com/codes/MODULE-SUBCLASSER_38442.aspx

Option Explicit

Implements ISubclasser
Private mtWindow As SubClassedWindow

Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Private Sub Form_Load()
SetWindowPos Me.hWnd, HWND_TOPMOST, 0&, 0&, 0&, 0&, SWP_NOSIZE Or SWP_NOMOVE
InitiateSubClassing mtWindow, Me, Me.hWnd, True, WM_ACTIVATEAPP
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
TerminateSubClassing mtWindow
End Sub

Private Function ISubclasser_WindowProc(ByVal hWnd As Long, ByVal uMsg As MessageConstants, ByVal wParam As Long, ByVal lParam As Long) As Long
If wParam Then
SetWindowPos Me.hWnd, HWND_TOPMOST, 0&, 0&, 0&, 0&, SWP_NOSIZE Or SWP_NOMOVE
Else
SetWindowPos Me.hWnd, HWND_NOTOPMOST, 0&, 0&, 0&, 0&, SWP_NOSIZE Or SWP_NOMOVE
End If
End Function
cs_Swinger Messages postés 6 Date d'inscription mercredi 25 décembre 2002 Statut Membre Dernière intervention 22 février 2012
22 févr. 2012 à 07:53
2012...Il existe encore des gens qui développe sur VB6 (plus pour longtemps, je vous rassure!).
J'avais cherché comment laisser une feuille TOPMOST seulement d'une application et pas de toutes, et ceci sans être en VBmodal, pendant plusieurs mois en vain...HUELCE, je ne sais pas si tu vas lire ce message, mais dans tout les cas, je te dit un tres grand merci!
cs_Ouneufe Messages postés 60 Date d'inscription mardi 4 septembre 2001 Statut Membre Dernière intervention 19 janvier 2009
18 févr. 2008 à 17:18
c'est bien cette source, juste ce qu'il me fallait.

Merci.
ROOTVL69 Messages postés 10 Date d'inscription jeudi 18 septembre 2003 Statut Membre Dernière intervention 3 août 2007
30 mai 2006 à 16:21
C'est vrai que le code produit des effets très sympas, mais la feuille disparait quand par exemple windows media player est en plein écran, ce qui me gene pour un projet en cours...
Quelqu'un a une idée?
huelce Messages postés 45 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 28 juillet 2004 1
21 mai 2006 à 19:25
lol
voila 2 ans que j'ai posé ce commentaire, et d'un coup je recois dans mon courrier "Vous avez recu un commentaire CodesSources" ?

Ce code, je l'avais cherché TRES longtemps moi aussi, et j'avais trouvé cette solution hyper pratique je sais plus ou...

Tant mieux si elle sert encore !

En attendant, je désactive le suivi de cette conversation !
Adieu donc ;)
big_S Messages postés 3 Date d'inscription mardi 24 mai 2005 Statut Membre Dernière intervention 19 mai 2006
19 mai 2006 à 02:53
impec c est ce ke je cherchais merci pr ton code
illumen75013 Messages postés 3 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 29 novembre 2005
17 mai 2006 à 18:29
HOURRA!!!!!
Vive lui !!!

des mois, que dis je, des années que je me tulupine le cerveau
à essayer d'avoir une vrai toolbox

fini ma fenetre dependante qui traine en premier plan quand j'ai plusieurs programmes d'ouverts

encore merci
StouffR Messages postés 4 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 15 avril 2006
6 janv. 2005 à 11:56
huelce: Pour moi ton code fait la même chose que le premier avec plus de codes.

Et puis ce genre de code ne permet pas de voir les msgbox :s
Silmon Messages postés 85 Date d'inscription mardi 6 janvier 2004 Statut Membre Dernière intervention 7 mai 2007
29 juil. 2004 à 17:19
Huelce, MERCI!!!

Cela faisait longtemps que je cherchais le moyen, d'utiliser
une form top-most relative.

Et j'en avait besoin justement dans le contexte d'une boite à outil.

J'avais crée un editeur de texte avec une fenetre pour rechercher un texte.
L'api SetWindowPos presentait evidemment ses problemes classiques. Aussi, est-je passé beaucoup de temps en testant avec d'autres parametres, utilisant d'autres moyens et recherchant dans les 11000 sources une solution pour rendre une fenetre topmost relativement a une et une seule autre fenetre.

Ton commentaire m'a grandement depanné. 10/10 rien que pour ça. Merci
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
26 juil. 2004 à 14:44
une recherche est toujours possible, et filtre un bon paquet de ces 11 000 sources ;)

Renfield - Admin CS
cs_Scorpio93 Messages postés 7 Date d'inscription mercredi 14 juillet 2004 Statut Membre Dernière intervention 4 juin 2006
26 juil. 2004 à 10:47
Tilois je n'ai pas consulter les plus de 11000 codes avant de déposer le mien.
Merci a huelce pour ses explications très claires
huelce Messages postés 45 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 28 juillet 2004 1
26 juil. 2004 à 01:50
Le but de cette source : maintenir une fenêtre non modale au premier plan quand elle perd le focus.
C'est à dire lui appliquer ce qu'on appelle communément le 'topmost'. Pour cela il suffit d'appeller UNE fois l'api SetWindowPos dans le form.load et c'est régler.

Pour te répondre, ce que je propose, et que j'applique pour toutes mes feuilles type 'boites à outils' n'est pas l'équivalent d'une feuille modale qui t'enpecherait d'utiliser une autre feuille, car qui dit modale dit garde le focus.

Je rééxplique donc, quand tu appliques le topmost à une feuille, c'est à dire quand tu fais :

'délcarations
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, Y, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Const HWND_TOPMOST = -1
'Const HWND_NOTOPMOST = -2
Const SWP_NOMOVE = &H2
Const SWP_NOSIZE = &H1
Const TOPMOST_FLAGS = SWP_NOMOVE Or SWP_NOSIZE

'Form.Load()
SetWindowPos Feuille.hwnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS

Cette feuille restera en effet au dessus d'une éventuelle feuille mère mais aussi au dessus de toutes les applications ouvertes ! Ce qui peut être très génant...

Prenons l'exemple des boites à outils de photoshop, elles sont topmost à photoshop, mais pas aux autres applications.

De plus, quand tu utilises un topmost pur, quand tu réduit la feuille mère (pour utiliser une autre app), ta boite à outils ne se réduit pas... et reste toujours au dessus des autres apps.

Pour réussir cela, il faut rendre la boite à outils fenetre fille de l'appellante (ou lui indiquer la mère comme parent, ce qui revient au même) avec l'api setwindowlong.
Dans ce cas, inutile d'utiliser le topmost, sauf si la fenêtre mère est aussi topmost au moment de l'ouverture de cette boite à outils.

Hmm j'ai peur de ne pas être clair dans mes explications...

Voici un exemple, pour une fenêtre type boite à outils.

'-- déclarations
'setwindowlong
Public Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
'Constantes 'parent' pour : SetWindowLong
Public Const GWL_HWNDPARENT As Long = -8
'pour SetWindowLong
Private OriginalParentHwnd As Long

'setwindowpos
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, Y, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Const HWND_TOPMOST = -1
Const SWP_NOMOVE = &H2
Const SWP_NOSIZE = &H1
Const TOPMOST_FLAGS = SWP_NOMOVE Or SWP_NOSIZE

'-- dans form.load()
'pour rendre Fmain (exemple d'une fenêtre mère nommée fMain) parent
OriginalParentHwnd = SetWindowLong(Me.hwnd, GWL_HWNDPARENT, fMain.hwnd)
'ensuite si fmain est topmost à ce moment là, et uniquement
SetWindowPos me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS

'-- dans le form.unload()
'remet à la normale avant de quitter (sécurité)
Dim R As Long
R = SetWindowLong(Me.hwnd, GWL_HWNDPARENT, OriginalParentHwnd)

Voilà, met ce code dans une fenêtre (ou plusieurs), et ouvre la (les) normalement depuis une fenêtre mère :
FrmFille.show

Résultat : elles seront bien toujours topmost à ta fenêtre mère, mais pas des autres fenêtres de ton bureau !
Réduit ta fenêtre mère et admire :)
cs_legion91 Messages postés 216 Date d'inscription mercredi 5 février 2003 Statut Membre Dernière intervention 15 décembre 2010
26 juil. 2004 à 00:02
huelce> c'est vrai que de facon general j'aime pas les timers (pas precis, ...) mais pour laisser une fenetre au premier plan (devant toute les fenetres) et ceux tout le temp ya pas 36façons.

Sinon ce que tu propose (j'ai pas chercher à le faire) c'est de faire une form modal lol, sa peut etre interressant.
huelce Messages postés 45 Date d'inscription jeudi 22 avril 2004 Statut Membre Dernière intervention 28 juillet 2004 1
25 juil. 2004 à 02:25
Heu legion91... quel intérêt d'utiliser un timer ?! C'est pas le genre de chose à dire aux newbies, il vont en mettre partout !
L'appel du topmost (cette source ne parle que de ca) dans le form.load est très bien comme ça. Ca t'évite un appel inutile à SetActiveWindow si je ne m'abuse.

Ce qui serait mieux c'est de montrer un exemple avec SetWindowLong (et GWL_HWNDPARENT par exemple) pour en plus du topmost, mettre la feuille fille de l'appellante. Cela permet qu'elle reste au dessus de la feuille mère sans pour autant rester au dessus de toutes les autres applications. Et ca a aussi bien d'autres avantages.
cs_legion91 Messages postés 216 Date d'inscription mercredi 5 février 2003 Statut Membre Dernière intervention 15 décembre 2010
24 juil. 2004 à 16:43
Deja ton code il y est deja sur le site mais avec une touche de mieux:


Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Declare Function SetActiveWindow Lib "user32" Alias "SetForegroundWindow" (ByVal hWnd As Long) As Long


Private Sub Timer1_Timer()
SetActiveWindow Me.hWnd
SetWindowPos Me.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
End Sub

Et dans ce code la oui elle reste au premier plan.
Golog Messages postés 224 Date d'inscription jeudi 31 janvier 2002 Statut Membre Dernière intervention 22 décembre 2009
24 juil. 2004 à 15:00
c kler, y a j'c po cbs d'exemple de ce code sur le site...
Tilois Messages postés 721 Date d'inscription dimanche 10 juin 2001 Statut Membre Dernière intervention 27 mars 2011 7
24 juil. 2004 à 10:25
Dit moi, tu as repomper ce code sur le site ou quoi ?
Rejoignez-nous