Changing the background color of a BUTTON

Post Reply
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Changing the background color of a BUTTON

Post by xProgrammer »

Hi Antonio

I can't see how to do it. Is it currently possible? If not could it be added? It would really help in my application. (I want to change the background color when a button is clicked and change it back again when another one is clicked).

Thanks
Doug
(xProgrammer)
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Antonio

I have done a little research and in GTK+2.0 it sounds like it isn't too difficult, you need something like this:

Code: Select all

  GdkColor color;

  gdk_color_parse ("red", &color);

  gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);
The code required in earlier versions is greater. Do you use GTK+2.0?
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Doug,

Afaik we are using GTK+ 2.0. Please try this code in Class TWindow:

Code: Select all

METHOD SetColor( cColor ) INLINE GtkSetColor( ::hWnd, cColor )

#pragma BEGINDUMP

#include <hbapi.h>
#include <gtk/gtk.h>

HB_FUNC( GTKSETCOLOR )
{
   GdkColor color; 

   gdk_color_parse( hb_parc( 1 ), &color ); 
   gtk_widget_modify_fg( ( GtkWidget * ) hb_parnl( 1 ), GTK_STATE_NORMAL, &color );
}

#pragma ENDDUMP
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

Thanks. I will try that. I take it that I will have to compile the code in the modified window.prg and what else? Am I producing a new library? or object code to be linked? or what?

Sorry for the (probably) naive questions but I haven't had to do that sort of thing before.

Thanks

Doug
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Doug,

You have to modify window.prg and then compile it and link it as another PRG of your application
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

I did that and got the following error in the terminal window from whioch I launched my application:

(<unknown>:30895) Pango-CRITICAL **: pango-color-parse: assertion 'spec != NULL' failed

Seems like a parameter passing problem?

The call in my code was:

Code: Select all

   btnSelect:SetColor("red")
)

But we must be close since we are getting a message from pango_color_parse.

I just found out more - I changed METHOD SetColor in two ways.

Firstly I hard coded red - which stopped the error message (bur unfortunately didn't give me a red button) and I included a MsgInfo (just to check that the code was being traversed.

Code: Select all

METHOD SetColor( cColor ) INLINE  MsgInfo( "red"), GtkSetColor( ::hWnd, cColor )

#pragma BEGINDUMP

#include <hbapi.h>
#include <gtk/gtk.h>

HB_FUNC( GTKSETCOLOR )
{
   GdkColor color;

   gdk_color_parse( "red", &color );
   gtk_widget_modify_fg( ( GtkWidget * ) hb_parnl( 1 ), GTK_STATE_NORMAL, &color );
}

#pragma ENDDUMP 
I just tried setting the color of oWnd to red - again no error but also no red.

I will do some more research, but if you have any ideas please let me know.

Thanks

Doug
(xProgrammer)
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

Progress!

I changed

Code: Select all

gtk_widget_modify_fg
to

Code: Select all

gtk_widget_modify_bg
And we have a red button (background) in the normal state.

So we are very close. Now we have to work out:

Why hb_parc(1) doesn't seem to be getting the value "red".

List of states to which colors can be applied (That should be easy enough for me to find))

The function that sets a color for the text. (Actually I am happy just controlling the background color, but others may want to change the text color)

Thanks and regards
Doug
(xProgrammer)
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

States are as follows:

enum GtkStateType

Code: Select all

typedef enum
{
  GTK_STATE_NORMAL,
  GTK_STATE_ACTIVE,
  GTK_STATE_PRELIGHT,
  GTK_STATE_SELECTED,
  GTK_STATE_INSENSITIVE
} GtkStateType;
This type indicates the current state of a widget; the state determines how the widget is drawn. The GtkStateType enumeration is also used to identify different colors in a GtkStyle for drawing, so states can be used for subparts of a widget as well as entire widgets.

GTK_STATE_NORMAL
State during normal operation.

GTK_STATE_ACTIVE
State of a currently active widget, such as a depressed button.

GTK_STATE_PRELIGHT
State indicating that the mouse pointer is over the widget and the widget will respond to mouse clicks.

GTK_STATE_SELECTED
State of a selected item, such the selected row in a list.

