Arnor2000
Messages postés32Date d'inscriptionmercredi 17 mars 2004StatutMembreDernière intervention24 novembre 2004
-
5 juil. 2004 à 18:25
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013
-
8 juil. 2004 à 08:14
Bonjour à tous !
Je fait un composant pour améliorer une picturebox avec plein de fonctionnalités (Je dépose la source dès que je l'ai terminée, promis !), mais j'ai un problème.
J'ai une image dans une stdPicture (imgImage as StdPicture) et je m'en sert pour mettre à jour UserControl.Picture, et je veux redimentionner mon imgImage pour qu'elle prenne la taille de mon controle. Donc en fait j'ai ma procédure Refresh (qui sert à rafraichir mon controle) qui appel une autre procédure qui adapte imgImage à la taille de mon controle avec la méthode PaintPicture (par l'intermédiaire d'une PictureBox temporaire imgTemp), jusque là, pas de problème.
Mais c'est dès que ma nouvelle image recalculée s'applique dans UserControl.MaskPicture (pour faire la transparence déjà géré par mon controle) que ca prend au moins une seconde à charger... ce qui est étrange c'est que juste avant j'applique ma nouvelle image recalculée dans UserControl.Picture et là le chargement est instantané !
Je met le code des mes deux procédures pour que vous voyez mieux ce que je veux dire :
Private Sub ImageControle()
imgTemp.Height = UserControl.Height
imgTemp.Width = UserControl.Width
imgTemp.AutoRedraw = True
imgTemp.Refresh
imgTemp.PaintPicture imgImage, 0, 0, UserControl.Width, UserControl.Height
imgTemp.Refresh
Set imgImage = imgTemp.Image
End Sub
Private Sub Refresh()
UserControl.Cls
If numAdapter = Image_au_Controle And imgImage <> 0 Then Call ImageControle
UserControl.Picture = imgImage
UserControl.MaskColor = lngCouleurTransparence
If bolTransparence Then
UserControl.MaskPicture = imgImage
UserControl.BackStyle = 0
Else
UserControl.BackStyle = 1
End If
End Sub
J'ai aussi remarqué que si je ne redimentionne pas imgTemp (au début de ImageControle), tout s'affiche immédiatement... mais ce n'est pas une solution de mettre imgTemp très grand sans le redimentionner car à ce moment là quand j'enregistrement les propriétés dans le WriteProperty ca me fait une Form1.frx grosse de 3mo ! Et ca prend du temps à l'écriture et à la lecture !
Bon voila en gros mes problèmes ! Si quelqu'un a une explication, une autre méthode, ou une astuce pour palier à ce problème, merci beaucoup d'avance !!
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 6 juil. 2004 à 09:43
Utilise plutôt la fonction de l'API StretchBlt au lieu de PaintPicture. De Même, au lieu d'utiliser des stdPicture, utilise plutôt des contexte compatible avec ton usercontrol, que tu peux créer grâce à la fonction de l'API CreateCompatibleDC.
Arnor2000
Messages postés32Date d'inscriptionmercredi 17 mars 2004StatutMembreDernière intervention24 novembre 2004 6 juil. 2004 à 16:02
Je ne sais pas comment utiliser CreateCompatibleDC, d'ailleur il ne vaudrait mieux pas utiliser CreateCompatibleBitmap ?
En fait une fois que j'ai créé un HDC compatible à mon UserControl(il faut qu'il soit compatible à quoi, en fait ?), il faut faire comment pour charger une image dedans ?
Je pense que c'est dans ce Property Set qu'il faut le charger, au départ il est comme ca :
Public Property Set Image(ByVal Value As StdPicture)
Set imgImage = Value
Call Refresh
MsgBox HDCimage
PropertyChanged "Image"
End Property
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 6 juil. 2004 à 16:49
Crée une variable privée qui stocke le handle de ton DC.
Ensuite, créer un DC compatible avec ton UserControl :
CreateCompatibleDC(UserControl.hdc)
Ensuite, il faut charger ton image dans ce DC avec la fonction LoadImage, mais ton value doit alors être de type String ! :
LoadImage(App.hInstance, Value, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
Et ensuite, tu n'a plus qu'à afficher ton image dans le Paint de ton contrôle grâce à la fonction StretchBlt.
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 6 juil. 2004 à 18:25
Ben à mon avis, ton problème de lenteur est due, d'une, que VB est très lent pour la manipulation d'umage, et de deux, que la transparence ralentit l'affichage !
Si le résultat est encore trop lent, tu peux toujours travailler avec des régions plutôt que de gérer la transparence avec VB !
Public Property Let Image(ByVal Value As String)
HDCmemoire = CreateCompatibleDC(UserControl.hdc)
HDCimage = LoadImage(App.hInstance, App.Path & "\Domino noir.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE)
SelectObject HDCmemoire, HDCimage
GetObject HDCimage, Len(bmp), bmp
Call Refresh
PropertyChanged "Image"
End Property
Public Sub Refresh()
UserControl.Cls
HDCcontrole = GetDC(UserControl.hwnd)
If HDCmemoire <> 0 Then
StretchBlt(HDCcontrole, 0, 0, UserControl.Width, UserControl.Height, HDCmemoire, 0, 0, bmp.bmWidth, bmp.bmHeight, SrcCopy)
End If
UserControl.MaskColor = lngCouleurTransparence
If bolTransparence Then
UserControl.MaskPicture = UserControl.Picture
UserControl.BackStyle = 0
Else
UserControl.BackStyle = 1
End If
End Sub
Le seul endroit où ca peut coincer c'est dans le StretchBlt car je suis sur qu'il y a la bonne image de chargée car bmp.bmWidth par exemple me donne les bonnes valeur...
Pour ce qui est de la rapidité du MaskPicture, justement tant que je ne redientionne pas l'image chargée il est quasi instantané (je l'ai testé qui prennait moins d'une seconde avec une image en 2048*2048 contre plus de 10 secondes avec la méthode des régions !) donc je ne tient pas à changer de méthode !
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 7 juil. 2004 à 08:15
Quel est le problème rencontré ? Utilise-tu un ScaleMode en pixel pour ton usercontrol ?
10 secondes avec les régions ??? Ben dis donc, c'était loin d'être optimisé comme méthode alors ! Je parierais que c'était en utilisant la fonction de VB Point ? ou à la limite la fonction GetPixel ?
Non, pour les régions, pour obtenir un soupçon de rapidité, il faut manipuler directement les bits de l'image et non les pixels, tu y gagne énormément : voir ma source nommée Découpage rapide d'une feuille pour te donner un ordre d'idée ;-)
Arnor2000
Messages postés32Date d'inscriptionmercredi 17 mars 2004StatutMembreDernière intervention24 novembre 2004 7 juil. 2004 à 17:03
dsl d'avoir mis si longtemps, j'ai regardé tes sources pour essayer de comprendre ce qui m'arrive...
en fait je n'arrive pas à mettre l'image que j'ai dans HDCmemoire dans UserControl.Picture, en fait au mieux je peux faire UserControl.hdc mais ca marche pas...
Le mieux que j'ai obtenu c'est que ce soit tout blanc en passant par un PictureBox caché.
Ce qui me gène vraiment je pense que c'est que UserControl.Picture n'ait pas de hdc ce qui m'empèche d'utiliser Stretchbtl qui a besoin du hdc de la destination.
Pour ce qui est de la rapidité de maskPicture, tu devrait l'essayer toi-même, il suffit de créer un nouveau controle personnalisé, et de remplir MaskColor, MaskPicture et puis Picture en passant
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 7 juil. 2004 à 19:06
Le usercontrol possède bien un DC rattaché : pour récupèrer son hanlde, c'est bien UserControl.hDC ! Faut pas oublié de raffraichir l'affichage après l'appel de StretchBlt !
Pour le MaskPicture, je connais t'en fait pas, mais je le trouve très lent : j'ai fait une source (ou du moins j'ai commencé) de bouton personnalisable, et avec la transparence, dès que le bouton est assez grand, ca devient lent !
Arnor2000
Messages postés32Date d'inscriptionmercredi 17 mars 2004StatutMembreDernière intervention24 novembre 2004 7 juil. 2004 à 23:24
J'ai réussit à avoir mon image qui s'affiche une fraction de seconde quand je passe d'un fond opaque à un fond transparent ! Je n'arrive toujours pas à comprendre pourquoi à ce moment là et pas tout le temps, mais en tout cas ce dont je suis sur c'est que j'ai passé mon image dans le UserControl en faisant StretchBlt(UserControl.hdc, 0, ... et que mon UserControl.Picture est vide alors que c'est lui qu'il faut remplir non ?
En fait mon problèmec'est surtout que je n'y connais rien aux DC et à cette méthode pour afficher les images. Alors le mieux je pense, c'est que je commence par comprendre comment ca marche avant d'essayer de faire marcher mon controle... Je vais essayer de trouver un tutoriel qui m'explique tout a fond !
Merci beaucoup en tout cas de m'avoir montrer la piste à suivre pour arriver à un affichage rapide !
cs_DARKSIDIOUS
Messages postés15814Date d'inscriptionjeudi 8 août 2002StatutMembreDernière intervention 4 mars 2013130 8 juil. 2004 à 08:14
Ah oui forcément, si tu ne sais pas comment utiliser les API "classiques" pour l'affichage d'image, tu risque avoir du mal à les mettre en place.
Essaye déjà de manipuler les fonction BitBlt, puis StretchBlt dans des contrôles PictureBox standard, et ensuite, tu devrais mieux y arriver dans un UserControl.
Sache que la propriété Picture est directement liée à la propriété Image : La propriété Image stocke ce que tu dessine contrairement à la propriété Picture.