I would like to create a selection area tool. This tool should allow you to draw a rectangular area on the screen with the mouse.
I use full-screen, translucent, darkened swt Shell as the background against which I draw a white rectangle to represent the selected area.
My problem is that I did not find an effective way to update the rectangle area. So far I have used the redraw method, but the visual effect was pretty ugly, even I thought I was trying to redraw only the desired area:
public ManualScreenAreaSelector(final Display display) { shell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP); shell.setBounds(display.getClientArea()); // shell.setFullScreen(true); shell.setAlpha(180); shell.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); shell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); } @Override public void mouseMove(final MouseEvent e) { if (editionMode) { // retrieve the rectangular area corresponding to mouse selection final Rectangle r = makeRectangleFromSelection(clickCoordinates, new Point(ex, ey)); // make the ugly 'tint' effect shell.redraw(); GC gc = new GC(shell); gc.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_WHITE)); gc.setAlpha(150); gc.fillRectangle(rx, ry, r.width, r.height); gc.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_BLACK)); gc.fillRectangle(0, 0, rx, ry); gc.fillRectangle(0, 1080 - ry, rx, 1080 - ry); gc.dispose(); lastX = ex; lastY = ey; } } @Override public void mouseDown(final MouseEvent e) { // Right click = reset selection if (e.button == 3) { shell.redraw(); selectedArea = null; if (editionMode) { editionMode = false; shell.removeMouseMoveListener(ManualScreenAreaSelector.this); } } else if (e.button == 1) { // left-click enter edition mode // Reset previous selection selectedArea = null; editionMode = true; clickCoordinates = new Point(ex, ey); lastX = ex; lastY = ey; shell.addMouseMoveListener(ManualScreenAreaSelector.this); } } @Override public void mouseUp(final MouseEvent e) { // left click, only if edition was set if ((e.button == 1) && editionMode) { editionMode = false; shell.removeMouseMoveListener(ManualScreenAreaSelector.this); selectedArea = makeRectangleFromSelection(clickCoordinates, new Point(ex, ey)); shell.dispose(); } }
Therefore, I would like to know if there is a more efficient solution in SWT without using the redraw method.

EDIT I used 3 images to make a choice:
- The first is a screen image (screenshot)
- Secondly, the screen image + alpha mixed dark rectangle
- The third is a buffer on which I draw an alpha-mixed image + rectangle copied from a screenshot.
Performance is acceptable as there is only one alpha blending operation (for the second image).
There is only one problem left when I used the graphical control of the shell to draw the shell when I used the alpha mixed image for the first time as a background shell, everything else works when sending mouse events:
public ManualScreenAreaSelector(final Display display) { screenWidth = display.getClientArea().width; screenHeight = display.getClientArea().height; // create a new Image of the screen backGround = new Image(display, display.getBounds()); GC gc = new GC(display); gc.copyArea(backGround, 0, 0); gc.dispose(); // Copy background image and add alpha blended effect aplhaBackGround = new Image(backGround.getDevice(), backGround.getImageData()); GC alphaGC = new GC(aplhaBackGround); alphaGC.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); alphaGC.setAlpha(200); alphaGC.fillRectangle(0, 0, screenWidth, screenHeight); alphaGC.dispose(); // create the shell shell = new Shell(display, SWT.NO_TRIM | SWT.ON_TOP | SWT.NO_BACKGROUND); shell.setBounds(display.getClientArea()); // get shell graphics control shellGraphics = new GC(shell); // set the shell image to screen image <-- does nothing shellGraphics.drawImage(aplhaBackGround, 0, 0); // Image for the shell bufferImage = new Image(shell.getDisplay(), shell.getBounds()); shell.print(shellGraphics); } public void mouseMove(final MouseEvent e) { if (editionMode) { // Get selected area final Rectangle selectedArea = makeRectangleFromSelection(clickCoordinates, new Point( ex, ey)); // Copy alpha blended background into the buffer GC gc1 = new GC(aplhaBackGround); gc1.copyArea(bufferImage, 0, 0); gc1.dispose(); // Paint "normal" background over selected area GC gc2 = new GC(bufferImage); gc2.drawImage(backGround, selectedArea.x, selectedArea.y, selectedArea.width, selectedArea.height, selectedArea.x, selectedArea.y, selectedArea.width, selectedArea.height); // draw the painted image on the shell shellGraphics.drawImage(bufferImage, 0, 0); gc2.dispose(); } }