使用xlib绘制边框(框架)

8
能否使用xlib绘制无标题栏,无关闭按钮,并且鼠标按钮不响应的透明窗口?仅仅是具有特定颜色和宽度的边框?类似于这个图片中的橙色矩形:enter image description here
我需要创建上述的此透明窗口。同时,我还想以编程方式实现移动、调整大小、关闭和闪烁(在计时器上更改边框颜色)的可能性。
我已经成功创建了无标题栏的透明窗口并在窗口的每一侧绘制了矩形以制造边框效果:
#define W_WIDTH 640
#define W_HEIGHT 480

#define X_POS 100
#define Y_POS 120
#define BORDER_WIDTH 2

Display *dpy;
Window w;

XRectangle rectangles[4] =
    {
    { X_POS, Y_POS, W_WIDTH, BORDER_WIDTH },
    { X_POS, Y_POS, BORDER_WIDTH, W_HEIGHT },
    { X_POS, W_HEIGHT - BORDER_WIDTH, W_WIDTH, BORDER_WIDTH },
    { W_WIDTH - BORDER_WIDTH, Y_POS, BORDER_WIDTH, W_HEIGHT }
    };

int main(int argc, char *argv[])
{
    GC gc;
    XGCValues gcv;
    int run = 1;

    dpy = XOpenDisplay(NULL);

    XVisualInfo vinfo;
    XMatchVisualInfo(dpy, DefaultScreen(dpy), 32, TrueColor, &vinfo);
    XSetWindowAttributes attr;
    attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vinfo.visual, AllocNone);

    w = XCreateWindow(dpy, DefaultRootWindow(dpy), X_POS, Y_POS,
                      W_WIDTH, W_HEIGHT, BORDER_WIDTH, vinfo.depth,
                      InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr);
    XColor color;
    Colormap colormap;
    char orangeDark[] = "#FF8000";
    colormap = DefaultColormap(dpy, 0);
    XParseColor(dpy, colormap, orangeDark, &color);
    XAllocColor(dpy, colormap, &color);

    gcv.line_width = BORDER_WIDTH;
    gc = XCreateGC(dpy, w, GCLineWidth, &gcv);

    XSelectInput(dpy, w, ExposureMask);
    Atom window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
    long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
    XChangeProperty(dpy, w, window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
    XMapWindow(dpy, w);
    XSync(dpy, False);

    while(run)
    {
        XEvent xe;
        XNextEvent(dpy, &xe);
        switch (xe.type)
        {
            case Expose:
                XSetForeground(dpy, gc, color.pixel);
                XDrawRectangles(dpy, w, gc, rectangles, 4);
                XFillRectangles(dpy, w, gc, rectangles, 4);
                XSync(dpy, False);
                break;
            default:
                break;
        }
    }

    XDestroyWindow(dpy, w);
    XCloseDisplay(dpy);

    return 0;
}

这段代码几乎可以正常工作,但是我的橙色边框是半透明的,在浅色窗口上几乎看不见:

enter image description here

请问我需要如何更改代码才能绘制实心橙色矩形?另一个选择是在橙色窗口内部绘制透明矩形,但我在互联网上没有找到如何做到这一点的任何信息。


2
通常窗口边框由窗口管理器处理。因此,您可能不想要这个边框,而是想要一个无边框窗口,其内部有矩形边缘和透明中心。 - hyde
谢谢。那么应该实现第二个变体。您能否分享如何在我的橙色矩形中制作透明中心的示例? - rudolfninja
我没有这样的示例。 - hyde
有没有一些链接可以阅读,以实现在我的橙色窗口中实现透明的中心? - rudolfninja
1
@rudolfninja https://dev59.com/ZJvga4cB1Zd3GeqP1Wm7如何在Xlib中创建半透明白色窗口 - S.S. Anne
@JL2210,感谢您的回复,但不幸的是这并不是我需要的...或者也许它是,但我不明白它如何解决我的问题。您的意思是,我的窗口不应该完全透明吗? - rudolfninja
1个回答

8

两个主要错误。

  1. 没有将attrgcv初始化为0
  2. 没有使用attr.colormap进行颜色分配

这应该会有帮助:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

#define W_WIDTH 640
#define W_HEIGHT 480

#define X_POS 100
#define Y_POS 120
#define BORDER_WIDTH 2

int main(int argc, char *argv[]) {
    XRectangle rectangles[4] = {
        { X_POS, Y_POS, W_WIDTH, BORDER_WIDTH },
        { X_POS, Y_POS, BORDER_WIDTH, W_HEIGHT },
        { X_POS, W_HEIGHT - BORDER_WIDTH, W_WIDTH, BORDER_WIDTH },
        { W_WIDTH - BORDER_WIDTH, Y_POS, BORDER_WIDTH, W_HEIGHT }
    };
    Display *dpy = XOpenDisplay(NULL);
    XSetWindowAttributes attr = {0};
    XGCValues gcv = {0};
    XVisualInfo vinfo;
    GC gc;

    Window w;

    int run = 1;

    XMatchVisualInfo(dpy, DefaultScreen(dpy), 32, TrueColor, &vinfo);
    attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vinfo.visual, AllocNone);

    XColor color;
    char orangeDark[] = "#FF8000";
    XParseColor(dpy, attr.colormap, orangeDark, &color);
    XAllocColor(dpy, attr.colormap, &color);

    w = XCreateWindow(dpy, DefaultRootWindow(dpy), X_POS, Y_POS,
                      W_WIDTH, W_HEIGHT, BORDER_WIDTH, vinfo.depth,
                      InputOutput, vinfo.visual, CWColormap | CWBorderPixel | CWBackPixel, &attr);

    gcv.line_width = BORDER_WIDTH;
    gc = XCreateGC(dpy, w, GCLineWidth, &gcv);

    XSelectInput(dpy, w, ExposureMask);
    long value = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
    XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
                    XA_ATOM, 32, PropModeReplace, (unsigned char *) &value, 1);
    XMapWindow(dpy, w);
    XSync(dpy, False);

    while(run) {
        XEvent xe;
        XNextEvent(dpy, &xe);
        switch (xe.type) {
            case Expose:
                XSetForeground(dpy, gc, color.pixel);
                XDrawRectangles(dpy, w, gc, rectangles, 4);
                XFillRectangles(dpy, w, gc, rectangles, 4);
                XSync(dpy, False);
                break;

            default:
                break;
        }
    }

    XDestroyWindow(dpy, w);
    XCloseDisplay(dpy);

    return 0;
}

结果:

输入图像描述


谢谢。看起来解决了我的问题。还有一个问题:在Expose事件处理程序中需要XSetBackground吗?没有这个调用一切都正常工作,但可能在某些情况下需要它。 - rudolfninja
@rudolfninja 不好意思,那是我实验的剩余物。代码已修复。 - hidefromkgb
能否像橡皮筋一样用鼠标绘制矩形? - kenn
@kenn 当然可以。不过代码看起来会有很大的不同。 - hidefromkgb
@hidefromkgb,您能否发布一段示例代码吗?我需要将其作为一个问题来询问吗? - kenn
@kenn 首先,请至少尝试自己做一下。 - hidefromkgb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接