Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Fenetre ne s'affichant pas avec le style WS_EX_LAYERED

20 réponses
Avatar
Vincent Torri
Je desire me familiariser avec UpdateLayeredWindow et j'ai donc ecrit un
petit programme de test qui cree une fenetre dont le contenu est bleu.

Le programme se trouve ici:

www.maths.univ-evry.fr/pages_perso/vtorri/files/layer.c

Si je n'utilise pas WS_EX_LAYERED, la fenetre s'affiche sans probleme,
avec son contenu bleu

Si j'utilise WS_EX_LAYERED, la fenetre est cree, mais ne s'affiche pas.
Elle est neanmoins notifiee dans la barre des taches.

Ce n'est pas une fenetre fille

Quel est le probleme ?

merci

10 réponses

1 2
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fcc10b$0$12628$:

Vincent Torri a écrit :

Donc voici le code:

http://www.maths.univ-evry.fr/pages_perso/vtorri/files/layer.c
[...]


il y a sûrement quelque chose d'invalide dans les HDC utilisés
dans le code montré, ainsi que dans sa séquence - les coordonnées dans
'client' par exemple sont négative du fait de l'appel précédent à
SetWindowLongPtr(w, GWL_EXSTYLE, WS_EX_LAYERED).



pour 'client', en fait, le 2eme parametre de ClientToScreen est in/out et
doit etre initialise a (0,0). Une fois ceci fait, il est correctement
initialise.
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fccc63$0$17784$: >
j'ai un code qui tombe en marche avec
UpdateLayeredWindow(...,ULW_ALPHA) mais pas avec ULW_COLORKEY, je
regarderais (p.e.) demain.



le probleme peut-il venir du fait que les couleurs doivent etre pre-
multipliees ? dans ce cas, il est peut-etre possible de s'en sortir avec
ULW_ALPHA, mais en remplissant correctement le mask_bitmap

Vincent
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fccc63$0$17784$:


j'ai un code qui tombe en marche avec
UpdateLayeredWindow(...,ULW_ALPHA) mais pas avec ULW_COLORKEY, je
regarderais (p.e.) demain.



Je pense avoir un debut. Deja, je me suis trompe pour la composante alpha
: 255 == opaque et 0 == transparent. Comme la partie rouge a une
composante alpha valant 255, c'est elle qui doit etre affichee. Donc j'ai
modifie le code et ca a l'air de marcher. Il suffit que dans la fonction
de blend, le 3eme membre soit a 255. Voila le code modifie :

http://www.maths.univ-evry.fr/pages_perso/vtorri/files/layer3.c

Neanmoins, il y a 3 problemes (peut-etre lies):

1) La premiere fois que j'appuie sur 't', j'active la transparence, mais
le bord de la fenetre disparait (la partie non-client)
2) la deuxieme fois que j'appuis sur 't', c'est cense desactiver la
transparence, mais ca ne re-affiche pas correctement la fenetre avec le
contenu initial. J'ai essaye d'envoyer le message WM_PAINT pour forcer
l'affichage, mais ca ne marche pas.
3) quand j'appuie une 3eme fois sur 't', j'active la transparence, mais
la fenetre est plus petite (comme si la partie non-client etait integre
dans la partie client, a cause de l'etape 2.

Ca avance lentement, mais ce n'est pas parfait.
Avatar
Sylvain SF
Vincent Torri a écrit :

Neanmoins, il y a 3 problemes (peut-etre lies):

1) La premiere fois que j'appuie sur 't', j'active la transparence, mais
le bord de la fenetre disparait (la partie non-client)



oui cela semble être toujours le cas avec UpdateLayeredWindow, à tout
le moins lorsque le filtre ne joue que sur des extrêmes transparent
et opaque - SetLayeredWindowAttributes en jouant sur le canal alpha
permet d'obtenir un frame translucide.

2) la deuxieme fois que j'appuis sur 't', c'est cense desactiver la
transparence, mais ca ne re-affiche pas correctement la fenetre avec le
contenu initial. J'ai essaye d'envoyer le message WM_PAINT pour forcer
l'affichage, mais ca ne marche pas.



on ne doit pas envoyer un WM_PAINT, il faut invalider!
ici le problème est qu'un InvalidateRect classique invalide
la zone client, pas le frame; de plus la fenêtre perd sa taille
et sa position du fait que le frame était masqué, l'affichage en
mode normal (sans layer) restaure donc la fenêtre avec comme
position et dimension celles de la zone client.

il faut donc sauvegarder les épaisseurs du cadre pour redimensionner
la fenêtre et forcer le réaffichage du cadre - SetWindowPos permet
de faire cela.

