ich habe eine anwendung bei der ich ein Zeigermessinstrument darstelle. Der Zeiger ist ein gefülltes Polygon dem ich im XAML einen "DropShadowEffect" mitgegeben habe. Die Bewegung des Zeigers animiere ich über eine DoubleAnimation mit der ich die Rotation des Zeiger-Polygons beeinflusse. Das klappt alles auch gut. Allerdings wandert logischerweise der DropShadow auch immer mit dem Zeiger mit. Da das nicht ganz natürlich ist (Die Lichtquelle ist ja in der realität fix) müsste auch der Winkel des Dropshadow während der animation angepasst werden. Hat jemand eine Idee wie man das bewerkstelligen könnte?
Vielen Dank für die Hilfe!
Ich habe alles wie vorgeschlagen auf einem Canvas absolut gezeichnet und eine ViewBox drumherum gesetzt. Damit ist das Problem gelöst. :-)
ich habe noch ein Problem mit WPF. Ich möchte eine runde Skala mit 100 Teilstrichen zeichnen. Ich dachte mir in einer Schleife den ersten Teilstrich in die Mitte zu zeichnen, dann das ganze umgebende Element (Grid) um den Mittelpunkt um 3,6 Grad zu drehen und den nächsten Teilstrich an die selbe Stelle wie den ersten strich zu zeichnen und das in einer Schleife 100 mal. Leider wandert aber das Koordinatensystem mit wenn ich eine RotateTransform auf das äußere Grid anwende. Der ehemalige Punkt 0,0 ist also nach einer 90 Grad Drehung im Uhrzeigersinn nicht mehr oben Links sondern oben Rechts.
Ich würde aber gerne nach dem Rotieren das Koordinatensystem beibehalten. Gibt es dafür eine Möglichkeit?
Danke schonmal für die Antwort! Ich habe nun ein Grid anstatt einen Canvas genommen und die Hintergrund Ellipse in meinem Style passt sich auch der Größe des umgebenden Elements an wenn ich das CustomControl in einem Testprojekt in z.B. einem Stackpanel einbinde.
Mir ist aber noch nicht ganz klar wie ich weiter Elemente im Style meines Custom Controls zeichnen kann die später auch auf die größe des umgebenden Containers Skaliert werden. Wenn man sich das Thermometer vorstellt soll auch der Zeiger und die Skala usw. proportional zur größe des umgebenden Containers skaliert werden. Zum besseren Verständnis hier mien XAML. Die zweite Ellipse mit dem Namen "PART_Middle" soll auch nicht mit einer festen Height und Width gezeichnet werden sondern erstmal unabhängig. Und da stehe ich auf dem Schlauch:
ich bin gerade ein WPF Custom Control am Entwickeln. Es wird ein analoges Thermometer. Also ein Control, dem man eine Temperatur geben kann und der Zeiger wandert dann an die Position.
Jetzt ist es so, dass ich in meiner Generic.xaml einen Style definiert habe der die Elemente des Controls beinhaltet (Ellipse mit Gradient als Hintergrund, Zeiger als Path usw.).
Da das Control später beliebig in andere Proejkte eingebunden werden soll, stelle ich mir die Frage wie ich die Elemente im Control skalenunabhängig zeichnen kann. Ich würde also gerne das Koordinatensystem des Controls auf 0 bis 1 skalieren und darin alles unabhängig von der späteren tatsächlichen Größe zeichnen. Wenn jemand später dieses Control einbindet, soll in der XAML über Width und Height der User die Größe des Controls Festlegen können.
Sowas ähnliches hatte ich in Android schonmal gemacht. Da gibt es folgende Lösung:
ich habe einen LED Cube gebaut. Wer nicht weiß was das ist kann sich dieses Video hier anschauen: Klick.
Ich würde gerne eine PC-Software schreiben die die Leuchtpunkte so eines 8x8x8 LED Würfels am PC abbildet. In etwa sowas hier: Klick. Mit der Software soll man dann diese Leuchtpunkte anklicken können. Wenn man die geünschten Punkte markiert hat, wird das 8x8x8 Array binär gespeichert (Also ein Frame für die Animation des LED Würfels).
Könnt ihr mir Tips geben welches Framework dafür gut geeignet wäre. Habe reichlich erfahrung mit Windows Forms. Allerdings bin ich im Bereich 3D Programmierung noch Neuling.
Ich habe mir nun folgendes zusammengefrickelt. Es funktioniert damit tatsächlich. Da ich einen EventHandler Invoke konnte ich nicht den Lösungsweg mit dem "MethodInvoker" nehmen wie im FAQ beschrieben. Ist meine Lösung ok oder gibt es da einfacherer/elegantere Arten sowas zu beheben? Ich hab wirklich nur solange rumprobiert bis es funktioniert hat...wie es genau funktioniert habe ich noch nicht begriffen
ich nutze die API eines Displayherstellers um ein USB-LCD Display anzusprechen. Im GUI-Thread (in meiner Form) erzeuge ich ein Objekt der Diplayklasse und registriere einen EventHandler. Der Eventhandler wird aufgerufen wenn die API eine Logmeldung auszugeben hat. Diese Logmeldung schreibe ich dann im EventHandler in eine ListBox auf meiner Form. Das funktioniert auch alles super solange ich die ganze Logik des Displays im GUI-Thread erledige. Da dies aber aus diversen Gründen nicht geht habe ich die ganze Funktionalität in einen separaten Thread ausgelagert.
Das Objekt der Diplayklasse übergebe ich in meiner Form an den Konstruktor einer von BackgroundWorker abgeleiteten Klasse die die ganze Arbeit mit dem Display in einem seperaten Thread erledigt.
Sobald nun der Log-Eventhandler aufgerufen wird (der ja im GUI Thread registriert ist) kommt es zum "ungültigen Threadübergreifenden Vorgang". Das aber nicht immer! Nur in dem Falle wenn im BackgroundWorker ein anderes Event der API ausgelöst wird (ScrollFinished Event - Wenn das Display einen kompletten Text-Scrolldurchgang erledigt hat). Ich erkenne keinen direkten Zusammenhang warum dieses Event etwas direkt mit dem Log zu tun haben sollte (denn alle anderen Logmeldungen die nicht durch das ScrollFinished Event im BackgroundWorker ausgelöst werden kommen ja durch).
Dafür habe ich noch keine geeignete Lösung gefunden. Der Sachverhalt ist nicht ganz einfach, ich hoffe ich konnte es halbwegs verständlich rüberbringen. Hier ein paar Code-Snippets:
GUI Klasse:
private iMonWrapperApi imon; //Das ist die API
private DisplayHandler displayHandler; //Das ist die von BackgroundWorker abgeleitete Klasse die die Logik enthält
this.imon = new iMonWrapperApi();
this.imon.Log += wrapperApi_Log; //Registrierung des Eventhandlers im GUI Thread
this.imon.StateChanged += wrapperApi_StateChanged; //Wenn z.b. ein Diplay vom USB angeschlossen oder abgezogen wird wird dieses Ereignis aufgerufen
this.displayHandler = new DisplayHandler(this.imon); //Übergabe des API Objekts an den BackgroundWorker
this.displayHandler.RunWorkerAsync(); //Starte den Backgroundworker
private void wrapperApi_Log(object sender, iMonLogEventArgs e)
{
listBoxLog.Items.Add(e.message);
}
BackGroundWorker Klasse:
class DisplayHandler : BackgroundWorker
{
public DisplayHandler(iMonWrapperApi imon)
{
.....
this.imon.StateChanged += stateChanged;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
//Hier wird die Arbeit verrichtet
}
private void stateChanged(object sender, iMonStateChangedEventArgs e)
{
//Falls ein LCD Display angeschlossen wurde unterstützt es die Scrollfunktion und der passende EventHandler muss registriert werden. Bei anderen Displaytypen wird dieser Eventhandler wieder getrennt!
if (diplayType == iMonDisplayType.LCD)
this.imon.LCD.ScrollFinished += lcdScrollFinished;
else
this.imon.LCD.ScrollFinished -= lcdScrollFinished;
}
private void lcdScrollFinished(object sender, EventArgs e)
{
Thread.Sleep(1000); //Warte eine Sekunde
this.update(); //Beginne Text von Vorne aufs LCD zu schreiben
}
}
Ich hoffe Ihr habt ein paar Tips für mich.
Viele Grüße Viper
Einwandfrei! Danke.
Hier auch nochmal der genaue code falls es jemanden interessiert:
string value = "&HAFAF"; //Debug only
string temp1 = value.Remove(0, 2); //Remove the leading "&H" from string
short temp2 = Convert.ToInt16(temp1, 16); //Convert the 16-bit hex-value to short
string temp3 = Convert.ToString(temp2, 2); //Convert the short value to binary string
string result = temp3.PadLeft(16, '0'); //Fill with zeros
ich habe ein Gerät das mir über die RS232 Schnittstelle fortlaufend einen String mit einem 16-bit Hex-Wert sendet. Der String hat das Format: "&HFFFF". Also zuerst immer &H mit anschließender Information. Aus diesem String würde ich gerne einen anderen String erzeugen der die Informationen Binär Codiert enthält. Das Resultat aus obigem Beispiel würde also dann: "1111111111111111" sein. Ich habe also aus dem Stirng die ersten zwei Zeichen entfernt um den reinen Wert zu bekommen. Nun hapert es also daran den String "FFFF" in "1111111111111111" umzuwnadlen...
ich habe eine Klasse "ProgramParser". Die Klasse hat eine statische Klassenvariable "ArrayList program". Diese ArrayList wird in einer ebenfalls statischen Methode der Klasse instanziert und gefüllt. In einer anderen statischen Methode wird wieder auf diese Instanz der ArrayList zugegriffen. Meine Frage wäre nun wie man das aus SW-Architekten Sicht eleganter lösen kann. Oder ist das OK so?
Mein anderer Gedanke war die komplette Klasse von "außen" zu instanzieren und im Konstruktor dann die ArrayList zu instanzieren. Diese würde ja dann solange leben wie das Objekt der Klasse lebt. Aber auf die unten programmierte Art müsste ja die ArrayList bis zum Ende des Programms leben oder? Die Daten darin sind jedenfalls wichtig und sie müssen während der Laufzeit des Programms ständig verfügbar sein.
Hier der stark gekürzte Code:
Viele Grüße
Viper
class ProgramParser
{
public static string lastError;
//TODO: Ist das so okay???
static ArrayList program;
public ProgramParser()
{
}
public static bool StartConvertingFromQBasicToDeviceIndependent(string filename)
{
program = new ArrayList();
try
{
...tue viele Dinge...
program.Add(line);
}
}
catch (Exception ex)
{
lastError = ex.Message;
return false;
}
}
public static bool saveProgramToFile(string filename)
{
try
{
...tue vieles...
foreach (string line in program)
{
sw.WriteLine(line);
}
sw.Close();
return true;
}
catch (Exception ex)
{
lastError = ex.Message;
return false;
}
}
}
ja die Dateien werden anscheinend nicht mit dem Setup des Visual Studio 2008 Express mit auf den Zielrechner kopiert. Wie gesagt, in der Debug Session bekomme ich keinen FileNotFoundException. Beid er Debug Session liegen die Files dann auch wirklich im Ordner /bin/Debug/CUDAKernel. Aber wenn ichd as Projekt veröffentliche landen diese nicht im Setup Projekt...
Das bringt auch nichts...die Binärdateien habe ich im VS2008 im Ordner CUDAKErnel organisiert. Wie muss ich diese bereitstellen (als Resource, eingebettete Ressource,...???) damit sie mit dem SETUP-Projekt mitkopiert werden und ich auf diese an definierter Stelle aus dem Code heraus zugreifen kann.
ich lade in meinem C# Projekt Binärdateien die im Unterordner "CUDAKernel" liegen.
Diese Binärdateien habe ich markiert als "Ins Ausgabeverzeichnis immer kopieren".
Wenn ich nun das Projekt aus VS Express 2008 heraus starte funktioniert alles wunderbar, wenn ich es jedoch mit dem Veröffentlichungsassistenten veröffentliche und anschließend installiere dann wirft obengenannter Code eine "FileNotFound" Exception.
Ich habe jetzt schon einiges herumprobiert aber war noch nicht erfolgreich. Ich muss diese Binärdateien auch nach dem Veröffentlichen laden können.
möchte gerne in meiner Windows Form Zeiten durch ein Balkendiagramm darstellen.
Ich führe Berechnungen auf CUDA Grafikkarten und die gleichen Berechnungen auf der CPU durch. Die vergangenen Zeiten messe ich dann und will diese gerne skaliert als Balkendiagramm darstellne.
Ich benötige also 2 Balken:
1. Zeit für CUDA Berechnung
2. Zeit für CPU Berechnung
Ein Beispiel:
Matrizenmultiplipkation 1024x1024 Matrix:
CUDA: 212,46363 ms
CPU: 668,2464 ms
Die x-Dimension soll dann auf eine Sinnvolle Größe skaliert werden. Nach obigem Beispiel wären das dann 700 ms.
Gibt es für solch ein Vorhaben ein Control oder sonstwas fertiges? Die Zeit bis zu meinem Projektabschluss drängt
ich beschäftige mich gerade mit CUDA.NET und habe diverse Matrix-Berechnungen auf die GPUs von NVidia ausgelagert.
Zum Vergleich der eingesparten Zeit möchte ich gerne die Zeiten der Matrizenberechnungen auf der normalen CPU unter .NET messen. Die Berechnungsfunktionen liefern auf der GPU und CPU das gleiche Ergebnis. Allerdings erwarte ich auf der GPU bei großen Matrizen eine deutlich geringere Ausführungszeit.
Eine Stopwatch ist für meine Bedürfnisse nicht hochauflösend genug. Manche Berechnungen dauern deutlich unter 1ms.
in VB.NET gibt es das Shared Schlüsselwort mit dem man Klassen- oder Strukturmember freigeben kann und dann nur an eine Stelle auf den Speicher zugeriffen wird.
Sandcastle ist ja relativ kryptisch zu nutzen um einfach mal schnell eine HTML Doku zu erzeugen. Gibt es wirklich kein "One-Click-Tool" für diese Aufgabe? Falls nein werde ich mich wohl mal in Sandcastle einarbeiten müssen.
habs jetzt so gemacht: also ich hab das Objekt jetzt nur einmalig in meiner Basisklasse erzeugt und fülle dieses Objekt jeweils in den abgeleiteten Klassen und stopfe es in den ReportProgress. Funktioniert wunderbar :)
ich nutze in meinem Projekt einen BackgroundWorker und würde gerne im ReportProgress neben dem Progress in % auch noch einen String und eine boolsche Variable im Userstate mitgeben. Dazu habe ich mir folgende Klasse angelegt:
namespace XYZProjekt
{
class UserStateObject
{
public string message;
public bool success;
}
}
im ProgressChanged Eventhandler des Backgroundworkers mache ich dann prinzipiell folgendes:
jetzt muss ich aber immer bei jedem GUI Zugriff des Backgroundworkers(und das sind sehr viele) eine Instanz von der Klasse UserStateObject erzeugen und diese dann füllen und übergeben.
Geht das nicht irgendwie einfacher? Also ohne jedesmal eine neue Instanz von UserStateObject zu erzeugen?