hi,
danke, aber das projekt kenne ich schon.
der ersteller verwendet buttons für die einzelnen zellen im scheduler.
das finde ich ehrlich gesagt bescheiden und glaube auch nicht, dass das best practice bei der erstellung von custom controls ist.
sollte ich mich irren?
hi!
bisher arbeite ich ausschließlich mit winforms.
offensichtlich bediene ich mich dabei einer aussterbenden technologie.
um am ball zu bleiben, möchte ich nach und nach auf wpf umsteigen.
für eine anwendung habe ich den outlook-kalender in winforms nachgebaut.
im anhang ist ein visueller eindruck von dem control.
die gesamte darstellung findet im prinzip im onpaint-event statt und wird über mouse-events (termine verschieben, auf termin klicken, timeline verschieben, etc) gesteuert.
läuft alles super.
wie geht man hier in wpf heran?
"zeichnet" man auch alles selbst? ich verwende ja hier keine buttons oder labels in dem control. ist ja alles per "hand" (code) gezeichnet, mit DrawRectangle und co. macht man das in wpf auch so?
prinzipiell scheint es ja ein OnRender() event zu geben. glaube aber nicht, dass ich jetzt einfach alles für den OnRender event umschreiben muss und dann alles läuft 😉
für ein paar denkanstöße und literatur-/tutorial-tipps wäre ich sehr dankbar!
grüße
das scheint genau das zu sein, was ich gesucht habe.
vielen dank!
hi!
ich experimentiere jetzt schon seit einigen tagen mit abgerundeten rechtecken herum.
zum erstellen dient folgender code:
Graphics g = e.Graphics;
ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);
g.SmoothingMode = SmoothingMode.AntiAlias;
bigRect = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
using (GraphicsPath outerPath = RoundedRectangle(bigRect, 5))
{
using (SolidBrush outerBrush = new SolidBrush(Color.Black))
{
g.FillPath(outerBrush, outerPath);
}
}
private static GraphicsPath RoundedRectangle(Rectangle rectangle, int radius)
{
GraphicsPath path = new GraphicsPath();
int l = rectangle.Left;
int t = rectangle.Top;
int w = rectangle.Width;
int h = rectangle.Height;
int d = radius << 1;
path.AddArc(l, t, d, d, 180, 90); // topleft
path.AddLine(l + radius, t, l + w - radius, t); // top
path.AddArc(l + w - d, t, d, d, 270, 90); // topright
path.AddLine(l + w, t + radius, l + w, t + h - radius); // right
path.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottomright
path.AddLine(l + w - radius, t + h, l + radius, t + h); // bottom
path.AddArc(l, t + h - d, d, d, 90, 90); // bottomleft
path.AddLine(l, t + h - radius, l, t + radius); // left
path.CloseFigure();
return path;
}
ich habe auch schon einige andere funktionen aus dem netz zur erstellung von abgerundeten rechtecken verwendet. alle haben jedoch ein problem:
wenn ich "g.SmoothingMode = SmoothingMode.AntiAlias;" weglasse - was ich in meinem fall leider tun muss - zeichnet die kantenglättung oder der HighQuality modus im zuge der weichzeichnung einen 1 pixel dünnen rahmen um das rechteck. ich brauche aber leider scharfe kanten.
gibt es also eine möglichkeit, nicht geglättete, abgerundete rechtecke mit identischen ecken zu erstellen?
vielen dank!
hi!
die hintergrundfarbe habe ich bereits auf transparent gesetzt:
public CustomButton()
{
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
this.BackColor = Color.Transparent;
}
es ist richtig, dass die hintergrundfarbe der hintergrundfarbe des parent-steuerelementes entspricht. bei einer textbox mag das noch gehen (so lange kein text drin steht, dann würde sich das rechteck wieder abzeichnen), aber bei einem datagridview mit den gridlines dazwischen, sieht man das rechteck dann wiederum sehr deutlich, da es die gridlines überdeckt.
es muss doch eine möglichkeit geben, dieses hintergrund-rechteck auszublenden oder wirklich transparent zu machen!? 8o
btw: wenn ich "ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);" rausnehme, ist das rechteck dahinter einfach schwarz, aber immer noch existent.
grüße!
hi!
im anhang ist ein 32kb bild, das mein problem sofort verdeutlicht.
das sind zwei custom buttons, die ich im Form_Load() so erstelle:
CustomButton button1 = new CustomButton();
button1.Parent = this;
button1.Location = new System.Drawing.Point(100, 90);
button1.Size = new System.Drawing.Size(150, 150);
button1.BringToFront();
CustomButton button2 = new CustomButton();
button2.Parent = this;
button2.Location = new System.Drawing.Point(400, 90);
button2.Size = new System.Drawing.Size(150, 150);
button2.BringToFront();
ist der button auf Form1 ist alles okay, da diese die gleiche hintergrundfarbe hat. ist der button über einer textbox oder jedem anderen weißen steuerelement, habe ich einen unschönen, rechteckigen rand.
hier die kleine klasse dazu:
class CustomButton : Button
{
public CustomButton()
{
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
this.BackColor = Color.Transparent;
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle|= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//has to be empty!!!
}
protected override void OnPaint(PaintEventArgs e)
{
base.InvokePaintBackground(this, e);
Graphics g = e.Graphics;
ButtonRenderer.DrawParentBackground(g, ClientRectangle, this);
g.SmoothingMode = SmoothingMode.HighQuality;
//Funktion zum Zeichnen des abgerundeten Rechtecks aufrufen
using (GraphicsPath outerPath = RoundedRectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height, 20.00F))
{
using (SolidBrush outerBrush = new SolidBrush(Color.Black))
{
g.FillPath(outerBrush, outerPath);
}
}
}
//abgerundetes Rechteck erstellen
private GraphicsPath RoundedRectangle(float x, float y, float width, float height, float radius)
{
GraphicsPath gp = new GraphicsPath();
gp.AddLine(x + radius, y, x + width - (radius * 2), y); // Line
gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); // Corner
gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); // Line
gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); // Corner
gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); // Line
gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); // Corner
gp.AddLine(x, y + height - (radius * 2), x, y + radius); // Line
gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner
gp.CloseFigure();
return gp;
}
}
wie ihr seht, habe ich schon versucht einige tipps aus anderen threads zu befolgen, leider wird das rechteckt mit der farbe der Form1 nicht ausgeblendet.
habt ihr eine idee?
danke!!
vielen dank für die info!
könnt ihr evtl. noch ein wenig präzisieren, wo genau ich in meinem geposteten code die zeile
SetStyle(ControlStyles.ResizeRedraw, true);
einfügen muss?
im OnCreateControl geht es nicht.
muss ich nich ein protected override void InitializeComponent() {}
einfügen und dort die zeile reinkopieren?
EDIT:
habe mittels
MessageBox.Show(this.GetStyle(ControlStyles.ResizeRedraw).ToString());
mal den zustand abgefragt. dieser steht bereits auf True. wenn ich bei OnCreateControl einsetze:
SetStyle(ControlStyles.ResizeRedraw, false);
, ändert er sich auch auf False. wie dem auch sei: ob True
oder False, der button lässt sich nicht in der größe verändern. habt ihr noch eine idee?
EDIT #2:
gelöst. leider ist der fehler hier nicht mehr ersichtlich, da der mod die ganze klasse gelöscht hat 👍
nochmal danke für die tipps!
hi,
folgendes problem:
da ich custom buttons benötige, bediene ich mich einer klasse, die von der button-klasse erbt, deren OnPaint event überschreibt und dem button mittels gdi ein ansprechendes äußeres gibt.
alle mouse-events (OnEnter, OnLeave,..) werden erkannt und der button jeweils neu gezeichnet.
wenn ich den button nun jedoch zur laufzeit in der größe verändern will, wird er nicht neu gezeichnet, er wird entweder abgeschnitten (height verringert), oder der height-wert wird tatsächlich größer, aber der button an sich nicht.
in der hauptform habe ich im designer folgendes stehen um den button zu erstellen:
this.button1 = new WindowsFormsApplication1.CustomButton();
this.button1.CaptionFont = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.button1.CaptionText = null;
this.button1.EndText = "Ende";
this.button1.FillColor = System.Drawing.Color.FromArgb(((int)(((byte)(210)))), ((int)(((byte)(194)))), ((int)(((byte)(245)))), ((int)(((byte)(157)))));
this.button1.Location = new System.Drawing.Point(57, 23);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(190, 176);
this.button1.StartText = "Start";
this.button1.TabIndex = 0;
this.Controls.Add(this.button1);
...
private CustomButton button1;
dadurch wird er auch direkt erstellt.
auf der form habe ich noch zwei weitere, normale buttons, um den custom button in der größe zu verändern. diese enthalten:
private void button2_Click(object sender, EventArgs e)
{
button1.Size = new System.Drawing.Size(190, button1.Size.Height - 10);
}
private void button3_Click(object sender, EventArgs e)
{
button1.Size = new System.Drawing.Size(190, button1.Size.Height + 10);
}
egtl. hätte ich erwartet, dass der button neu gezeichnet wird. wenn ich ihn im designer in der größer verändere, zeichnet er sich auch nicht sofort neu, sondern erst, wenn das programm gestartet wird.
habt dank!