Advanced ActiveX Buttons

kSet Button ActiveX

The kSet Button control is designed for developers who want an alternative to the standard Windows command button. It offers everything that the standard button offers plus a whole lot more.

For creation of control the library ATL 3.0 and VC++ 6.0 (SP 3.0) was used.
Control can be in several states: static, hover, push, disabled and to contain the image and text, allows flexibly changing appearance.
kSet Button control don't subclass an existing window.

Properties
Enabled: sets a value that determines if the control can receive user input.
HoverEnabled: permit a hover state
AppearanceStatic: sets a appearance of control for a static state
AppearanceHover: sets a appearance of control for a hover state
AppearancePush: sets a appearance of control for a push state
ShowFocus: manner of display of focus (draws a rectangle, transition in a hover state, nothing)
ShowStateAsFlat: display a condition through change of backcolor if appearance equal flat or border
BorderColor: the border color of the button.
HighlightColor: the color used to display portions of the button that are highlighted
ShadowColor: the color used to display portions of the button that require shadow effects
TextPushColor: foreground color used to display text of the button at a push state
TextHoverColor: foreground color used to display text of the button at a hover state
TextStaticColor: foreground color used to display text of the button at a static state
PictureAlignment: a value that determines the placement of the picture in relation to the caption.
PictureSpacing: a value that determines the spacing to be used between the picture and the caption.
PicturePush: the picture to be displayed on the button at a push state.
PictureHover: the picture to be displayed on the button at a hover state.
PictureStatic: the picture to be displayed on the button at a static state.
PictureDisabled: When the control is disabled, the STATIC picture displayed will automatically be changed to a disabled look. The disabled state can be overridden by setting the PictureDisabled property.
TextPush: a value that determines the text displayed in the button at a push state
TextStatic: a value that determines the text displayed in the button at a static state
TextHover: a value that determines the text displayed in the button at a hover state
FontHover: the font used for the text at a hover state.
FontStatic: the font used for the text at a hover state.
FontPush: the font used for the text at a hover state.

Methods
DoClick: feign pressing the button
AboutBox: displays the about dialog containing the product name and version.

Event
Click: Occurs when the user presses and releases the mouse button.

Implementation
As the control don't subclass an existing window was already mentioned earlier.
All code engaged by display of the button is concentrated in a class _ Render < > which is mixed class. We use at drawing the button simple wrapper classes for GDI handles such as HFONT, HPEN, etc. Directly draws the button an array of functions, the pointers on which are stored in a static array.

[renderbutton.h]
template <class T>
class _Render
{
...
typedef void (_Render::*PTR_FDRAW)(_kDrawDC& dc, RECT& rc);
static PTR_FDRAW& f_table (int appearance, int status)
{
  static PTR_FDRAW& f_table (int appearance, int status)
  {
  //appearance, status
  static PTR_FDRAW table[8][4] = {...};
  ...
  return table[appearance][status];
  }
}
...
};

template <class T>
void _Render<T>::DrawIt(HDC hdc, int state, RECT& rc)
{
PTR_FDRAW ff;

// We choose function depending on a state and appearance of the button
switch (state)
{
case 0:
  ff = f_table(pT->m_AppearanceStatic, state);
      ...
        }
           
        //draws a button   
(this->*ff)(_kDrawDC(hdc), rc);
...
//display the text
DrawState(...);
...
//draws focus rectangle if need
DrawFocusRect(hdc, &rc_focus);
...
//display an image through method IPicture interface
pPic->Render(...);
...
}

We imported function "TrackMouseEvent" from user32.lib for tracking of mouse pointer.

[kbutton.cpp]
void _kButton::DetectTrackMouse()
{
m_pfTrackMouseEvent = (PTRF_TrackMouseEvent)GetProcAddress
(GetModuleHandle(_T("user32")),_T("TrackMouseEvent"));
}

Or at absence (in Windows 95) is traced moving the mouse from second thread through a class _kMouseMoveImpl.