GTK_STATE_INSENSITIVE
State indicating that the widget is unresponsive to user actions.

And the color changing methods are:

Code: Select all

gtk_widget_modify_fg ()

void                gtk_widget_modify_fg                (GtkWidget *widget,
                                                         GtkStateType state,
                                                         const GdkColor *color);
Sets the foreground color for a widget in a particular state. All other style values are left untouched. See also gtk_widget_modify_style().

widget :
a GtkWidget

state :
the state for which to set the foreground color

color :
the color to assign (does not need to be allocated), or NULL to undo the effect of previous calls to of gtk_widget_modify_fg().

Code: Select all

gtk_widget_modify_bg ()

void                gtk_widget_modify_bg                (GtkWidget *widget,
                                                         GtkStateType state,
                                                         const GdkColor *color);
Sets the background color for a widget in a particular state. All other style values are left untouched. See also gtk_widget_modify_style().

Note that "no window" widgets (which have the GTK_NO_WINDOW flag set) draw on their parent container's window and thus may not draw any background themselves. This is the case for e.g. GtkLabel. To modify the background of such widgets, you have to set the background color on their parent; if you want to set the background of a rectangular area around a label, try placing the label in a GtkEventBox widget and setting the background color on that.

widget :
a GtkWidget

state :
the state for which to set the background color

color :
the color to assign (does not need to be allocated), or NULL to undo the effect of previous calls to of gtk_widget_modify_bg().

Code: Select all

gtk_widget_modify_text ()

void                gtk_widget_modify_text              (GtkWidget *widget,
                                                         GtkStateType state,
                                                         const GdkColor *color);
Sets the text color for a widget in a particular state. All other style values are left untouched. The text color is the foreground color used along with the base color (see gtk_widget_modify_base()) for widgets such as GtkEntry and GtkTextView. See also gtk_widget_modify_style().

widget :
a GtkWidget

state :
the state for which to set the text color

color :
the color to assign (does not need to be allocated), or NULL to undo the effect of previous calls to of gtk_widget_modify_text().

Code: Select all

gtk_widget_modify_base ()

void                gtk_widget_modify_base              (GtkWidget *widget,
                                                         GtkStateType state,
                                                         const GdkColor *color);
Sets the base color for a widget in a particular state. All other style values are left untouched. The base color is the background color used along with the text color (see gtk_widget_modify_text()) for widgets such as GtkEntry and GtkTextView. See also gtk_widget_modify_style().

Note that "no window" widgets (which have the GTK_NO_WINDOW flag set) draw on their parent container's window and thus may not draw any background themselves. This is the case for e.g. GtkLabel. To modify the background of such widgets, you have to set the base color on their parent; if you want to set the background of a rectangular area around a label, try placing the label in a GtkEventBox widget and setting the base color on that.

widget :
a GtkWidget

state :
the state for which to set the base color

color :
the color to assign (does not need to be allocated), or NULL to undo the effect of previous calls to of gtk_widget_modify_base().

However I tried modify_text for my button and it didn't work. I tried setting background colors for different states and got that working fine with this code:

Code: Select all

METHOD SetColor( cColor ) INLINE  MsgInfo( "red"), GtkSetColor( ::hWnd, cColor )

#pragma BEGINDUMP

#include <hbapi.h>
#include <gtk/gtk.h>

HB_FUNC( GTKSETCOLOR )
{
   GdkColor color;
   GdkColor acolor;

   gdk_color_parse( "red", &color );
   gdk_color_parse( "yellow", &acolor );
   gtk_widget_modify_bg( ( GtkWidget * ) hb_parnl( 1 ), GTK_STATE_NORMAL, &color );
   gtk_widget_modify_bg( ( GtkWidget * ) hb_parnl( 1 ), GTK_STATE_PRELIGHT, &acolor );
}

#pragma ENDDUMP 
So a generic SetColor might take color names for the various states.

Could you tell me the best way to debug why I don't seem to be getting the string valuse passed in to the C code.

Thanks

Doug
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

I should have worked it out before - the problem with your original code is that where you have hb_parc( 1 ) it should in fact he hb_parc( 2). Now parameter passing appears fine.

