Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

FENETRE NON RECTANGULAIRE (WIN32)


Information sur la source

Catégorie :API Niveau : Débutant Date de création : 24/02/2005 Date de mise à jour : 07/03/2005 22:51:21 Vu / téléchargé: 6 767 / 886

Note :
7,8 / 10 - par 5 personnes
7,80 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (21)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
Façon la plus simple de créer une fenêtre non rectangulaire à l'aide d'un bmp et de la transparence.
Le prog tourne uniquement sur windows 2000 ou supérieur! C'est testé au lancement (merci BruNews).
Touche Echap pour quitter.
Codé en C/WIN32, compilé sous VS.NET 2003, testé sous XP.
 

Source

  • #define _WIN32_WINNT 0x0500
  • #include <windows.h>
  • #include "resource.h"
  • HBITMAP hBmp = 0;
  • HINSTANCE hInst = 0;
  • SIZE SizeBmp = {128, 128};
  • char szAppName[] = "BmpPerso";
  • LRESULT CALLBACK AppWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  • {
  • switch(uMsg) {
  • case WM_CREATE:
  • hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BMP));
  • SetLayeredWindowAttributes(hWnd, RGB(255, 0, 255), 0, LWA_COLORKEY);
  • return 0;
  • case WM_ERASEBKGND: {
  • HDC hDC, hMemDC;
  • HBITMAP hOldBmp;
  • hDC = (HDC)wParam;
  • if(hBmp) {
  • hMemDC = CreateCompatibleDC(hDC);
  • hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);
  • BitBlt(hDC, 0, 0, SizeBmp.cx, SizeBmp.cy, hMemDC, 0, 0, SRCCOPY);
  • SelectObject(hMemDC, hOldBmp);
  • DeleteDC(hMemDC);
  • }
  • }
  • return 1;
  • case WM_NCHITTEST:
  • return HTCAPTION;
  • case WM_KEYDOWN:
  • if(wParam == VK_ESCAPE) PostMessage(hWnd, WM_CLOSE, 0, 0);
  • return 0;
  • case WM_DESTROY:
  • DeleteObject(hBmp);
  • PostQuitMessage(0);
  • return 0;
  • }
  • return DefWindowProc(hWnd, uMsg, wParam, lParam);
  • }
  • int InitInstance()
  • {
  • WNDCLASSEX wclsx;
  • wclsx.cbSize = sizeof(WNDCLASSEX);
  • wclsx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  • wclsx.lpfnWndProc = AppWndProc;
  • wclsx.cbClsExtra = 0;
  • wclsx.cbWndExtra = 0;
  • wclsx.hInstance = hInst;
  • wclsx.hIcon = 0;
  • wclsx.hCursor = LoadCursor(NULL, IDC_ARROW);
  • wclsx.hbrBackground = 0;
  • wclsx.lpszMenuName = 0;
  • wclsx.lpszClassName = szAppName;
  • wclsx.hIconSm = 0;
  • return RegisterClassEx(&wclsx);
  • }
  • DWORD VerifWin2KMini()
  • {
  • OSVERSIONINFO osvi;
  • osvi.dwPlatformId = osvi.dwMajorVersion = 0;
  • osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  • GetVersionEx(&osvi);
  • if(osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0;
  • return (osvi.dwMajorVersion >= 5);
  • }
  • int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int)
  • {
  • MSG msg;
  • if(!VerifWin2KMini()) return 0;
  • hInst = hInstance;
  • if(!InitInstance()) return 0;
  • HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szAppName, szAppName,
  • WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS,
  • CW_USEDEFAULT, CW_USEDEFAULT, SizeBmp.cx, SizeBmp.cy,
  • 0, 0, hInst, 0);
  • ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd);
  • while(GetMessage(&msg, NULL, 0, 0)) {
  • TranslateMessage(&msg);
  • DispatchMessage(&msg);
  • }
  • return msg.wParam;
  • }
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include "resource.h"

HBITMAP hBmp = 0;
HINSTANCE hInst = 0;
SIZE SizeBmp = {128, 128};
char szAppName[] = "BmpPerso";

