]> git.saurik.com Git - wxWidgets.git/blobdiff - utils/framelayout/src/newbmpbtn.cpp
Added Aleksandras' framelayout code, with more or less working Linux Makefiles
[wxWidgets.git] / utils / framelayout / src / newbmpbtn.cpp
diff --git a/utils/framelayout/src/newbmpbtn.cpp b/utils/framelayout/src/newbmpbtn.cpp
new file mode 100644 (file)
index 0000000..6ca0afb
--- /dev/null
@@ -0,0 +1,759 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        No names yet.
+// Purpose:     Contrib. demo
+// Author:      Aleksandras Gluchovas
+// Modified by:
+// Created:     ??/09/98
+// RCS-ID:      $Id$
+// Copyright:   (c) Aleksandras Gluchovas
+// Licence:    wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef __GNUG__
+#pragma implementation "newbmpbtn.cpp"
+#pragma interface "newbmpbtn.cpp"
+#endif
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+/*
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+*/
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "newbmpbtn.h"
+#include "wx/utils.h"     // import wxMin,wxMax macros
+
+///////////// button-label rendering helpers //////////////////
+
+static int* create_array( int width, int height, int fill = 0 )
+{
+       int* array = new int[width*height];
+
+       int len = width*height;
+       for( int i = 0; i != len; ++i ) array[i] = fill;
+
+       return array;
+}
+
+#define GET_ELEM(array,x,y) (array[width*(y)+(x)])
+
+#define MIN_COLOR_DIFF 10
+
+#define IS_IN_ARRAY(x,y) ( (x) < width && (y) < height && (x) >= 0 && (y) >= 0 )
+
+#define GET_RED(col)    col        & 0xFF  
+#define GET_GREEN(col) (col >> 8)  & 0xFF        
+#define GET_BLUE(col)  (col >> 16) & 0xFF 
+
+#define MAKE_INT_COLOR(red,green,blue) (     (red)                      | \
+                                         ( ( (green) << 8 ) & 0xFF00  ) | \
+                                                                                ( ( (blue)  << 16) & 0xFF0000) \
+                                       )   
+
+#define IS_GREATER(col1,col2) ( ( (GET_RED(col1)  ) > (GET_RED(col2)  ) + MIN_COLOR_DIFF ) && \
+                                ( (GET_GREEN(col1)) > (GET_GREEN(col2)) + MIN_COLOR_DIFF ) &&  \
+                                                               ( (GET_BLUE(col1) ) > (GET_BLUE(col2) ) + MIN_COLOR_DIFF )         \
+                                                         )
+
+#define MASK_BG           0
+#define MASK_DARK  1
+#define MASK_LIGHT 2
+
+// helper function, used internally
+
+static void gray_out_pixmap( int* src, int* dest, int width, int height )
+{
+       // assuming the pixels along the edges are of the background color
+       int bgCol = GET_ELEM(src,0,0);
+
+       int x = 0;
+       int y = 1;
+
+       do
+       {
+               int cur       = GET_ELEM(src,x,y);
+
+               int r = GET_RED(cur);
+               int g = GET_GREEN(cur);
+               int b = GET_BLUE(cur);
+
+               if ( IS_IN_ARRAY(x-1,y-1) )
+               {
+                       int upperElem = GET_ELEM(src,x-1,y-1);
+
+                       // if the upper element is lighter than current
+                       if ( IS_GREATER(upperElem,cur) )
+                       {
+                               GET_ELEM(dest,x,y) = MASK_DARK;
+                       }
+                       else
+                       // if the current element is ligher than the upper
+                       if ( IS_GREATER(cur,upperElem) )
+                       {
+                               GET_ELEM(dest,x,y) = MASK_LIGHT;
+                       }
+                       else
+                       {
+                               if ( GET_ELEM(dest,x-1,y-1) == MASK_LIGHT )
+                                       
+                                       GET_ELEM(dest,x,y) = MASK_BG;
+
+                               if ( GET_ELEM(dest,x-1,y-1 ) == MASK_DARK )
+
+                                       GET_ELEM(dest,x,y) = MASK_DARK;
+                               else
+                                       GET_ELEM(dest,x,y) = MASK_BG;
+                       }
+               }
+
+               // go zig-zag
+
+               if ( IS_IN_ARRAY(x+1,y-1) ) 
+               {
+                       ++x;--y;
+               }
+               else
+               {
+                       while( IS_IN_ARRAY(x-1,y+1) ) 
+                       {
+                               --x;++y;
+                       }
+
+                       if ( IS_IN_ARRAY(x,y+1) )
+                       {
+                                       ++y; continue;
+                       }
+                       else
+                       {
+                               if ( IS_IN_ARRAY(x+1,y) )
+                               {
+                                       ++x; continue;
+                               }
+                               else break;
+                       }
+               }
+
+       } while(1);
+}
+
+// alg. for making the image look "grayed" (e.g. disabled button)
+// NOTE:: used GetPixel(), which is Windows-Only!
+
+void greay_out_image_on_dc( wxDC& dc, int width, int height )
+{
+       // assuming the pixels along the edges are of the background color
+       wxColour bgCol;
+       dc.GetPixel( 0, 0, &bgCol );
+
+       wxPen darkPen ( wxColour(128,128,128),1, wxSOLID );
+       wxPen lightPen( wxColour(255,255,255),1, wxSOLID );
+       wxPen bgPen   ( bgCol,                1, wxSOLID );
+
+       int* src  = create_array( width, height, MASK_BG );
+       int* dest = create_array( width, height, MASK_BG );
+
+       int y = 0;
+       for( y = 0; y != height; ++y )
+
+               for( int x = 0; x != width; ++x )
+               {
+                       wxColour col;
+                       dc.GetPixel( x,y, &col );
+
+                       int r = col.Red(), 
+                               g = col.Green(), 
+                               b = col.Blue();
+
+                       int o = MAKE_INT_COLOR( r,g,b );
+
+                       GET_ELEM(src,x,y) = MAKE_INT_COLOR( col.Red(), col.Green(), col.Blue() );
+               }
+
+       gray_out_pixmap( src, dest, width, height );
+
+       for( y = 0; y != height; ++y )
+
+               for( int x = 0; x != width; ++x )
+               {
+                       int mask = GET_ELEM(dest,x,y);
+
+                       switch (mask)
+                       {
+                               case MASK_BG    : { dc.SetPen( bgPen ); 
+                                                       dc.DrawPoint( x,y ); break;
+                                                             }
+                               case MASK_DARK  : { dc.SetPen( darkPen ); 
+                                                       dc.DrawPoint( x,y ); break;
+                                                             }
+                               case MASK_LIGHT : { dc.SetPen( lightPen ); 
+                                                       dc.DrawPoint( x,y ); break;
+                                                             }
+                               default : break;
+                       }
+               }
+
+       delete [] src;
+       delete [] dest;
+}
+
+///////////////////////////////
+
+/***** Impelementation for class wxNewBitmapButton *****/
+
+IMPLEMENT_DYNAMIC_CLASS(wxNewBitmapButton, wxPanel)
+
+BEGIN_EVENT_TABLE( wxNewBitmapButton, wxPanel )
+
+       EVT_LEFT_DOWN( wxNewBitmapButton::OnLButtonDown )
+       EVT_LEFT_UP  ( wxNewBitmapButton::OnLButtonUp   )
+       EVT_MOTION   ( wxNewBitmapButton::OnMouseMove   )
+
+       EVT_SIZE ( wxNewBitmapButton::OnSize  )
+       EVT_PAINT( wxNewBitmapButton::OnPaint )
+
+       //EVT_KILL_FOCUS( wxNewBitmapButton::OnKillFocus )
+
+       EVT_ERASE_BACKGROUND( wxNewBitmapButton::OnEraseBackground )
+
+END_EVENT_TABLE()
+
+wxNewBitmapButton::wxNewBitmapButton( const wxBitmap& labelBitmap, 
+                                                                         const wxString& labelText,
+                                                                         int  alignText,
+                                                                         bool isFlat,
+                                                                         int  firedEventType, 
+                                                                         int  marginX,
+                                                                         int  marginY,
+                                                                         int  textToLabelGap,
+                                                                         bool isSticky)
+       :       mpDepressedImg( NULL ),
+               mpPressedImg  ( NULL ),
+               mpDisabledImg ( NULL ),
+               mpFocusedImg  ( NULL ),
+
+               mMarginX( marginX ),
+               mMarginY( marginY ),
+               mTextAlignment( alignText ),
+               mIsFlat( isFlat ),
+
+               mIsPressed       ( FALSE ),
+               mDragStarted     ( FALSE ),
+               mPrevPressedState( FALSE ),
+               mTextToLabelGap  ( textToLabelGap ),
+
+               mBlackPen( wxColour(  0,  0,  0), 1, wxSOLID ),
+               mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
+               mGrayPen ( wxColour(192,192,192),
+                          1, wxSOLID ),
+               mLightPen( wxColour(255,255,255), 1, wxSOLID ),
+
+               mFiredEventType( firedEventType ),
+               mIsSticky( isSticky ),
+               mIsCreated( FALSE ),
+               mSizeIsSet( FALSE ),
+
+               mHasFocusedBmp( FALSE ),
+               mIsInFocus( FALSE ),
+
+               mDepressedBmp( labelBitmap ),
+               mLabelText( labelText ),
+               mImageFileType( -1 )
+{
+}
+
+wxNewBitmapButton::wxNewBitmapButton( const wxString& bitmapFileName,
+                                                                         const int       bitmapFileType,
+                                                                         const wxString& labelText,
+                                                                         int  alignText,
+                                                                         bool isFlat,
+                                                                         int  firedEventType, 
+                                                                         int  marginX,
+                                                                         int  marginY,
+                                                                         int  textToLabelGap,
+                                                                         bool isSticky)
+
+       :       mpDepressedImg( NULL ),
+               mpPressedImg  ( NULL ),
+               mpDisabledImg ( NULL ),
+               mpFocusedImg  ( NULL ),
+
+               mMarginX( 2 ),
+               mMarginY( 2 ),
+               mTextAlignment( alignText ),
+               mIsFlat( isFlat ),
+
+               mIsPressed       ( FALSE ),
+               mDragStarted     ( FALSE ),
+               mPrevPressedState( FALSE ),
+               mTextToLabelGap  ( 2 ),
+
+               mBlackPen( wxColour(  0,  0,  0), 1, wxSOLID ),
+               mDarkPen ( wxColour(128,128,128), 1, wxSOLID ),
+               mGrayPen ( wxColour(192,192,192),
+                          1, wxSOLID ),
+               mLightPen( wxColour(255,255,255), 1, wxSOLID ),
+
+               mFiredEventType( wxEVT_COMMAND_MENU_SELECTED ),
+               mIsSticky( FALSE ),
+               mIsCreated( FALSE ),
+               mSizeIsSet( FALSE ),
+
+               mHasFocusedBmp( FALSE ),
+               mIsInFocus( FALSE ),
+
+               mLabelText( labelText ),
+               mImageFileName( bitmapFileName ),
+               mImageFileType( bitmapFileType )
+{
+       //mDepressedBmp.LoadFile( bitmapFileName, bitmapFileType );
+}
+
+wxNewBitmapButton::~wxNewBitmapButton(void) 
+{
+       DestroyLabels();
+}
+
+void wxNewBitmapButton::DrawShade( int outerLevel,
+                                                                  wxDC&  dc,
+                                                              wxPen& upperLeftSidePen,
+                                                                  wxPen& lowerRightSidePen )
+{
+       wxBitmap* pBmp = GetStateLabel();
+
+       int x = mMarginX - (outerLevel + 1);
+       int y = mMarginY - (outerLevel + 1);
+
+       int height = pBmp->GetHeight() + (outerLevel + 1)*2 - 1;
+       int width  = pBmp->GetWidth()  + (outerLevel + 1)*2 - 1;
+
+       dc.SetPen( upperLeftSidePen );
+       dc.DrawLine( x,y, x + width, y  );
+       dc.DrawLine( x,y, x, y + height );
+
+       dc.SetPen( lowerRightSidePen );
+       dc.DrawLine( x + width, y, x + width, y + height + 1  );
+       dc.DrawLine( x, y + height, x + width, y + height );
+}
+
+void wxNewBitmapButton::DestroyLabels()
+{
+       if ( mpDepressedImg ) delete mpDepressedImg;
+       if ( mpPressedImg   ) delete mpPressedImg;
+       if ( mpDisabledImg  ) delete mpDisabledImg;
+       if ( mpFocusedImg   ) delete mpFocusedImg;
+
+       mpDepressedImg = NULL;
+       mpPressedImg   = NULL;
+       mpDisabledImg  = NULL;
+       mpFocusedImg   = NULL;
+}
+
+wxBitmap* wxNewBitmapButton::GetStateLabel()
+{
+       if ( IsEnabled() )
+       {
+               if ( mIsPressed )
+               {
+                       return mpPressedImg;
+               }
+               else
+               {
+                       if ( mIsInFocus )
+                       {
+                               if ( mHasFocusedBmp )
+
+                                       return mpFocusedImg;
+                               else
+                                       return mpDepressedImg;
+                       }
+                       else
+                               return mpDepressedImg;
+               }
+       }
+       else
+               return mpDisabledImg;
+}
+
+void wxNewBitmapButton::RenderLabelImage( wxBitmap*& destBmp, wxBitmap* srcBmp,
+                                                                                 bool isEnabled, bool isPressed )
+{
+       if ( destBmp != 0 ) return;
+
+       // render lables on-demand
+
+       wxMemoryDC srcDc;
+       srcDc.SelectObject( *srcBmp );
+       wxFont fnt( 9, wxDECORATIVE , wxNORMAL, wxNORMAL );
+
+       bool hasText = ( mTextAlignment != NB_NO_TEXT ) &&
+                          ( mLabelText.length() != 0 );
+
+       bool hasImage = (mTextAlignment != NB_NO_IMAGE);
+
+       wxSize destDim;
+       wxPoint txtPos;
+       wxPoint imgPos;
+
+       if ( hasText )
+       {
+               long txtWidth, txtHeight;
+
+               srcDc.SetFont( fnt );
+               srcDc.GetTextExtent( mLabelText, &txtWidth, &txtHeight );
+
+               if ( mTextAlignment == NB_ALIGN_TEXT_RIGHT )
+               {
+                       destDim.x = srcBmp->GetWidth() + 2*mTextToLabelGap + txtWidth;
+
+                       destDim.y = 
+                               wxMax( srcBmp->GetHeight(), txtHeight );
+
+                       txtPos.x = srcBmp->GetWidth() + mTextToLabelGap;
+                       txtPos.y = (destDim.y - txtHeight)/2;
+                       imgPos.x = 0;
+                       imgPos.y = (destDim.y - srcBmp->GetHeight())/2;
+               }
+               else
+               if ( mTextAlignment == NB_ALIGN_TEXT_BOTTOM )
+               {
+                       destDim.x = 
+                               wxMax( srcBmp->GetWidth(), txtWidth );
+
+                       destDim.y = srcBmp->GetHeight() + mTextToLabelGap + txtHeight;
+
+                       txtPos.x = (destDim.x - txtWidth)/2;
+                       txtPos.y = srcBmp->GetHeight() + mTextToLabelGap;
+                       imgPos.x = (destDim.x - srcBmp->GetWidth())/2;
+                       imgPos.y = 0;
+               }
+               else wxASSERT(0);// unsupported alignment type
+       }
+       else
+       {
+               imgPos.x = 0;
+               imgPos.y = 0;
+               destDim.x = srcBmp->GetWidth();
+               destDim.y = srcBmp->GetHeight();
+       }
+
+       destBmp = new wxBitmap( int(destDim.x), int(destDim.y) );
+
+       wxMemoryDC destDc;
+       destDc.SelectObject( *destBmp );
+
+       // FOR NOW:: hard-coded label background
+       wxBrush grayBrush( wxColour(192,192,192), wxSOLID );
+       wxPen   nullPen( wxColour(0,0,0), 1, wxTRANSPARENT );
+
+       destDc.SetBrush( grayBrush );
+       destDc.SetPen( nullPen );
+
+       destDc.DrawRectangle( 0,0, destDim.x+1, destDim.y+1 );
+
+       if ( isPressed )
+       {
+               ++imgPos.x; ++imgPos.y;
+               ++txtPos.x; ++txtPos.y;
+       }
+
+       if ( hasImage )
+       {
+               destDc.Blit( imgPos.x, imgPos.y, 
+                                        srcBmp->GetWidth()+1,
+                                        srcBmp->GetHeight()+1,
+                                        &srcDc, 0,0, wxCOPY );
+       }
+
+       if ( hasText )
+       {
+               wxWindow* pTopWnd = this;
+
+               do
+               {
+                       wxWindow* pParent = pTopWnd->GetParent();
+
+                       if ( pParent == 0 ) break;
+
+                       pTopWnd = pParent;
+               } while(1);
+
+               destDc.SetFont( fnt );
+
+               // FOR NOW:: hard-coded text colors
+               destDc.SetTextForeground( wxColour(  0,  0,  0) );
+               destDc.SetTextBackground( wxColour(192,192,192) );
+
+               destDc.DrawText( mLabelText, txtPos.x, txtPos.y );
+       }
+
+       if ( !isEnabled )
+       
+               greay_out_image_on_dc( destDc, destDim.x, destDim.y );
+
+       // adjust button size to fit the new dimensions of the label
+       if ( !mSizeIsSet && 0 )
+       {
+               mSizeIsSet = TRUE; 
+               SetSize( -1,-1, 
+                                destBmp->GetWidth()  + mMarginX*2,
+                                destBmp->GetHeight() + mMarginY*2, 0 
+                       );
+       }
+}
+
+void wxNewBitmapButton::RenderLabelImages()
+{
+       if ( !mIsCreated ) return;
+
+       if ( !IsEnabled() )
+       {
+               RenderLabelImage( mpDisabledImg, &mDepressedBmp, FALSE );
+       }
+       else
+
+       if ( mIsPressed ) 
+
+               RenderLabelImage( mpPressedImg,   &mDepressedBmp, TRUE, TRUE );
+       else
+       {
+               if ( mIsInFocus )
+               {
+                       if ( mHasFocusedBmp )
+                       
+                               RenderLabelImage( mpFocusedImg, &mFocusedBmp, TRUE, FALSE );
+                       else
+                               RenderLabelImage( mpDepressedImg, &mDepressedBmp, TRUE, FALSE );
+               }
+               else
+                       RenderLabelImage( mpDepressedImg, &mDepressedBmp, TRUE, FALSE );
+       }
+}
+
+void wxNewBitmapButton::DrawDecorations( wxDC& dc )
+{
+       if ( mIsFlat )
+       {
+               DrawShade( 1, dc, mGrayPen,  mGrayPen  );
+               
+               if ( mIsInFocus )
+               {
+                       if ( mIsPressed )
+               
+                               DrawShade( 0, dc, mDarkPen,  mLightPen  );
+                       else
+                               DrawShade( 0, dc, mLightPen,  mDarkPen  );
+               }
+               else
+                       DrawShade( 0, dc, mGrayPen,  mGrayPen  );
+       }
+       else
+       {
+               if ( mIsPressed )
+               {
+                       DrawShade( 0, dc, mDarkPen,  mGrayPen  );
+                       DrawShade( 1, dc, mBlackPen, mLightPen );
+               }
+               else
+               {
+                       DrawShade( 0, dc, mGrayPen,  mDarkPen  );
+                       DrawShade( 1, dc, mLightPen, mBlackPen );
+               }
+       }
+}
+
+void wxNewBitmapButton::SetLabel(const wxBitmap& labelBitmap, 
+                                                                const wxString& labelText )
+{
+       DestroyLabels();
+
+       mLabelText    = labelText;
+       mDepressedBmp = labelBitmap;
+
+       RenderLabelImages();
+}
+
+void wxNewBitmapButton::SetAlignments( int alignText,
+                                                                      int marginX,
+                                                                          int marginY,
+                                                                          int textToLabelGap)
+{
+       DestroyLabels();
+
+       mMarginX        = marginX;
+       mMarginY        = marginY;
+       mTextAlignment  = alignText;
+       mTextToLabelGap = textToLabelGap;
+
+       RenderLabelImages();
+}
+
+// event handlers
+
+void wxNewBitmapButton::OnLButtonDown( wxMouseEvent& event )
+{
+       mPrevPressedState = FALSE;   
+       mDragStarted      = TRUE;
+       mIsPressed        = TRUE;
+       Refresh();
+
+       if ( !mIsInFocus )
+       
+                       CaptureMouse();
+}
+
+void wxNewBitmapButton::OnLButtonUp( wxMouseEvent& event )
+{
+       if ( !mDragStarted ) return;
+
+       mDragStarted = FALSE;
+       mIsPressed   = FALSE;
+       mIsInFocus   = FALSE;
+       Refresh();
+
+       ReleaseMouse();
+
+       if ( IsInWindow( event.m_x, event.m_y ) ) 
+       {
+               // fire event, if mouse was released
+               // within the bounds of button
+               wxCommandEvent cmd( mFiredEventType, GetId() );
+               GetParent()->ProcessEvent( cmd );
+       }
+}
+
+bool wxNewBitmapButton::IsInWindow( int x, int y )
+{
+       int width, height;
+       GetSize( &width, &height );
+
+       return ( x >= 0 && y >= 0 &&
+                        x < width &&
+                        y < height );
+}
+
+void wxNewBitmapButton::OnMouseMove( wxMouseEvent& event )
+{
+       if ( !mIsInFocus && IsInWindow( event.m_x, event.m_y ) )
+       {
+               if ( !mDragStarted )
+                       CaptureMouse();
+
+               mIsInFocus = TRUE;
+       }
+       else
+       if ( mIsInFocus && !IsInWindow( event.m_x, event.m_y ) )
+       {
+               mIsInFocus = FALSE;
+
+               if ( !mDragStarted )
+                       ReleaseMouse();
+       }
+
+       if ( mDragStarted )
+       {
+               if ( IsInWindow( event.m_x, event.m_y ) )
+
+                       mIsPressed = TRUE;
+               else
+                       mIsPressed = FALSE;
+
+               if ( mIsPressed != mPrevPressedState )
+                       
+                       Refresh();
+
+               mPrevPressedState = mIsPressed;
+       }
+
+       // FOR NOW::
+       Refresh();
+}
+
+void wxNewBitmapButton::OnSize( wxSizeEvent& event )
+{
+               //Reshape();
+}
+
+void wxNewBitmapButton::Reshape( )
+{
+       bool wasCreated = mIsCreated;
+       mIsCreated = TRUE;
+
+       if ( !wasCreated )
+       {
+               // in the case of loading button from stream, check if we
+               // have non-empty image-file name, load if possible 
+
+               if ( mImageFileName != "" )
+               {
+                       mDepressedBmp.LoadFile( mImageFileName, mImageFileType );
+
+                       //wxMessageBox("Image Loaded!!!");
+               }
+
+               RenderLabelImages();
+
+               wxBitmap* pCurImg = GetStateLabel();
+
+               int w = pCurImg->GetWidth(),
+                       h = pCurImg->GetHeight();
+
+               SetSize( 0,0, w + mMarginX*2, h + mMarginY*2 , 0 );
+       }
+}
+
+void wxNewBitmapButton::DrawLabel( wxDC& dc )
+{
+       wxBitmap* pCurBmp = GetStateLabel();
+
+       if ( pCurBmp == NULL )
+       {
+               wxSizeEvent evt;
+               OnSize( evt ); // fake it up!
+
+               RenderLabelImages();
+               pCurBmp = GetStateLabel();
+       }
+
+       wxMemoryDC mdc;
+       mdc.SelectObject( *pCurBmp );
+
+       dc.Blit( mMarginX, mMarginY, 
+                        pCurBmp->GetWidth(),
+                        pCurBmp->GetHeight(),
+                        &mdc, 0,0, wxCOPY 
+                  );
+
+       mdc.SelectObject( wxNullBitmap );
+}
+
+void wxNewBitmapButton::OnPaint( wxPaintEvent& event )
+{
+       wxPaintDC dc(this);
+
+       // first, make sure images for current state are prepared
+       RenderLabelImages();
+
+       DrawLabel( dc );
+
+       DrawDecorations( dc );
+}
+
+void wxNewBitmapButton::OnEraseBackground( wxEraseEvent& event )
+{
+       // do nothing
+}
+
+void wxNewBitmapButton::OnKillFocus( wxFocusEvent& event )
+{
+       // useless
+
+       wxMessageBox("kill-focus for button!");
+}
+