Now the function needs to be made more utilitarian - ie change any of the colors (bg, fg, text, base) for any state. State can be passed as a parameter.

Regards
Doug
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Doug,

There was a bug in my code. This is the right one:

Code: Select all

METHOD SetColor( cColor ) INLINE GtkSetColor( ::hWnd, cColor ) 

#pragma BEGINDUMP 

#include <hbapi.h> 
#include <gtk/gtk.h> 

HB_FUNC( GTKSETCOLOR ) 
{ 
   GdkColor color; 

   gdk_color_parse( hb_parc( 2 ), &color ); 
   gtk_widget_modify_fg( ( GtkWidget * ) hb_parnl( 1 ), GTK_STATE_NORMAL, &color ); 
} 

#pragma ENDDUMP 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

This version allows you to pass in the state to apply the color to as a second parameter:

Code: Select all

METHOD SetColor( cColor, iState ) INLINE  GtkSetColor( ::hWnd, cColor, iState )

#pragma BEGINDUMP

#include <hbapi.h>
#include <gtk/gtk.h>

HB_FUNC( GTKSETCOLOR )
{
   GdkColor color;

   gdk_color_parse( hb_parc( 2 ), &color );
   gtk_widget_modify_bg( ( GtkWidget * ) hb_parnl( 1 ), hb_parni( 3 ), &color );
}
The state parameter can then be:

Code: Select all

#define GTK_NORMAL 1
#define GTK_ACTIVE   2
#define GTK_PRELIGHT 3
#define GTK_SELECTED 4
#define GTK_INSENSITIVE 5
Next step is to either have multiple methods (SetBGColor, SetFGColor, SetTextColor and SetBaseColor, or pass in an additional parameter (switch).

Regards
Doug
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Correction to above - defines should be:

Code: Select all

#define GTK_NORMAL 0
#define GTK_ACTIVE   1
#define GTK_PRELIGHT 2
#define GTK_SELECTED 3
#define GTK_INSENSITIVE 4
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Doug,

I think we should implement it this way:

METHOD SetColor( cForeColor, cBackColor [, nState] )
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

Hi Antonio

I certainly want to manipulate text-color as well (So that if a GET is set to WHEN .F. it isn't in that dull gray which some users find hard to read).

That would only leave base-color which means perhaps we should consider doing all four.

Maybe we could have:

Code: Select all

METHOD SetColor( cForeColor[, cBackColor[, cTextColor[, cBaseColor [, nState]]]] )
such that passing a NULL for any color just means that the corresponding gtk_widget-modify method is not invoked and the present setting is left unaltered.

Perhaps even better would be the following:

METHOD SetColor( aColors[, nState])

where aColors is an array of the four possible color settings

Code: Select all

#define GTK_FOREGROUND 1
#define GTK_BACKGROUND 2
#define GTK_TEXT              3
#define GTK_BASE             4
so in usage we would have something like:

Code: Select all

aGTK_Colors := ARRAY( 4 )
aGTK_Colors[GTK_BACKGROUND] := "red"
aGTK_Colors[GTK_TEXT]              := "black"
btnEXAMPLE:SetColors( aGTK_Colors, GTK_PRELIGHT )
The SetColor Method would presumably contain code like:

Code: Select all

LOCAL iLen
iLen := LEN( aColors )
IF iLen < 0
  RETURN
ENDIF
IF !Empty( a Colors[1] )
   GtkSetFGColor( ::hWnd, aColors[1], iState )
ENDIF
IF iLen < 2
   RETURN
ENDIF
IF !EMPTY( aColors[2] )
   GtkSetBGColor( ::hWnd, aColors[2], iState )
ENDIF
etc

Just my suggestion.

Thanks for your help
Regards
Doug
(xProgrammer)
User avatar
xProgrammer
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Post by xProgrammer »

For anyone following this who wants to know what colors can be created this way the list is available in text form at

http://www-swiss.ai.mit.edu/~jaffer/Color/rgb.txt

or to see the colors go to

http://sedition.com/perl/rgb.html

alternatively search for rgb.txt

Regards
Doug
(xProgrammer)
Post Reply