Java 删除在SWT显示器上使用GC创建的图形

Java 删除在SWT显示器上使用GC创建的图形,java,swt,Java,Swt,我在显示器上创建了一个GC,然后画了一些图。我的问题是如何取消绘图 代码如下所示: final GC gc = new GC(display); gc.setForeground(display.getSystemColor(SWT.COLOR_RED)); gc.setLineWidth(5); gc.drawRectangle(rectangle); gc.dispose(); 背景: 我需要让用户从其他应用程序中选择一个窗口。我期望的行为可以在这里看到:相反,我所有的屏幕都充满了红色矩形

我在显示器上创建了一个GC,然后画了一些图。我的问题是如何取消绘图

代码如下所示:

final GC gc = new GC(display);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setLineWidth(5);
gc.drawRectangle(rectangle);
gc.dispose();
背景: 我需要让用户从其他应用程序中选择一个窗口。我期望的行为可以在这里看到:相反,我所有的屏幕都充满了红色矩形

即使它是仅限Windows的解决方案,对我来说也没问题

编辑:抱歉,即使在我关闭应用程序后,红色垃圾仍然存在

EDIT2:工作示例:

public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);

        shell.addListener(SWT.MouseMove, new Listener() {
            @Override
            public void handleEvent(Event event) {
                final Point displayPoint = display.map(shell, null, event.x, event.y);
                final POINT point = new POINT();
                point.x = displayPoint.x;
                point.y = displayPoint.y;
                final int windowHandle = OS.WindowFromPoint(point);
                if (windowHandle != 0 && windowHandle != shell.handle) {
                    RECT rect = new RECT();
                    if (OS.GetWindowRect(windowHandle, rect)) {
                        Rectangle rectangle = new Rectangle(rect.left, rect.top, rect.right - rect.left,
                                rect.bottom - rect.top);
                        final GC gc = new GC(display);
                        gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
                        gc.setLineWidth(5);
                        gc.drawRectangle(rectangle);
                        gc.dispose();
                    }
                }
            }
        });

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();
    }
要使用它,请从shell(而不是标题栏)启动鼠标拖动,并将其悬停在使用真实windows控件(而不是swing、QT、XUL)的应用程序上。目标应用程序的一个很好的例子是Total Commander。您将看到屏幕上充满了红色矩形。理想情况下,我希望只有一个红色矩形可见


我知道我可以用模拟红色矩形的区域制作一个新的外壳,但是如果鼠标跳过这个区域,我就卡住了。

要做到这一点,你必须绘制一个覆盖整个显示的
外壳。处置
外壳时,将删除绘制的矩形


我不知道如何在光标下找到窗口…

要做到这一点,您必须在覆盖整个显示的
外壳上绘制。处置
外壳时,将删除绘制的矩形


我不知道如何在光标下找到窗口…

我编写了一些代码。这不是完美的解决方案,因为在多次尝试之后,我无法使除“窗口”边框之外的所有内容透明,所以我只是使整个壳(覆盖“窗口”区域)部分透明(尽管效果很好)

这是密码

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.POINT;
import org.eclipse.swt.internal.win32.RECT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class ShellBorder {

    private Display display = new Display();
    private Shell shell = new Shell(display);
    private RECT currRect = null;
    private Shell paintShell = null;

    public ShellBorder() {

        shell.addListener(SWT.MouseUp, new Listener() {

            @Override
            public void handleEvent(Event event) {
                paintShell.dispose();

                // do whatever you need
                // ...

                currRect = null;
            }
        });

        shell.addListener(SWT.MouseMove, new Listener() {
            @Override
            public void handleEvent(Event event) {
                final Point displayPoint = display.map(shell, null, event.x, event.y);
                final POINT point = new POINT();
                point.x = displayPoint.x;
                point.y = displayPoint.y;
                if(currRect == null) {
                    getWindowAndDrawBorder(point);
                } else {
                    // cursor is outside the current rectangle
                    if (point.x < currRect.left || point.x > currRect.right || point.y < currRect.top || point.y > currRect.bottom) {
                        currRect = null;
                        paintShell.dispose();
                        getWindowAndDrawBorder(point);
                    }
                }
            }

            private void getWindowAndDrawBorder(POINT point) {
                long windowHandle = OS.WindowFromPoint(point);
                if (windowHandle != 0 && windowHandle != shell.handle) {
                    RECT rect = new RECT();
                    if (OS.GetWindowRect(windowHandle, rect)) {
                        currRect = rect;

                        paintShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
                        paintShell.setLocation(currRect.left, currRect.top);
                        paintShell.setSize(currRect.right - currRect.left, currRect.bottom - currRect.top);
                        paintShell.setLayout(new FillLayout());
                        paintShell.setAlpha(50);

                        Canvas canvas = new Canvas(paintShell, SWT.NO_BACKGROUND);
                        canvas.addPaintListener(new PaintListener() {
                            public void paintControl(PaintEvent e) {
                                GC gc = e.gc;
                                gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
                                gc.setLineWidth(5);
                                gc.drawRectangle(new Rectangle(0, 0, paintShell.getSize().x, paintShell.getSize().y));
                            }
                        });
                        paintShell.open();
                    }
                }
            }
        });

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();

    }

    public static void main(String[] args) {
        new ShellBorder();
    }
}
import org.eclipse.swt.swt;
导入org.eclipse.swt.events.PaintEvent;
导入org.eclipse.swt.events.PaintListener;
导入org.eclipse.swt.graphics.GC;
导入org.eclipse.swt.graphics.Point;
导入org.eclipse.swt.graphics.Rectangle;
导入org.eclipse.swt.internal.win32.OS;
导入org.eclipse.swt.internal.win32.POINT;
导入org.eclipse.swt.internal.win32.RECT;
导入org.eclipse.swt.layout.FillLayout;
导入org.eclipse.swt.widgets.Canvas;
导入org.eclipse.swt.widgets.Display;
导入org.eclipse.swt.widgets.Event;
导入org.eclipse.swt.widgets.Listener;
导入org.eclipse.swt.widgets.Shell;
公共类边界{
私有显示=新显示();
私有外壳=新外壳(显示);
private RECT currect=null;
私有Shell paintShell=null;
公共边界(){
addListener(SWT.MouseUp,newlistener()){
@凌驾
公共无效handleEvent(事件){
paintShell.dispose();
//你需要什么就做什么
// ...
currect=null;
}
});
shell.addListener(SWT.MouseMove,newlistener()){
@凌驾
公共无效handleEvent(事件){
final Point displayPoint=display.map(shell,null,event.x,event.y);
最终点=新点();
点x=显示点x;
点y=显示点y;
if(currect==null){
getWindowAndDrawBorder(点);
}否则{
//光标位于当前矩形之外
if(点xcurrect.right | |点.ycurrect.bottom){
currect=null;
paintShell.dispose();
getWindowAndDrawBorder(点);
}
}
}
私有void getWindowAndDrawBorder(点){
长windowHandle=OS.WindowFromPoint(点);
if(windowHandle!=0&&windowHandle!=shell.handle){
RECT RECT=新的RECT();
if(OS.GetWindowRect(windowHandle,rect)){
currect=rect;
油漆外壳=新外壳(显示器,SWT.NO|U装饰| SWT.ON|U顶部);
paintShell.setLocation(currect.left,currect.top);
paintShell.setSize(currect.right-currect.left,currect.bottom-currect.top);
setLayout(新的FillLayout());
漆壳。setAlpha(50);
Canvas Canvas=新画布(画壳,SWT.无背景);
addPaintListener(新的PaintListener(){
公共无效油漆控制(油漆事件e){
GC=e.GC;
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.设置线宽(5);
drawRectangle(新矩形(0,0,paintShell.getSize().x,paintShell.getSize().y));
}
});
paintShell.open();
}
}
}
});
shell.pack();
shell.open();
而(!shell.isDisposed()){
如果(!display.readAndDispatch()){
display.sleep();
}
}
display.dispose();
}
公共静态void main(字符串[]args){
新的ShellBorder();
}
}

我做了一些代码。这不是完美的解决方案,因为在多次尝试之后,我无法使除“窗口”边框之外的所有内容透明,所以我只是使整个壳(覆盖“窗口”区域)部分透明(尽管效果很好)

这是密码

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.win32.OS;
import org.eclipse.swt.internal.win32.POINT;
import org.eclipse.swt.internal.win32.RECT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

public class ShellBorder {

    private Display display = new Display();
    private Shell shell = new Shell(display);
    private RECT currRect = null;
    private Shell paintShell = null;

    public ShellBorder() {

        shell.addListener(SWT.MouseUp, new Listener() {

            @Override
            public void handleEvent(Event event) {
                paintShell.dispose();

                // do whatever you need
                // ...

                currRect = null;
            }
        });

        shell.addListener(SWT.MouseMove, new Listener() {
            @Override
            public void handleEvent(Event event) {
                final Point displayPoint = display.map(shell, null, event.x, event.y);
                final POINT point = new POINT();
                point.x = displayPoint.x;
                point.y = displayPoint.y;
                if(currRect == null) {
                    getWindowAndDrawBorder(point);
                } else {
                    // cursor is outside the current rectangle
                    if (point.x < currRect.left || point.x > currRect.right || point.y < currRect.top || point.y > currRect.bottom) {
                        currRect = null;
                        paintShell.dispose();
                        getWindowAndDrawBorder(point);
                    }
                }
            }

            private void getWindowAndDrawBorder(POINT point) {
                long windowHandle = OS.WindowFromPoint(point);
                if (windowHandle != 0 && windowHandle != shell.handle) {
                    RECT rect = new RECT();
                    if (OS.GetWindowRect(windowHandle, rect)) {
                        currRect = rect;

                        paintShell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP);
                        paintShell.setLocation(currRect.left, currRect.top);
                        paintShell.setSize(currRect.right - currRect.left, currRect.bottom - currRect.top);
                        paintShell.setLayout(new FillLayout());
                        paintShell.setAlpha(50);

                        Canvas canvas = new Canvas(paintShell, SWT.NO_BACKGROUND);
                        canvas.addPaintListener(new PaintListener() {
                            public void paintControl(PaintEvent e) {
                                GC gc = e.gc;
                                gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
                                gc.setLineWidth(5);
                                gc.drawRectangle(new Rectangle(0, 0, paintShell.getSize().x, paintShell.getSize().y));
                            }
                        });
                        paintShell.open();
                    }
                }
            }
        });

        shell.pack();
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();

    }

    public static void main(String[] args) {
        new ShellBorder();
    }
}
import org.eclipse.swt.swt;
导入org.eclipse.swt.events.PaintEvent;
导入org.eclipse.swt.events.PaintListener;
导入org.eclipse.swt.graphics.GC;
导入org.eclipse.swt.graphics.Point;
导入org.eclipse.swt.graphics.Rectang