Laden...

Forenbeiträge von rastalt Ingesamt 234 Beiträge

06.05.2009 - 14:25 Uhr

@rastalt: Dein pattern berücksichtigt das Zeichen "°" noch nicht (macht aber nix) und hat noch den Schönheitsfehler, dass ausser ".gif" auch noch "xgif" möglich ist, da dein Punkt noch nicht escaped ist.

Ersteres war beabsichtigt, da ich, wie eingangs erwähnt, davon ausgegangen bin, dass < und > nur als Begrenzung für die gewollten Stellen benutz wird. Zweiteres war keine Absicht, vielen Dank für den Hinweis. 🙂
Insgesamt erscheint mir dein Pattern dann doch besser geeignet.

06.05.2009 - 14:21 Uhr

hierfür musst du dann aber threading und events verwenden.

Das könnte dann in etwa so aussehen:


public class FileOpener
{
	public event EventHandler FileClosed;

	private Thread openingThread;
	private string file;

	public FileOpener(string file) {
		this.file = file;
	}

	public void Open() {
		this.openingThread = new Thread(new ThreadStart(OpenInThread));
		this.openingThread.Start();
	}

	private void OpenInThread() {
		Process p = new Process();
		p.StartInfo.FileName = this.file;
		p.Start();
		p.WaitForExit();

		if(FileClosed != null)
			FileClosed(this, new EventArgs());
	}
}

In diesem Zusammenhang musst du dann noch [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke) beachten.

@herbivore: Da hast du natürlich recht. Das hatte ich vergessen zu erwähnen.

06.05.2009 - 14:01 Uhr

und das was ich suche fängt immer mit °> an und hört mit .gif<° auf

aber es gibt noch andere sachen die mit °> anfangen und mit <° aufhören


>([^>]+.gif)<

Was das Erlernen von Regulären Ausdrücken angeht, kann ich mich herbivore nur anschließen. Hier im Forum gibt es auch einen Artikel darüber, den ich dir sehr empfehlen kann. In Kombination mit von mir genannten Tool solltest du dann in der Lage sein Ausdrücke selbst zu erstellen.

06.05.2009 - 12:51 Uhr

Mit Process.Start("datei.txt") kannst du die Datei im eingestellten Standardeditor öffnen.

Wenn du nach dem Schließen noch was mit der Datei machen willst musst du dir eine Instanz von Process erstellen und dann WaitForExit() aufrufen.

06.05.2009 - 12:46 Uhr

So, mal eben Regex-Lab angeschmissen. 😉

Wenn < und > wirklich nur als Begrenzung für die Dateinamen eingesetzt werden sollte es folgender Ausdruck tun:


>([^<]+)

/Edit: Ich schreibe zu schnell.
/Edit2: Viel zu schnell ...

06.05.2009 - 11:04 Uhr

Es gibt sogenannte UserProperties. Das hatten wir schonmal in Outlook Item ID.

06.05.2009 - 09:35 Uhr

Im Blog von Peter Bucher findest du es noch etwas genauer.

04.05.2009 - 09:35 Uhr

Er liest und liest und liest, bis die 30 stellen des INT Arrays belegt sind.
Das will ich jedoch nicht, die 30 soll flexibel erkannt werden - also sobald eine 0 als Zahl kommt, ist die Freundesliste fertig ausgelesen.
Mein Problem ist nun, dass hier bei 5 Freunden - 5 Zahlen und 25x 0 steht.

Das ist eine Eigenheit des Arrays. Leere Felder werden zunächst mit einem Standardwert "befüllt". Bei int ist das halt 0, bei object etc. wäre es null. Was du suchst ist die generische Liste List<int>, wie hier auch schon erwähnt wurde.

/Edit:

Wie kann ich denn bei der List erkennen wann die erste 0 kommt und ab da nicht mehr weiter lassen?

Gar nicht. Es liegt ja nicht an deinem SQL-Result, dass dort 0 steht, sondern am Array an sich.

30.04.2009 - 16:23 Uhr

In dem Fall von vbprogger würd ich es sogar noch anders handhaben als jaensen:


TextBox tb = ctrl as TextBox;
if(tb != null) {
    // ...
}

-> [Tipp] Casten aber richtig: Begriffe wie Cast / is / as

30.04.2009 - 14:52 Uhr

