Back to Skills

implementing-hit-testing

verified

Enables mouse event reception for WPF FrameworkElement using DrawingContext by drawing transparent backgrounds. Use when custom-drawn elements don't receive mouse events.

View on GitHub

Marketplace

dotnet-claude-plugins

christian289/dotnet-with-claudecode

Plugin

wpf-dev-pack

development

Repository

christian289/dotnet-with-claudecode
5stars

wpf-dev-pack/skills/implementing-hit-testing/SKILL.md

Last Verified

January 23, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/christian289/dotnet-with-claudecode/blob/main/wpf-dev-pack/skills/implementing-hit-testing/SKILL.md -a claude-code --skill implementing-hit-testing

Installation paths:

Claude
.claude/skills/implementing-hit-testing/
Powered by add-skill CLI

Instructions

# WPF FrameworkElement Hit Testing

An essential pattern for receiving mouse events when rendering directly with `OnRender(DrawingContext)` in a class that inherits from `FrameworkElement`.

## 1. Problem Scenario

### Symptoms
- Events like `MouseLeftButtonDown`, `MouseMove` don't fire on controls inheriting from `FrameworkElement`
- Nothing happens when clicking

### Cause
WPF Hit Testing is performed based on rendered pixels. If nothing is drawn in `OnRender()` or there's no background, that area is considered "empty" and mouse events won't be delivered.

---

## 2. Solution

### 2.1 Draw Transparent Background (Required)

```csharp
namespace MyApp.Controls;

using System.Windows;
using System.Windows.Media;

public sealed class MyOverlay : FrameworkElement
{
    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);

        // ⚠️ Required: Draw transparent background (for mouse event reception)
        dc.DrawRectangle(
            Brushes.Transparent,
            null,
            new Rect(0, 0, ActualWidth, ActualHeight));

        // Actual rendering logic follows
        DrawContent(dc);
    }

    private void DrawContent(DrawingContext dc)
    {
        // Draw actual content
    }
}
```

---

## 3. Why Transparent?

### Transparent vs null

| Setting | Hit Test Result | Visual Result |
|---------|-----------------|---------------|
| `Brushes.Transparent` | ✅ Success | Not visible |
| `null` | ❌ Failure | Not visible |
| `new SolidColorBrush(Color.FromArgb(0, 0, 0, 0))` | ✅ Success | Not visible |

`Transparent` is an "existing" brush with Alpha channel of 0. WPF Hit Testing checks if a brush **exists**, so it behaves differently from `null`.

---

## 4. Practical Example

### 4.1 Measurement Tool Overlay

```csharp
namespace MyApp.Controls;

using System.Windows;
using System.Windows.Media;

public sealed class RulerOverlay : FrameworkElement
{
    private static readonly Pen LinePen;
    private static readonly Brush TextBr

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
5223 chars