[GPS] Tue Jun 18, 2002: The following code makes all text in Tk 3D. It only works in Unix, but the concept could be ported to Windows. It passes all ANSI-C tests with gcc 2.95.3. I tested it with OpenBSD 3.0 x86. You can compile it with: cc -ansi -Wall -W -pedantic -pedantic-errors -I/usr/local/include -I/usr/X11R6/include -L/usr/local/lib -L/usr/X11R6/lib -lX11 -lm -ltcl83 -ltk83 3D_Tk_Text.c It comes with an example built in that looks like this: [http://www.xmission.com/~georgeps/images/wiki/3D_Tk_Text.png] (This is a ''HACK''. I wrote this years ago, and some systems may need the _ dropped in the dlsym usage. You may also find that -ansi disturbs the compilation. See the comp.windows.x archives for an example of someone doing something similar based on this code in Linux.) ---- #include #include #include #include #include #include #include GC lightGC; GC darkGC; /*Make these typedefs because ANSI forbids assignment between function pointer and `void *' */ typedef int (*oldXDrawText) (Display *dis, Drawable drawable, GC gc, int x, int y, XTextItem *item, int nItems); typedef int (*oldXDrawText16) (Display *dis, Drawable drawable, GC gc, int x, int y, XTextItem16 *item, int nItems); typedef int (*oldXDrawString) (Display *dis, Drawable drawable, GC gc, int x, int y, _Xconst char *string, int length); typedef int (*oldXDrawString16) (Display *dis, Drawable drawable, GC gc, int x, int y, _Xconst XChar2b *string, int length); oldXDrawText oldXDrawTextPtr; oldXDrawText16 oldXDrawText16Ptr; oldXDrawString oldXDrawStringPtr; oldXDrawString16 oldXDrawString16Ptr; int XDrawText (Display *dis, Drawable drawable, GC gc, int x, int y, XTextItem *item, int nItems) { XCopyGC (dis, gc, GCFont, lightGC); XCopyGC (dis, gc, GCFont, darkGC); (*oldXDrawTextPtr) (dis, drawable, lightGC, x - 1, y - 1, item, nItems); (*oldXDrawTextPtr) (dis, drawable, darkGC, x + 1, y + 1, item, nItems); return (*oldXDrawTextPtr) (dis, drawable, lightGC, x, y, item, nItems); } int XDrawText16 (Display *dis, Drawable drawable, GC gc, int x, int y, XTextItem16 *item, int nItems) { XCopyGC (dis, gc, GCFont, lightGC); XCopyGC (dis, gc, GCFont, darkGC); (*oldXDrawText16Ptr) (dis, drawable, lightGC, x - 1, y - 1, item, nItems); (*oldXDrawText16Ptr) (dis, drawable, darkGC, x + 1, y + 1, item, nItems); return (*oldXDrawText16Ptr) (dis, drawable, gc, x, y, item, nItems); } int XDrawString (Display *dis, Drawable drawable, GC gc, int x, int y, _Xconst char *string, int length) { XCopyGC (dis, gc, GCFont, lightGC); XCopyGC (dis, gc, GCFont, darkGC); (*oldXDrawStringPtr) (dis, drawable, lightGC, x - 1, y - 1, string, length); (*oldXDrawStringPtr) (dis, drawable, darkGC, x + 1, y + 1, string, length); return (*oldXDrawStringPtr) (dis, drawable, gc, x, y, string, length); } int XDrawString16 (Display *dis, Drawable drawable, GC gc, int x, int y, _Xconst XChar2b *string, int length) { XCopyGC (dis, gc, GCFont, lightGC); XCopyGC (dis, gc, GCFont, darkGC); (*oldXDrawString16Ptr) (dis, drawable, lightGC, x - 1, y - 1, string, length); (*oldXDrawString16Ptr) (dis, drawable, darkGC, x + 1, y + 1, string, length); return (*oldXDrawString16Ptr) (dis, drawable, gc, x, y, string, length); } int main (int argc, char *argv[]) { Tcl_Interp *interp; char evalStr[] = { "option add *font -*-lucida-medium-*-*-*-14-*-*-*-*-*-*-*;" "option add *Text.background white;" "option add *Text.foreground black;" "pack [frame .f] -side top -fill x;" "pack [button .f.b -text {Hello World}] -side left;" "pack [entry .f.e] -side left;" "pack [label .f.l -text {Sample Text}] -side left;" "pack [text .t] -side top -fill both;" }; void *libHandle; Tk_Window tkwin; Window xWin; Display *dis; Colormap colormap; XColor xLightColor; char lightColor[] = "gray90"; XColor xDarkColor; char darkColor[] = "gray30"; int nScreen; Tcl_FindExecutable (argv[0]); interp = Tcl_CreateInterp (); if (Tcl_Init (interp) != TCL_OK) { fprintf (stderr, "Tcl_Init error %s", Tcl_GetStringResult (interp)); exit (1); } if (Tk_Init (interp) != TCL_OK) { fprintf (stderr, "Tk_Init error %s", Tcl_GetStringResult (interp)); exit (1); } tkwin = Tk_MainWindow (interp); dis = Tk_Display (tkwin); nScreen = DefaultScreen (dis); colormap = DefaultColormap (dis, nScreen); Tk_MakeWindowExist (tkwin); xWin = Tk_WindowId (tkwin); lightGC = XCreateGC (dis, xWin, 0, 0); darkGC = XCreateGC (dis, xWin, 0, 0); XParseColor (dis, colormap, lightColor, &xLightColor); XAllocColor (dis, colormap, &xLightColor); XSetForeground (dis, lightGC, xLightColor.pixel); XParseColor (dis, colormap, darkColor, &xDarkColor); XAllocColor (dis, colormap, &xDarkColor); XSetForeground (dis, darkGC, xDarkColor.pixel); libHandle = dlopen ("/usr/X11R6/lib/libX11.so.6.2", RTLD_LAZY); fprintf (stderr, "dlopen %s\n", dlerror ()); oldXDrawTextPtr = (oldXDrawText) dlsym (libHandle, "_XDrawText"); fprintf (stderr, "dlsym %s\n", dlerror ()); oldXDrawText16Ptr = (oldXDrawText16) dlsym (libHandle, "_XDrawText16"); fprintf (stderr, "dlsym %s\n", dlerror ()); oldXDrawStringPtr = (oldXDrawString) dlsym (libHandle, "_XDrawString"); fprintf (stderr, "dlsym %s\n", dlerror ()); oldXDrawString16Ptr = (oldXDrawString16) dlsym (libHandle, "_XDrawString16"); fprintf (stderr, "dlsym %s\n", dlerror ()); if (Tcl_Eval (interp, evalStr) != TCL_OK) { fprintf (stderr, "error %s\n", Tcl_GetStringResult (interp)); } Tk_MainLoop (); return 0; } ---- Cool. Except I'd want to shoot anybody who actually deployes 3D text in an application - GUI design 101. [DKF]: It can work, but ''only'' if done subtly. Many of the fancy graphical effects (including virtually all alpha-blending effects as well as 3D text) need to be used with a very large helping of good taste and discretion or they fail to make the GUI more usable. They often work better with large items (windows, "headlines", etc.) than small. ---- [DKF]: You can do a similar thing on a canvas by just drawing the text twice (e.g. [Unavailable appearance]). That also lets you do extra cool effects, like text that jumps out at you when the mouse pointer goes over it...