Vlastní Shape s tolerancí kliknutí – metoda HitTestCore


Pro uživatele grafického editoru může být problém vybrat a editovat čáru, která má šířku 1 pixel. Proto by mu mohlo velmi usnadnit práci, kdyby klikání na čáru mělo nějakou toleranci. A právě v tomto článku bych chtěl naznačit, jak je možné vytvořit Shape, na který je možné kliknout s tolerancí.

Jak už z nadpisu vyplývá, celý článek se týká metody HitTestCore. Tuto metodu najdeme ve třídě Visual a jedná se o virtuální a protected metodu. To znamená, že když tvoříme vlastní třídu, která dědí ze třídy Visual, můžeme tuto metodu překrýt vlastním chováním – to je obsahem tohoto článku.

Metoda HitTestCore není tedy nijak svázána se třídou Shape, takže popisovanou techniku je možné využít na jakékoliv třídě, ale jako příklad je Shape ideální.

Vlastní Shape – překrytí HitTestCore

Když vytváříme vlastní Shape, musíme překrýt abstraktní vlastnost DefiningGeometry, tato vlastnost vrací geometrii vykreslovaného objektu a právě tuto geometrii můžeme využít:

protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
    HitTestResult result = base.HitTestCore(hitTestParameters);

    if ((result == null) && (this.DefiningGeometry != null))
    {
        Pen pen = new Pen(Brushes.Black, 1);
        double tolerance = 10;

        var strokeContains = this.DefiningGeometry.StrokeContains(
            pen,
            hitTestParameters.HitPoint,
            tolerance,
            ToleranceType.Absolute);

        if (strokeContains)
        {
            result = new PointHitTestResult(this, hitTestParameters.HitPoint);
        }
    }

    return result;
}

V kódu vidíme, že nejprve se volá base.HitTestCore, tedy nejprve se pokusíme využít defaultní chování (přesné kliknutí na objekt), teprve poté, když defaultní chování nenašlo žádný výsledek, nastupuje použití tolerance. Jak už bylo řešeno výše, využívá se geometrie – konkrétně metoda StrokeContains, která umí pracovat právě i s požadovanou tolerancí.

Tento kód stačí použít ve vlastním třídě (viz následující odstavec!) a například událost MouseDown bude u objektu vyvolána i když uživatel neklikne přesně na něj.

Ale pozor! Tato metoda se volá velmi často, nevyužívá se totiž pouze při klikání na objekt, ale i při pohybu myší – MouseEnter, MouseMove atd. Proto by neměla obsahovat žádné složité výpočty, protože by velmi snadno mohlo dojít ke zpomalení aplikace. Proto by také nemělo neustále docházet k naprosto zbytečném vytváření objektu Pen! Toto opakované vytváření v této metodě je zde pouze kvůli přehlednosti článku!

Zdroje:

, ,

Komentáře jsou uzavřeny.