[VC++2005] Eigene Button Klasse?

Eine PictureBox nur wegen eines Images auf so einem kleinem Control zu verwenden ist eine Resourcenverschwendung. ;)
Du kannst deine Bilder bequem mit Graphics.DrawImage( Bitmap, Rectangle ) auf deinen Button zeichnen.
Und wenn Du deinen Button "disabled" zeichnen möchtest,
kannst dafür System.Windows.Forms.ControlPaint.DrawImageDisabled verwenden.

Das ist auch gar nicht so schwer. Ich hab bereits einen eigenen Button der links, rechts und in der mitte ein Bild hat.
Die Bilder links und rechts lassen sich wahlweise ein und ausblenden (Für eine Art Toolbar zB).
Weiterhin kann er auch Pfeile anzeigen die ich in einen GraphicsPath erstelle
und mit Graphics.DrawPath( Pen, GraphicsPath ) drauf male.
Diese lassen sich zudem mithilfe einer Matrix in jede beliebige Richtiung drehen.

Alles Property-gesteuert.

Mein Button zB besteht unter anderem aus diesen Klassen:
  • ButtonBase - Stellt alle Ereignisse zur Verfügung.
  • ImageButton - Zeichnet den Button.
  • ImageButtonDesigner - Erbt von ControlDesigner und entfernt ein paar Propertys die nicht mehr benötigt werden.
    Beispielsweise die hier:
C#:
public class ImageButtonDesigner : ControlDesigner {
	protected override void PostFilterProperties( IDictionary properties ) {
		properties.Remove( "BackgroundImage" );
		properties.Remove( "BackColor" );
	}
}
  • ImageRectangles - Speichert und berechnet die Rectangles der Bilder.
 
Zuletzt bearbeitet:
Hey Danke Cosmo :D

Aber irgendwie kann ich weder DrawImage noch DrawIcon verwenden ;-(

Wenn ich ein Icon zeichnen möchte, passiert gar nichts und bei einem Image erhalte ich immer folgende Fehlermeldung:
"error C3622: 'System::Drawing::Image': a class declared as 'abstract' cannot be instantiated"

ich verwende es so:
C++:
e->Graphics->DrawImage(System::Drawing::Image("M:\\Kaw\\ZugCtl\\Picgrgerade.bmp"), System::Drawing::Rectangle(this->Location.X, this->Location.Y, this->m_icon->Width, this->m_icon->Height));
 
Moin,
was soll das jetzt werden?
  • Ich würde mir dafür die 2 Objekte erst mal instanzieren. ;)
    Ließ mal was in der Exeption Message steht. [edit]Du solltest eigentlich wissen was das nicht geht.[/edit] :-(
  • Ist es Nonsens diese 2 Objekte bei jedem Repaint neu erstellen zu wollen,
    da das eine echte Resourcenverschwendung ist. Grafische Programmierung ist eine hohe Kunst die es zu Beherrschen gilt.
    Ansonsten hast einen immens hohen Speicherverbrauch wie bei Javaprogrammen. :p
  • Hab ich den Vorschlag gemacht, dass Du Dir dafür Helferklassen baust, die die Werte speichern.
  • Die Bilder solltest in deinen Resoucen unterbringen.
    Bau dir eine Klasse, deren Propertys die zu speichernden Infomationen repräsentieren:
C#:
[System.ComponentModel.DesignerCategory( "Code" )]
public class ResourcesManagerBase : Component{
	protected Bitmap myBitmap;

	[Category( "MyCategory" )]
	public Bitmap MyBitmap {
		get { return myBitmap; }
		set { myBitmap = value; }
	}
}
Danach erstellst eine Klasse die von der ResourcesManagerBase Klasse erbt:
C#:
[System.ComponentModel.DesignerCategory( "Component" )]
class ResourcesManager : ResourcesManagerBase
Und öffnest diese nun im Designer. Jetzt siehst das Property im PropertyGrid der Eigenschaften und fügst das Build hinzu.
Jetzt benötigst Du eine Klasse, die dir das Bild zur Laufzeit aus deinen Resourcen bereit stellt.
Definier einen ResourceManager innerhalb der Klasse und stell Propertys bereit, mit denen Du die Bilder nun direkt ansprechen kannst:
C#:
public class Resources {

	static ResourceManager resourceMan;

	[EditorBrowsable( EditorBrowsableState.Advanced )]
	static ResourceManager ResourceManager {
		get {
			if ( (resourceMan == null) ){
				ResourceManager temp = new ResourceManager(
					typeof (ResourcesManager).FullName,
					typeof (ResourcesManager).Assembly );
				resourceMan = temp;
			}
			return resourceMan;
		}
	}

	public static Bitmap MyBitmap {
		get { return ( (Bitmap) ( ResourceManager.GetObject( "$this.MyBitmap" ) ) ); }
	}
}
Jetzt kannst Du deine Bilder bequem zur Laufzeit aus deinen Resoucen auslesen. ;-)
Ein weiterer Vorteil ist, dass Du jetzt auch noch verschiedene Styles für deinen Controls anbieten kannst,
indem Du die ResourcesManager Klasse in einer anderen Assembly unterbringst
und diese mittels eines Style Managers auswählbar machst... ;)
Und denk daran, jedes mal ein Objekt bei einem immer wiederkehrenden Funktionsaufruf zu erstellen ist Schwachsinn.
Es wird jedes mal eine neuer Speicherplatz im RAM belegt. Wenn Du hingenen aber ein Objekt definierst was die Werte bereit hält,
werden die Informationen immer aus ein und dem selben Speicherbereich gelesen und geschrieben.
Ergo, solltest Dir jetzt auch was wegen dem Rectangle einfallen lassen, in welches dein Bild gezeichnet werden soll...
 
Zuletzt bearbeitet:
Zurück