LRESULT CALLBACK AppWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch(uMsg) {
		case WM_CREATE:
			hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BMP));
			SetLayeredWindowAttributes(hWnd, RGB(255, 0, 255), 0, LWA_COLORKEY);
			return 0;
		case WM_ERASEBKGND: {
			HDC hDC, hMemDC;
			HBITMAP hOldBmp;
			hDC = (HDC)wParam;
			if(hBmp) {
				hMemDC = CreateCompatibleDC(hDC);
				hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);
				BitBlt(hDC, 0, 0, SizeBmp.cx, SizeBmp.cy, hMemDC, 0, 0, SRCCOPY);
				SelectObject(hMemDC, hOldBmp);
				DeleteDC(hMemDC); 
			}
	      }
			return 1;
		case WM_NCHITTEST:
			return HTCAPTION;
		case WM_KEYDOWN:
			if(wParam == VK_ESCAPE) PostMessage(hWnd, WM_CLOSE, 0, 0);
			return 0;
		case WM_DESTROY:
			DeleteObject(hBmp);
			PostQuitMessage(0);
			return 0;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int InitInstance()
{
	WNDCLASSEX wclsx;
	wclsx.cbSize        = sizeof(WNDCLASSEX);
	wclsx.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wclsx.lpfnWndProc   = AppWndProc;
	wclsx.cbClsExtra    = 0;
	wclsx.cbWndExtra    = 0;
	wclsx.hInstance     = hInst;
	wclsx.hIcon         = 0;
	wclsx.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wclsx.hbrBackground = 0;
	wclsx.lpszMenuName  = 0;
	wclsx.lpszClassName = szAppName;
	wclsx.hIconSm       = 0; 
	return RegisterClassEx(&wclsx);
}

DWORD VerifWin2KMini()
{
	OSVERSIONINFO osvi;
	osvi.dwPlatformId = osvi.dwMajorVersion = 0;
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osvi);
	if(osvi.dwPlatformId != VER_PLATFORM_WIN32_NT) return 0;
	return (osvi.dwMajorVersion >= 5);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int)
{
	MSG msg;
	if(!VerifWin2KMini()) return 0;
	hInst = hInstance;
	if(!InitInstance()) return 0;
	HWND hWnd = CreateWindowEx(WS_EX_LAYERED, szAppName, szAppName, 
										WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS,
										CW_USEDEFAULT, CW_USEDEFAULT, SizeBmp.cx, SizeBmp.cy,
										0, 0, hInst, 0);
	ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd);
	while(GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

27 février 2005 16:30:18 :
- Modification mineure grâce au commentaire de Boing (merci à lui).
07 mars 2005 22:51:21 :
- Dernière mise à jour (voir le commentaire de Boing pour les détails).

Commentaires et avis

signaler à un administrateur
Commentaire de Boing le 25/02/2005 09:14:24

Hello,

Tu devrais plutôt afficher ton Bitmap en réponse à WM_ERASEBKGND comme ça tu évites plus tard des réaffichages intempestifs car WM_PAINT est appelé pour toutes les invalidations et WM_ERASEBKGND uniquement lorsqu'on invalide avec erase = TRUE.

Pour faire la "même" chose à peu prés et que cela fonctionne en plus sous 98 on utilise la fonction SetWindowRgn. On calcul la région du bitmap de fond et on restreint la fenêtre à cette région. Par contre, avec SetWindowRgn, on ne gère pas les transparences partielles.

Benoît

signaler à un administrateur
Commentaire de minet03 le 25/02/2005 18:20:38

ah quel dommage !!! c'est un code si intéressant, le seul problème c'est que tu ne commente rien dedans !!! c'est très dommage. Si tu pouvais juste rajouter des commentaire sur les ligne les plus importante, et pourquoi pas expliqué à quoi servent les fonctions (surtout la troisième, celle après l'enregistrement de la classe). 6/10

signaler à un administrateur
Commentaire de Urgo le 25/02/2005 18:55:14

C'est pourtant clair :

DWORD VerifWin2KMini()  // Vérifie si l'OS est W2K minimum (cf description de la source), l'appli ne démarrera pas si tu as Windows 98 par exemple.
Pk cette fonction? Tout simplement à cause de l'API SetLayeredWindowAttribute (pour la transparence) => VOIR MSDN

#define _WIN32_WINNT 0x0500 // Instruction qui indique que l'on utilise W2K ou supérieur, permet une compilation sans erreur => VOIR MSDN pour précisions

