Link to home
Start Free TrialLog in
Avatar of hotsextoy
hotsextoy

asked on

Background Transparent Bitmap Buttons

Hello,
    I'm using VC5, and using the CBitmapButton class to get bitmaps on buttons
   but i also want the background of the image to be transparent, in effect getting
  a custom shaped buttons like circles and triangles rather than plain vanilla squares...
                                                                                                                 Pat b
 
Avatar of Tommy Hui
Tommy Hui

There are some classes at www.codeguru.com that lets you create triangle and circle buttons. Take a look there.

Avatar of hotsextoy

ASKER

Sorry bout that, but i was hope in for the actual Bitmap to make the shap of the button, not just circles, squares, triangles, (sorry if it was misleading...again i want to make the background of the bitmap transparent so that when i load it to the button with AutoLoad then the button would apear to have it's own shape...if that's possible...if there is an alternate method then i'm up for that to...anyways thanx
                                                                                    Pat b
Then you cannot make use of CBitmapButton. You have to write your own button.
hmm, i kinda figured that, just hopeing there was a faster way...thanx
                                                                                                 Pat b

ASKER CERTIFIED SOLUTION
Avatar of jstolan
jstolan

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I have code for owner-drawn transparent bitmap or icon buttons..

I can post this for you if you like.

Using icons makes it really very simple as the transparency is much easier to achieve.  With bitmaps you need a bit of extra code to draw transparently (or you can use an image list - but I haven't gotten around to changing my code to make use of them yet).

Would you like me to post the code up here???

Creating an ActiveX control seems a lot more effort than (seems) required for what you want.

The ActiveX control is not difficult and it provides a LOT of functionality.  For example, it's trivial to determine if the user clicked on the rectangular area of the control or on the portion of the ICON which is actually visible.

My experience with these controls is you always want them to do just a little bit more.  ActiveX makes that very achievable.

OwnerDrawn buttons using DrawState lets you do things like show the button embossed or monochrome by setting style bits.  AFAIK CPictureHolder doesn't support that (you can simply render)

You can also just as easily detect where in the button rect the mouse was clicked (by responding to the mouse button down event).  I have buttons that do that, and changes appearance and the cursor as the mouse moves over them etc etc.

These could be wrapped up in an ActiveX control .. by I don't want to do the extra work involved.  Subclassing an existing button on a dialog (using ClassWizard) and doing the drawing and message handling (if requried) myself is just as easy.

hmm, seems i have waged war of the roses here...and i'm kinda confused as to which way to go...both methods are foreign to me, ive actually never dealt with buttons using icons and haven't really messed with active x, either...i'll try the icon method tonight and see...but not quite sure what to look for...anyhow, i would like for u two to post or email me source code fore button transparencies...and any other button libs for that matter...(i also had intended them to move when clicked on, some buttons keep a down state when pressed, most of my buttons are supposed to act as a toggle like radio's in a set of buttons, and some other minor stuff) anyhow i kinda had ideas on how to do it all, except for the transparency part...but anyrate if u have code for other button states then please email me :
hotsextoy@hotmail.com         i'll also be willing give out all the points i have it's not much though (trust me)...anyhow thanx
Pat b
   
Here is code cut from a more extensive icon button (the full code supports
* flat (IE) look, normal look or no button border.
* checked state (for radio-like button).
* icon, text or both
* dynamic cursor shape change over the button
* visited flag and color change (like a hyper link)
* text that can grows to fill the button
* text with a raised 3D appearance.

I can give you source that includes any/all of the above, However, this hacked version should just display an icon transparently, and show it greyed out if disabled.  It can be easily enhanced by adding to it, or deriving from it.

You use this by simple adding a button to you dialog and then using ClassWizard to create a control variable for it of class CIconButton.  Then you set the assiciated icon when you init the control variable in the dialog constructor.

Here's the code...

IconButton.h
============

#ifndef _QIconButton_
#define _QIconButton_

class QIconButton : public CButton {
  DECLARE_DYNAMIC(QIconButton)
public:
  QIconButton(UINT iconId=0)
    : CButton()
    , m_bDrawBackground(true)
    , m_iconId(iconId)
    , m_hicon(0)
  {}
  ~QIconButton() {
    if (m_hicon) {
      ::DestroyIcon(m_hicon);
    }
  }
  // icon
protected:
  UINT m_iconId;
  HICON m_hicon;
public:
  void SetIconId(UINT iconId);
  UINT IconId() const { return m_iconId; }
  // drawing
private:
  bool m_bDrawBackground;
protected:
  void Draw(CDC* pDC, const CRect& rect, UINT state=0);
protected:
  //{{AFX_MSG(QIconButton)
  afx_msg BOOL OnEraseBkgnd(CDC* pDC);
  //}}AFX_MSG
  //{{AFX_VIRTUAL(QIconButton)
  virtual void PreSubclassWindow();
  virtual void DrawItem(LPDRAWITEMSTRUCT lpDIS);
  //}}AFX_VIRTUAL
  DECLARE_MESSAGE_MAP();
};
#endif

IconButton.cpp
==============

#include "stdafx.h"
#include "IconButton.h"

BEGIN_MESSAGE_MAP(QIconButton, CButton)
//{{AFX_MSG_MAP(QIconButton)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNAMIC(QIconButton,CButton)

void QIconButton::SetIconId(UINT iconId) {
  if (IconId() == iconId) return;
  m_iconId = iconId;
  if (m_hicon) ::DestroyIcon(m_hicon);
  m_hicon = NULL;
  if (GetSafeHwnd()) Invalidate();
}

void QIconButton::PreSubclassWindow() {
  SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
}

void QIconButton::DrawItem(LPDRAWITEMSTRUCT lpDIS) {
  if (m_bDrawBackground) {
    m_bDrawBackground = false;
    // if not redrawing the whole thing,
    CWnd* pParent = GetParent();
    CRect rect; GetWindowRect(rect);
    pParent->ScreenToClient(rect);
    pParent->InvalidateRect(rect);
    pParent->UpdateWindow();
  } else {
    m_bDrawBackground = true;
    CDC* pDC = CDC::FromHandle(lpDIS->hDC);
    ASSERT_VALID(pDC);
    CRect rectClient = lpDIS->rcItem;
    Draw(pDC,rectClient,lpDIS->itemState);
  }
}

BOOL QIconButton::OnEraseBkgnd(CDC*) {
  return true;
}

void QIconButton::Draw(CDC* pDC, const CRect& rect, UINT state) {
  if (! m_hicon) {
    LPTSTR iconname = MAKEINTRESOURCE(IconId());
    HINSTANCE hinst = ::AfxFindResourceHandle(iconname,RT_GROUP_ICON);
    m_hicon = (HICON)::LoadImage(hinst,iconname,IMAGE_ICON,rect.Size().cx,rect.Size().cy,LR_DEFAULTCOLOR|LR_SHARED);
  }
  pDC->DrawState(rect.TopLeft(), rect.Size(), m_hicon, (state & ODS_DISABLED?DSS_DISABLED:DSS_NORMAL), (HBRUSH)NULL);
}

I'll send you an E-mail tonight.  It will have an ActiveX control called CPieces, should be pretty easy to modify into a button.  It's a little long to post here, and I can give you the whole project file.  

My only complaint with RonSlow's method is that it is going to be tricky determining if the user clicked on the visible icon or just in the control rectangle. Sure the mouse move will give you the position, but then you have to get the color underneath, etc.  But if you don't care about that, his method is probably easier (although a little less powerful).

BTW, you might consider changing your handle.  I had E-mail notification checked and my wife wanted to know who the hell "hotsextoy" was.  Fortunately the message was obviously pretty technical and boring.  LOL
jstolan .. how does your control detect click on the icon .. the same technique could probably be used here as well.  It can certainly respond to clicks a different positions within the button .. (respond to Lbutton down rather than mouse move).

If hotsextoy is interested, I can send a fuller owner-drawn icon button class with the features mentioned.

Oops, I'm really embarrassed.

In fact the control I sent last night will respond when the user clicks anywhere in the rectangular region of the control.  I was thinking of an earlier version I did with circular and triangular buttons.  The control did a test on the point to determine if it was InCircle and InTriangle, and only responded if the test was positive.

A similar test could be done here for the icon, but it is not implemented.  A similar test could be added just as easily to Ronslow's button.  It sounds like Ronslow's button is probably closer to what you need.  It won't hurt my feelings if you reject my answer to give him the points.
Thanx, guys about all this info, it's really been helpful...i haven't implemented yet but i have some time today so i'll try it out...I'm accepting ur answer cause i beleive in "e" for effort method.  But i think ROnslow's method is better, so i'll give him more points...anyways thanx to the both of u.
                                                                   Pat b

PS.  I thought about changeing my handle but i've had it for soo long, it kinda grows on you even when i myself grows up (i had it since high school) ..