Você está na página 1de 7

VBSmart.

com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

Home > Code Library > SmartNetButton Control

Last Update 29 Oct 2001

Search:

SmartNetButton Control
About this page Noticed the new flat buttons available on VS.Net IDE? On this page you will find a free control that mimics the .Net button behaviour, plus an article that describes how to build such a control. Downloads SmartNetButton.ocx SmartNetButton Demo Requires SmartSubclass

Options:

Introduction
The first thing I noticed when I first opened Microsoft .Net Beta was its new flat buttons. When the button is flat it uses a smooth color to show the picture and when the mouse is over it, draws a blue rectangle and also adds a nice shadow. This gives the effect of having a floating picture when the button is raised. I thought it would be a good idea to have a control that would allow me to have '.Net' buttons, and this is what this page is all about: how to build a '.Net' button. Because the only difference between 'SmartNetButton' and 'SmartButton' is in its drawing behaviour, I would suggest you read my article 'How to implement a flat button' if you want to get more information about how to build a flat button. This article will focus on how we can add the '.Net' special effects to a flat button and will also describe the properties, methods and events that are available on my free control 'SmartNetButton'.

Smooth Colors
How can we 'smooth' the button picture when the mouse isn't over the button? This was my first question. My first thought was that we could have two picture properties, one to be used when the button is flat and the other one to be painted when the mouse is over the button. This would obviously work but... it would be a time-consuming solution: every time we want to change the picture we have to 'smooth' it again. So then I decided to find out what kind of 'rule' Microsoft uses to smooth the pictures and, after doing several screenshots of 'VS.Net', I found there was a relationship between the original and final colors for every pixel.

1 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

Button Flat and Smooth

Button Raised and Normal

As you can see above, the open-folder picture comprises mainly four colors: yellow, white, black and brown. If we compare the original color with its smooth version, we come up with following table: Smooth Color Black Brown Yellow White RGB(76,76,76) RGB(166,166,76) RGB(255,255,76) RGB(255,255,255) Original Color RGB(0,0,0) RGB(128,128,0) RGB(255,255,0) RGB(255,255,255) Increment (76,76,76) (38,38,76) (0,0,76) (0,0,0)

We can get new points of reference by repeating the same process to other icons: Smooth Color Grey Blue Light Blue Light Orange RGB(211,211,211) RGB(76,76,166) RGB(51,102,255) RGB(255,204,102) Original Color RGB(192,192,192) RGB(0,0,128) RGB(108,140,255) RGB(255,223,140) Increment (19,19,19) (76,76,38) (57,38,0) (0,19,38)

Seems clear that there's a relationship between the original and final colors. This relationship is always expressed in terms of RGB increment. If we now break-down this relationship we come-up with the following table: R/G/B Value 0 32 64 96 128 160 192 224 256 Increment 76 57 57 38 38 19 19 0 0

Things are now getting easy. Now we only need to express this relationship through a mathematical formula:

Private Function pTransform(ByVal X As Long) As Long pTransform = 76 - Int((X + 32) / 64) * 19 End Function
What's next then? we have a formula to transform a sub-color (red, green or blue) into a new smoothed sub-color. The next step is to use this formula to transform a whole picture. As far as I know, VB6 doesn't provide a way for accessing individual pixels of an image. Therefore, we will have to use native APIs. You can find below a VB sample of a function that receives a picture as a parameter and returns the picture handle of the new smoothed picture.

Public Function fSmoothPicture(ByRef m_Picture As StdPicture) As Long ' Local Variables... Dim memDc1 As Long, memDc2 As Long Dim oldBitmap1 As Long, oldBitmap2 As Long Dim memBitmap As Long Dim x As Long, y As Long, w As Long, h As Long, c As Long

2 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

' Get the Width and Height of the picture... w = UserControl.ScaleX(m_Picture.Width, vbHimetric, vbPixels) h = UserControl.ScaleY(m_Picture.Height, vbHimetric, vbPixels) ' Create two device contexts in memory... memDc1 = CreateCompatibleDC(UserControl.hDC) memDc2 = CreateCompatibleDC(UserControl.hDC) ' Create a bitmap in memory... memBitmap = CreateCompatibleBitmap(UserControl.hDC, w, h) ' Select m_Picture in device1 and the new bitmap in device2... oldBitmap1 = SelectObject(memDc2, m_Picture.Handle) oldBitmap2 = SelectObject(memDc2, memBitmap) ' Copy each pixel from device1 to device2 ' and apply a color transformation... For x = 0 To w - 1 For y = 0 To h - 1 c = GetPixel(memDc1, x, y) SetPixel memDc2, x, y, c + pMask(c) Next y Next x ' Restore the original bitmaps... SelectObject memDc1, oldBitmap1 SelectObject memDc2, oldBitmap2 ' Delete device context... DeleteDC memDc1 DeleteDC memDc2 ' Return the new bitmap handle... fSmoothPicture = memBitmap End Function
This function works only for bitmaps. If the function parameter 'm_Picture' holds an icon or a complex image, you will have to render the image on the target device context before applying the transformation. You have seen in the above code that we're using a function, called 'pMask()', to transform each pixel color. What this function does is to split the color into its RGB components, transform each sub-color and return the new smooth color. Well, we have the first '.Net' effect sorted out. In the next section we our going to discuss how to add a dynamic shadow to the picture.

How to add a shadow to the picture