The class _kMouseMoveImpl inherits logic of work with threads from class _ApartmentThread<> and realizes tear-off interface IMouseMove.

[mousemove.h]
class ATL_NO_VTABLE _kMouseMoveImpl :
public _IMouseMove,
public CComTearOffObjectBase<_kButton>,
public _ApartmentThread<_kMouseMoveImpl, _IMouseMove, &IID__IMouseMove>
{
...
}


[kbutton.h]
COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(IID__IMouseMove, _kMouseMoveImpl, m_pUnkMouseMove.p)

[kbutton.cpp]
void _kButton::TrackMouse()
{
if (m_pfTrackMouseEvent)
{
...
}
else
{
CComQIPtr<_IMouseMove> pI(GetControllingUnknown());
pI->_StartThread(100);
}
}


Use of a class as tear-off interface allows saving memory, as the necessity in kMouseMoveImpl arises only at work under Win95. The similar circuit is applied and at animation of pressing the button (for example by a call a method DoClick)

[kButton.cpp]
STDMETHODIMP _kButton::DoClick(VARIANT_BOOL bAnimate)
{
...
CComQIPtr<_IAnimationClick> pI(GetControllingUnknown());
pI->_StartThread(100);
...
}


The class _ApartmentThread encapsulating a work with STA - creation threads, marshals an interface pointer, etc.

[apartmentthread.h]
template <class Derived, class T, const IID* piid>
class _ApartmentThread
{
...
HRESULT _StartThread(int nTimeOut)
{
...
if (SUCCEEDED(CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream))) m_hThread = CreateThread(0, 0, &Apartment, (void*)this, 0, &dw);
...
}
...
}


The properties of control are realized with the help of the macros IMPLEMENT_XXX taken from a file atlctr.h
For properties FontXXX h PictureXXX were written macros: IMPLEMENT_PICTURE_PROPERTY h IMPLEMENT_FONT_PROPERTY and mixed classes _HelperPictureProperty<> and _HelperFontProperty<>

The events are realized through dispinterface IkButtonEvents and custom interface IkButtonEvents for C++ containers.

I used for calculation of ShadowColor and HighlightColor the HSL color model realized in a class HSLModel.

[kbutton.h]
void _kButton::Get3DColors (COLORREF clr, COLORREF& clrShadow, COLORREF& clrHighlight)
{
_HSLModel hsl(clr);
_HSLModel _hs1 = hsl;
BYTE lum = hsl.luminance();
hsl.luminance (lum / 3 * 2);
_hs1.luminance (lum + ((240 - lum) / 2));
clrShadow = hsl.rgb();
clrHighlight = _hs1.rgb();
}

For Visual Basic IDE realized ICategorizeProperties interface in a class _ kICategorizeProperiesImpl.

[categorizeproperties.h]
template <class T>
class ATL_NO_VTABLE _kICategorizeProperiesImpl :
public ICategorizeProperties
{
STDMETHOD(MapPropertyToCategory)(DISPID dispid, PROPCAT* ppropcat )
...
STDMETHOD(GetCategoryName)(PROPCAT propcat, LCID lcid, BSTR* pbstrName)
...
}

[kbutton.h]
class ATL_NO_VTABLE _kButton :
...
public _kICategorizeProperiesImpl<_kButton>,
...
{
...
BEGIN_CATEGORY_PROP_NAME_MAP(_kButton)
CATEGORY_PROP_NAME(1, _T("Picture"))
CATEGORY_PROP_NAME(2, _T("Color"))
END_CATEGORY_PROP_NAME_MAP()

BEGIN_PROPERTY_TO_CATEGORY_NAME_MAP (_kButton)
PROPERTY_TO_CATEGORY(dispidTextPush, PROPCAT_Text)
PROPERTY_TO_CATEGORY(dispidPictureDisabled, 1)
...
END_PROPERTY_TO_CATEGORY_MAP()
...
}