3) quand j'appuie une 3eme fois sur 't', j'active la transparence, mais
la fenetre est plus petite (comme si la partie non-client etait integre
dans la partie client, a cause de l'etape 2.



exactement, plutôt le partie non-client qui était nulle avant cette
restauration est prise sur la zone clientèle qui diminue d'autant.

Ca avance lentement, mais ce n'est pas parfait.



<http://cjoint.com/?ffbKtOvCMI>

avance un peu le schimblink (compilation c++).

Sylvain.
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fd6ac6$0$12627$:

Vincent Torri a écrit :

Neanmoins, il y a 3 problemes (peut-etre lies):

1) La premiere fois que j'appuie sur 't', j'active la transparence,
mais le bord de la fenetre disparait (la partie non-client)



oui cela semble être toujours le cas avec UpdateLayeredWindow, à tout
le moins lorsque le filtre ne joue que sur des extrêmes transparent
et opaque - SetLayeredWindowAttributes en jouant sur le canal alpha
permet d'obtenir un frame translucide.



J'ai trouve un site qui en parle et j'ai relu le code de Christian qui en
parle aussi. Apparemment, il faut envoyer le message WM_PRINT avec
PRF_NONCLIENT:

SendMessage(layer_window, WM_PRINT, (WPARAM)mask_dc,
PRF_NONCLIENT);

La partie non client est bien affichee mais dans la partie client :-).
Apparemment, il faut agrandir la partie geree par UpdateLayeredWindow a
non plus la seule partie client, mais la totalite de la fenetre. Bon, il
y a de l'espoir :-)

2) la deuxieme fois que j'appuis sur 't', c'est cense desactiver la
transparence, mais ca ne re-affiche pas correctement la fenetre avec
le contenu initial. J'ai essaye d'envoyer le message WM_PAINT pour
forcer l'affichage, mais ca ne marche pas.



il faut donc sauvegarder les épaisseurs du cadre pour redimensionner
la fenêtre et forcer le réaffichage du cadre - SetWindowPos permet
de faire cela.



nickel ! merci !

Vincent
Avatar
Sylvain SF
Vincent Torri a écrit :

J'ai trouve un site qui en parle et j'ai relu le code de Christian qui en
parle aussi. Apparemment, il faut envoyer le message WM_PRINT avec
PRF_NONCLIENT:

SendMessage(layer_window, WM_PRINT, (WPARAM)mask_dc,
PRF_NONCLIENT);



oui, je commence à comprendre également.
parce que la fenêtre complète est mise en cache, il faut évidemment
donner une bitmap complète de la fenêtre à UpdateLayeredWindow,
ie que le HDC source (mask_dc) contienne une bitmap (mask_bitmap)
représentant toute la fenêtre, or ton 'mask_bitmap' est créé avec
la dimension de la zone cliente, il faut ici le zone complète
(GetWindowRect et non GetClientRect).
également il faut dessiner le frame dans cette bitmap, via un
WM_PRINT(PRF_NONCLIENT) ou directement par un DrawFrameControl,
et finalement la zone cliente en calculant son origine.

La partie non client est bien affichee mais dans la partie client :-).
Apparemment, il faut agrandir la partie geree par UpdateLayeredWindow a
non plus la seule partie client, mais la totalite de la fenetre. Bon, il
y a de l'espoir :-)



tu répondais précedemment:

"Ce petit programme est pour moi un prelude a l'integration
"de la gestion des fenetres non rectangulaire et translucides
"dans cette bibliotheque"

ma compréhension (la logique?) voudrait qu'une fenêtre non
rectangulaire ne dispose pas de cadre (en tout cas pas celui
de la zone non-client d'une fenêtre normale, un cadre custom
pouvant être dessiné selon le patatoïde de la fenêtre créée).

la question de la NC-area est donc a priori irrévélante pour
de telles fenêtres; tout en étant nécessaire pour les fenêtres
rectangulaires et translucides; ces 2 types de fenêtres demandant
donc 2 gestions.

Sylvain.
Avatar
Sylvain SF
Vincent Torri a écrit :

le probleme peut-il venir du fait que les couleurs doivent etre pre-
multipliees ? dans ce cas, il est peut-etre possible de s'en sortir avec
ULW_ALPHA, mais en remplissant correctement le mask_bitmap



la pré-multiplication des couleurs, ie:

struct PtOfBitmap {
byte r, g, b, a;
};

PtOfBitmap pt;
pt.r = MulDiv( pt.r, pt.a, 255 );
pt.g = MulDiv( pt.g, pt.a, 255 );
pt.b = MulDiv( pt.b, pt.a, 255 );

n'est utile que si la bitmap (32bits) contient un canal alpha
pré-initialisé, par exemple parce qu'elle résulte du chargement
d'un format d'image gérant cette transparence (eg .png).

SF.
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fd972a$0$12645$:

Vincent Torri a écrit :

J'ai trouve un site qui en parle et j'ai relu le code de Christian
qui en parle aussi. Apparemment, il faut envoyer le message WM_PRINT
avec PRF_NONCLIENT:

SendMessage(layer_window, WM_PRINT, (WPARAM)mask_dc,
PRF_NONCLIENT);



oui, je commence à comprendre également.
parce que la fenêtre complète est mise en cache, il faut évidemment
donner une bitmap complète de la fenêtre à UpdateLayeredWindow,
ie que le HDC source (mask_dc) contienne une bitmap (mask_bitmap)
représentant toute la fenêtre, or ton 'mask_bitmap' est créé avec
la dimension de la zone cliente, il faut ici le zone complète
(GetWindowRect et non GetClientRect).
également il faut dessiner le frame dans cette bitmap, via un
WM_PRINT(PRF_NONCLIENT) ou directement par un DrawFrameControl,
et finalement la zone cliente en calculant son origine.



oui, j'en suis venu a cette conclusion aussi, sans pour autant avoir les
reponses exactes :-) J'ai un peu essaye et je n'ai pas reussi a gerer
correctement les bords.

tu répondais précedemment:

"Ce petit programme est pour moi un prelude a l'integration
"de la gestion des fenetres non rectangulaire et translucides
"dans cette bibliotheque"

ma compréhension (la logique?) voudrait qu'une fenêtre non
rectangulaire ne dispose pas de cadre (en tout cas pas celui
de la zone non-client d'une fenêtre normale, un cadre custom
pouvant être dessiné selon le patatoïde de la fenêtre créée).



Ha, la encore, c'est un manque de precision de ma part. La gestion des
bords sous Linux est faite independamment de la fenetre (c'est le
gestionnaire de fenetre qui s'en occuppe), c'est une des tres grosses
differences entre les fenetres sous Windows et sous Unix. Donc, une
fenetre sous linux correspondrait uniquement a la partie client d'une
fenetre de Windows. Donc une fenetre transparente sous Linux peut tres
facilement avoir un bord, et c'est en effet le comportement par defaut si
on gere la transparence et si on n'enleve pas les bords.

Neanmoins, je suis d'accord avec toi, une fenetre non rectangulaire ne
devrait pas avoir de bords. C'est juste que je voulais avoir le meme
comportement sous Windows et sous Linux. Mais bon, c'est vraiment tres
tres galere sous Windows.

Je demanderai au developpeur principal si ne pas avoir de bord est genant
ou pas.

Pour l'instant, je vais me contenter de ne pas avoir de bords. On verra
pour la suite et je reviendrai avec de nouvelles questions si j'ai
vraiment besoin d'avoir les bords.

la question de la NC-area est donc a priori irrévélante pour
de telles fenêtres; tout en étant nécessaire pour les fenêtres
rectangulaires et translucides; ces 2 types de fenêtres demandant
donc 2 gestions.



En effet, et c'est la 2eme tache a laquelle je vais m'atteler (et qui me
reste a gerer au niveau de l'API de nos bibliotheques) : avoir la gestion
de la translucidite (le mot existe ??) pixel par pixel (et non une
translucidite uniforme qui est tres facile a avoir). Je pense que je dois
utiliser la encore UpdateLayeredWindow().

Vincent

PS: Au cas ou tu te demanderais ce que sont ces bibliotheques, je porte
sous Windows les bibliotheques utilisees par le gestionnaire de fenetres
Enlightenment. Un exemple d'utilisation de ces bibliotheques (orientees
graphisme) permet de faire ce genre de choses:

http://calaos.fr/pub/video/calaos_media_music.ogg
http://calaos.fr/pub/video/calaos_widgets.ogg
Avatar
Sylvain SF
Vincent Torri a écrit :

oui, j'en suis venu a cette conclusion aussi, sans pour autant avoir les
reponses exactes :-) J'ai un peu essaye et je n'ai pas reussi a gerer
correctement les bords.



en fait c'est simple: quand on a (enfin) des bords, on n'en veut plus!

<http://cjoint.com/?ffolcvSNTT>

selon l'image .bmp source, j'utilise SetLayeredWindowAttributes
si 24 bits (pas de canal alpha) ou UpdateLayeredWindow si 32 bits.

l'avantage de SetLayeredWindowAttributes est que l'on update
facilement le contenu; avec UpdateLayeredWindow et contrairement
à ce que je pensais, il n'y a pas moyen d'updater ce contenu,
il faut recréer un layer - en altérant la bitmap kivabien si
c'est possible ou en le recréant.