Hm, dann würde das Caret ja nur kurz ans Ende "springen". Mir geht es aber darum, dass es dort verweilt. Das mit dem Zwischenspeichern habe ich ja bereits gemacht (this.selectionStart und this.selectionLength).

Oder meinst du das als Ersatz für SelectAll()? Ich denke das nimmt sich nicht viel. Mir geht es eher darum zu vermeiden, dass die Auswahl verändert werden muss.

30.04.2009 - 11:13 Uhr

Ich hab dafür jetzt einen Workaround gefunden:


int index = GetInsertPosition(mousePosition);
IntPtr charPos = new IntPtr(index);
int res = SendMessage(this.Handle, EM_POSFROMCHAR, charPos, IntPtr.Zero).ToInt32();

Point position = new Point(res);

if(res == -1) { // Workaround
	SelectAll();
	GetCaretPos(out position);
	Select(this.selectionStart, this.selectionLength);
}

SetCaretPos(position.X, position.Y);

Wirklich schön ist das aber nicht. Also wenn jemand eine bessere Lösung hat, immer her damit. 🙂

30.04.2009 - 10:26 Uhr

Hallo zusammen,

ich sitze immer noch an meiner Drag&Drop-TextBox und habe schon wieder ein Problem, das mich jetzt ne ganze Weile beschäftigt.

Das Drag&Drop an sich ist kein Problem. Nur möchte ich gerne, dass das Caret (also der blinkende Cursor) sich immer dort befindet, wo der Text beim "loslassen" eingefügt würde.

Ich löse das momentan mittels SetCaretPos und SendMessage aus der user32.dll.

In der TextBox:


int insertPosition = GetInsertPosition(mousePosition)

IntPtr mousePos = new IntPtr(insertPosition);
IntPtr result = SendMessage(this.Handle, EM_POSFROMCHAR, mousePos, IntPtr.Zero);

Point caretPosition = new Point(restult.ToInt32());

SetCaretPos(caretPosition.X, caretPosition.Y);

Das Problem ist nun, dass EM_POSFROMCHAR zwar wunderbar funktioniert, aber nicht, wenn sich der Mauszeiger hinter das letzte Zeichen befindet. Dann ist result leider -1.

Normalerweise würde ich ja einfach SelectioStart nehmen, aber dann wäre meine Auswahl ja aufgehoben, was bei Drag&Drop irritierend ist.

Google war mir dabei auch nicht behilflich und im IRC konnte mir auch niemand helfen, ihr seid jetzt meine letze Hoffnung. 😉

29.04.2009 - 12:27 Uhr

Hatte es so verstanden, dass du die Software nur aus der Softwareliste entfernen willst, dieser Begriff häufiger in deinem Beitrag aufgetaucht ist.

Was passiert, wenn du auf den "Entfernen"-Button klickst ist abhängig von der Software. Grundsätzlich wird aber das ausgeführt was in "UninstallString" unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall{Schlüssel des Programms}\ steht. Wenn dort allerdings auch nur die kaputte uninst.exe aufgerufen wird, sieht es eher schlecht für dich aus. Im nachhinein lässt sich ja nicht mehr nachvollziehen, wo sich das Programm überall verewigt hat (Registry, System-Order etc.).

Mein Vorschlag wäre dann, eine saubere VM aufzusetzen und das Setup des Programms mit FileMon und RegMon zu beobachten. Dann kannst du eine Deinstallationsroutine nachbauen. Das wird aber wahrscheinlich mit einigem Aufwand verbunden sein.

/Edit: Wobei das vermutlich noch uneleganter wäre. 😉 Was stört dich denn an deiner aktuellen Lösung?

29.04.2009 - 11:59 Uhr

Googel mal nach deinem Titel. Der erste Treffer scheint vielversprechend zu sein.

29.04.2009 - 09:05 Uhr

Ich bin mir jetzt nicht so sicher ob du von TextBox ableitest, oder selbst ein Control entworfen hast. Falls ersteres zutrifft:

Das OnPaint einer TextBox zu überschreiben ist nicht so trivial. Das zeichnen der TextBox passiert wohl gaaanz tief im Kern von Windows und OnPaint wird leider nicht aufgerufen.

Mittels

SetStyle(ControlStyles.UserPaint, true);

kann der Aufruf von OnPaint erzwungen werden, jedoch muss man dann alles selbst zeichnen.

Dein Ansatz, Matscher, mit dem Überschreiben von WndProc, ist schon der richtige.

28.04.2009 - 15:46 Uhr

Also ich verstehe dich so, dass du dich auf einer Internetseite einloggen möchtest. In dem Link von Nitro2k7 geht es wohl eher darum, wie man ein Login auf einer Internetseite erstellt. Hab mir das jetzt nicht durchgelesen aber da es geht ja offensichtlich um ASP.NET.

Was du brauchst sind die (Http-)WebRequest- und die CookieContainer-Klasse. Am besten einfach mal die Forensuche benutzen oder danach googeln.

28.04.2009 - 14:14 Uhr

@LaTino: Gibt es ein Wort für Nicht-Sitzen oder für Nicht-Autofahren? 😉

28.04.2009 - 14:05 Uhr

GetWindowThreadProcessId gibt die Thread-ID zurück. Process.ID hingegen die Process-ID. Steht auch alles in der Doku.

28.04.2009 - 09:22 Uhr

Der Teil deines Codes wo der Fehler auftritt muss in das Try, die Ausnahmebehandlung in das Catch.

Also z.B. so:


// ...

try {
    PingReplay replyr1 = pingSender.Send(name_r1, timeout, buffer, options);
    if(replayr1.Status == IPStaus.Success)
    {
        LED.ColorOff = Color.Lime;

    }else{
        LED.ColorOff = Color.Red;
    }
}
catch(PingException e) {
    // hier kannst du noch auf den Fehler reagieren
}

Beachte bitte auch [Hinweis] Wie poste ich richtig? Punkt 1.1.1, ansonsten folge doch einfach mal meinem Link. 😉

28.04.2009 - 09:13 Uhr

try {
    throw new Exception();
}
catch(Exception)
{
    // hier die Fehlerbehandlung
}

Guckst du hier 😜

28.04.2009 - 09:09 Uhr

Tue das ganze einfach in einen Try-Catch-Block.

27.04.2009 - 16:18 Uhr

Mittels der Eigenschaft InitialDirectory. Den Pfad zu den Eigenen Dateien findest du über Environment.GetFolderPath() und den entsprechenden Environment.SpecialFolder.

27.04.2009 - 15:53 Uhr

Strg + U, wie Uppercase wandelt in Kleinschreibung? 🙂

Ja, tut es. Aber hätte ich's nicht ausprobiert, würde ich's auch nicht glauben. 😉

27.04.2009 - 14:59 Uhr

Du musst einfach prüfen ob es sich bei dem Control auch wirklich um einen RadioButton handelt. Ansonsten kommt es zu der genannten Fehlermeldung.


foreach(Control c in _panPanel1.Controls)
{
    RadioButton rb = c as RadioButton;
    if(rb != null) {
        rb.Checked = true;
    }
}

/Edit: Siehe auch: [Tipp] Casten aber richtig: Begriffe wie Cast / is / as

24.04.2009 - 15:29 Uhr

Hier meine (etwas komplexere) Lösung:

/Edit: Danke herbivore, hast mich doch auf den richtigen Weg gebracht.


using System;
using System.Drawing;
using System.Windows.Forms;

class MyTextBox : TextBox
{
	int selectionStart = -1;
	int selectionLength = -1;

	/// <summary>
	/// Tritt ein, wenn die Maustaste losgelassen wird.
	/// </summary>
	protected override void OnMouseUp(MouseEventArgs mevent) {
		base.OnMouseUp(mevent);

		RefreshSelection();
	}

	/// <summary>
	/// Wird aufgerufen, wenn der Mauszeiger über eine Zelle bewegt wird.
	/// </summary>
	protected override void OnMouseEnter(EventArgs e) {
		base.OnMouseEnter(e);

		RefreshSelection();
	}

	/// <summary>
	/// Wird ausgelöst, wenn sich der Mauszeiger über der Form befindet und eine Maustaste gedrückt wird.
	/// </summary>
	protected override void OnMouseDown(MouseEventArgs e) {
		base.OnMouseDown(e);

		if(this.selectionStart != -1 && this.selectionLength != -1) {

			if(this.IsMouseOnSelection(e.Location)) {

				this.Select(this.selectionStart, this.selectionLength);
			}
			else {
				this.RefreshSelection();
			}
		}
	}