SIZE SizeBmp = {128, 128}; // Largeur puis hauteur du bmp utilisé

Voir http://www.cppfrance.com/code.aspx?ID=10721 pour comparer le nombre de lignes de code; moi je ne tourne plus sur Windows 98 depuis un bon moment!

Ici je ne suis pas obligé de traiter le message WM_ERASEBKGND, car le membre hbrBackground de la structure WNDCLASSEX est passé à zéro lors de la création de la classe de la fenêtre.

Bye
Urgo

signaler à un administrateur
Commentaire de minet03 le 25/02/2005 20:28:53

ok merci (mais c'est sans doute l'expression W2K que je ne comprend pas). Cela dit ces commentaire seront bien mieux dans le code.

signaler à un administrateur
Commentaire de Urgo le 25/02/2005 21:03:33

1Ko = 1024 octets
W2K = Windows 2000

Faut lire la description de la source avant de se ruer sur le code...

Va faire un tour sur http://msdn.microsoft.com si tu ne connais pas, tu y trouveras ton bonheur...

Télécharge JR4 et CP5 (si c'est pas déjà fait), ici :
http://brunews.free.fr/brunews/index.htm
(site de notre cher admin CS (Codes-Sources, pas le FPS non de dieu! :p) : le fabuleux BruNews)

Bye
Urgo

signaler à un administrateur
Commentaire de Boing le 26/02/2005 13:54:06

Hello Urgo,

C justement parceque tu mets hbrBackground à 0 (ou NULL) que tu devrais faire ton affichage du bitmap de fond de la fenêtre dans WM_ERASEBKGND...
C pas obligatoire, c'est juste plus optimisé.

Quand au support de Windows 98... Ca dépend de l'utilisateur visé. Je suis d'accord avec toi, si tu ne vises pas 98 le code que tu proproses est mieux. D'ailleurs je t'ai mis 8/10 pour la simplicité et la clareté de l'exemple.

a+
Benoît

signaler à un administrateur
Commentaire de Urgo le 26/02/2005 14:45:04

Ok, cette fois-ci j'ai compris. Merci à toi!

Le code sera mis à jour d'ici demain.

Bye
Urgo

signaler à un administrateur
Commentaire de yoyo269 le 06/03/2005 10:36:06

Bravo Urgo,

très bonne source.
Moi je dis ça vaut bien un 8/10.

YOYO, @+.

signaler à un administrateur
Commentaire de Boing le 07/03/2005 09:46:11

Hello Urgo,

Juste un petite remarque supplémentaire, Lorsque tu utilises SelectObject, tu dois sauvegarder le Handle de l'objet précédent et le rétablir une fois que tu as fini. De cette façon, GDI est capable de faire le nettoyage.

donc :
HBITMAP OldBmp = NULL;
hMemDC = CreateCompatibleDC(hDC);
OldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);
BitBlt(hDC, 0, 0, SizeBmp.cx, SizeBmp.cy, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, OldBmp);
DeleteDC(hMemDC);

Le gros problème, c'est que le debugger intégré à Visual ne gère pas les ressources et GDI donc on ne sait jamais ce qui se passe vraiment sauf à regarder les ressources de l'OS qui diminuent... Ou alors il faut utiliser un autre debugger.

Petite astuce aussi :
Tu interceptes WM_LBUTTONDOWN et tu le transfères sur WM_NCLBUTTONDOWN, tu peux utiliser WM_NCHITTEST et renvoyer HTCAPTION. C'est pratique, tu peux renvoyer la valeur que tu veux, HTCLOSE pour une zone de fermeture,  HTNOWHERE pour une zone non cliquable...

A+
Benoît

signaler à un administrateur
Commentaire de Urgo le 07/03/2005 23:01:25

Source mise à jour (sans doute la dernière).
Je te remerci Benoît pour ton aide!

Ciao
Christian

signaler à un administrateur
Commentaire de _Jonathan le 10/03/2005 15:41:23

J'utilise devc++, et apparement LWA_COLORKEY n'est pas déclaré...
J'ai cherché dans windows.h et winuser.h mais je ne l'ai pas trouvé.
Meme sur msdn, j'ai trouvé un exemple, mais pas le code de LWA_COLORKEY...
Je pourré savoir le nombre que cette constante défini? ^^

