IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Discussion :

Comportement de NtUserDrawIconEx()


Sujet :

Windows

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut Comportement de NtUserDrawIconEx()
    Bonjour,

    Je participe - à temps partiel - à la construction d'un programme qui reproduira un peux l'explorateur windows, en mieux, en utilisant les ressources de la carte vidéo.
    Ceci dit, MÊME les icônes seront dessinés avec une fonction utilisant des algorithmes d'anti-aliasing, genre supersampling - oui c'est lent mais on est encore au stade alpha.

    Pour l'instant, j'essaie de reproduire le comportement de NtUserDrawIconEX() - alias DrawIconEx(). Ensuite, j'implémenterai similaire, maiss utilisant des fonctions extraites de bibliothèques spécialisées.

    Mais... je désire ne pas dépenser trop de temps sur ce travail. Voilà pourquoi je m'essaie ici.

    Mon problème est qu'avec ma fonction actuelle, la qualité est plus que médiocre. Ce n'est rien comparé au travail fait par NtUserDrawIconEx().
    DrawIconEx utilise sûrement d'autres fonctions comme MaskBlt, TransparentBlt, etc. Je me débrouille, mais je ne connais pas bien GDI32.
    J'aimerais qu'on m'aide à raffiner mon code.

    Voici ladite fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    void __stdcall EXPERIMENTAL_DrawIcon(const HDC hDC, const int x, const int y, const HICON hIcon, const HBRUSH hbrBackground) {
    
    	//
    	// Note: On travaille avec des icones 48x48 seulement.
    	//
    
    	ICONINFO icon_info;
    	HDC hdcmem, hdctmp;
    	HBITMAP hbm_mem, hbm_old_1, hbm_old_2;
    
    	hdcmem    = CreateCompatibleDC(hDC);
    	hdctmp    = CreateCompatibleDC(hDC);
    	hbm_mem   = CreateCompatibleBitmap(hDC, 48, 48);
    	hbm_old_1 = SelectObject(hdcmem, hbm_mem);
    
    	GetIconInfo(hIcon, &icon_info);
    
    	if (hbrBackground) {
    		HBRUSH hbrOld;
    
    		hbrOld = SelectObject(hdcmem, hbrBackground);
    		PatBlt(hdcmem, 0x0, 0x0, 48, 48, PATCOPY);
    		SelectObject(hdcmem, hbrOld);
    	}
    
    
    	hbm_old_2 = SelectObject(hdctmp, icon_info.hbmMask);
    	BitBlt(hdcmem, 0x0, 0x0, 48, 48, hdctmp, 0x0, 0x0, SRCAND);
    
    	if (icon_info.hbmColor) {
    		SelectObject(hdctmp, icon_info.hbmColor);
    		BitBlt(hdcmem, 0x0, 0x0, 48, 48, hdctmp, 0x0, 0x0, SRCINVERT);
    	}
    
    	BitBlt(hDC, x, y, 48, 48, hdcmem, 0, 0, SRCCOPY);
    
    	SelectObject(hdctmp, hbm_old_2);
    	SelectObject(hdcmem, hbm_old_1);
    	DeleteObject(hbm_mem);
    	DeleteDC(hdctmp);
    	DeleteDC(hdcmem);
    }

    Voici des icônes dessinés avec NtUserDrawIconEx():



    Voici des icônes dessinés avec la fct expérimentale:




    Comme vous voyez, la différence est très choquante...
    Il y a du noir aux contours...



    Merci,

    Sincèrement,

    Array

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    C'est à cause des histoires d'Alpha Blending, que BitBlt() et cie ne supportent pas.
    Essaie la fonction AlphaBlend().
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    Je vois.

    Mais, dois-je utiliser AlphaBlend() pour appliquer le masque AND (noir et blanc) ET le masque XOR (couleur)? ou seulement pour l'un des masques?


    Merci bcp :-]

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Je ne sais même pas s'il y a un masque AND dans les icônes avec canal Alpha.
    Je pense que tu dois pouvoir te contenter du masque couleur, qui a sans doute une opacité de 100% partout où ça compte.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    Citation Envoyé par Médinoc
    Je ne sais même pas s'il y a un masque AND dans les icônes avec canal Alpha.
    C'est ce que j'aimerais essayer, mais la fonction AlphaBlend n'affiche simplement rien. J'ai regardé les valeurs de retour... elle 'return' un code de succès.
    Avec GetLastError(), niet...

    Comment AlphaBlend() fonctionne...?

    EDIT: Ha, après quelques recherches, j'ai découvert que AlphaBlend était une fonction à moitié réussie - M$ -, et qu'il fallait pré-multiplier les valeurs du canal RGB avec celles du canal alpha *sigh*.

  6. #6
    Membre confirmé Avatar de Array
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    210
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 210
    Par défaut
    Voilà, j'ai un autre problème.

    Dans ma fonction pour 'loader' un icon, appelée KqnLoadWinIcon, je fais divers appels avec les fonctions de resources:

    1. Appel à FindResource, avec le hModule de la DLL/EXE ayant été chargée avec LoadLibraryEx().
    2. Appel à LoadResource()
    3. Appel à LockResource()

    Rendu à lockresource, j'obtiens un pointeur sur une structure ICONIMAGE, définie comme suit (très similaire à une struct BITMAPINFO) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    typedef struct
    {
    	BITMAPINFOHEADER icHeader;    // DIB header
    	RGBQUAD          icColors[1]; // Color table
    	BYTE             icXOR[1];    // DIB bits for XOR mask
    	BYTE             icAND[1];    // DIB bits for AND mask
    } ICONIMAGE, *LPICONIMAGE;
    
    // Source: http://msdn.microsoft.com/en-us/library/ms997538.aspx
    Rendu là, j'essaie de passer un pointeur sur icColors à une fonction que j'ai fait, intitulée EXPERIMENTAL_DoAlphaPreMultiply(ic_colors, width, height).

    Mais, aussitôt que ma fonction essaie de modifier les données de icColors, bug!!! rien à faire - et ce n'est pas une erreur de mauvais déréférencement, le pointeur *est valide* -, comme si la mémoire était read-only.

    Alors que faire?
    Comment éditer les valeurs de icColors? Dois-je faire un malloc, puis copier TOUTE la structure avec memcpy? Ce serait vrm long... Y-a-t-il un moyen plus facile et/ou rapide?

    Merci,

    Array


    EDIT: En effet, comme cité ici, on ne peut écrire sur la mémoire chargée avec LoadLibraryEx() avec LOAD_LIBRARY_AS_DATAFILE. Sur Vista, il y a une option LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE qui me donnerait des privilèges d'écriture, mais... c'est seulement pour Vista et +, donc je ne peux l'utiliser...
    Y-aurait-t-il un moyen de déverouiller la mémoire par une autre fct?
    Est-ce que je pourrais remplacer la fonction LoadLibraryEx() avec une fonction écrite en C pur, qui ne ferait que copier l'exécutable dans la mémoire avec getchar(), malloc(), etc?

    Merci bcp

Discussions similaires

  1. open avec comport
    Par Goldocrack dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/04/2009, 08h12
  2. [HttpClient] comportement bizarre, saute des catch()...
    Par iubito dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 04/02/2004, 15h25
  3. [Sybase] Comportement bizarre d'une table
    Par sdozias dans le forum Sybase
    Réponses: 4
    Dernier message: 03/02/2004, 10h39
  4. [Free Pascal] Comportement de Exec
    Par néo333 dans le forum Free Pascal
    Réponses: 3
    Dernier message: 01/11/2003, 17h46
  5. Réponses: 2
    Dernier message: 22/09/2003, 11h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo