|
There was a little bug, after hide/show of the parent forms which contains the iconit, the iconit wasnt redrawed and it generated a GDI+ exception.
Adding this override to Iconits.cs will resolve the problem
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (this.Visible == true)
{
g = this.CreateGraphics();
draw(3);
}
}
-- Everything is possible, even the impossible! ^_^
|
|
|
|
|
Hi,
First, this simple control is really nice.
Ok, if you change the BackColor of a Iconit to, let's say, Transparent, because you want it to appear with its parent backcolor, when you move the mouse in and out the control, all of the bitmaps displayed during the process remain on screen. If you minimize the window or switch to another and back, the display is ok again.
I fixed this with a simple change in this line:
private void draw(int state)
{
...
// OLD LINE: g2.Clear(this.BackColor);
g2.Clear(((this.Parent == null) || (this.BackColor != Color.Transparent)) ? this.BackColor : this.Parent.BackColor);
...
}
This way, if you want your Iconit to inherit its parent backcolor just set the Iconit's backcolor to Transparent. You won't have to change backcolor for every Iconit if you decide to change your container backcolor (e.g. a Form). In case you need your Iconit with a different backcolor than the container's, well, just set the backcolor for your iconit.
Have a nice day.
|
|
|
|
|
If I use this component in the forms which is not rectangle( set the TransparencyKey) , it can't work properly .
How can I fix this problem ?
|
|
|
|
|
Read my "Bug + Fix: BackColor problem" post in this thread.
|
|
|
|
|
Thanks ~~~~~
|
|
|
|
|
Hi Hanifku,
Really enjoyed this, and I hope we'll see a new version soon incorporating the comments on speeding it up.
best, Bill
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis
|
|
|
|
|
I think this piece of code is great. I just found the following behavior which is kind of interesting:
When you hover the mouse and the icon is resized and is showing full color and you click or double click, nothing happens. Good.
If you do the same, wait until the tooltip shows up, and then click or double click, the icon loses its color.
Anyway, this is a really cool control. Congrats!!!
A.G
|
|
|
|
|
Hi,the click event handler you need to add in by each of it for your iconit button.
inside the windows Designer generate form code, each iconits button you use need to add. let say..
this.iconits7.Click += new System.EventHandler(this.iconits_Click);<br />
<br />
private void iconits_Click(object sender, System.EventArgs e)<br />
{<br />
<br />
}
I do realize that, but nothing affect much for me since if user click already, The other's action they concentrate on....
|
|
|
|
|
What I noticed is that the Tooltip stops showing after the first time you click on the Iconit. Once clicked, the tooltip won't show up again.
Ideas?
|
|
|
|
|
I noticed your routeen to update the alpha of the bitmap is using a slower method (actually, about the slowest there is). Here is a significantly faster version of your routeen. It uses an unsafe code function, which allows the use of pointers. This function will adjust the original alpha by the input alpha amount. Since it uses pointers to directly edit the memory of the copied bitmap, it is hundreds of times faster than using the GetPixel/SetPixel method of GDI+. In fact, GDI+ essentially does the first and last parts of my function (locking pixels, finding the pixel in memory, reading/writing it, and unlocking), every time you call GetPixel or SetPixel. By using an unsafe function with pointers, you eliminate the repetitive locking/seeking/unlocking of pixel data in memory, which greatly improves performance.
public unsafe Bitmap returnAlpha(Bitmap bmp, int alpha)
{
if (bmp.PixelFormat != PixelFormat.Format24bppRgb
&& bmp.PixelFormat != PixelFormat.Format32bppArgb)
throw new ArgumentException();
Bitmap bmpCopy = new Bitmap(bmp.Width, bmp.Height, PixelFormat.32bppArgb);
GraphicsUnit gu = GraphicsUnit.Pixel;
RectangleF rectF = bmp.GetBounds(ref gu);
Rectangle rect = Rectangle.Round(rectF);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.Read, bmp.PixelFormat);
rectF = bmpCopy.GetBounds(ref gu);
rect = Rectangle.Round(rectF);
BitmapData copyData = bmpCopy.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte* oPx = (byte*)bmpData.Scan0;
byte* cPx = (byte*)copyData.Scan0;
uint black = 255;
byte b, a;
for (int y=0; y<bmpData.Height; y++)
{
for (int x=0; x<bmpData.Width; x++)
{
*cPx = *oPx;
*(cPx+1) = *(oPx+1);
*(cPx+2) = *(oPx+2);
if (bmpData.PixelFormat == PixelFormat.Format32bppArgb)
{
b = *(oPx+3);
}
else
{
b = (byte)((*cPx + *(cPx+1) + *(cPx+2)) / 3);
}
a = 0;
if (b > 0)
{
a = (byte)Math.Min(255, Math.Max(0, b-alpha));
}
*(cPx+3) = a;
cPx += 4;
if (bmpData.PixelFormat == PixelFormat.Format24bppRgb)
oPx += 3;
else
oPx += 4;
}
if (bmpData.PixelFormat == PixelFormat.Format24bppRgb)
oPx += bmpData.Width;
}
copyBmp.UnlockBits(copyData);
bmp.UnlockBits(bmpData);
return copyBmp;
}
-- modified at 23:23 Thursday 20th April, 2006
|
|
|
|
|
For some reason, CodeProject is stripping whitespace from my code. Sorry for it being all packed together.
|
|
|
|
|
I've tested your method, it's fanstastic.
Just in case people donn't, above Jon Rista method need to add
using System.Drawing.Imaging;
******************************************
I alterred the iconits.cs few place to remove those resources killer
namespace alterred<br />
{ <br />
public class Iconits : System.Windows.Forms.UserControl<br />
{<br />
private System.ComponentModel.IContainer components;<br />
private System.Windows.Forms.Timer timer1;<br />
private System.Windows.Forms.ToolTip t=new ToolTip();<br />
Bitmap[] bmp; <br />
int flag;<br />
bool enter;<br />
Graphics g,g2;<br />
<br />
int imwidth,imheight;<br />
double curwidth,curheight;<br />
double addx,addy;<br />
Bitmap dblbuffer;<br />
bool blur=true;<br />
<br />
public Iconits()<br />
{<br />
InitializeComponent();<br />
bmp=new Bitmap[4]; <br />
for (int i=0;i<4;i++)<br />
bmp[i]=new Bitmap(Width,Height);<br />
dblbuffer=new Bitmap(Width,Height);
g2=Graphics.FromImage(dblbuffer); <br />
<br />
IconSize=new Size(Width/2,Height/2); <br />
g=this.CreateGraphics(); <br />
}<br />
<br />
<br />
protected override void Dispose( bool disposing )<br />
{<br />
if( disposing )<br />
{<br />
if(components != null)<br />
{<br />
components.Dispose();<br />
}<br />
}<br />
base.Dispose( disposing );<br />
}<br />
<br />
#region Component Designer generated code<br />
<br />
private void InitializeComponent()<br />
{<br />
this.components = new System.ComponentModel.Container();<br />
this.timer1 = new System.Windows.Forms.Timer(this.components);<br />
this.timer1.Interval = 10;<br />
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);<br />
this.BackColor = System.Drawing.SystemColors.Control;<br />
this.Name = "Iconits";<br />
this.Size = new System.Drawing.Size(160, 128);<br />
this.Paint += new System.Windows.Forms.PaintEventHandler(this.Iconits_Paint);<br />
this.MouseEnter += new System.EventHandler(this.Iconits_MouseEnter);<br />
this.MouseLeave += new System.EventHandler(this.Iconits_MouseLeave);<br />
<br />
}<br />
#endregion<br />
<br />
private void Iconits_Paint(object sender, System.Windows.Forms.PaintEventArgs e)<br />
{ <br />
<br />
draw(3); <br />
}<br />
<br />
private void calc()<br />
{<br />
curwidth=imwidth;<br />
curheight=imheight;<br />
<br />
addx=(double)(Width-imwidth)/10;<br />
addy=(double)(Height-imheight)/10;<br />
}<br />
<br />
<br />
private void draw(int state)<br />
{<br />
int st;<br />
<br />
if (blur)<br />
st=state;<br />
else<br />
st=0;<br />
<br />
<br />
g2.Clear(this.BackColor);<br />
g2.DrawImage(bmp[st],(int)((double)Width-curwidth)/2,(int)((double)Height-curheight)/2,(int)curwidth,(int)curheight); <br />
g.DrawImageUnscaled(dblbuffer,0,0); }<br />
<br />
private void timer1_Tick(object sender, System.EventArgs e)<br />
{ <br />
if (enter)<br />
{<br />
if (curwidth<Width)<br />
{<br />
curwidth+=addx;<br />
}<br />
<br />
if (curheight<Height)<br />
{<br />
curheight+=addy;<br />
}<br />
<br />
if (curwidth>=Width&&curheight>=Height) timer1.Enabled = false; flag++;<br />
}<br />
else<br />
{<br />
if (curwidth>imwidth)<br />
{<br />
curwidth-=addx;<br />
}<br />
<br />
if (curheight>imheight)<br />
{<br />
curheight-=addy;<br />
}<br />
<br />
if (curwidth<=imwidth&&curheight<=imheight) timer1.Enabled = false;<br />
<br />
flag--;<br />
}<br />
<br />
if (flag>9) draw(0); <br />
else if (flag>6) draw(1);<br />
else if (flag>3) draw(2);<br />
else draw(3); <br />
}<br />
<br />
private void Iconits_MouseEnter(object sender, System.EventArgs e)<br />
{ <br />
enter=true;<br />
timer1.Enabled=true;<br />
}<br />
<br />
private void Iconits_MouseLeave(object sender, System.EventArgs e)<br />
{<br />
enter=false; <br />
timer1.Enabled = true;<br />
}<br />
<br />
public Bitmap Icon<br />
{<br />
get { return bmp[0]; }<br />
set { <br />
<br />
bmp[0]=value; <br />
alpha.returnAlpha3(ref bmp[0],60, ref bmp[1]);
alpha.returnAlpha3(ref bmp[0],120,ref bmp[2]);<br />
alpha.returnAlpha3(ref bmp[0],180,ref bmp[3]); draw(0); <br />
}<br />
}<br />
<br />
public new Size Size<br />
{<br />
get { return new Size(Width,Height); }<br />
set <br />
{<br />
Width = ((Size)value).Width;<br />
Height= ((Size)value).Height; <br />
if (Width>160) <br />
{<br />
Width=160;<br />
}<br />
if (Height>128) <br />
{<br />
Height=128; <br />
}<br />
calc();<br />
}<br />
} <br />
<br />
public Size IconSize<br />
{<br />
get { return new Size(imwidth,imheight); }<br />
set<br />
{<br />
imwidth=((Size)value).Width;<br />
imheight=((Size)value).Height;<br />
if (imwidth>Width) imwidth=Width;<br />
if (imheight>Height) imheight=Height;<br />
calc();<br />
}<br />
}<br />
<br />
public bool Blur<br />
{<br />
get { return blur; }<br />
set<br />
{<br />
blur=value;<br />
if (!blur)<br />
{<br />
bmp[1].Dispose();<br />
bmp[2].Dispose();<br />
bmp[3].Dispose();<br />
}<br />
else<br />
{<br />
alpha.returnAlpha3(ref bmp[0], 60 ,ref bmp[1]);<br />
alpha.returnAlpha3(ref bmp[0], 120 ,ref bmp[2]);<br />
alpha.returnAlpha3(ref bmp[0], 180 ,ref bmp[3]);<br />
<br />
}<br />
}<br />
}<br />
<br />
public string About<br />
{<br />
get { return "Iconits 0.1.0 - ITS Informatics Surabaya, author: Yojana Hanif. Jayoscar Modify Abit"; }<br />
}<br />
<br />
public string TooltipText<br />
{<br />
get { return t.GetToolTip(this); }<br />
set { t.SetToolTip(this,value); <br />
}<br />
}<br />
}<br />
}<br />
<br />
This part on the alpha.cs<br />
public static void returnAlpha2(ref Bitmap bmp, int alpha, ref Bitmap bmpModify)<br />
{<br />
Color col; <br />
<br />
for (int i=0;i<bmp.Width;i++)<br />
for (int j=0;j<bmp.Height;j++) <br />
{<br />
col=bmp.GetPixel(i,j); <br />
if (col.A>0)<br />
bmpModify.SetPixel(i,j,Color.FromArgb(min(col.A-alpha),col.R,col.G,col.B)); <br />
} <br />
}
Well, everyone give some feedback see how this change you feel. Comment/suggestion welcome.
-- modified at 7:02 Friday 21st April, 2006
|
|
|
|
|
Another quick note, if you use the alphatizing routeen I wrote. You will need to enable unsafe code blocks in your projects properties, otherwise it won't compile.
|
|
|
|
|
Don't you mean 'routine'???
|
|
|
|
|
Probably a mistake in copying and pasting ?
Timer1_Tick :
You have a couple of conditional expressions that are not complete like :
if (enter)
{
if (curwidth {
curwidth+=addx;
}
if (curheight {
curheight+=addy;
}
In the alpha modification the nested for loops are not filled out and framed as needed :
public static void returnAlpha2(ref Bitmap bmp, int alpha, ref Bitmap bmpModify)
{
Color col;
//Bitmap bmp2=new Bitmap(bmp);
for (int i=0;i for (int j=0;j {
col=bmp.GetPixel(i,j);
if (col.A>0)
bmpModify.SetPixel(i,j,Color.FromArgb(min(col.A-alpha),col.R,col.G,col.B));
}
//return bmp2;
}
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis
|
|
|
|
|
Hello,
please check this Code-Block!
There's some mismatch happens
eg. :
change:
"for (int i=0;i for (int j=0;j {" ???
to:
for (int i=0;i<bmp.width;i++)
for="" (int="" j="0;j<bmp.Height;j++)"
="" {
...
eg1.="" :
change:
"if="" (curwidth="" {
curwidth+="addx;
}
if" (curheight="" {
curheight+="addy;
}"
to:
if">imwidth)
{
curwidth-=addx;
}
if (curheight>imheight)
{
curheight-=addy;
}
Best Regards
Tim
|
|
|
|
|
returnAlpha3 - the 3? What am I missing? Where is the method defined?
thanks
Ralph
|
|
|
|
|
Hi, Jon, nice mod.
In 'returnAlpha :
Bitmap bmpCopy = new Bitmap(bmp.Width, bmp.Height, PixelFormat.32bppArgb);
... should be ... PixelFormat.Format32bppArgb
At the end of 'returnAlpha : you are unlocking bmpCopy, not copyBmp ?
copyBmp.UnlockBits(copyData);<br />
bmp.UnlockBits(bmpData);<br />
return copyBmp;
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis
|
|
|
|
|
Looks like your correct about both errors. I just typed all that into the forum post box from memory as best I could, I never actually compiled it. As for the second error you mentioned, I just typoed. It is supposed to be bmpCopy, not copyBmp. Sorry about that.
|
|
|
|
|
Cool !!! Simple but Effective ... Keep it up
Babu Aboobabacker E.I
-- modified at 16:29 Thursday 20th April, 2006
|
|
|
|
|
Thank you very much, for an excellent piece of code
Regards,
Santosh Ku Sahoo
|
|
|
|
|
Great work
|
|
|
|
|
I've had a look at Task Manager whilst the demo is running, and each time I mouse over one of the icons, the memory usage increases by about 60k.
Is there anyway to combat this? You could imagin someone could have alot of fun with this code but some one would soon run out of memory?
Regards
Gav
|
|
|
|
|
Ridiculous as it sounds, minimize the window. I have no idea what's going on but what the memory drop when it's minimized, when you restore the window again, the memory usage is much less. I'm guessing that it's the GC kicking in but honestly don't know. This may even be something completley different.
It's just weird.
|
|
|
|
|
The rate of memory consumption dramatically decreases if you cache the 'g2' Graphics variable, instead of creating a new Graphics from 'dblbuffer' in the draw() method. One of the problems is that g2 was never being disposed. Rather than creating a new Graphics from 'dblbuffer' every time the draw() method is called, set g2 whenever the dblbuffer variable is set (such as in the constructor and in the Icon property setter). And be sure to dispose of g2 before setting it to a new value.
Josh
|
|
|
|
|