6

I'm developing an assistive technology application (in C#) that overlays information on top of the currently open window. It detects clickable elements, and labels them.

To do this, I'm currently creating a borderless, transparent window with TopMost set to "true", and drawing the labels on that. This means there is always a window hovering in front of the current application, on which I can draw the labels.

The problem is, this window doesn't cover the right-click menu - only other windows. When the user right-clicks, the context menu is drawn above the overlay.

I need to be able to label elements in the right-click menu, but I can't draw on top of it with the current implementation. Does anybody know of a solution?

Edit: This is the relevant code for drawing the overlay. I've set the form options in the form designer, not in the code explicity, so I'm not sure how much it will help. I've removed the code not related to drawing, or the form itself:

public partial class OverlayForm : Form
{
    public OverlayForm()
    {

    }

    protected override void OnPaint(PaintEventArgs eventArgs)
    {
        base.OnPaint(eventArgs);
        Graphics graphics = eventArgs.Graphics;
        Brush brush = new SolidBrush(this.labelColor);
        foreach (ClickableElement element in this.elements)
        {
            Region currentRegion = element.region;
            graphics.FillRegion(brush, currentRegion);
        }
    }    
}
JCC
  • 492
  • 3
  • 17
  • 1
    Could you show your code for doing the overlay – Jacobr365 May 23 '16 at 15:56
  • @Jacobr365 - Sure thing, added. :) – JCC May 23 '16 at 16:12
  • I don't think that's possible. The context menu is drawn even more "top-most" than your form, as it gains focus and a higher z-order by the OS. – DonBoitnott May 23 '16 at 16:26
  • 1
    The context menu is a window itself, and you'd need another window to overlay it for that. Otherwise you need to continuously push your window back to the top. This is really hackish, but the task seems to force hacky solutions. – Ray May 25 '16 at 10:14
  • Id rather just derive a custom context menu and override the OnPaint there – Aiden Strydom May 25 '16 at 10:17
  • @RayKoopa - yep, the whole program so far has been a bit of a hack job since I'm interfacing between other programs. However, all the other solutions seem to be using various tools as intended. I'm not sure pushing windows above the context menu is intended, so I've no idea if it will remain stable between versions of Windows. Seems like the best solution so far, though. – JCC May 25 '16 at 11:00
  • @AidenStrydom - it needs to overlay and label arbitrary programs, so I'd need to directly modify their right-click menus. Do you have any links that might help with that? It's not something I have experience with. – JCC May 25 '16 at 11:01

2 Answers2

0

I've found a bit of a hack solution.

By periodically bringing the overlay window to the front, I can bring it to the top of the Z-order where it covers the right-click menu. It's not perfect, but it does work. This is the core concept, with multithreading stripped out:

public class OverlayManager
{
    OverlayForm overlay;

    public OverlayManager() 
    {
        this.overlay = new OverlayForm();
        this.overlay.Show();
        this.RepeatedlyBringToFront();
    }

    private void RepeatedlyBringToFront()
    {
        while (true)
        {
            this.overlay.BringToFront();
            Thread.Sleep(50);
        }
    }
}

(This assumes "OverlayForm" is a form with the relevant flags set in the form designer - i.e. "Always on Top," "Transparency Key," "Borderless," "Maximised," etc.)

I've only tested this on Windows 8.1. I don't know if the Z-order behaves this way on other versions.

JCC
  • 492
  • 3
  • 17
0

Add a contextmenu to your form and then assign it in the control's properties under ContextMenuStrip.

ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Item 1");
cm.MenuItems.Add("Item 2");

pictureBox1.ContextMenu = cm;
Ray
  • 7,940
  • 7
  • 58
  • 90
  • I need to be able to draw over any context menu in any application, I'm afraid - not just this program. The tool extends all programs to make them accessible to disabled users. Are you suggesting that I implement this menu in the overlay window, and fill it with replacement strips that are identical to the underlying context menu, with labels added? – JCC May 25 '16 at 10:51