Downloads

Download demo project - 45 Kb
Download source - 204 Kb


Comments

  • Error during compiling the demo

    Posted by danandu on 09/27/2007 06:36am

    when i was trying this kind of button, it gave me the following error, file not found: Cannot open type library file: '..\..\controls\kSetEditor\kSetEditor.tlb': No such file or directory AND i searched for that .tlb file and even i could not find it. This KSetButton is an article presented in the Buttons section of CG. I was compiling the demo project and i got into this error. Is there any solution?

    Reply
  • I am unable to click button using accelerator key

    Posted by Legacy on 07/27/2003 12:00am

    Originally posted by: N.K.SINGH

    I am unable to click button using accelerator key for example Alt+S to click start button.
    

    Reply
  • The Perfect Button : yet another BUG

    Posted by Legacy on 04/28/2002 12:00am

    Originally posted by: Nir Cohen

    the disabled pictured do not work
    (even after the 'Enebled/disabeld' BUG fixed)

    Reply
  • It's Great Fun

    Posted by Legacy on 02/03/2002 12:00am

    Originally posted by: Feroz Zahid

    I found this code as a very good example code. Let all try it.
    

    Reply
  • A silly question

    Posted by Legacy on 01/29/2002 12:00am

    Originally posted by: sunita

    I am a newbie.Can you tell me how i can create array on command buttons?
    :)
    i will appreciate,you help.
    Thanks bye.

    Reply
  • Some Bugs Report

    Posted by Legacy on 07/23/2001 12:00am

    Originally posted by: zengsiyu

    Thank you for your Work.use your Ksetbutton control can make a good looking Application Interface.But it have some bugs:

    1. It can work in Unicode,but have some problem.
    When you set the caption properties by chinese,you input two word(chinese),you must add two blank space.
    2. Properties Enabled bugs
    when you set the enabled properties to false,and back to true, the buttons looking is still disable, and can't click.


    zengsiyu
    2001.7.22

    Reply
  • Enabled=true and Enabled=false doesn't work

    Posted by Legacy on 04/08/2001 12:00am

    Originally posted by: aloha1734

    if you change the button to enabled=false at run time, you won't be able to have it enable by resign the value like Enabled=true.
    is this a bug?

    Reply
  • Text Over Picture? and wordwrap

    Posted by Legacy on 01/07/2001 12:00am

    Originally posted by: Anurak

    When I set Picture to center, The picture stay on top layer and cover the text. How can I show text over the picture? Is it support wordwrap? When The text too long, it cannot show the exceed text.

    Reply
  • Can I add a tooltip to this control??

    Posted by Legacy on 07/24/2000 12:00am

    Originally posted by: Bush

    Hi , Im using ur button.I couldnt figure out how would i add a tooltip to ksetbutton.Any help is appreciated.

    Bhushan

    Reply
  • Yet another bug with a bad fix.

    Posted by Legacy on 04/18/2000 12:00am

    Originally posted by: Aykut

    When a modal dialog (like afxmessagebox) is created in the button 
    
    OnButtonPress function , after the dialog ends the button again gets the focus.
    So when I end the dialog with enter key the button is again pressed and dialog reappears.
    I tested and saw that this continues forever.

    So I add

    ::SetFocus(NULL);

    after

    anydlg.DoModal();

    But this should be done by the control itself.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • "Security" is the number one issue holding business leaders back from the cloud. But does the reality match the perception? Keeping data close to home, on premises, makes business and IT leaders feel inherently more secure. But the truth is, cloud solutions can offer companies real, tangible security advantages. Before you assume that on-site is the only way to keep data safe, it's worth taking a comprehensive approach to evaluating risks. Doing so can lead to big benefits.

  • Is your sales and operations planning helping or hurting your bottom line? Here are 5 useful tips from the experts at Quintiq to guide you to a better S&OP strategy.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds