[C#] Een rubberband / selection rectangle tekenen

Pagina: 1
Acties:

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:18
Ik ben een applicatie aan het maken waarin ik een stuk van een afbeelding wil selecteren. Dit wil ik doen dmv. een rubberband rectangle; je kent het wel: je klikt met de linkermuisknop op die afbeelding en naar mate je je muis beweegt, vergroot of verkleint de rectangle zich, tot wanneer je de muis los laat.

Nu heb ik even rondgekeken en wat uitgeprobeerd, en ik heb ondertussen 2 mogelijke 'technieken' gevonden.

In het eerste geval maak ik gebruik van de ControlPaint.DrawReversibleLine static method om een 'reversible rectangle' te tekenen op m'n image.
Die functie ziet er zo uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void DrawReversibleRectangle ( Point startPoint,  int toX, int toY, Control onControl )
{
    ControlPaint.DrawReversibleLine ( onControl.PointToScreen (startPoint),
                                      onControl.PointToScreen (new Point (toX, startPoint.Y)),
                                      Color.Red ); // horizontale lijn van het startpunt 
    ControlPaint.DrawReversibleLine ( onControl.PointToScreen (startPoint),
                                      onControl.PointToScreen (new Point (startPoint.X, toY)),
                                      Color.Red ); // verticale lijn vanaf startpunt
    ControlPaint.DrawReversibleLine ( onControl.PointToScreen (new Point (toX, startPoint.Y)),
                                      onControl.PointToScreen (new Point (toX, toY)),
                                      Color.Red );
    ControlPaint.DrawReversibleLine ( onControl.PointToScreen (new Point (startPoint.X, toY)),
                                      onControl.PointToScreen (new Point (toX, toY)),
                                      Color.Red );                          
}


Dit is redelijk eenvoudig, je moet er gewoon altijd voor zorgen dat, als je al een rectangle hebt, je die rectangle eerst opnieuw tekent met dezelfde coördinaten, zodanig dat hij uitgewist wordt. Daarna roep je die method opnieuw aan met de nieuwe waardes.

Er is echter één probleem met deze methodiek. Zoals je kunt zien, wil ik dat de rectangle een rode kleur heeft. Echter, dat is niet altijd het geval zoals je hieronder kunt zien:

Afbeeldingslocatie: http://users.pandora.be/fgzone/pics/rubberrect.jpg

Zoals je ziet, heeft de rectangle ook blauwachtige lijnen. :? Nu vermoed ik dat dat te maken heeft met de achtergrondskleur waarop die lijn getekend wordt.
Nu is de vraag natuurlijk hoe ik er hier kan voor zorgen dat die rectangle volledig rood is?

Een andere techniek die ik net ff bekeken heb, gaat de DrawLine method gebruiken van een Graphics object, en als de lijn 'uitgewist' moet worden, dan wordt er blijkbaar een andere Brush (TextureBrush) gebruikt, die als parameter in de constructor de originele image meekrijgt.
Nu, veel informatie over die TextureBrush vind ik niet in de .NET help, maar ik ga er dan maar vanuit dat die brush ervoor zorgt dat de net getekende lijn 'overschreven' wordt. :?

Zijn er hier misschien mensen die ervaring hebben met het maken van een dergelijke 'selection-rectangle'? Zoja, hoe hebben jullie het aangepakt? Welke van de 2 hierboven beschreven (of nog andere) technieken heeft de voorkeur ?

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Deze lijn wordt geXORed met de kleur. Zodoende krijg je ook de oorspronkelijke kleur weer terug als je hem nog eens tekent.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Op de code project site ben ik eens keer een artikel over "marching ants" tegengekomen. Misschien wel interessant voor je.

http://www.codeproject.co...sp?target=marching%7Cants

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

EfBe is right: dit is de klassieke rubberbanding manier als reeds op AmigaOS in gebruik (en prolly MacOS 0.1) voordat Windows het jatte: er wordt simpelweg geXOR'ed zodat je altijd contrast hebt (ook op een rood plaatje in jouw geval) en je altijd goedkoop het ding kunt tekenen en weghalen (Amiga's Blitter kon dit al native hardwarematig, een lijn XOR'en).

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 25-05 20:56
Dat 'altijd contrast' is wat al te enthousiast. Vooral lichtgrijs is vervelend; als je een felrode lijn (R,G,B=255,0,0) XOR't met grijs (R,G,B=127,127,127) krijg je bijna exact dezelfde grijs (R,G,B=128,127,127).

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Soultaker schreef op 04 mei 2004 @ 01:28:
Dat 'altijd contrast' is wat al te enthousiast. Vooral lichtgrijs is vervelend; als je een felrode lijn (R,G,B=255,0,0) XOR't met grijs (R,G,B=127,127,127) krijg je bijna exact dezelfde grijs (R,G,B=128,127,127).
Daarom doe je een normale XOR rubberband ook altijd met een bitwise NOT (de complete XOR), waardoor (255, 0, 0) automagisch (0, 255, 255) wordt (rood -> cyaan), wat best wel contrast geeft ;)

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 25-05 20:56
Dat snap ik niet. :P Leg eens uit...?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Soultaker schreef op 04 mei 2004 @ 14:38:
Dat snap ik niet. :P Leg eens uit...?
Normale XOR doet een full-NOT, dus fel rood (0xFF0000) wordt na inversie 0x00FFFF, oftewel cyaan. De enige kleur die moeilijk doet is middelgrijs (0x808080) die na een NOT op 0x7f7f7f uitkomt waardoor je de band niet tot nauwelijks ziet.