merci!

signaler à un administrateur
Commentaire de _Jonathan le 10/03/2005 15:53:47

Un autre probleme :
SetLayeredWindowAttributes n'est pas déclarée non plus...
Quelqu'un pourait m'aider?

signaler à un administrateur
Commentaire de yoyo269 le 10/03/2005 17:19:37

Pour Jonathan :

#define LWA_COLORKEY    0x01

et

SLWA_FUNC MySetLayeredWindowAttributes;
HMODULE hUser32 = GetModuleHandle("USER32.DLL");
if (!hUser32) return false;
MySetLayeredWindowAttributes = (SLWA_FUNC)GetProcAddress(hUser32, "SetLayeredWindowAttributes");

J'espère que ça te servira.

YOYO, @+.

signaler à un administrateur
Commentaire de _Jonathan le 10/03/2005 18:30:37

oui, merci, tout marche maintenant, j'ai trouvé une source qui l'expliquai ^^

merci, a+

signaler à un administrateur
Commentaire de pixelinf le 09/08/2005 22:41:15

Petit probleme sur le programme, il ne prend plus en compte les messages, par exemple pour le traitement de la touche espace :

case WM_KEYDOWN:
            if(wParam == VK_ESCAPE) PostMessage(hWnd, WM_CLOSE, 0, 0);
            return 0;

ça ne marche pas, est ce que vous avez rencontré le même problème ou je suis le seul ? merci d'avance.

signaler à un administrateur
Commentaire de Urgo le 14/08/2005 18:14:51

OUI, tu es "le seul" (Da Only One) à avoir ce problème, merci de finir cette conversation par mp (si besoin est) afin d'éviter toute pollution avec des commentaires HS.

signaler à un administrateur
Commentaire de pixelinf le 14/08/2005 20:56:51

tu es susceptible on dirait, je n'ai pas critiqué ce que tu as fait, mais c'est juste chez moi il y a un problème, enfin bref!
En attendant, tu aurais dû t'abstenir de mettre ce genre de "commentaire".
Tu as le droit de fermer ta bouche mec ok :)

Bonne soirée

signaler à un administrateur
Commentaire de Urgo le 14/08/2005 23:10:53

Gros malin, j'ai été tout à fait correct dans ma réponse, excepté le fait que je ne t'ai pas vouvoyer, mais vu que tu n'as pas voulu donner ton âge je me suis accordé cette liberté.
Et puis ce genre de commentaire "ça marche pas", ça m'avance vachement...
Ca te fait ça uniquement avec mon exe, ou aussi lorsque tu compiles? Tu travailles sous dev, sous vs....?
Oui effectivement je suis direct dans mes propos et ça dérange, mais si tu n'es pas content tu peux toujours aller voir ailleurs, rien ne t'en empêche.

Je n'ai jamais refuser d'aider qqun lorsque cela était dans mes capacités.

signaler à un administrateur
Commentaire de pixelinf le 14/08/2005 23:25:33

Salut, Urgo repartons du bon pied ok, j'ai 21 ans voilà pour info :).

Donc enfait, je sais pas si ça vient de moi, mais desfois il ne prend pas en compte le fait que j'appuis sur echap, je suis sous devcpp, c'est pas ton exe qui marche pas, c'est quand je je prend ton code et je compile, il faut peut être faire une manip particuliere pour la compile ou direct ? De plus quand je met l'image dans le fichier ressource ça marche pas, il n'affiche pas la fenêtre, je susi obligé de charger une image de l'extérieure, tu sais c'est dû à quoi ?

(Cependant ton code est super c'est ce que je cherchais).

Merci d'avance.


signaler à un administrateur
Commentaire de Urgo le 15/08/2005 00:10:42

J'en ai aucune idée, faudrais que tu vois ça avec un utilisateur de dev-cpp...
Dans cette source j'utilise LoadBitmap(..), y'a rien de mystique si tu connais le Win32.

Ciao

signaler à un administrateur
Commentaire de Ombitious_Developper le 10/12/2006 13:06:19

Salut:

Très bonne source. (8/10)

Juste une question: Comment ajouter des boutons sans pourtant gâcher l'images utiliser comme fond?

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,624 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.