I am using fltk 1.3.2.
I set the button's label color with
_button->labelcolor(fl_rgb_color(162, 60, 62));
but when I press the button, the color is changed.
I couldn't find the function how set the active label color.
Does anyone know how to do that?
Edit:
I use Fl::background() and Fl::foreground() functions before creating the window. This make the problem.
Edit2:
This example shows the problem.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <iostream>
void HitMe(Fl_Widget* w)
{
std::cout << "Ouch" << std::endl;
}
int main(int argc, char ** argv)
{
Fl::background(0x60, 0x66, 0x60);
Fl_Window *window = new Fl_Window(320,130);
Fl_Button *b = new Fl_Button(10, 10, 130, 30, "A red label");
b->labelcolor(fl_rgb_color(162, 60, 20));
b->callback(HitMe);
window->end();
window->show(argc,argv);
return Fl::run();
}
When I commented out Fl::background() function everything is alright.
What you are seeing is the contrasting colour (see commented out code below). FLTK does this when the button is pressed. It gets the colour of the button, works out the contrasting colour based on the foreground and background colours. Have a look at the help for fl_contrast for more details.
Basically, if there is enough contrast, it will use the foreground colour otherwise it will find a contrasting colour for your background.
What can you do about it?
do nothing - that is how it is
choose a lighter background colour which will satisfy the contrast conditions
make your own button type with its own draw method
class KeepFGButton : public Fl_Button
{
public:
KeepFGButton(int x, int y, int w, int h, const char* s)
: Fl_Button(x, y, w, h, s)
{
}
void draw() {
if (type() == FL_HIDDEN_BUTTON) return;
Fl_Color col = value() ? selection_color() : color();
draw_box(value() ? (down_box() ? down_box() : fl_down(box())) : box(), col);
draw_backdrop();
// Remove the code that changes the contrast
//if (labeltype() == FL_NORMAL_LABEL && value()) {
// Fl_Color c = labelcolor();
// labelcolor(fl_contrast(c, col));
// draw_label();
// labelcolor(c);
//}
//else
draw_label();
if (Fl::focus() == this) draw_focus();
}
};
int main(int argc, char ** argv)
{
Fl::background(0x60, 0x66, 0x60);
Fl_Window *window = new Fl_Window(320, 130);
Fl_Button *b = new KeepFGButton(10, 10, 130, 30, "A red label");
...
Try the following and let me know if, when you run it, the label becomes white. If it doesn't then there is possibly something else that you are doing that is not quite right. If it does, I don't know what the problem is.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <iostream>
void HitMe(Fl_Widget* w)
{
std::cout << "Ouch" << std::endl;
}
int main(int argc, char ** argv) {
Fl_Window *window = new Fl_Window(320,130);
Fl_Button *b = new Fl_Button(10, 10, 130, 30, "A red label");
b->labelcolor(fl_rgb_color(162, 60, 20));
b->callback(HitMe);
window->end();
window->show(argc,argv);
return Fl::run();
}
This is definitely too late to help the author, but in the event that this helps anyone else searching for an answer to this still relevant issue in FLTK, I'm going to offer my solution:
If you dig through the source code for FLTK 1.3.4-2 (current stable as of this post), there are a couple of built-in colormap indices which are referenced when the drawing of shadow boxes or frames are called: FL_DARK3 (for the boxes) and FL_DARK2 (for the scrollbar back color in Fl_Scroll). You can look at this FLTK documentation to see how to reset these colors to anything you wish at runtime. In particular, anticipating that this ugly red default mess will show up whenever there's a sufficiently dark background, it works well for me to just set these to a slightly lighter version of the overlayed box color:
Fl_Color boxColor = 0x88888800;
Fl_Color boxShadowColor = 0xaaaaaa00;
Fl::set_color(FL_DARK3, boxShadowColor);
Fl::set_color(FL_DARK2, boxShadowColor);
Now create your label as above and the display will be free of the red shadow. N.b. it is also possible to override the standard background2() behavior which resets FL_BACKGROUND_COLOR to the one produced by fl_contrast:
Fl::set_color(FL_BACKGROUND2_COLOR, yourBgColor);
The same trick works for other hard to reset colors like FL_INACTIVE_COLOR and FL_SELECTION_COLOR.
Hope this workaround helps.
Related
I have an ncurses-based text application i am writing. I have a function called colorPlot:
void colorPlot(int x, int y, int foregroundColor, int backgroundColor, char plotChar)
{
init_pair(0, foregroundColor, backgroundColor);
attrset(COLOR_PAIR(0));
mvaddch(y, x, plotChar);
}
But whenever i try to call it in my main function:
int main(void) {
initscr();
start_color();
colorPlot(1, 1, COLOR_RED, COLOR_WHITE, '#');
refresh();
getch();
endwin();
}
It only prints white-on-black. Why isn't it printing red-on-white?
Color pair 0 (see manual for start_color) is reserved:
color pair 0 is special; it denotes "no color".
Color pair 0 is assumed to be white on black, but is
actually whatever the terminal implements before color
is initialized. It cannot be modified by the application.
Was trying to code. C, Linux. User enter some string and date. If it's today, then program should show a window with his string. Then this window should be closed by code, not user. And then it will pop up again after a short period of time. gtk_widget_destroy and gtk_widget_hide don't work.
`(aa:26429): Gtk-CRITICAL **: IA__gtk_widget_hide: assertion 'GTK_IS_WIDGET (widget)' failed`
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
/* numbered markers placed below by msw for reference */
char str[50];
int main( int argc, char *argv[] )
{
printf("Enter your string\n>:");
fgets( str, 50, stdin );
char time_buf[10], date[10];
int a=strlen(time_buf);
int i=0;
time_t endwait;
time_t start = time(NULL);
time_t seconds = 30;
endwait=start+seconds;
printf("Enter date\n>:");
fgets(date, 10, stdin);
time_t now;
time(&now);
strftime(time_buf, 21, "%Y-%m-%d", gmtime(&now));
if (strncmp(time_buf,date,9) == 0) {
printf("TODAY!\n");
while (start < endwait) {
GtkWidget *label;
GtkWidget *window;
gtk_init( &argc, &argv );
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_window_set_title( GTK_WINDOW( window ),"ALARM");
label = gtk_label_new( str );
gtk_container_set_border_width(GTK_CONTAINER(window), 50);
gtk_container_add( GTK_CONTAINER( window ), label );
gtk_widget_show_all( window );
g_signal_connect(G_OBJECT(window),"destroy",
G_CALLBACK( gtk_main_quit ),NULL)
gtk_main(); // mark 1 ###
gtk_widget_destroy (label); // mark 2 ###
//gtk_widget_hide(window);
start = time(NULL);
sleep(10);
}
} else {
printf("NOT TODAY");
return 0;
}
}
GTK has an event loop, started with gtk_main. Actually, it is wrapping a glib event loop, to which you can add timeouts using g_timeout_add_full (or simply g_timeout_add). This is the good way to handle your issue (make some GTK signal handler register a Glib timeout which could e.g. call gtk_widget_hide or gtk_exit ...)
The big problem is that after you invoke gtk_main() at mark 1, your program does not get to run again until gtk_main exits. Prior to gtk_main returning, all widgets from the toplevel down will be destroyed. That's why I assume the error happened at mark 2 where you try to destroy a label that's already been destroyed.
It is still not clear to me why you'd want the behavior. Screen-wide popup notification behaves differently than gtk/glib/X11 programs because it is different. If I am running a program and a top-level window comes to the screen I should know what caused it and be able to get rid of it. It is more intuitive for the user if you scrap the popup, put a label below the entry¹ and change its text to "" when you want it to be invisible. And what #BasileStarynkevitch said.
¹What entry? The one that you should have to enter the string in. it would be an odd program that takes input from the console and displays output in a window.
i am making a program which needs to be run in desktop mode. How can I check in C? And also, is it possible to get screen width and height in C(of the monitor)?
This is a very broad question, but I'll bite. I'm assuming that by "desktop mode" you mean a running X window system. Since you don't seem to have a preferred widget toolkit, I'll show an example which uses Xlib.
You could simply try to open the display and check the return value. If it's up, you can retrieve the screen resolution as well:
#include <stdio.h>
#include <X11/Xlib.h>
int main(int argc, char ** argv)
{
int screen_num;
unsigned int display_width, display_height;
Display *display;
/* First connect to the display server, as specified in the DISPLAY
environment variable. */
display = XOpenDisplay(NULL);
if (!display)
{
fprintf(stderr, "unable to connect to display");
return 1;
}
/* pull useful data out of the display object */
screen_num = DefaultScreen(display);
/* Display size is a member of display structure */
display_width = DisplayWidth(display, screen_num);
display_height = DisplayHeight(display, screen_num);
fprintf(stdout, "resolution is %d x %d\n", display_width, display_height);
return 0;
}
You have to compile with -lX11. All of this and much more can be learned from the Xlib programming tutorial here.
I want to move my GTK_WINDOW across the screen automatically. Currently I have it in a draw/move loop, but that's terribly choppy. I'm very new to GTK programming (and gui programming in general). What am I missing?
You haven't said what sort of path you want the window to follow. If the path is some simple function of time -- that is, if you have a way to compute where you want the window to be at any given time -- you could try the method illustrated in following code. For the quite-simple menu in the example, it works ok on my Linux system and produces fairly smooth motion.
The key to the method is that instead of moving the window a given distance per timer event, it finds out the current time and moves the window to the location it should be at, at that time. Thus, the time derivative of speed of motion should be constant, which avoids ragged or choppy motion even if timer events occur irregularly. (As noted in g-timeout-add() description, irregularity can easily occur.)
In this example, the path is from top left of window to bottom left and back, repeatedly. The constant 'HalfTime' in timerEvent() controls how long it takes to move from corner to corner. The constant 3 in the g_timeout_add() call sets the timer interval to 0.003 seconds, or about 333 moves per second (MPS). (You may want to try more-reasonable rates, such as 20, 30, 40, etc MPS; I used the number 3 because I didn't look up g-timeout-add() before using it, and assumed the delay was hundreths of seconds, for about 33 MPS, rather than milliseconds, for about 333 MPS.) If your window contents are quite complex, fewer MPS will be practical. Also, I tried some slower rates and got more of an impression of choppiness.
/* $Id: app12.c $
Re: animating position of a top-level Gtk window
jiw July 2011 -- Offered without warranty under GPL v3
terms per http://www.gnu.org/licenses/gpl.html */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gtk/gtk.h>
typedef struct DATA { GTimer *timer; GtkWidget *window; int w, h; }
DataStruct;
gboolean timerEvent(void *dataset) {
enum { HalfTime=8, CycTime=2*HalfTime };
gulong micros;
DataStruct *data =dataset;
double t = fabs(fmod (g_timer_elapsed (data->timer, µs), CycTime));
int x = (t*data->w)/HalfTime, y = (t*data->h)/HalfTime;
gtk_window_move (GTK_WINDOW(data->window),
t<HalfTime? x : 2*data->w-x, t<HalfTime? y : 2*data->h-y);
return TRUE; /* Keep timeout running */
}
int main(int argc, char **argv) {
GtkWidget *vbox, *b;
GdkScreen *gds;
DataStruct data;
data.timer = g_timer_new();
gtk_init (&argc, &argv);
data.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW(data.window), 200, 150);
g_signal_connect (G_OBJECT(data.window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER(data.window), vbox);
b = gtk_button_new_with_label ("Click to Exit");
gtk_box_pack_start (GTK_BOX(vbox), b, TRUE, TRUE, TRUE);
g_signal_connect (b, "clicked", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (data.window);
gds = gdk_screen_get_default (); /* Get pointer to screen */
data.w = gdk_screen_get_width (gds); /* Find out screen width */
data.h = gdk_screen_get_height (gds); /* Find out screen height */
printf ("Screen size = %d by %d\n", data.w, data.h); fflush(stdout);
g_timeout_add(3, timerEvent, &data); /* Create .003 sec timer */
gtk_main();
return (0);
}
I need a fast command line app to return the color of the pixel under the mouse cursor.
How can I build this in VC++, I need something similar to this, but ideally not in .NET so it can be run many times per second?
Off the top of my head, the straightforward way:
#include <stdio.h>
#include <Windows.h>
int main(void) {
POINT p;
COLORREF color;
HDC hDC;
BOOL b;
// Get the device context for the screen
hDC = GetDC(NULL);
if (hDC == NULL)
return 3;
// Get the current cursor position
b = GetCursorPos(&p);
if (!b)
return 2;
// Retrieve the color at that position
color = GetPixel(hDC, p.x, p.y);
if (color == CLR_INVALID)
return 1;
// Release the device context again
ReleaseDC(GetDesktopWindow(), hDC);
printf("%i %i %i", GetRValue(color), GetGValue(color), GetBValue(color));
return 0;
}
ETA: Appears to work, at least for me.
ETA2: Added some error checking
ETA3: Commented code, compiled executable and a Visual Studio Solution can be found in my SVN repository.