'Disabling' bitmaps with the API

rilucero
rilucero used Ask the Experts™
on
Hi all,

  I am in the process of developing a custom command button control and I'm having a little trouble with the graphical aspects of it.  My button is currently fully functional in that it raises events, draws edges, draws text and graphics and much more.   Right now, I have a property that allows me to set the graphic for the enabled position and the disabled position, and that works fine as well.  However, I would like to find a slicker solution to this so that the 'disabling' of the original bitmap graphic is done programatically.

  I have tried using the DRAWSTATE API function with the DST_BITMAP and DSS_DISABLED flags set.  This definitely changes the bitmap but the effect is less than desirable.  The bitmaps I'm sending into the function have a grey background and a very highly contrasted 'foreground.  What I'm looking for is a function that will keep the background the same colour and only apply the embossing to the foreground of the bitmap.  My feeling is that I need to make the bitmap transparent, convert it to mono and THEN emboss it.  Incidentally, the DST_ICON flag used with icons provides the exact effect I need but unfortunately, I need to use bitmaps.  

  Does anyone have any hints on how to generate a disabled effect on a bitmap that mimics a standard disabled windows icon?  Thanks for any suggestions!

Rafael
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Why not do ways with the command button completely and just build the image on a pciture box.

You could use the PaintPicture with a raster operation which would produce a diabled affect.

Back later....

Author

Commented:
Hi,

  I'm actually not using a command button.  All I have is a UserControl container and I'm rendering the bitmaps with the PaintPicture method.  This is working like a charm but my problem is 'disabling' the rendered bitmap.  Like I said, I already tried the DrawState API command but didn't like the results.  

  I'm not quite sure what you mean by using a 'raster effect' with PaintPicture.  My code for painting the bitmap right now is something like this:

UserControl.PaintPicture New_Picture, 0, 0, , , , , , , vbSrcCopy
 
How can I use PaintPicture to give me a disabled effect?

Rafael
Here is the process:

Yake a copy of your BTIMAP:

picCopy.Width=PicSource.Width
picCopy.Height=PicSource.Height
picCopy.PaintPicture picSource,0,0


Process the bitmap with the desired affect:

Create a single dimension safe arry pointer to the picture with a three byte matrix.

See for an example:

http://www.visualbasicforum.com/t25347.html 

The example at this site can be improved big-time I will show you how.

Instead of a bitmap with 2 dimensions I created a single dimensional array using a three byte element size:


Private Type PixelDef
  Blue As Byte
  Green As Byte
  Red As Byte
End Type

So you can loop throught the image like this:

Sub ProccessImage(Action As Actions)


Dim cp As Long
Dim Av As Long
Dim bt As Byte
Dim GreyFactor As Single

GreyFactor = 0.333333
cp = 0

Select Case Action
   
    Case Is = Actions.ConvertToGreyScale

    ' loop through image
    Do While cp < aSize ' asize is the size of the pic in pixels
        Av = (0& + Pixels(cp).Red + Pixels(cp).Green + Pixels(cp).Blue) * GreyFactor
        bt = Av
        Pixels(cp).Red = bt
        Pixels(cp).Green = bt
        Pixels(cp).Blue = bt
        cp = cp + 1
    Loop
   
    Case Is = Actions.GreyOutButtonImage
   
        Dim BackGround As PixelDef
       
        BackGround.Red = x ' set your background mask
        BackGround.Green = x ' set your background mask
        BackGround.Blue = x ' set your background mask
       
        ' loop through image
        Do While cp < aSize ' asize is the size of the pic in pixels
            GrayThisPixel = True
            Do
              If Pixels(cp).Red <> BackGround.Red Then Exit Do
              If Pixels(cp).Green <> BackGround.Green Then Exit Do
              If Pixels(cp).Blue <> BackGround.Blue Then Exit Do
   
              GrayThisPixel = False
              Exit Do
            Loop
            If GreyThisPixcel Then
                 Av = (0& + Pixels(cp).Red + Pixels(cp).Green + Pixels(cp).Blue) * GreyFactor
                 bt = Av
                 Pixels(cp).Red = bt
                 Pixels(cp).Green = bt
                 Pixels(cp).Blue = bt
            End If
            cp = cp + 1
        Loop

   
End Select

End Sub


Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Take the code for the link then add the following into the declarations:

Private Type SAFEARRAY1d
    cDims As Integer
    fFeatures As Integer
    cbElements As Long
    cLocks As Long
    pvData As Long
    Bounds(0 To 1) As SAFEARRAYBOUND
End Type

Private Type PixelDef
  Blue As Byte
  Green As Byte
  Red As Byte
End Type

Private Pixels() As PixelDef

Private SA1d As SAFEARRAY1d


I changed the loadPicArray as follows.

Hope this helps:~)


Public Function LoadPicArray(p As StdPicture) As Boolean

'returns true if function works.
If GetObjectAPI(p.Handle, Len(BMP), BMP) Then    'retrieve bitmap information about p
    If BMP.bmWidth Then
        mvarBytesPerPixel = BMP.bmWidthBytes \ BMP.bmWidth
        If (mvarBytesPerPixel > 0) And (mvarBytesPerPixel < 4) Then
            ' make the local matrix point to bitmap pixels
            aSize = BMP.bmHeight * BMP.bmWidth
            With SA1d
              .cbElements = 3
              .cDims = 1
              .Bounds(0).lLbound = 0
              .Bounds(0).cElements = aSize

              .pvData = BMP.bmBits
            End With
            ' copy bitmap data into byte array
            CopyMemory ByVal VarPtrArray(Pixels), VarPtr(SA1d), 4

            LoadPicArray = True
        Else
            mvarErrorMsg = "Colour resolution must be 1-3 bytes instead of " & CStr(mvarBytesPerPixel)
        End If
    Else
        mvarErrorMsg = "Picture width cannot be zero"
    End If
Else
    mvarErrorMsg = "Can't retrieve BMP object"
End If

End Function

In simple terms the above code will be run on the copy of you bitmap.  It will then convert to greyscale only the part of the image which is not part of the background of the bitmap.

Author

Commented:
Hi inthedark,

  Thank you very much for the detailed response.  However, I'm still having a little problem.  It seems that no matter what bitmap I try to use with the LoadPicArray procedure, I get a bytes per pixel value of 4 which returns the colour resolution error message.  Here is what I'm doing.  I have a control called ToolButton which has a property called ToolPicture.  In a form, I have the following code:

Set ArcToolButton1.ToolPicture = LoadResPicture(106, 0)

The bitmap in the resource file is a 16 colour bitmap that I created in Paintshop Pro.

In my user control, I have a variable defined as:

dim m_ToolPicture as StdPicture

And in my ToolPicture property, I have:

Set m_ToolPicture = New_Picture

Finally, in the Enabled method of my user control, I use the LoadPicArray like this:

dim bLoaded as boolean
bLoaded = LoadPicArray(m_ToolPicture)
       

Like I said, every bitmap I have tried returns a pixel depth of 4.  Any ideas why this may be and how to fix the problem?  Thanks again!

Rafael
Author of the Year 2009

Commented:
Hi rilucero,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Accept inthedark's comment(s) as an answer.

rilucero, if you think your question was not answered at all or if you need help, just post a new comment here; Community Support will help you.  DO NOT accept THIS comment as an answer.

EXPERTS: If you disagree with that recommendation, please post an explanatory comment.
==========
DanRollins -- EE database cleanup volunteer

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial