删除在SWT显示器上创建的GC制作的图纸

时间:2011-08-04 15:04:37

标签: java swt

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

代码如下所示:

final GC gc = new GC(display);
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setLineWidth(5);
gc.drawRectangle(rectangle);
gc.dispose();

上下文: 我需要让用户从其他应用程序中选择一个窗口。我期望的行为可以在这里看到:http://tools.tortoisesvn.net/SendMessage.html相反,我的所有屏幕都填充了红色矩形。

即使它是仅限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。你会看到屏幕上充满了红色的矩形。理想情况下,我希望只有一个红色矩形可见。

我知道我可以创建一个带有模拟红色矩形的区域的新外壳,但是如果鼠标跳过它,我就会卡住。

3 个答案:

答案 0 :(得分:1)

我制作了一些代码。这不是完美的解决方案,因为经过多次尝试后我无法使除“窗口”边框之外的所有内容都变得透明,所以我只是将整个外壳(覆盖“窗口”区域)部分透明(并且它很好虽然效果很好。

这是代码

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();
    }
}

答案 1 :(得分:0)

要执行此操作,您必须使用覆盖整个显示的Shell。放置Shell时,将删除绘制的矩形。

我不知道如何找到光标下的窗口......

答案 2 :(得分:0)

在我的第一个回答中,我假设你想在桌面上测试其他应用程序的窗口。由于情况并非如此,您应该查看我对How to draw over child elements of a Composite in SWT?的回答,该回答会在再次删除矩形时自动处理相关部分的重绘...