begin process at 2008 08 21 05:26:08
1 229 217 membres
48 nouveaux aujourd'hui
14 260 membres club

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 230 / 854

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

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;
}
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

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).
  • 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

Pub



Appels d'offres

Recherche developpeur ...
Budget : 700€
extraction dinformatio...
Budget : 300€
campagne Adwords
Budget : 5 000€

CalendriCode

Août 2008
LMMJVSD
    123
45678910
11121314151617
18192021222324
25262728293031

Boutique

Boutique de goodies CodeS-SourceS