	/// <summary>
	/// Bestimmt ob sich die Maus über dem ausgewählten Text befindet
	/// </summary>
	/// <param name="mousePosition">Position der Maus</param>
	/// <returns>True falls die Maus sich über dem ausgewählten Text befindet, sonst false</returns>
	private bool IsMouseOnSelection(Point mousePosition) {

		bool onSelection = false;

		if(this.Text != string.Empty && this.selectionStart != -1 && this.selectionLength != -1) {
			try {
				RectangleF rect = MeasureTextCharacterInRange(this.selectionStart, this.selectionLength);
				PointF mousePositionF = new PointF(mousePosition.X, mousePosition.Y);

				onSelection = rect.Contains(mousePositionF);
			}
			catch(Exception) {
				onSelection = false;
			}
		}

		return onSelection;
	}

	/// <summary>
	/// Misst die Zeichen in der Textbox in einem angegebenen Bereich
	/// </summary>
	/// <param name="start">Index des ersten zu messenden Zeichens</param>
	/// <param name="length">Anzahl der zu messenden Zeichen</param>
	/// <returns>RectangleF welches den Text umschließt</returns>
	private RectangleF MeasureTextCharacterInRange(int start, int count) {
		RectangleF rect = RectangleF.Empty;

		if(this.Text != string.Empty) {
			using(Graphics g = CreateGraphics()) {
				StringFormat format = new StringFormat();
				format.SetMeasurableCharacterRanges(new[] { new CharacterRange(start, count) });

				Region[] regs = g.MeasureCharacterRanges(this.Text, this.Font, new RectangleF(0, 0, this.Width, this.Height), format);

				rect = regs[0].GetBounds(g);
			}
		}

		return rect;
	}

	/// <summary>
	/// Überprüft ob sich die Auswahl beändert hat und merkt sich ggf. die neue Auswahl
	/// </summary>
	private void RefreshSelection() {
		if(this.SelectedText != string.Empty) {
			this.selectionStart = this.SelectionStart;
			this.selectionLength = this.SelectionLength;
		}
		else {
			this.selectionLength = -1;
			this.selectionStart = -1;
		}
	}
}

24.04.2009 - 14:25 Uhr

warum so kompliziert?

Da hast du natürlich Recht. Gelegentlich neige ich dazu, die einfachste Lösung zu übersehen. 😁

24.04.2009 - 10:16 Uhr

Das Verfahren aus Adressen Koordinaten zu gewinnen nennt sich "Geokodieren". Google hat dafür einen Webservice im Rahmen seiner Google Maps-API, allerdings gibt es da ein Limit von 15.000 Anfragen innerhalb eines Tages (oder so).
Weitere Infos gibts hier: Google Maps-API: Geokodierung

/Edit: Ach Mensch, "brauche ich nicht" hab ich wohl überlesen. 😭

24.04.2009 - 10:01 Uhr

Falls du trotz der, von kleines_eichhoernchen angesprochenen, Punkte den Dateinamen aus dem Datum zusammenbauen willst kannst du mittels Path.GetInvalidFileNameChars() entsprechende Zeichen entfernen.


string RemoveInvalidFileNameChars(string fileName) {
	foreach(char c in Path.GetInvalidFileNameChars()) {
		fileName = fileName.Replace(c.ToString(), string.Empty);
	}
	return fileName;
}

23.04.2009 - 15:25 Uhr

Ja, das habe ich mir auch überlegt, aber ich bin leider an das Standard TextBox-Control gebunden. Verfolge gerade einen anderen Ansatz und werde meine Lösung dann hier posten.

23.04.2009 - 15:20 Uhr

@Corpsegrinder: Rein vom Gefühl her würde ich sagen, dass das nicht funktioniert. Du vergleichst ja alle Items nur mit dem ersten und nicht jedes mit jedem.

/Edit: Oh, das ist natürlich totaler Schwachsinn von mir. Erst denken, dann schreiben ...

Hier trotzdem mein generischer Ansatz (wobei deiner dann warscheinlich performanter ist):