As I said in the introduction, the '.Net' button adds a shadow to the picture when the button is raised. We're now going to see how we can easily implement this effect. First of all, we've seen that it is a bad idea to have 2 picture properties in our control. So, how then can we add a shadow to the picture? The answer is "by using the API DrawStatus". DrawStatus is a very powerful API that allows us to draw a picture on a device context. We can draw the picture using a 'normal' mode or, by using its flag DSS_MONO, draw the picture using a single color. We can use this function to draw a greyed version of the picture (this will be the shadow) to then draw the normal picture 2 pixels away so it will seem to be floating over the canvas.

3 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

Draw the picture using a grey color to simulate a shadow. The following VB method draws a picture on the usercontrol device context. The picture will be drawn normal or greyed depending on the value of its parameter 'bShadow'.

Private Sub fDrawPicture( _ ByRef m_Picture As StdPicture, _ ByVal X As Long, _ ByVal Y As Long, _ ByVal bShadow As Boolean) Dim lFlags As Long Dim hBrush As Long Select Case m_Picture.Type Case vbPicTypeBitmap lFlags = DST_BITMAP Case vbPicTypeIcon lFlags = DST_ICON Case Else lFlags = DST_COMPLEX End Select If bShadow Then hBrush = CreateSolidBrush(RGB(128, 128, 128)) End If DrawState _ UserControl.hDC, _ IIf(bShadow, hBrush, 0), _ 0, _ m_Picture.Handle, _ 0, _ X, Y, _ UserControl.ScaleX(m_Picture.Width, vbHimetric, vbPixels), _ UserControl.ScaleY(m_Picture.Height, vbHimetric, vbPixels), _ lFlags Or IIf(bShadow, DSS_MONO, DSS_NORMAL) If bShadow Then DeleteObject hBrush End If End Sub

About the free .Net control


SmartNetButton is a free control that mimics the '.Net' flat button behaviour. You can freely use it in your applications. The control has two main items: a Caption property and a Picture property. You can set whether to show the Caption or not through property ShowCaption. Each item has its own displaying area:

4 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

The size of the caption area is set as a % of the total size and we use property CaptionAreaPercent to change this value. You can place the caption area to the left, right, top or bottom of the picture area. You can change this position using property CaptionAreaLayout. Each individual area (caption or picture) has its own properties to help you positioning. Each area is divided into 9 possible layouts:

You can use properties CaptionLayout and PictureLayout to change the position of each item within its display area. There are also 4 properties for each area that will help you to better tune the layout. These properties set the offset between each position and the edge of its display area. You have CaptionOffsetLeft, CaptionOffsetTop, CaptionOffsetRight and CaptionOffsetBottom for the caption. You have PictureOffsetLeft, PictureOffsetTop, PictureOffsetRight and PictureOffsetBottom for the picture:

Finally, you can find below a table containing all SmartNetButton properties, methods and events: Properties BackColor BackColorPop BackColorPush BackColorSmooth Caption CaptionAreaLayout CaptionAreaPercent CaptionBackColor CaptionBackColorSmooth CaptionLayout CaptionOffsetBottom CaptionOffsetLeft CaptionOffsetRight CaptionOffsetTop (1) Container (1) DragIcon (1) DragMode EdgeColor Methods (1) Drag (1) Move ReleaseButton (1) ShowWhatsThis (1) ZOrder Events Click DragDrop DragOver Hide MouseDown MouseHold MouseMove MouseUp Resize Show

(1) (1) (1) (1) (1) (1) (1) (1) (1)

5 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

(1) Enabled (1) Font (1) ForeColor (1) Height (1) Index (1) Left (1) Name (1) Object (1) Parent Picture PictureLayout PictureOffsetBottom PictureOffsetLeft PictureOffsetRight PictureOffsetTop RepeatDelay RepeatLapse ShadowColor ShadowOffset ShowCaption ShowCaptionSmooth ShowPushColor ShowShadow ShowSmooth (1) Tag (1) ToolTipText (1) Top (1) Visible (1) WhatsThisHelpID (1) Width (1) Please read Visual Basic documentation for a complete description of this property/method/event.

Last Changes
31.May.2001 Application wasn't closing properly when VB 'End' statement was called from 'Click' event. This bug is now fixed.

Private Sub SmartNetButton1_Click() End End Sub


Thanks to Victor Henskens for finding and reporting this bug. 18.June.2001 SmartNetButton didn't support access keys (ALT+Key). This bug is now fixed. Event AccessKeyPress is fired when the access key is pressed. Thanks to Jan Tielens for finding and reporting this bug. 26.September.2001 SmartNetButton didn't respond to keyboard events. This bug is now fixed. The button now responds to keyboard events just as it does to mouse events. Thanks to Jos Aguado for finding and reporting this bug. 27.September.2001 SmartNetButton was always 'popped' when it got the focus. This bug is now fixed. Property 'TabStop' has now a default value of False and there's a new property 'RespondToKeyEvents' that sets whether or not the control responds to keyboard events. If we want the button to show a push/pop effect when it gets/loses the focus, we must explicitly set both properties to True. Thanks to David Moino for finding and reporting this bug. 28.September.2001

6 of 7

10/16/2010 9:53 AM

VBSmart.com - SmartNetButton

file:///G:/IMAGE%20Processing/smartnetbutton.htm

SmartNetButton was giving an error with MS Access. This bug is now fixed. Thanks to Ken Young for finding and reporting this bug. 05.October.2001 SmartNetButton wasn't refreshing properly if DoEvents() was called from its event Click(). This bug is now fixed. The button now doesn't lose its 'push/pop' effect when DoEvents() is called. Thanks again to David Moino for finding and reporting this bug.

Copyright 2001, Andrs Pons (andres@vbsmart.com). All rights reserved.

7 of 7

10/16/2010 9:53 AM

Você também pode gostar