Een alternatieve manier is om 0x808080 als XOR te gebruiken, dan wordt rood 0x7f8080 (middelgrijs) en wordt de eerdergenoemde middelgrijs 0x000000 oftewel zwart. Deze methode garandeert dus contrast, maar minder dan de full complement.

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 25-05 20:56
edit:
Ik zeg domme dingen; even nadenken hoor. :P

[ Voor 88% gewijzigd door Soultaker op 04-05-2004 17:36 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:18
Die 'DrawReversibleLine' werkt dus dmv een XOR operaties, een aangezien de achtergrond verschillende kleuren heeft, krijgt m'n lijn dus ook verschillende kleuren?

Die methode met de texturebrush werkt niet met XOR operaties; de oorspronkelijke image wordt daar opnieuw getekend over de lijn die je net getekend hebt.
Ik heb net ff een testje gedaan, en een lijn getekend op een lege picture-box. Die lijn werd getekend door een Pen met een TextureBrush en zo kon ik m'n afbeelding waarop die texturebrush gebaseerd was ahw 'hertekenen' op m'n picturebox.

Ik heb het nu min of meer werkend dmv die TextureBrush (nouja, min of meer, de basis werkt).

https://fgheysels.github.io/


  • mr_taipan
  • Registratie: Februari 2002
  • Laatst online: 03-12-2024
Ik wil ook over een plaatje heen tekenen. Nu vraag ik mij af of dat ook op een soort van layer kan.

Ik wil geen xor gebruiken omdat de kleur van de lijn dan afhangt van de achtergrond en dat wil ik niet.

  • whoami
  • Registratie: December 2000
  • Laatst online: 15:18
mr_taipan schreef op 06 mei 2004 @ 10:17:
Ik wil ook over een plaatje heen tekenen. Nu vraag ik mij af of dat ook op een soort van layer kan.
Waarom op een layer?
Je kunt tekenen op het Graphics object.
Je kan ws ook wel een panel oid over je plaatje leggen, en dan de Opacity van dat panel zodanig zetten dat het panel volledig doorzicht is.
Je app moet dan wel draaien op een OS dat layers enzo ondersteund.

https://fgheysels.github.io/

Pagina: 1