static bool AlleItemsGleich<T>(T[] list) where T : IComparable {
	for(int i = 0; i <= list.Length - 1; i++) {
		for(int u = i; u <= list.Length - 1; u++) {
			if(!list[i].Equals(list[u])) {
				return false;
			}
		}
	}
	return true;
}

23.04.2009 - 10:30 Uhr

Hallo zusammen,

ich weiß, es gibt bereits einige Threads zu diesem Thema, aber diese haben mir nicht wirklich weitergeholfen. Auch bei Google finde ich nichts gescheites.

Ich versuche ein Drag & Drop zwischen Textboxen zu realisieren, wobei nur der ausgewählte Text verschoben/kopiert werden soll.

Mein Problem ist folgendes: Ich markiere Text in einer TextBox und um ihn zu verschieben klicke ich in die TextBox und würde dann mit gedrückter Maustaste ein Ziel aussuchen. Allerdings "vergisst" die TextBox die Auswahl sobald man sie wieder anklickt.

Ein gutes Beispiel wie es nicht sein sollte - aber leider ist - ist Notepad. Dort verliert das Eingabefeld auch seine Auswahl sobald man es erneut anklickt.

Was ich erreichen will ist, dass sich die TextBox so verhält wie z.B. der Code-Editor in Visual Studio oder die gerenderten Textboxen in Firefox, IE und Co.

Kennt jemand das Problem und kann mir vielleicht einen Hinweis geben wie ich es Lösen kann? Gerne auch per PInvoke, wobei mir eine "reine Managed-Lösung" natürlich besser gefallen würde.

Ich hoffe ich konnte mein Problem verständlich erklären.

rastalt

/Edit: Ups, hab den Titel nicht ganz ausgefüllt.

20.04.2009 - 16:54 Uhr

Das weiß ich nicht. Im .Net 2.0 SDK ist es auf jeden Fall enthalten. Das kannst du hier runterladen.

20.04.2009 - 16:50 Uhr

Mit Tausender Trennzeichen:


string.Format("{0:0,0}", zahl);

Mit Tausender Trennzeichen und zwei Nachkommastellen:


string.Format("{0:n}");

/Edit: Öh, es geht um Datenbanken? Mist ...

20.04.2009 - 16:42 Uhr

Der Fehler wird wohl in SucheNachDateien() liegen. GefDateien ist dementsprechend leer und die Schleife wird nicht durchlaufen. Setze dir am Besten mal einen Breakpoint in die genannte Methode und durchlaufe sie Schritt für Schritt um den Fehler zu lokalisieren.

/Edit: Willkommen auf myCSharp.de (das wollte ich immer schon mal sagen 😄)!

20.04.2009 - 16:25 Uhr

Schau dir mal die Beispiel in dem von mir geposteten Link an bzw. lies dir den Artikel mal durch.

/Edit: Vielleicht hilft dir MSDN: Gewusst wie: Mit dem XML Schema Definition-Tool Klassen und XML-Schemadokumente generieren auch noch weiter.

20.04.2009 - 16:20 Uhr

Es gibt auch noch das Tool XSD von Microsoft. Damit lässt sich auf diverse Arten zwischen XSD-, XML- und Code-Dateien konvertieren. Siehe auch MSDN: XML Schema Definition-Tool (Xsd.exe)

Es bietet beispielsweise die Möglichkeit aus XML ein XSD zu machen, welches sich wiederum in Code übersetzen lässt.

20.04.2009 - 15:39 Uhr

Die Übernahme soll noch in diesem Sommer abgeschlossen werden. Die Sun-Aktionäre müssen dem Verkauf erst zustimmen. Quelle: ZDNet: Oracle kauft Sun für 7,4 Milliarden Dollar

20.04.2009 - 14:13 Uhr

Assri Komla hat dir die Lösung doch bereits verraten.

17.03.2009 - 06:40 Uhr

Also sind private Klassen möglich - auch abstrakte, aber eben nur nested.

Hm ... irgendwie verstehe ich aber den Sinn davon nicht. Man kann doch mit einer abstracten, privaten Nested-Class genauso wenig anfangen wie mit einer abstracten, privaten Nicht-Nested-Class. Oder übersehe ich das jetzt nur was?

/Edit: Mist, hät ich mir den Code erstmal durchlesen sollen. Ist natürlich klar, was man damit anfangen kann.

11.03.2009 - 20:33 Uhr

