C#-Code:
public event EventHandler IdChanged;
und
C#-Code:
public EventHandler IdChanged;
**************************************************
Ganz einfach :
Mit public event EventHandler IdChanged
definierst Du ein event mit Namen IdChanged, mit
public Eventhandler IdChanged
definierst Du einen delegate namens IdChanged.
Ein Delegate ist ein Funktionszeiger, stellt also gewissermaßen den Prototypen einer Klasse von Funktionen dar. In Deinem Fall würdest Du eine Instanz eines solchen "Zeigers" anlegen und das ist etwas KOMPLETT anderes als ein event zu definieren !
Ja, soweit ich weiss kann man sich aus den VS.NET XML-Kommentaren mit NDoc eine HTML-Dokumentation im MSDN-Stil erstellen lassen. Das ins Visual Studio eingebaute Tool (Extras -> Kommentarwebseiten erstellen) find ich nicht so besonders toll, ansonsten kann ich noch das Kings Tools - Doxygen Plugin fürs Visual Studio empfehlen, selbst wenn man keine Doxagen-Kommentare verwendet liefert das eine recht gute Doku inklusive Diagrammen (falls man Graphviz benutzt).
Benutzt Du C++ mit managed extensions ?
Falls ja, kannst Du den C++ Code fast genauso behandeln als wäre es C# (abgesehen von syntaktischen Feinheiten), andernfalls solltest Du Dir das Kapitel Marshalling mal durchlesen.
Falls die C++ DLL explizit nicht die CLR verwenden soll, überleg Dir lieber mal ob es nicht auch eine reine Funktionsbibliothek sein kann, ohne Klassenkontext. Das Marshalling von Klassen ist extrem kompliziert und teilweise auch nicht möglich (je nachdem wie die Klasse aufgebaut ist), daher würd ich das nur noch im absoluten Muss-Fall überhaupt probieren.
Hat sich erledigt. die Vertices waren falsch definiert 😠
Hallo zusammen !
Ich hab ein Problem hier bei dem ich irgendwie nicht weiter komme.
Ich hatte mir das D3D-Tutorial von Hauptmann hier im Forum durchgelesen und wollte damit mal etwas rumexperimentieren. Ein einfaches Tetris-Spiel hielt ich als Testprojekt für geeignet.
So weit, so gut, anfangs war ich erstaunt wie einfach das alles ist aber jetzt stehe ich vor einem Rätsel...
Es geht darum einen der Tetris-Blöcke zu zeichnen und zwar diesen hier :
***
*
Ich hab nun das obige Teil in einzelne Blöcke unterteilt (deren 4 Stück) und wollte diese Blöcke nun abhängig von der aktuellen Spielfeld-Koordinate des Teils zeichnen.
Das hab ich so versucht :
private void SetVertices(BlockDetails[,] newCoords)
{
int bufferCount = 0;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
if(newCoords[i,j].Info.Filled)
{
mVerts[bufferCount].X = newCoords[i,j].Coordinate.X * 20;
mVerts[bufferCount].Y = newCoords[i,j].Coordinate.Y * 20;
mVerts[bufferCount].Z = 0.5f;
mVerts[bufferCount].Color = Color.Yellow.ToArgb();
mVerts[bufferCount+1].X = newCoords[i,j].Coordinate.X * 20 + 20;
mVerts[bufferCount+1].Y = newCoords[i,j].Coordinate.Y * 20;
mVerts[bufferCount+1].Z = 0.5f;
mVerts[bufferCount+1].Color = Color.Yellow.ToArgb();
mVerts[bufferCount+2].X = newCoords[i,j].Coordinate.X * 20 + 20;
mVerts[bufferCount+2].Y = newCoords[i,j].Coordinate.Y * 20 + 20;
mVerts[bufferCount+2].Z = 0.5f;
mVerts[bufferCount+2].Color = Color.Yellow.ToArgb();
mVerts[bufferCount+3].X = newCoords[i,j].Coordinate.X * 20;
mVerts[bufferCount+3].Y = newCoords[i,j].Coordinate.Y * 20 + 20;
mVerts[bufferCount+3].Z = 0.5f;
mVerts[bufferCount+3].Color = Color.Yellow.ToArgb();
mVerts[bufferCount+4].X = newCoords[i,j].Coordinate.X * 20 + 20;
mVerts[bufferCount+4].Y = newCoords[i,j].Coordinate.Y * 20 + 20;
mVerts[bufferCount+4].Z = 0.5f;
mVerts[bufferCount+4].Color = Color.Yellow.ToArgb();
mVerts[bufferCount+5].X = newCoords[i,j].Coordinate.X * 20;
mVerts[bufferCount+5].Y = newCoords[i,j].Coordinate.Y * 20;
mVerts[bufferCount+5].Z = 0.5f;
mVerts[bufferCount+5].Color = Color.Yellow.ToArgb();
bufferCount += 6;
}
}
}
}
Das Array, welches die 24 benötigten Vertices enthält hab ich so definiert :
private CustomVertex.TransformedColored[] mVerts;
mVerts = new CustomVertex.TransformedColored[24];
Den VertexBuffer lege ich so an :
private VertexBuffer mVertexBuffer;
mVertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColored), 24, mDevice, Usage.WriteOnly, CustomVertex.TransformedColored.Format, Pool.Default);
Und zuguter letzt das Rendern :
mDevice.BeginScene();
mDevice.VertexFormat = CustomVertex.TransformedColored.Format;
mDevice.SetStreamSource(0,mVertexBuffer,0);
mDevice.DrawPrimitives(PrimitiveType.TriangleList,0,8);
mDevice.EndScene();
mDevice.Present();
Ich habe hier die TriangleList benutzt, da es so einfacher ist in der oben geposteten Schleife die einzelnen Blöcke abhängig von den Koordinaten zu zeichnen. Würde ich TraingleStrip verwenden könnte ich das nicht einheitlich in einer Schleife tun.
Das Problem ist nun, dass jeweils nur "halbe" Blöcke gezeichnet werden.
Weiss da jemand was ich falsch mache ? Liegts evtl. an der TriangleList ? Gibt es vielleicht ein Problem wenn die TriangleList ein Array kriegt in dem Punkte mit denselben Koordinaten drinstehen ?
Danke schonmal im Voraus und sorry, dass es so lang geworden ist.
(Anbei noch ein Screenshot, wie es momentan aussieht)
Ich würd ne eigene Button-Klasse erstellen (von Button abgeleitet) und im Paint-Event dieser neuen Klasse meine Button-Grafik zeichnen lassen.
Schau Dir dazu am Besten mal die Graphics-Klasse an oder such mal bei Codeproject, da gibts bestimmt genug zu dem Thema.
Hallo zusammen !
Ich möchte ein Datagrid Control basteln, in dem ich in einer Spalte ein Bild oder ein kleines Icon anzeigen kann.
Ich hab bereits gelesen dass man dazu eine eigene Implementierung des DatagridColumnStyle bauen muss, aber ich krieg es irgendwie nicht hin.
Hat da zufällig jemand etwas Code zur Hand ?
Danke schonmal !
Kann sein, aber XPath erfordert ja ganz andere Element-Typen und scheint nicht mit den üblichen XDOM - Klassen zu funktionieren.
Aber der Tip von KingPin war hilfreich, ich hab die ReadXml - Methode des Datasets gefunden und nutze die jetzt. Ist zwar auch nicht das Genialste, aber immerhin besser als vorher.
Hallo zusammen !
Ich hab bisher noch nicht sehr viel mit XML-Handling gemacht in C#, brauche es jetzt aber für ein bestimmtes Projekt. Daher wollte ich mir eine XMLReader-Klasse bauen, die es mir ermöglicht, einen bestimmten Knoten zu suchen und falls vorhanden auszulesen und alle Knoten mit derselben Bezeichnung auszulesen.
Ich hab dazu nun folgendes implementiert :
using System;
using System.Xml;
using System.Data;
namespace HMO.XmlHandling
{
/// <summary>
/// Zusammenfassung für Class1.
/// </summary>
public class XMLReader
{
#region Members
private string mPath;
private XmlDocument mDocument;
private XmlElement mRoot;
#endregion
#region Constructors
public XMLReader()
{
mPath = "";
mDocument = new XmlDocument();
}
public XMLReader(string path)
{
mPath = path;
mDocument = new XmlDocument();
mDocument.Load(mPath);
mRoot = mDocument.DocumentElement;
}
#endregion
#region Methods
#region ReadNode
/// <summary>
/// Public method to read the first matching node entry in the xml-file.
/// </summary>
/// <param name="node">the node of which we want to read the contents</param>
/// <returns>If the node was found, it returns it's content, otherwise null</returns>
public string ReadNode(string node)
{
string retVal = "";
// only try to search if the xml-document was properly initialized
if(mRoot != null)
ReadNode(mRoot, node, ref retVal);
// if the node couldn't be found in the xml-file return null, otherwise
// return it's content
if(retVal == "")
return null;
else
return retVal;
}
/// <summary>
/// Private, recursive method to search the node inside the whole xml-file.
/// </summary>
/// <param name="localRoot">the next rootNode to search in</param>
/// <param name="node">the searched node name</param>
/// <param name="retVal">byref return-value</param>
private void ReadNode(XmlNode localRoot, string node, ref string retVal)
{
// is the xml-document initialized properly ?
if(mRoot != null)
{
// compare each node in this hirarchy level to the searched node name
foreach(XmlNode docNode in localRoot.ChildNodes)
{
// this is the node we want to read ?
if(docNode.Name == node)
{
// set return value and abort the recursion -> the node was found
retVal = docNode.InnerText;
break;
}
// This was not the searched node ? Then look if it has child nodes.
if(docNode.ChildNodes.Count != 0)
{
// recursion
foreach(XmlNode docChildNode in docNode.ChildNodes)
{
ReadNode(docChildNode, node, ref retVal);
// If there is a result available, return it and abort recursion.
if(retVal != "")
break;
}
}
}
}
}
#endregion
#region ReadNodes
public DataTable ReadNodes(string nodeName, bool recursive)
{
// create the datatable where we want to store the results in
DataTable retVal = new DataTable(nodeName);
retVal.Columns.Add(new DataColumn("content", typeof(string)));
// was the xml-document initialized properly ?
if(mRoot != null)
{
// either do a deep or a flat search depending on the input parameter
if(recursive)
ReadNodes(mRoot, nodeName, ref retVal, true);
else
ReadNodes(mRoot, nodeName, ref retVal, false);
}
// If no entry was found, return null, otherwise return the resulting
//datatable containing all results.
if(retVal.Rows.Count == 0)
return null;
else
return retVal;
}
private void ReadNodes(XmlNode localRoot, string nodeName, ref DataTable retVal, bool recursion)
{
// is the xml-document initialized properly ?
if(mRoot != null)
{
DataRow row;
// compare each node in this hirarchy level to the searched node name
foreach(XmlNode docNode in localRoot.ChildNodes)
{
// this is the node we want to read ?
if(docNode.Name == nodeName)
{
// add value to the DataTable and continue
row = retVal.NewRow();
row["content"] = docNode.InnerText;
retVal.Rows.Add(row);
}
// should we search in the childnodes as well ?
if(recursion)
{
// Continue with childNodes if there are any.
if(docNode.ChildNodes.Count != 0)
{
// recursion
foreach(XmlNode docChildNode in docNode.ChildNodes)
{
ReadNodes(docChildNode, nodeName, ref retVal, recursion);
}
}
}
}
}
}
#endregion
#region NodeExists
public bool NodeExists(string nodeName)
{
bool retVal = false;
// Search the node in the whole file.
NodeExists(mRoot, nodeName, ref retVal);
return retVal;
}
private void NodeExists(XmlNode localRoot, string nodeName, ref bool retVal)
{
// is the xml-document initialized properly ?
if(mRoot != null)
{
// compare each node in this hirarchy level to the searched node name
foreach(XmlNode docNode in localRoot.ChildNodes)
{
// this is the node we want to read ?
if(docNode.Name == nodeName)
{
// node was found, abort search
retVal = true;
break;
}
// This was not the searched node ? Then continue the search in the
// child nodes.
if(docNode.ChildNodes.Count != 0)
{
// recursion
foreach(XmlNode docChildNode in docNode.ChildNodes)
{
NodeExists(docChildNode, nodeName, ref retVal);
// If the node was found, abort the search.
if(retVal)
break;
}
}
}
}
}
#endregion
#endregion
#region Public Properties
public string Path
{
get { return mPath; }
set { mPath = value; }
}
#endregion
}
}
Jetzt meine Frage dazu : Mir ist nichts anderes eingefallen, als jeweils per foreach rekursiv durch die Knotenstruktur zu wandern. Gibt es da vielleicht sauberere Möglichkeiten ? Ich will nicht dass sich das Programm später tothängt wenn die XML-Datei mal etwas größer ist.
Also was ich suche wäre ein Zugriff wie z.B. bei ner SQL-Tabelle, so dass man einen oder mehrere Knoten gezielt direkt ansprechen kann.
Wäre super wenn jemand was wüsste.
Danke schonmal !
Hallo zusammen,
also bis vor kurzem funktionierte noch alles, aber als ich jetzt seit längerer Zeit mal wieder ein bereits bestehendes Webprojekt im Visual Studio .NET 2003 öffnen wollte, konnte er es plötzlich nimmer laden.
Wenn ich die projektmappe öffne, steht ewig da "Das Web http://localhost/WebApplication1" wird geöffnet. Irgendwann (hab schonmal 15 Minuten gewartet) friert Visual Studio dann ein und wenn ich es über den Taskmanager noch abschiesse steht kurz vor dem Ende noch da, dass ASP.NET auf dem lokalen Webserver nicht installiert sei.
Wenn ich nun aber im Browser localhost aufrufe zeigt er mir korrekt die default-Seite an, auch das betreffende Webprojekt kann ich problemlos über den Browser aufrufen und ausführen.
Hat jemand ne Idee was da los sein könnte ? Ich kann im VS auch keine neuen Projekte mehr anlegen, sonst hätt ichs einfach in ne neue Projektmappe nochmal neu eingebunden ... 🙁
Wäre super, wenn jemand ne Idee hat,
Danke schonmal.
Gitb bei mir trotzdem ne ArgumentException...
Du kannst den Koordinateneditor ruhig über Process starten. Zur Verbindung mit dem Hauptprogramm, bzw. zum Zugriff auf die Hashtable-Klasse in deinem Hauptprogramm würde ich die Hashtable-Klasse von MarshalByRefObject erben lassen und dann den Koordinator per Remoting darauf zugreifen lassen. Würde aber nur funktionieren, solange auch dein Hauptprogramm läuft, da du eine Anwendung brauchst, die die Hashtable-Klasse "hostet".
Infos zu Remoting gibt z.B. bei Codeprojekt zu Hauf. Eine simple Verbindung zum Auslesen der Daten ist keine große Sache, vielleicht 10 Zeilen Code auf Server und auf Client-Seite.
Wenn Du alles richtig gemacht hast, sollte das UserControl bereits unter "Eigene Benutzersteuerelemente" in der Toolbox erscheinen.
Ich hatte vor Kurzem das selbe Problem, habe aber keine Lösung gefunden und hab meiner Tabelle dann einfach ne ID-Spalte hinzugefügt. Würd mich aber auch interessieren wenn das irgendwie geht.
Hallo zusammen !
Ich krieg so langsam die Krise hier ... Ich hab mir vor Kurzem einen ASP.NET Webspace-Provider zugelegt und versuche nun krampfhaft diese SCH.... zum Laufen zu bringen. Sorry, aber ich bin momentan etwas gereizt ...
Also Folgendes :
Ich versuche mittels VS.NET 2003 ein C# ASP.NET Webprojekt zu erstellen. Weder wenn ich dirket die URL meines Webspace angebe noch wenn ich versuche lokal ein Wbprojekt zu erstellen funktioniert es ...
Wenn ich es über die URL versuche kriege ich mittels File Share Zugriff einen Web-Access Fehler angezeigt (UNC-Freigabe ist nicht vorhanden oder Sie haben keine Berechtigung) und mittels Frontpage-Zugriff sagt er einfach "Not Found".
Versuche ich lokal ein ASP.NET Projekt anzulegen sagt er mir, der aktuelle Benutzer sei nicht Mitglied der Gruppe VS-Entwickler.
ICh hab schon so ziemlich alles versucht um dieses behämmerte Benutzerkonto in die Gruppe VS-Entwickler zu kriegen, aber es geht einfach nicht. Es gibt in der Systemsteuerung unter Win XP die Kategorie Benutzerkonten. Da kann ich aber nur festlegen ob das Konto ein Adminbenutzer oder ein Benutzer mit eingeschränkten Rechten sein soll .... Wie kriege ich also meinen Benutzer in die Gruppe "VS-Entwickler" ????
Ich habe den IIS 5.0 installiert, habe aber keinen Plan wie oder was ich da konfigurieren muss, da es quasi Null Doku dazu gibt. In der MSDN steht nur ich soll mein Modem-Kabel überprüfen (????). So langsam rege ich mich echt auf und wenn das so weiter geht (Ich versuche seit einer Woche das zum Laufen zu kriegen) dann werd ich wohl den Provider wieder kündigen und wieder mit PHP rumwerkeln müssen ... 🙁
Es wäre super wenn mir hier jemand helfen könnte, alles richtig einzustellen, bin hier echt am Verzweifeln.
Im Form-Designer auf den Knopf doppelklicken und an der Codestelle wo du rauskommst folgenden Code eingeben :
MessageBox.Show( (3+4).ToString() );
Der GAC hat aber nix mit "Registrierung" im eigentlichen Sinn zu tun. .NET-Assemblys können und müssen auch nicht registriert werden.
Kannst zum einen hier im Forum / bei Google nach Properties suchen oder aber dem Konstruktor des Form2 die Instanz des Form1 als Referenz mitgeben.
Am Einfachsten wäre es, die Variable im Form1 statt auf private auf public zu setzen. Das ist zwar unschön, funzt aber, da dann die Sicherheitsebene so definiert ist, dass eben jeder drauf zugreifen darf.
Also das Selektieren mittels rechter Maustaste solltest Du so hinkriegen :
private void treeView1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
treeView1.SelectedNode = treeView1.GetNodeAt(e.X, e.Y);
}
}
Der Rest sollte ja dann auch kein Problem mehr sein.
Kapier ich net, geht auch während der Runtime, musst nur nach der Änderung evtl. neu zeichnen...
Versuchst du vielleicht ein Workaround für die Combobox-Eigenschaft Readonly zu bauen ? Also wenn Du readonly anstelle von enabled setzt, kann der user den inhalt nicht mehr verändern aber das Control bleibt trotzdem weiss.
Ich würde zum Erstellungszeitpunkt des Dialoges alle Usercontrols in die Controls-Collections packen und alle bis auf den, der standardmäßig angezeigt werden soll auf visible=false stellen. Wenn dann eine andere Optionengruppe angwählt wird, würd ich die Visibility ändern.
myctrl.Width = 100;
myctrl.Height = 200;
Eigentlich logisch oder ?
Wenn Du im Designer die Größe eines Objektes änderst, änderst Du damit nur die Width- und Height-Properties des Objektes. Diese sind in der Eigenschaftenseite des Controls bzw. Forms unter Size zusammengefasst (wenn man es aufklappt sieht man Width und Height). Die Properties im Eigenschaftenfenster sind genauso auch über den Code editierbar.
@norman_timo
Nein, die Assemblyversion hat nix mit Sourcesafe zu tun.
@bootsmann
Schon klar, dass man da irgendwie rankommt, aber wie ist ja grad die Frage 🙂
Also ich würd fast mal drauf tippen, dass notes das auch aus der Kommandozeile heraus kann. Falls dem so ist, bräuchtest Du "nur" eine Konsolenanwendung die zuerst den Benutzer anmeldet und danach die Mail verschickt. Evtl durch den Start einer Batch-Datei...
Ich hab grad mal wieder den alten Thread gefunden und wollte ihn mal hochheben da ich das Problem derzeit wieder habe. Vielleicht weiss ja jemand doch noch was darüber.
Jau, das Problem kenne ich und hab genau aus diesem Grund meine Projekte diesbezüglich mit C++ realisiert.
Mir kommt das ganze Socket und Remoting System des 1.1er Frameworks ziemlich verbuggt vor. So lange alles im lokalen Netz abläuft ist es kein Problem, aber wenn Du das Internet als Medium nutzen willst gibt es nicht nachvollziehbare Probleme, die bei Microsoft nicht bekannt zu sein scheinen und zu denen man auch keine Doku im Netz findet.
Also mein Tip : Benutz was anderes für verteilte Anwendungen übers Internet.
public class MySpecialPaintedTextBox : TextBox
{
public MySpecialPaintedTextBox() : base();
new private void OnPaint(object sender, PaintEventArgs e)
{
//Deine Implementierung
}
//....
}
Statt der Textboxen dann natürlich die neue Klasse benutzen. Im Form-Designer kannste den neuen Textbox-Typ über den Reiter Benutersteuerelemente auf dem Form oder einem anderen Usercontrol setzen.
Vielen Dank @Xggene - damit wird mir etwas klarer wie Du/Ihr das gemeint habt.
Ich werds mal mit dem neuen Ansatz versuchen, nochmals Danke an alle !
Also so auf Anhieb fällt mir ein, dass Du ja immer nur so viele Datensätze aus der Datenbank laden könntest, wie in dem Treeview angezeigt werden können. Erst wenn der Benutzer das Treeview weiteraufklappt, bzw. runterscrollt werden die nächsten Daten nachgeladen und in das Treeview hinzugefügt.
Das hätte den Effekt, dass immer nur vielleicht 20 oder 30 Sätze maximal gelsen werden müssen, was die Wartezeit erheblich verringern dürfte.
Hab den Thread hier grad nochmal gesehen,
wenn er ein leeres Form anzeigt, wo du ein gefülltes Form erwartest, dann liegts wahrscheinlich dran, dass Du entweder die resx - Datei des Form garnicht mitkopiert hast oder aber das Form auf eine falsche resx-Datei zuzugreifen versucht.
Frage : Ist das Form als localizable konfiguriert ? D.h. unterstützt es mehrere Sprachversionen ?
Hm, sorry, ich kann mir nicht vorstellen, wie ich Eigenschaften und Contextmenüs zu Tiles hinzufügen soll die keine eigenen Objekte darstellen. Sicher krieg ich raus wo ich mit der Maus geklickt habe (Koordinaten) aber wie soll ich nun ein Objekt das an Position 5/10 steht durch Klick z.B. aktivieren wenn es sich dabei garnet um ein Objekt handelt ?
Oder wie soll ich z.B. einer Kiste die auf einem bestimmten Feld steht eine Aktion zuweisen, wenn die Kiste kein Objekt ist sondern nur eine Graphik an einer Position innerhalb meines Spielfelds oder wegen mir Picturebox ?
Es geht ja net nur um das Zeichnen von Grafiken irgendwo auf dem Spielfeld, sondern die einzelnen Objekte die sich an einer beliebigen Position im Spielfeld aufhalten können, sollen alle eigene Fähigkeiten, eigene Aktionen etc. haben können. Natürlich sollen auch zwei Objekte, die sich irgendwo auf der Karte treffen miteinander interagieren können (z.B. Objekt Schlumpf nimmt Pilz) wobei in dem Beispiel Schlumpf und Pilz jeweils ein eigenes Objekt wären.
Ich weiss net ob ich es zu unklar ausdrücke oder ausgedrückt habe, aber meiner Meinung nach ist all das oben Beschriebene ohne eigene Objekte für die einzelnen "Dinge" auf dem Spielfeld net realisierbar.
Hallo nochmal,
Leider hat es mit SuspendLayout und ResumeLayout nicht funktioniert. Es dauert noch immer unheimlich lange. Die Wartezeit scheint irgendwie mit dem Hinzufügen der einzelnen Controls in die Form.Controls - Collection zu tun zu haben. Selbst wenn ich die Controls vor dem Hinzufügen auf Visible=false setze, werden sie zwar nicht angezeigt aber die Anwendung hängt trotzdem 🙁
@herbivore
Deine Spielfeldvariante hilft mir leider nicht weiter, da für jedes Tile gewisse Aktionen mittels eines ContextMenü ausgeführt werden können müssen (witziger Satz lol).
Ausserdem sollte es möglich sein, jedem Teil bestimmte Eigenschaften zuzuweisen. Also es geht nicht nur rein um das Zeichnen.
Hat sonst noch jemand eine Idee ? Kann doch nicht sein, dass sowas noch nie gemacht worden ist.
Also ich hab hier auf der Arbeit grad mal in der MSDN nach SuspendLayout und ResumeLayout geschaut und es sieht anhand der Beispiele ziemlich danach aus als wär das genau das was ich brauche 🙂
Ich werds heute Abend mal ausprobieren wenn ich daheim bin, danke auf jeden Fall mal 🙂
Schonmal mit dem globalen ThreadExceptionHandler versucht ?
/// <summary>
/// The application's main entry point
/// </summary>
[STAThread]
static void Main()
{
System.Windows.Forms.Application.ThreadException += new
ThreadExceptionEventHandler(GlobalExceptionHandler);
MyApp app = new MyApp();
// evtl. irgendwas initialisieren
app.Init();
System.Windows.Forms.Application.Run(app);
}
Jo ich würd da auch anstatt Kindfenster für jeden "Frame" jeweils ein Usercontrol anlegen und dann je nach Bedarf im Hauptfenster die Anzeige ändern.
Hi !
Also das Anzeigen erst wenn alle Controls angelegt wurden hab ich schon versucht, indem ich erst alle Controls in ein Controls[] - Array gepackt hab und dann versucht habe das Array mittels AddRange() in die Controls-Collection einzufügen.
Das ging dann zwar auch ohne Wartezeit, aber dafür waren die ganzen Eigenschaften von den einzelnen Controls futsch, z.B. die Location war komplett zufällig 😦
Hallo zusammen !
Also ich habe folgendes Problem.
Im folgenden Testprogramm, welches ich mir gebastelt hab, erstelle ich eine Art Spielfeld, welches eine variable Größe haben kann.
Hier das Programm : Testprogramm
Die einzelnen Felder werden durch Usercontrols dargestellt, da diese später mittels Rechts-/Linksklick bestimmte Aktionen bereitstellen sollen.
Das Problem liegt nun darin, dass es sehr lange dauert z.B. ein Feld der Größe 100 x 100 zu erstellen. Hier bräuchte ich Ideen / Erfahrungen Eurerseits wo ich hier Zeit einsparen könnte.
Hier mal noch die betreffenden Codezeilen :
Die Funktion zum Initialisieren des Feldes (wird durch Druck des Buttons ausgeführt) :
public void InitializeGrid(int lengthX, int lengthY, ITile tileType)
{
this.Controls.Clear();
for(int i=0; i<lengthX; i++)
{
for(int j=0; j<lengthY; j++)
{
// nächstes Tile anlegen
ITile newTile = tileType.Create(tileType.TileWidth, tileType.TileHeight);
// Position des neuen Tiles im Grid festlegen
newTile.TileLocation =
new System.Drawing.Point(i*tileType.TileWidth,j*tileType.TileHeight);
// Neues Tile in den Container einfügen
this.Controls.Add((System.Windows.Forms.Control)newTile);
// Tile anzeigen
newTile.ShowTile();
}
}
}
Und hier die Paint-Methode der Klasse die in diesem Fall das ITile-Interface implementiert :
private void CustomTile_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int breite = this.Width;
int hoehe = this.Height;
System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
gp.AddLine(0, 0, breite - 1, 0);
gp.AddLine(breite - 1, 1, breite - 1, hoehe - 1);
gp.AddLine(breite - 1, hoehe - 1, 1, hoehe - 1);
gp.AddLine(0, hoehe - 1, 0, 1);
gp.CloseFigure();
e.Graphics.FillPath(new SolidBrush(Color.WhiteSmoke), gp );
}
Ziel der Übung soll am Ende eine kleine Entwicklungsumgebung für Brettspielchen wie Mensch ärgere Dich nicht oder Reversi sein (falls jemand Lust hat mitzumachen, bitte melden g).
Also ich danke schonmal vorab für alle Tips !
Mir ist da grad noch ein guter Vergleich eingefallen. Stell Dir vor, an Deinem Auto ist der Motor kaputt. Es macht doch einen Unterschied ob Du nun in die Werkstatt gehst und Dir einen neuen Motor kaufst oder ob Du dir nun sämtliche Einzelteile aus denen ein Motor besteht besorgen und diese zu einem neuen Motor zusammensetzen musst bevor Du ihn benutzen kannst, oder ?
Genauso verhält es sich mit der OOP. Du fängst irgendwann an, baust Dir die Einzelteile zusammen und erhälst somit fertige Bauteile, die Du immer wieder verwenden kannst.
Du musst Dir nicht jedesmal eine neue Schraube herstellen bevor Du weiterarbeiten kannst, sondern Du machst Dir einmal einen Plan einer Schraube und gibst diesen deinen Arbeitern (in diesem Fall dein PC) - der kann dann unendlich viele davon herstellen.
Du baust Dir also aus elementaren Teilchen immer größere, komplexere Teile zusammen, die Du dann auch zu immer größeren Gesamtprojekten verknüpfen kannst.
Natürlich funktioniert das ab einer gewissen Komplexität nicht mehr. So kannst Du z.B. nicht in alle Autos immer denselben, einmal gebauten Porsche-Motor einbauen. Aber : Du hast recht große Einzelteile aus denen jeder Motor aufgebaut ist immer zur Verfügung. Also Du hast Schrauben, Zylinder, Kolben etc. und diese kannst Du dann immer zu neuen Typen von Motoren zusammenbasteln.
Oder vielleicht willst Du ja auch irgendwann mal ein Getriebe statt einem Motor bauen, dann haste immer noch die Schrauben, denn da brauchste immer dieselben.
Die Motoren, Getriebe etc. sind Deine Programme, die Zylinder, Kolben, Schrauben etc. sind Deine Klassen.
Naja in dem konkreten Beispiel Taschenrechner würde Dir das Gruppieren Deiner Rechenfunktionen in einer eigenen Klasse z.B. den Vorteil bringen, dass Du die Klasse wiederverwenden kannst.
Stell Dir mal vor in 2 Jahren willst Du ein umfangreiches Datenverarbeitungs-Tool bauen das unter Anderem auch einen Taschenrechner zur Verfügung stellen soll. Die Klasse aus deinem alten Taschenrechner-Projekt kannst Du 1:1 übernehmen ohne auch nur eine einzige Zeile neuen Code bauen zu müssen. Einfach einbinden und von der UI des neuen Projektes aus die notwendigen Funktionen aufrufen.
Steckst Du die Rechenfunktionen dagegen direkt in das UI kannste nix wiederverwenden, weil der ganze Code mit der einen UI des Taschenrechner-Programms verknotet ist.
Das OOP-Konzept dient in erster Linie zur Wiederverwertbarkeit, oder glaubste bei jeder Windows-Version fängt man wieder bei Null an ? Dann wären wir wohl immer noch bei Windows 3.11 heute 🙂
Andere wichtige Faktoren sind auch Struktur, Lesbarkeit und Pflegbarkeit Deines Codes.
Stell Dir mal vor Du baust ein Programm, wo an 5 Stellen derselbe Code ausgeführt werden muss. Wenn Du jetzt 5 Mal den Code an die jeweilige Stelle schreibst und Du irgendwann feststellst, dass da ein Fehler drin liegt, dann musste diesen Fehler an 5 Stellen korrigieren und aufpassen, dass Du die 6. Stelle an der vielleicht ein Kollege den Code auch nochmal reingebastelt hat, nicht vergisst. Da isses doch besser Du hast eine zentrale Funktion, die dann an x-beliebig vielen Stellen aufgerufen wird. Bemerkst Du einen Fehler, korrigierst Du ihn direkt in der Funktion und schon wirkt sich die Fehlerbehebung auf alle Stellen aus, an der die Funktion aufgerufen wird.
Hast Du schonmal der kompletten Code neu erstellt ? Hast Du zwischenzeitlich Änderungen an den Projekteinstellungen gemacht oder die Ausgabeverzeichnisse geändert ? Gibt es zwei unterschiedliche Versionen deines Programms in zwei unterschiedlichen Ordnern ?
Jo das ist ein ähnliches Prinzip wie bei C++ wo es oft gängige Praxis ist, eine Variable zu Deklarieren, diese dann in irgendeine externe Funktion zu schmeissen, wobei das Speicherhandling dann extern passiert und man sich im eigentlichen "Hauptptogramm" nicht drum kümmern muss.
Wenn mich nicht Alles täuscht entspricht das der C++ Parameterübergabe mittels &
Ach ich hab grad gesehen, dass Du noch eine zweite Frage gestellt hast 🙂
Also die Security-Exception kommt daher, dass bei der Version 1.1 des Frameworks (mit der das VS 2003 arbeitet) einige Änderungen in den Remoting-Klassen und in den Sicherheitseinstellungen vorgenommen wurden.
Um die Sicherheitsexception loszuwerden musst Du die TypeFilterLevel-Eigenschaft des ServerProviders (also üblicherweise BinaryServerFormatterSinkProvider oder SoapServerFormatterSinkProvider) auf TypeFilterLevel.Full setzen.
Auch dazu ein Beispiel :
Viel Spaß noch beim Tüfteln ... 🙂
Hi !
Um die Lebensdauer des RemoteObjects auf unendlich lange zu setzen, musst Du im RemoteObject die von der Klasse MarshalByRefObject bereitgestellte Funktion InitializeLifeTimeService wie folgt überschreiben :
public override object InitializeLifetimeService()
{
return null;
}
Wenn Du stattdessen eine bestimmte, begrenzte Lebensdauer festlegen willst musst Du mit Leases arbeiten.
Hier gibts dazu ein Beispiel :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemmarshalbyrefobjectclassinitializelifetimeservicetopic.asp
Grüße,
Lynix
Hallo zusammen !
Ich hab mal wieder ein Problemchen mit meinen Remoting-Experimenten 🙁
Also mein Client übergibt bei der Aufnahme der Verbindung zum Server eine Instanz einer Klasse an den Server.
Der Server speichert diese Instanz in einer Hashtable ab (jeder Client der sich verbindet übergibt eine eigene Instanz und der Server merkt sich einfach alle).
So weit, so gut.
Problem :
Wenn ich nun vom Server aus versuche irgendwelche Properties aus der Instanz auszulesen oder Methoden der Instanz aufzurufen, funktioniert es nicht 😦
Das sieht das z.B. so aus :
Im RemoteObject auf der Server-Seite :
public bool CheckAllClients(int mCallerID)
{
bool retVal = false;
foreach(DictionaryEntry entry in mClientCollection)
{
// Den caller selbst nicht überprüfen
if(entry.Key != mCallerID)
{
if( ((ClientData)(entry.Value)).DataReceivedFlag)
retVal = true;
}
}
return retVal;
}
Hier bleibt er einfach in der Zeile mit der if-Anweisung hängen und macht ca. 2 Minuten lang nix mehr. Danach kommt mal eine NullReferenceException obwohl er mir im Überwachungsfenster anzeigt, dass entry.Value belegt ist, er mir aber sagt dass die property DataReceivedFlag nicht ermittelt werden kann (wobei ich durch Debuggen im Client sehe, dass sie belegt ist) - oder aber es kommt nach einer gewissen Zeit eine RemotingException.
Die Klasse ClientData hab ich genau wie das RemoteObject von MarshalByRefObject erben lassen, Firewalls sind alle abgeschaltet, und der Router ist abgestöpselt.
Weiss jemand woran das liegen könnte ?
Zur weiteren Info : Ich benutze das Framework Version 1.1, Windows XP (ja Windows Firewall is auch abgeschaltet) und nutze den HttpChannel in Verbindung mit einem Binary(Server/Client)Formatter.
Ich will die Anwendung später über das Internet benutzen können, also sprich Server und Client sollen auf durch das Internet getrennten Rechnern laufen.
Das witzigste an der Sache ist, dass alles ohne Probleme funktioniert, wenn ich das Ganze im lokalen Netzwerk teste, aber sobald ich den Test übers Internet mache ergeben sich o.g. Probleme.
Wäre super wenn jemand mit Erfahrungen bzgl. .NET Remoting übers Internet mir hier weiterhelfen könnte.
Danke und nochmal nachträglich ein frohes Neues 🙂
Hmpf, ich hab noch immer keine Lösung gefunden ... Das Beispiel hilft mir auch nicht wirklich da es nicht viel mit dem zu tun hat was ich machen will ...
Kann es vielleicht sein, dass ich den Client- oder Serverchannel anders anlegen muss ? Vielleicht weitere Properties setzen, damit ein Event-Callback ermöglicht wird ?
*verzweifel*
Versuch mal die Order-Instanz in der Server-Applikation schon anzulegen und dann mittels Activator.GetObject auf die Clientseite zu holen. Dann kannste den Transparent Proxy auch zu einem Order casten und ganz normal damit arbeiten.
Wo rufst Du ShowPosition auf ?
Wenn Du den Aufruf machst bevor bo2 im Load-Event initialisiert wird, ist es klar, dass es kracht.
Also am Besten machst Du die Initialisierung gleich im Konstruktor.
Alternativ kannst Du auch abfangen ob die Binding = null ist.
int iCnt;
int iPos;
if( (bo2 != null) && (bo2.BindingManagerBase != null) )
{
iCnt = bo2.BindingManagerBase.Count; ***
iPos = bo2.BindingManagerBase.Position +1;
}
...
Du darfst die Datenbank nicht gleichzeitig im Entwurfsmodus geöffnet haben, ansonsten kann Dein Programm nicht drauf zugreifen. Ansonsten solltest Du sicherstellen, dass die DB an der richtigen Stelle liegt und kein anderer Prozess darauf zugreift.
An Deinem Code kann ich keinen Fehler entdecken.
OleDB ist der Standard-Provider für Access-Datenbanken - allein schon deshalb würd ich von ODBC abraten.
Ich werd DIr sicherheitshalber mal noch ein paar Funktionen zumailen, die ich mir zum Zugriff auf Access-DBs geschrieben habe, vielleicht klappts ja damit.