Ha, la encore, c'est un manque de precision de ma part. La gestion des
bords sous Linux est faite independamment de la fenetre (c'est le
gestionnaire de fenetre qui s'en occuppe), c'est une des tres grosses
differences entre les fenetres sous Windows et sous Unix. Donc, une
fenetre sous linux correspondrait uniquement a la partie client d'une
fenetre de Windows. Donc une fenetre transparente sous Linux peut tres
facilement avoir un bord, et c'est en effet le comportement par defaut si
on gere la transparence et si on n'enleve pas les bords.

Neanmoins, je suis d'accord avec toi, une fenetre non rectangulaire ne
devrait pas avoir de bords. [...]



et, hélas, SetLayeredWindowAttributes les conserve par défaut ...

Mais bon, c'est vraiment tres tres galere sous Windows.



mais non.

PS: Au cas ou tu te demanderais ce que sont ces bibliotheques, je porte
sous Windows les bibliotheques utilisees par le gestionnaire de fenetres
Enlightenment. Un exemple d'utilisation de ces bibliotheques (orientees
graphisme) permet de faire ce genre de choses:

http://calaos.fr/pub/video/calaos_media_music.ogg
http://calaos.fr/pub/video/calaos_widgets.ogg



si c'est pour proposer un window manager de remplacement à Win Vista
ou Win.7, j'ai peur que cela soit énormément d'effort pour rien ...

de même, si la lib. vise à faciliter le dév. de widgets, des APIs
MS récentes le font; reste une lib. générique pour construire son GUI,
la mode chez les gamins est plutôt win.form ou net.form (ou je sais pas
quoi mais une horreur), bref c'est pas gagné, les frameworks tels Qt
sont très peu utilisés sous Win32/64, cela reste néanmoins un beau défi.
courage.

Sylvain.
Avatar
Vincent Torri
Sylvain SF écrivait
news:49fe1eb2$0$17070$:

en fait c'est simple: quand on a (enfin) des bords, on n'en veut plus!



hahaha, oui, c'est moche, mais si ca peut avoir le meme comportement que
Linux, ca me va. Je gererai la partie sans bord aussi.

<http://cjoint.com/?ffolcvSNTT>



ton exemple marche nickel. Il faut que je regarde en detail pour
l'appliquer a mon exemple

selon l'image .bmp source, j'utilise SetLayeredWindowAttributes
si 24 bits (pas de canal alpha) ou UpdateLayeredWindow si 32 bits.



ok.

l'avantage de SetLayeredWindowAttributes est que l'on update
facilement le contenu; avec UpdateLayeredWindow et contrairement
à ce que je pensais, il n'y a pas moyen d'updater ce contenu,
il faut recréer un layer - en altérant la bitmap kivabien si
c'est possible ou en le recréant.

Mais bon, c'est vraiment tres tres galere sous Windows.



mais non.



est-ce le manque de doc ? Avant de poser mes questions ici, j'ai cherche,
pendant une semaine, sur google, pour (essayer de) trouver ce que je
voulais. Et je n'ai rien trouve d'explicite. Toujours des commentaires
sybillins.

PS: Au cas ou tu te demanderais ce que sont ces bibliotheques, je
porte sous Windows les bibliotheques utilisees par le gestionnaire de
fenetres Enlightenment. Un exemple d'utilisation de ces bibliotheques
(orientees graphisme) permet de faire ce genre de choses:

http://calaos.fr/pub/video/calaos_media_music.ogg
http://calaos.fr/pub/video/calaos_widgets.ogg



si c'est pour proposer un window manager de remplacement à Win Vista
ou Win.7, j'ai peur que cela soit énormément d'effort pour rien ...



ha non, je ne m'attaquerai pas a ca... Pas moi. J'ai d'autres trucs a
faire, et comme tu dis, ca sera certainement inutile.

de même, si la lib. vise à faciliter le dév. de widgets, des APIs
MS récentes le font; reste une lib. générique pour construire son GUI,
la mode chez les gamins est plutôt win.form ou net.form (ou je sais
pas quoi mais une horreur), bref c'est pas gagné,



Ces libs sont plus que des widgets. Il y a une distinction entre la gui
(decrite par un fichier texte) et le code, ce qui permets aux designers
de creer l'interface et a la tester sans avoir a faire de code du tout.
Le but etant de creer des interfaces qui sont impressionnantes et faciles
a faire (bon, derriere, il faut un bon designer), d'une maniere
differente de ce que proposent les toolkits de widgets habituels tels que
Qt, GtK, etc... qui sont tous bases sur de l'oriente objet.

les frameworks tels
Qt sont très peu utilisés sous Win32/64, cela reste néanmoins un beau
défi. courage.



oui, je me doute que les outils microsoft sont utilises en priorite. Et
c'est aussi un challenge pour moi (je porte aussi les libs sous Win CE,
et la, c'est vraiment un challenge :-) Je dois etre un peu fada.

merci pour les explications !

Vincent
1 2