Gegenfrage: Hast du schon ein Buch gelesen? [Hinweis] Wie poste ich richtig? Punkt 1.1.1

Und jetzt die Anwort: Das Do wird so lange ausgeführt, wie die Bedingung in im While wahr ist. Und was ist immer wahr bzw. true? Na klar, "true"! 😁

Also versuchs mal mit:


do {
}
while(/* hier die magische Bedingung */);

(Ich habs jetzt extra nicht ausgefüllt, damit du dir wenigstens meinen Beitrag durchliest.)

11.03.2009 - 16:57 Uhr

Ich denke JAck30lena wollte damit auch nur sagen, dass man es so leicht selbst implementieren kann.
Wenn man mal den Reflector anschmeißt sieht man tatsächlich, dass in den TryParse-Methoden kein Try-Catch-Block verwendet wird. Die Aufrufe werden an die statische Methode ParseNumber der internen Klasse Number delegiert. Verstanden hab ich die aber noch nicht, scheint aber mal einen Blick wert zu sein.

11.03.2009 - 11:09 Uhr

Ich verstehe nicht wieso du in diesem Fall Generika verwendest? Kannst du als Parameter nicht einfach DbConnection und DbCommand verwenden? Sollte doch dank Polymorphie funktionieren.

/Edit: Die Constraints, von denen Jack30Lena (der mal wieder schnell war) spricht, könnten übrigens so aussehen:


public bool Selection<T, U>(out Fehler fehler) where T : DbConnection where U: DbCommand {
    // ...
}

/Edit2: Aber wie gesagt, machs lieber nicht mit Generikas. 😉

06.03.2009 - 12:32 Uhr

Typischer Auslöser für dieses Problem ist, dass der Aufruf von InitializeComponent im Konstruktor der Form entfern wurde. Überprüfe das doch mal.

/Edit: Die von dir angemerkte Zeile kannst du im Debugger nicht erreichen, da dort kein Wert zugewiesen wird, sondern die Variable nur deklariert wird.

06.03.2009 - 08:54 Uhr

/Edit: Mist, das bringt dich wohl doch nicht weiter. Habe deinen Beitrag nicht aufmerksam genug gelesen.

Reagiere doch im Enter-Event. Wenn du die vorherige TextBox benötigst, kannst du dir diese ja merken.

Etwa so:


private TextBox lastTextBox = null;

private void txtFeld_Enter(object sender, EventArgs e) {
    if(lastTextBox != null) {
       // hier Werte in der Form aktualisieren
    }

    lastTextBox = sender as TextBox;
}

04.03.2009 - 14:53 Uhr

Ein nettes Tool, von dem du dir vielleicht auch ein paar Ideen abgucken könntest, ist Jing.

manchmal ist es ja wichtig, gewissen Dinge hervor zu heben. Ich erlebe das öfters weil der Kunde vor lauter Bäumen den Wald nicht mehr erkennt.
Vielleicht könntest Du noch irgendwie Stifte in verschiedenen farben einbauen.

Auch in diesem Fall kann ich raten dir mal Jing anzuschauen.

Du siehst, m0rius, es gibt echte Konkurrenz. 😉

04.03.2009 - 12:22 Uhr

Bei mir klappt das einwandfrei. Wenn ich nicht eingeloggt bin und auf "Antworten" klicke werde ich aufgefordert mich einzuloggen und danach auf die "Antwort erstellen"-Seite weitergeleitet.

Vielleicht hat da schon heimlich jemand nachgebessert? 😉

04.03.2009 - 08:13 Uhr

Um nochmal zusammen zu fassen was in demondriver235s Link bezüglich deiner Frage steht, hier ein kurzes Beispiel:


switch(bar) {
    case 1:
    case 2:
    case 3:
        someMethod();
        break;
    case 4:
    case 5:
        someOtherMethod();
        break;
    default:
        someDefaultMethod();
}

Dabei ist zu beachten, dass man nur von einem Case zum nächsten "fallen" kann, wenn dieser keine Ausdrücke beinhaltet. Folgender Code lässt sich dem entsprechend nicht kompilieren.


switch(bar) {
    case 1:
        someMethod();
    case 2:
        someOtherMethod();
        break;
}

In deinem Fall, hypersurf, würde ich aber auch eher michlGs Vorschlag folgen.