Laden...

Forenbeiträge von Andreas.May Ingesamt 915 Beiträge

19.05.2008 - 13:44 Uhr

Hrm, normal sollte das alles ohne Probleme gehen. Ansonsten über Win API Advapi32 GetUserName, siehe hierzu www.pinvoke.net. Wenn dann das selbe Problem auftritt versuchs mal über WMI kannst dir dafür mal das in Codeprojekt ansehen.

19.05.2008 - 13:36 Uhr

Hrm, wie wäre es mit einem richtig guten WMI Tool mit einen kleinen Assistenten.

    1. Assistent Schritt:
      Befragung was soll ausgelesen werden z.b. Hardware, Software, Prozesse, Dienste, Speicher usw.
      Visualisiert über nen paar schöne Icons.
    1. Assistent Schritt:
      Welche Informationsdaten sollen rausgelesen werden, z.B. visualisiert über eine Checklistbox.
  • usw.

  • letzte Assistentschritt:
    Fertiges Statement oder sogar Code den man sich in die Zwischenablage kopieren kann.

Features usw. kannst dir dann ja ausdenke, denke ein solches tool würde einem das Programmieren erleichtern. Ich vergesse eigentlich regelmäßig die passende Stichwörter dazu und muss erstmal ne weile lang im Netz suchen ob das gesuchte unter Win32 oder etwas anderen zu finden war.

zum thema WMI findet man viel hier im Forum: Denke Khalid's Beitrag könntest als Grundlage verwenden.

19.05.2008 - 12:52 Uhr

Hrm, vielelicht geht es mir nur mir so aber finde es etwas schwer lesbar. Vorallem gibt's da nen paar Dinge die evtl. in deinem Textfile stehen die mir nicht klar sind wie das hin und herkopieren in ArrayList wobei dann wieder die erste Reihe (col.RemoveAt(0)) löscht usw..

Vereinfache das ganze damit es lesbarer wird, z.B. wie folgt:


		private DataTable CreateSource()
		{
			DataTable dt = new DataTable();

			// TEST.txt
			//333; 23421312; 6575457; 234214; blubb;
			//5464; wertwert; 57554; 676585; asdf; hasdhidahd;
			//quack; sdafasdf; uztutru; rtutritrizti;

			using (StreamReader sr = new StreamReader(@"C:\Test.txt")) 
			{
				string text = sr.ReadToEnd();
				string[] rows = text.Split('\n');

				for (int i = 0; i < rows.Length; i++)
				{
					rows[i] = rows[i].Replace(";\r", string.Empty);
					string[] columns = rows[i].Split(';');

					DataRow row = dt.NewRow();
					for (int j = 0; j < columns.Length; j++)
					{
						if (!dt.Columns.Contains(string.Format("Column{0}", j)))
							dt.Columns.Add(new DataColumn(string.Format("Column{0}", j)));

						row[j] = columns[j];
					}

					dt.Rows.Add(row);
				}

				return dt;
			}
		}

Ansonsten geh mal alles stück für stück via Breakpoints durch ob auch wirklich Daten gefüllt werdne ob den Stream evtl. zu früh schließt usw.

17.05.2008 - 13:43 Uhr

30.000 mal Hilfe, das ist wirklich eine extreme Leistung - weiter so ! 🙂

16.05.2008 - 14:11 Uhr

dr4g0n76 hatte sich mal mit dem Thema befasst und ich denke in seinem Thread wirst du die Ansätze finden die du dafür brauchst. Eine fertige Lösung gab es noch nicht, das Thema ist auch nicht ganz ohne.

Der wichtigste Ausgangspunkt wäre die ntdll, hier anzusetzen denke ich wäre der richtige weg. dr4g0n76 nutze dafür die NtQueryInformationFile - ich denke das wird deine einzige Chance sein.

Über das struct FILE_INFORMATION_CLASS würde ich mal auf die FILE_NAMES_INFORMATION tippen, hier gibts ein WCHAR das dir die Namen zurückliefern könnte. Also, viel Glück beim Ausprobieren 🙂

Denk dran, das Ergebniss würde sicher auch den ein oder anderen interessieren oder zumindest den Weg.

16.05.2008 - 14:05 Uhr

Na ja, dafür brauchst keine Windows API Funktionen verwenden - mit .NET eigenen Hausmitteln kannst das ganze etwas einfacher lösen.

System.IO.File.Create()
System.IO.FileStream
System.IO.StreamWriter
System.IO.StreamReader
System.Text

Aber eigentlich ist das alles in der CfgFile.cs Klasse von tom-essen drinnen, kannst das Ding ja herunterladen und für's erstellen der .Ini File(s) erweitern. Dann klaust dir das beste raus von dem was ErfinderDesRades geschrieben hat und kombinierst das zusätzlich mit dem Artikel von egrath: Eigene Settings Provider.

16.05.2008 - 13:39 Uhr

Hrm, mach mal nen Invoke rein bei WriteMem oder beim button1_Click wo WriteMem aufrufst.

Bei WriteMem brauchst für as Invoke natürlich ein neues delegate:

private delegate void WriteMemDelegate(int i);

Du rufst zwar in der Methode WriteMem keine GUI Elemente auf, aber da dir ja das Handle des Fensters holst und via WriteProcessMemory könnte es dadurch zu Problemen kommen und der Thread vom Timer schmiert irgendwo zwischendrinnen ab, davon bekommst ja so direkt nichts mit, ausser evtl. im "Output" ("Ausgabe" in deutschen VS glaube ich) das der Trhead XY beendet wurde.

16.05.2008 - 13:01 Uhr

Hrm, nur so ne Frage? - Wenn dein Cheff meint das du dass so machen musst. Was ist dann das Ziel - sollen die MDI Fenster später aus dem MDIParent herausgezogen werden können um sie auf ein anderes Programm drauf zu setzen? Denn nur dann würde ich den Sinn dahinter erkennen, da SetParent für diesen Vorgang alleinig nicht ausreichen würde und du wirklich eigene GUI Threads benötigst.

16.05.2008 - 10:32 Uhr

Hrm, einen eigenen GUI Thread kannst du z.B. wie folgt erzeugen:


private static WPopUp m_wndPopUp;

        private WPopUp()
        {
            // register components
            this.InitializeComponent();
        }

        private static void Init()
        {
            if (m_wndPopUp == null)
            {
                m_wndPopUp = new WPopUp();
                Application.Run();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public static void ShowAsGUIThread()
        {
            new Thread(new ThreadStart(Init)).Start();
        }

Hier wird verhindert das ausser über die statische Methode ShowAsGUIThread das Popup (WaitForm) nicht initalisiert werden kann und ebenso wird damit überprüft ob das Form bereits schon instanziert ist.


public static IPopUp Instance
        {
            get { return m_wndPopUp; }
        }

Sollte man das WaitForm von aussen ansprechen wollen, so kann man auf nur die Threadsicheren Methoden zugreifen indem man die Instanz über eine Schnittstelle anspricht.

Denke so solltest die meisten überzeugen können das nichts schief geht. Ansonsten muss nur noch das von herbivore angesprochene beachtet werden. Man kann aber auch etwas schummeln sollte Quellcode vorhanden sein den man absolut nicht verändenr darf / kann der blockiert indem man folgendes ausprobiert:


RECT rec = new RECT();
					GetWindowRect(hWnd, ref rec);
					RedrawWindow(hWnd, ref rec, IntPtr.Zero, (uint)RDW_VALIDATE | RDW_UPDATENOW);

Via Win API kann man das entsprechende Fenster im WaitForm mit RedrawWindow neu Zeichnen lassen - selbst wenn dort im GUI Thread ein längerer Prozess am rumwerkeln ist. Allerdings ist das nen ziemlich schlechter stiel 😉

15.05.2008 - 12:19 Uhr

Warum ich es schöner finde ist leicht erklärt:

Es kann ja nur eine Zeile geben innerhalb seines Textdokuments, daher folgendes Schema was ich als Bsp. reingemacht habe:

Zeile 1 Spalte1 <Wert>; Spalte2 <Wert>; Spalte3 <Wert>;
Zeile 2 Spalte1 <Wert>; Spalte2 <Wert>;
Zeile 3 Spalte1 <Wert>;
Zeile 4 Spalte1 <Wert>; Spalte2 <Wert>; Spalte3 <Wert>; Spalte4 <Wert>;

Wenn er vorhat wie in Excel Cells zu erstellen die folgendes Schema aufweisen:

Zeile 1 Cell(0;0)<Wert>; Cell(0;1)<Wert>; Cell(0;2)<Wert>;
Zeile 2 Cell(1;0)<Wert>; Cell(1;1)<Wert>; Cell(1;2)<Wert>;
Zeile 3 Cell(2;0)<Wert>; Cell(2;1)<Wert>;
Zeile 4 Cell(3;0)<Wert>; Cell(3;1)<Wert>; Cell(3;2)<Wert>;

Hat er damit auch keine Probleme, dafür kann man ebenso ein Dictonary verwenden mit nen Jagged Array als Key.

Ich finde wenn man sich so seine schnellsuche vorstellt wird es einfacher zu indizieren als wenn man später über zich schleifen nach etwas suchen muss. Allerdings habe ich nur 3-4 minuten drüber nachgedacht und länger gebraucht für's tippen - lasse mich daher gerne eines besseren belehren 🙂

15.05.2008 - 12:09 Uhr

Das Problem kannst du auf verschiedenste Arten lösen.

1.) Entweder über Callback's via Thread / WaitHandles / AutoResetEvent / BackgroundWorker

2.) Du kannst dieses Problem auch über Invoke Lösen in zusammenhand mit System.Threading.Timer

Hrm, würde glaube ich eher via WaitHandels arbeiten da ich mal davon ausgehen würde das der Zeitintervall für jedne Button anders sein könnte. Klingt nämlich nach nen kleinen Push the Button Spiel für mich und um den schwierigkeitsgrad anzuheben würde ich ganz zum schluss den Zeitintervall für die Buttons unterschiedlich verkürzen, wäre gemeiner 😉

15.05.2008 - 11:59 Uhr

Hrm, würde das ganze etwas vereinfachen.

Erstmal muss man sich folgende Fragen stellen:

1.) Zeilen exestieren einmalig
2.) In jeder zeile kann einmalig nur eine spalte exestieren
3.) eine Spalte kann nur einen Wert besitzen
4.) Ein Wert kann x Fach vorkommen.
5.) Ich möchte schnell auf eine Zeile und die Spalte zugreifne können um den Wert auszulesen.

Lösung:



			Dictionary<int, Dictionary<int, string>> myFinder = new Dictionary<int, Dictionary<int, string>>();

			string write = "333;23421312;6575457;234214;blubb;\n5464;wertwert;57554;" + "676585;asdf;\nquack;sdafasdf;uztutru;rtutritrizti;";
			string[] zeilen = write.Split('\n');

			for ( int i = 0; i < zeilen.Length; i++)
			{
				string[] spalten = zeilen[i].Split(';');

				Dictionary<int, string> dic = new Dictionary<int,string>();

				for (int j = 0; j < spalten.Length; j++)
				{
					dic.Add(j, spalten[j]);
				}

				myFinder.Add(i, dic);
			}

			Console.WriteLine("Der Wert in der ersten Zeile und zweiten Spalte beträgt {0}", myFinder[0][1]);

Ist das selbe wie jagged Arrays, finde es nur schöner.

15.05.2008 - 11:39 Uhr

Hrm, würde eher zu Mutex greifen als über Process das ganze zu lösen.

Siehe hierzu: mehrere Programminstanzen verhindern?

15.05.2008 - 09:52 Uhr

public new int Maximum { get; set; }

14.05.2008 - 17:10 Uhr

Hrhr, dein code stimmt nur der Aufruf nicht .-)


		protected override void WndProc(ref Message m)
		{
			base.WndProc( ref m);
	

			EnableSystemMenuItems(this, false);
		}

Warum muss das so sein? - Ich kenne nicht die verantwortlichen WindowsNachrichten in welchen das dynamische verhallten der jeweiligen Menüeinträge gesetzt wird.

Sprich, wenn du nur nen Aufruf im Konstruktor z.B. hattest folgte spätestens beim Handle Create nen Add MenüItem für z.b. den Menüeintrag MinimizedBox mit der Eigenschaft Enabled = true usw..eine änderung deiner gesetzten Werte und das passiert bei irgendwelchen WindowsNachrichten.

Wie gesagt in welchen WindowsMessages das überall aufgerufen wird weis ich nicht, aber es werden schon einige sein 🙂

14.05.2008 - 16:52 Uhr

Hrm, mit GDI wärst ne weile dran, denke mit nen GIF wärst schneller fertig. Da ne PictureBox animierte Bidler darstellen kannst, machst einfach zwei Bilder. Eines wie die Blume ohne zu Blühen darstellt und wenn der Verbindungsaufbau gestartet wird, blüht deine Blume oder die Blätter wechseln die Farbe oder sowas.

14.05.2008 - 16:36 Uhr

Für das Deaktivieren bzw ausgrauen: MF_BYCOMMAND | MF_DISABLED| MF_GRAYED verwenden. Warum schließen überhaupt ohne MF_GRAYED nur Disabled wird ist mir grade nen Rätsel😉

/PS DrawMenuBar(frm.Handle); brauchst eigentlich nur nach nen DELETE eines Menüeintrags - schaden sollte es aber sonst auch nicht.

14.05.2008 - 15:31 Uhr

So jetzt aber:


		private const int WM_NCHITTEST = 0x84;
		private const int HTCAPTION = 0x02;
		private const int HTCLIENT = 0x01;
		private const int HTMENU = 5;
		private const int WM_NCRBUTTONDOWN = 0xA4;

		[DllImport("user32.dll")]
		private static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);

		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect);

		protected override void WndProc(ref Message m)
		{

			if (m.Msg == WM_NCRBUTTONDOWN)
			{
				Point pt = new Point((int)m.LParam);

				Rectangle ClientRect;
				Rectangle WindowRect;
				GetClientRect(m.HWnd, out ClientRect);
				GetWindowRect(m.HWnd, out WindowRect);

				// berechne die caption (wird um 2-3px größer sein als nötig, bereitet aber keine Probleme)
				Rectangle CaptionRect = new Rectangle(WindowRect.Location,
					new Size(WindowRect.Width, WindowRect.Height - WindowRect.Y - ClientRect.Height));

				if (CaptionRect.Contains(pt)) // + deine abfragen
					return;
				
			}

			if (m.Msg == WM_NCHITTEST)
			{
				Point pt = new Point((int)m.LParam);

				Rectangle ClientRect;
				Rectangle WindowRect;
				GetClientRect(m.HWnd, out ClientRect);
				GetWindowRect(m.HWnd, out WindowRect);

				// berechne die caption (wird um 2-3px größer sein als nötig, bereitet aber keine Probleme)
				Rectangle CaptionRect = new Rectangle(WindowRect.Location,
					new Size(WindowRect.Width, WindowRect.Height - WindowRect.Y - ClientRect.Height));

				if (CaptionRect.Contains(pt)) // + deine abfragen
					return;
			}

			base.WndProc(ref m);
		}
	}

Musst halt nur noch das von dir miteinfügen und kannst das ein oder andere noch vereinfachen - war nur zu faul 😉

14.05.2008 - 14:27 Uhr

Sorry der Code den ich gepostet habe ist falsch, korrigiere das grade .-)

14.05.2008 - 12:52 Uhr

... Hier stand ein Fehlerhafter Code 😉

14.05.2008 - 12:10 Uhr

Hrm, das ist schwer zu unterbinden und es gibt mehrere Wege dafür das zu lösen.
Aber erstmal zu den Problem, du brauchst dafür Kenntnisse im Umgang mit der Windows API.

Windows Fenster besitzen zwei größen, eine Clientgröße und eine wirkliche Fenstergröße. Die .NET Hausmittel geben dir über die MouseEvents nur den Clientbereich zurück nicht aber die äußeren Randbereiche. Sprich, wenn ein MouseMove mal bindest und auf die Titlebar des Fensters huscht kommt plötzlich kein Event. Des weiteren, das Standardverhallten von Fenstern wird in den WindowsNachrichten verarbeitet, das heisst klickst du auf einen Randbereich so wird in den WindowsNachrichten die Nachricht versendet, NonClientArea (Borders) MouseMove MouseLeftDown MouseLeftUp und eine Nachricht für den HitTestCode. Um nun zu vermeiden das alle Nachrichten durchgehen musst und diese zu immitieren, verändere nur die Nahcricht die ausschlaggebend ist und das ist WM_NCHITTEST - diese liefert als WindowsMessage.Result einen Integerwert zurück der schlussendlich das Verhallten weidergibt. Siehe hierzu www.pinvoke.net NCHITTEST. Du kannst also nun das Problem einfach Lösen indem die WndProc überschreibst die WindowsNachricht WM_NCHITTEST abfängst, schaust ob die NCHITTEST Returnwert = HTMENU (5) ist und gibst stattdessen wenn dein Kriterium sagt nee Menü soll nicht erlaubt sein stattdessen ein HTBORDER (18) oder HTOBJECT (19) zurück an das Message.Result.

So einfach, die anderen Lösungen dauern länger und man muss mehr beachten. Kannst dir auch mal den Artikel CustomBorders durchsehen, dort gibt es ein Projekt von dr4g0n76 der genau das dort nur in einen anderne zusammenhang behandelt. Oder kannst dir die UtilitiesLib mal von mir ansehen, mache das dort auch.

Wenn einen anderen Weg gehen möchtest sag bescheid, gibt wie gesagt noch mehr Möglichkeiten. Ist nur immer so viel zu tippen 😉

14.05.2008 - 11:52 Uhr

Beides ist möglich.

[PostMessage, WindowsNachricht versenden]
Der einfachste Weg wäre über Process den Prozess zu starten über WMI bekommst mit wann die Fremdanwendung wirklich da ist. Den es gibt immer einen gewissen zeitintervall bis das Programm wirklich komplett gestartet ist. Nun kannst du entweder über Prozess das MainWindowHandle finden und über Subclassing bei der WindowsMessage WM_CREATE, das Fenster ausfindig machen auf dem sich der Button befindet sollte das MainFenster nicht zufällig jenes sein auf dem sich der Button befindet. Oder du kannst ebenso versuchen das über WMI zu lösen, z.B. wenn ein Fenster erstellt wird mit dem Namen XYZ und dir dann das Handle davon holen. Anhand des Fensterhandels auf dem sich der Button befindet kannst du nun über die Windows API Funktion FindWindowEx anhand des Klassennamens des Buttons (wird wohl einfach "Button" heissen) alle Buttons auf dem Fenster raussuchen. Alle Buttons die du nun gefunden hast kannst du durchgehen und über z.B. WIn API GetWindowText oder SendMessage dir die Captions der Buttons zurückliefern lassen. Wenn die Caption mit dem gesuchten Button übereinstimmt dann hast du deinen gewünschten Button gefunden.

Nun gilt es mit Spy++ herauszufinden wie der Button reagiert und welche Windows Nachricht des Buttons wie z.B. WM_CLICK /WM_LBUTTONDOWN verarbeitet werden, direkt auf dme Button oder vielleicht sogar nur im Parent. Wenn im Parent kannst dir eh die Suche nach dne Button spaaren und direkt die NAchricht an das Fenster schicken auf dem sich der Button befindet. Wie gesagt, je nachdem was Spa++ auspuckt musst das verhallten immitieren. Zum versenden der Nachricht nutze PostMessage.
**
[Click immitieren]**
Dieser Weg ist der schlechteste da man hierbei die Maussteuerung übernimmt und soweiso den Button lokalisieren muss um über dessen Possition die Maus positionierne zu lassen. Würde daher davon abraten.

Ansonsten, wieder über Process den Prozess satrten, mit WMI schauen ob der Prozess gestartet wurde und dir über den SCOPE ein Event schmeissen lassen. Wieder über das Fensterhandle dne Button suchen oder über WMI. Dannach über GetClientRect dir über das Handle des Buttons die Location holen. Die (Rect.X + Rect.Width) / 2 berechnen wie (Rect.Y + Rect.Height) / 2 berechnen um das Center des Buttons als Point zu zuzuweisen. Dannach über Win API Funktion mouse_event den Point übergeben als X und Y Koordinaten wie das MouseEventFlag, LEFTDOWN und das wars.

/ps
Da waren andere schneller als ich Zeit zum Tippen gebraucht habe 😉

13.05.2008 - 21:07 Uhr

Falls das Interesse noch da ist: Habe mich damit beschäfftigt und ein Prototyp Widget geschrieben: Hier der Link.

13.05.2008 - 14:22 Uhr

Achso, das kannst dir etwas vereinfachen bzw. gibt es viele Möglichkeiten zu lösen.

Die gängigste und wohl einfachste lösung:
Anwendungseinstellungen - [Tutorial] Das neue Konfigurationsmodell im .NET Framework 2.0

Du kannst das aber auch über eigene Provider Lösen, macht dann Sinn wenn nen großes Programm mit Benutzer / Gruppen usw. nutzt - [Artikel] Eigene Settings Provider Kannst das aber auch in die Registry eintragen oder XML Files benutzen usw.. musst also nicht wie in dem Artikel unbedingt in *.ini Files speichern. Würde mir dann noch etwas einfallen lassen damit man nicht von jeden Control ableiten muss um die Attribute zu integrieren. Z.b könnte man dafür eine Komponente erstellen welche die Schnittstelle IExtenderProvider verwendet um dann von jeden Control die Properties auszulesen, zu suchen welche unterstützt werden und darüber die Attribute setzen lassen.

13.05.2008 - 11:35 Uhr

Das Stichwort dafür heisst immutable .-)


string blub = this.txtDatei.ToString();
         blub = blub.Replace("A", "Z"); // <= siehe diese zeile
         this.txtDatei.Text = blub;

13.05.2008 - 11:27 Uhr

Controls ansich zu serialisieren macht in der Regel keinen Sinn, da man ja nur Eingabewerte abspeichern oder weiterleiten möchte z.B. zur Auswertung oder für das erstellen von Sessions. Bei Sessions kommt ja noch hinzu, das jeder "Benutzer oder Gruppe" unterschiedliche Eingaben tätigt die dann auch beim wiedereinwählen in das Programm als Vorgabewerte unterschiedlich ausfallen. Also, wenn Hein sich anmeldet z.b. bei einer BDE hat jener grade eine Pinkelpause angemeldet, während Hugo gerade als letzten schritt 100 Klopapierrollen zurückmelden wollte als Gutmenge. Somit kann es ja nicht angehen das Heinz nach seiner Pinkelpause plötzlich 100 Klopapierrollen zurückmeldet.

Die Frage ist daher, was möchtest du genau damit bewirken wenn du ein Control serialisieren möchtest?

13.05.2008 - 11:20 Uhr

vielleicht kann man aber ein Konzept ähnlich von MSDN oder von Experts-Exchange verfolgen. [...]

Diese Idee finde ich persönlich klasse. Eine Bewertung von Threads nach ihrer Nützlichkeit würde das Suchen beschleunigen. Gerade bei relativ einfachen Themen bei denen es immer zu viele Lösungen gibt, würde man die Lösung als erstes in der Trefferliste auftauchen lassen deren Bewertung die höchste ist.

Blöd ist halt nur, das Threads die etwas älter sind dadurch verloren gehen könnten in der Suche, da sie ja nicht bewertet wurden.

13.05.2008 - 10:53 Uhr

Hrm, anfangen am besten mit Stift und Papier. Für das Steuerelement benutzt du einfach ein UserControl und schaust dir folgenden Link:
[Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox) an.

13.05.2008 - 10:49 Uhr

Tjar, Programmierer bekommen halt die meisten Mädels ab 😮)

/Ps
Schade ist nur das es nicht T-Shirts gibt mit nen paar Programmierergags drauf und dann www.mycsharp.de 🙂

09.05.2008 - 22:04 Uhr

Na ja, obs hilft weis ich nicht aber hatte einen solchen Fehler nur einmal als ich von VS2008 zurückkonvertieren wollte zu VS 2008. Dafür hatte ich das hatte ich das Projektfile umgeschrieben und einen eintrag in den Verweisen vergessen rauszunehmen. jenen der Linq einbindet, dieser hatte aussenrum einen Verweis aufs Framework 3.5.

Versuche das ganze mal umgekehrt und erstelle wenn es noch drauf hast, ein VS2005 Projekt, konvertiere es zu VS2008 und binde einen Verweis ein. Wenn dies klappt, erstll in VS 2008 ein neues Projekt und gehe in die Projekteigenschaft des Testprojektes und verweise dort auf das Framework 2.0. Versuch dann nochmals einen Verweis einzubinden wie System.Windows.Forms . Wenn das klappt hast evtl. irgend ein Frameworkproblem und evtl. hilft einfach eine neuinstallation von .Net Framework 3.5.

Naja, ansonsten... 😮)

09.05.2008 - 16:31 Uhr

So jetzt kann man sich trauen zu Antworten ,-)

[1. Lösung: Unschön]
Es gibt wie immer viele Möglichkeiten das zu bewerkstelligen. Du kannst Form1 an Form2 zum Beispiel im Konstruktor übergeben und dir im Form2 dann Form1 global merken um beim OnClick Event vom Button bei Form2, Form1.Close() zu beenden.

[2. Lösung: Custom Dialog]
Du kannst auch Form2 Modal machen da dieser als Dialog fungiert mit <Form2>.ShowDialog. Da hier ja Abfrägst:"Soll ob der Inhalt der TextBox ...". Wenn DialogResult zb == DialogResult.Yes dann (Form1.Close()) also this.Close();

[3. Lösung und die einfachste: MessageBox]
Ruf in Form1 MessageBox.Show() auf und übergib den string: "Soll der Inhalt der TextBox in der XML anstelle des alten Wertes gespeichert werden, oder soll dieser zusätzlich gespeichert werden?" - Wenn DialogResult == DialogResult.Yes. Tue in Form1 die entsprechende Aktion und beende Form1 mit this.Close().

Hätte noch nen paar mehr aber die reichen, denke ich 😉

[Edit]
Da waren einige schneller mit dem Tippen 😉

09.05.2008 - 15:32 Uhr

Also habe mir Punkt2 nochmals angesehen, um das Problem zumindest einzudämmen sollte man mit rechter Maustaste auf die Source klicken und getSpecific Version auswählen dazu eben den Hacken bei "Force get file versions already in workspace" betätigen und das Problem sollte damit nicht passieren - aber muss man halt jedesmal machen.

09.05.2008 - 15:19 Uhr

Hrm, mit __gc struct <Name> und wie JAck30lena meinte sollte es gehen. Aber aufpassen, schau dir auch __nogc an, wenn z.B. strukturen nicht durch den Garbage Collector jagen möchtest. Sowas kann man bei Hooks brauchen die man unmanged schreiben aber für C# dennoch zugreifbar machen möchte z.B. über ein Strukt. C++ möchte die ganze Zeit seine Informationen in den Stack bzw. die Struktur reinschreiben. Du hast aber nen Hook geschrieben der Evtl. in ner Klasse drinnen steckt die weil sie nicht mehr gebraucht wurde, eben vom GC gefressen wurde. Dein hook vom C++ möchte aber weiter reinschreiben - aber die Struktur ist ja weg...

Gut bin kein C++ Programmierer um das wirklich bewerten zu können, aber glaube das kommt eher selten vor.

Manchmal wünshcte ich, hätte doch Studiert, evtl würde es leichter fallen wenigstens erklären zu können warum 🙂

09.05.2008 - 14:29 Uhr

Wieso statisch 🤔

Brauchst doch nichts statisch definieren, ich glaube eher du brauchst ne ordentliche portion Kaffee und Sonne 😉

Du rufst doch wie folgt auf:

DatabaseService.Instance und bekommst nun die "public member / public methods oder public proeprties" von DatabaseService die von IDatabaseService angeboten werdne zurück.

Du brauchst da keine einzige zusätzliche statische Methode - den sonst ist's keine Singleton mehr.

Hier mal ein beispiel, hab's allerdings so runtergetippselt:



	public delegate void ErrorDelegate(string message);
	public interface IDatabaseService
	{
		string WieGehtDasABC { get; set; }
		event ErrorDelegate ErrorEvent;
	}

	public sealed class DatabaseService : IDatabaseService
	{
		public event ErrorDelegate ErrorEvent;
		private static IDatabaseService instance;
		public static IDatabaseService Instance
		{
			get
			{
				if (instance == null)
					instance = new DatabaseService();
				return instance;
			}
		}

		private string m_sNonsens = "ABC";

		public string WieGehtDasABC
		{
			get { return this.m_sNonsens; }
			set
            {
                    if(value != "ABC")
                            if(this.ErrorEvent != null)
                            this.ErrorEvent(string.Format("Da will mir jemand weismachen ABC wäre {0}", value));
                    else
                    this.m_sNonsens = value;
            }

		}
	}

	public class MyClass
	{
		private MyClass()
		{
			DatabaseService.Instance.ErrorEvent += new ErrorDelegate(OnError);

			DatabaseService.Instance.WieGehtDasABC = "ÄhmKeineAhnung?";
		}

		private void OnError(string error)
		{
			Console.WriteLine(error);
		}
	}

09.05.2008 - 13:50 Uhr

Ähm, da sind leider so viele Fehler drinnen das es etwas schwer wird anzufangen .-)


           Graphics grx;
           grx = null;

Das hier ergibt erstmal keinen Sinn, wozu solltest du eine lokale Variable deklarieren um sie auf null zu setzen um dannach...


if(grx == null){
  Graphics a;

.. zu fragen ob diese null ist um dann eine lokale Variable innerhalb eines Ausdrucks zu deklarieren der wiederum drei Fehler auslesen würde...


{
Graphics a;
a  = grx.FillRectangle (Brushes.AliceBlue, 100, 700, 100, 100);
}

...
Da grx.FillRectangle erstmal nen void zurückliefert und a immer null ist und a im falschen sinne gedacht eh niemals grfx sein könnte weil a deklarieren wolltest vom typen den vorher auf null abgefragt hast... dazu kommt noch das a irgendwo zugeweisen werden muss und es dann darauf ankommt ob a auch wieder disposen musst... Hab ich nen Fehler vergesssen?

Also, rate mal ins Blaue und du möchtest einfach nur nen Bildchen malen?


		private Bitmap DrawImage(Size size, Color color)
		{
			Bitmap bmp = new Bitmap(size.Width, size.Height);
			using (Graphics g = Graphics.FromImage(bmp))
			{
				g.FillRectangle(new SolidBrush(color), g.ClipBounds);
			}

			return bmp;
		}
		private void button1_Click(object sender, EventArgs e)
		{

			this.pictureEdit1.Image = DrawImage(new Size(20, 20), Color.Red); // zum testen die ausgabe auf ner picturebox
		}

09.05.2008 - 12:58 Uhr

Hrm, schreib ein Interface IDatabaseService und schreibe dort alle relevanten Methoden Properties usw. rein. Deine Singletonklasse hat ja logischerweise einen private Konstruktor und ist Sealed usw. Daher spricht ein Property oder Member an für die Instanz.


private static DatabaseService instance;

public static IDatabaseService Instance
{
   get 
   {
       if(instance == null)
         instance = new DatabaseService();
       return instance;
   }
}

// Constructor
private DatabaseService() { }

09.05.2008 - 12:51 Uhr

Hrm, wusste gar nicht mal dass das geht.

Wäre klasse wenn den Link und vielleicht dein Ergebniss mit reinposten könntest.
Im Geschäfft arbeiten wir ausschließlich via StrongName Signierungen, würde mich daher interessieren 🙂

09.05.2008 - 10:45 Uhr

Hrm, du kannst das auch über Win API abbilden was dir Khalid als Link reingestellt hat. Indem mit PostmEssage bei Protected override OnMouseMove beim Parentcotnrol ebenso durch alle Controls durchgehst und an WM_MOUSEMOVE über deren Handle die Nachricht weiterleitest, kannst als lParam ja das Parenthandle mit übergeben. Sollte deren eigener MouseMove dennoch interpretieren können. Wäre das selbe wie halt bei Khalid's beispiel nur nen fitzelchen weniger Code.

09.05.2008 - 10:41 Uhr

Hrm, der einfachste Weg um das zu realisieren wäre eine Trennung auch zwischen den Schnittstellen bzw. Interfaces gekoppelt mit Factory.

Das ganze habe ich damals bei meinen ersten Pluginprojekt wie folgt gelöst um auch später ein InternetLive Update zu realisieren:

  • Das erste Projekt beinhaltet nur eine Schnittstelle mit ein Proeprties, wie Version, Produktnummer alternativ kann diese auch leer sein - sie muss nur exestieren.
  • Das zweite Projekt ist eine Exe Anwendung welche die referenz vom ertsen Projekt beinhaltet.
  • Das dritte Projekt ist die Komunikationsbasisschicht und Hauptanwendung, diese wird vom zweiten Projekt geladen und zwar über die Schnittstelle des ersten Projekts.
  • Das zweite Projekt bekommt nun einen InternetLiveUpdater oder normalen Updater, ebenso da es ja die Hauptanendungs Dll also das dritte Projekt ladet über Assembly.LoadFrom soll diese auch wieder entladen können. Somit kann man die Hauptanwendung jederzeit umtasuchen.

Soo und nun gehts los, die Hauptanwendung also das dritte Projekt dient dazu Plugins mit Informationen wie deren Schnittstellenimplementation bereitzustellen. So wie Codeprojekt es anbietet nur etwas aufgedröselter. Dafür braucht man eine Klasse zum Laden und entladen der Module, quasi fast das selbe wie im zweiten Projekt. Um die Plugins zu Identifizieren benötigt es verschiedene Schnittstellen: IPlugin - beinhaltet Properties wie Version aber vorallem Dependencies, eine Liste von abhängigkeiten - den das Plugin kann ja andere Plugings als vorraussetzung benötigen, ebenso kann man noch andere wichtige implementationen in die Shcnittstelle mitreinbringen, eine davon wäre die bereitstellung der vorhandenen Liste von IForm's. IForm ist weiderum eine Schnittstelle welche Grundlegende Methoden von System.Windows.Form implementiert - also Methoden wie Show Hide und Properties wie Visible usw. Die nächste Schnittstelle ist für Plugins der Sorte IBusinessObject - diese besonderen Objecte bilden die BusinessLayer ab. Somit kann ein Plugin IForm's und IBusinessObjecte beinhalten, oder nur IBusinessObjecte oder nur IForm's. Das ist wichtig falls jemand externes irgendwann mal anbindungen an dein Modul schreiben möchte.

Soo das war der leichte Teil, die Komunikationsschicht ist ja das A und O eines Pluginsystems. Das wichtigste ist eine efiziente Fehlerfindung bei Komunikationsfehlern. Hierzu implementiere eine Singletonklasse in das dritte Projekt. In der Singletonklasse stellst du ein Delegate das z.B. über ein Proeprtie ansprichst bereit - sprich du zeigst auf den Instanzierten Handler nicht aber auf das Event. Intern stellst du eine private event mit dem Scope auf das delegate bereit. Soo was will man damit ereichen? Ganz einfach, man nutzt eine Intiligente Komposition als Informationsträger, diese realisiert man über das Command Patern. Hierzu kannst du eine Schnittstelle schreiben die zu den selben Schnittstellen gepackt werden wo sich auch IForm und IBusinessObject und IPlugin befindet, diese nennst du ICommand. ICommand beinhaltet nur ein Property Type und eine Methode void Execute, später kannst noch Undo, Redo hinzufügen aber ist erstmal nicht wichtig. Jetzt erstellst du eine Basisklasse (abstract) welche die Schnittstelle ICommand beinhaltet. Davon abgeleitet erstellst du z.B. folgende Klassen: FormAction, MenuAction, PluginAction und später evtl noch nen paar mehr. Die Singletonklasse mit dem delegate feuert und bearbeitet diese Klassen und zwar über die Schnittstelle ICommand. Was bedeutet das? - Ganz einfach, die ePlugins referenzieren auf das dritte Projekt diese Hauptanwendung und wenn etwas z.B. bei deiner Form passieren soll das diese angezeigt werdne soll oder einen Menüeintrag hinzufügen oder löschen soll so erstellst du eine diese Actions wie ForAction und oder MenuAction und übergibst diese an das Delegate der Singletonklasse. Und voila, du hast eine getrennte Schicht. Was ist nun mit den BusinessObjecten in den Forms? Diese Ladest du ja in die generische Liste im PluginLoader und stellst diesen Loader ebenso über die Singletonklasse zur verfügung, somit kannst du über die Schnittstelle IBusinessObject mit angabe des entsprechenden Plugins z.B. über dessen festen Namen als string bereit.

So, das Protokolieren und Fehlerfinden von Komunikationsfehlern zwische den Plugins ist dann das einfachste der wellt in dem Event der Singletonklasse verarbeitet und vershcickst du ja die Nachrichten von Plugin A auch an Plugin B ohne das diese sich überhaupt kennen, hier kannst du auch ein try catch einbauen und Fehler die erzeugt werdne abfangen und Protokollieren. Und besser noch, du kannst sogar alle Nachrichten mitloggen selbst jene die keinen Fehler erzeugten.

Hoffe das dir das weiterhilft .-)

Stichworte: Plugin, CommandPattern, Singleton, BusinessObjects, Actions

08.05.2008 - 22:42 Uhr

Hrm, ganz ohne ists nicht. Werde erst in enigen Wochen mich mal an Widgets versuchen.
Die Frage ist daher, möchtest du nur das Widgets anfür sich? Den das Dockingverhalten wird über ein Control von aussen her getriggert, dieses typische andocken ausdocken verhallten.

Ein Widgets anfür sich ist sowas wie eine NavBar die Gruppen von irgendwelchen controls oder Links (string + Bilder) zusammenfast. Der Rest ist auslegung. Andocken als minmierte Variante vom Parent und sich anhand der Bildschirmausrichtung vom Parent andockt als "minimiert" variante wie z.B. bei VS.

Naja das Andocken verlangt ein zusätzliches Control dafür werd ich im ersten Versuch ein NativeWindow verwenden das ich so gestallte das es auf dem Parent des Widgets als Grafisches Hilfsobject benutzt wird (ich möchte nicht auf dem Desktop dafür rummalen). dieses GrafischeControl übergibt dann die gewünschte position. Über SetWindow oder MoveWindow vielleicht auch einfacher setze ich dann das Widgets - wichtig ist das Borderverhalten (NonClientHittest) noch dafür so zu manipulieren das es auch "gut" aussieht, für z.B. ein preview wo sich das fenster andocken würde wenn ich es auf dem DockingControler ausrichte.

Also, bin selbst noch am rumgrübeln wie am besten.

Der einfachste weg wäre ne bestehende Form dafür zu verwenden und über SetParent zu arbeiten, aber finde den Weg nicht so ganz prikelnd. Flackereffekte, komisches Dockingverhalten, vorallem das rummalen auf dem Desktop behagt mir dabei nicht zur visualisierung des Dockings. Mal schauen, evtl finden sich noch mehr Ideen ein.

Die allerschnellste lösung, es gibt kostenpflichtige Controls bereits dafür wie bei DevExpress. Du kannst dir auch das hier mal ansehen wenn das ausreicht.

08.05.2008 - 22:20 Uhr

Okay, hat zwar gedauert aber herbivore hatte den richtigen richer 😉
Einfach den Eventhandler neu initalisieren und diesen als Member in der Hook Klasse halten und der Fehler sollte nicht mehr auftauchen.

08.05.2008 - 20:08 Uhr

Hrm, es geht auch etws einfacher. Du kannst ja auf deinen Controls eine Schnittstelle implementieren welche das event MouseEventHandler OnParentMouseMove; beinhaltet und beim Adden der controls so wie oben das event auf jene Controls mit dem passenden interface binden. Dann überschreibst beim Parent Control die OnMouseMove Methode und feuerst das Event ab. Und schon kannsta uf deinen childcontrols auf das Event reagieren.

Also es gibt viele Möglichkeiten das zu realisieren 🙂

08.05.2008 - 18:24 Uhr

Hallo purestrain,

haben hier zwar noch nicht lange TFS im Einsatz aber ein paar Dinge habe ich selbst bereits erlebt ein paar wiederum nicht.

1.) Das sollte eigentlich gehen, das konnte ich bisher nicht nachvollziehen.

2.) Fürchte das geht nicht anders, habe da auch keinen Schalter bis dato gesehen den man evtl. dafür umdrehen könnte.

3.) Das geht mehr oder weniger indem man das Binding auf der Solution entfernt mit "unbind". Ne schöne rechte Maustastenfunktion auf die Source habe ich leider nicht gefunden - wäre aber mal was 🙂

4.) <noch nicht probiert>

Was das auschecken betrifft so kann man hier vieles einstellen, bei der Firma für die ich arbeite ist es so das beim einfachen reinschreiben in eine Datei automatishc Shared Checkout verwendet wird. Mit rechter Maustaste auf die entsprechende Source kann man dann allerdings wählen. Ein sporadisches nicht auscheken konnte ich nicht reproduzieren - klappte bisher immer.

Zum großen und ganzen, bin mit TFS wirklich happy vereinfacht das Leben schonmal ungmein - klar das absolut nervigste ist bei dne Workitems eine Fehlende Sortierung bei Bugs/Taks usw... wenn man da mal eben mehrere Hundert nummern drinnen stehen hat die richtige zu finden ist schwer. Und ein Query jedesmal zu schreiben fehlt mir auch etwas die Lust dazu.

/Ps
Vielleicht kann ich in ein paar Wochen mehr dazu schreiben, im Moment ists noch etwas zu neu.

08.05.2008 - 17:33 Uhr

Oder hast sowas hier ?


public int i
{
     get { return ni = 0; }
}


oder sowas ?


for (int i = 0; i < 26; i++)
{
    i ^= i;
}

Usw.. da kann viel in deiner Klammer oder aussen drum rum stehen was dir nen streich spielt. Das mit dem Propertie ist mir zwar nicht genau für das selbe, aber in anderer form durch Copy & Paste auch schon passiert... 😉

08.05.2008 - 17:25 Uhr

Muh, hab mich verlesen, hatte es so verstanden vom Child zum Parent. Du willst aber die Parent MouseMove zum Client 😉

Eine Lösung dafür wäre ein lowlevel hook auf den eigenen Prozess und das Handle des Parents , praktischerweise ist dieser ja dme Child bekannt.

Unter folgenden Link findest du einen global hookLink, shcmeiß das LoadLibrary weg, stell das SetWindowHook um.


SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, <ParentHandle>, AppDomain.GetCurrentThreadId());

Kannst auch nen ThreadHook schreiben, und das <ParentHandle> weglassen, da es logisch ist das die Maus nur koordinaten des äussersten Containers versenden kann auf dem aktuellen GUI Thread. Ergo hast imemr das Parent.

Sieht so aus:


SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId());

Gibt aber auch andere sehr schöne hooks hier im Forum sogar in C++ 🙂

08.05.2008 - 17:13 Uhr

Hrm... versuch mal


 extern "C" __declspec( dllexport ) int __stdcall BoxProperties(int Length, int Height, int Width);

Bin leider kein C++ Fachmann...

08.05.2008 - 16:40 Uhr



        void control_ControlAdded(object sender, ControlEventArgs e)
        {
            Control con = (Control)sender;
            Control added = con.Controls[con.Controls.Count-1];
            added.MouseMove += new MouseEventHandler(added_MouseMove);
            //added.ControlAdded += new ControlEventHandler(control_ControlAdded);
        }

Das würde gehen, aber bedenke, die Koordinaten werden vom 0 Punkt des Childs aus jeweils berechnet! Wenn also Parent e.X - Child e.X machst wirst immer = 0 erhalten da Parent e.X = 0 und Child e.X = 0 ist. 🙂

Klingt zwar einfachc oder logisch, aber wenn so etwas berechnen möchtest denk dran, über Parent.Location und Child.Location (kannst auch .ClientRect wenn auch den Rand ausschließen möchtest). Über den sender identifizierst ja die Controls.

08.05.2008 - 13:23 Uhr

Hrm, es gibt verschiedene Wege die existenz eines Fensters herauszufinden. Klar mit FindWindowEx bekommst als returnwert den Pointer. Wenn dieser wiederum = Inptr.Zero ist (0) so weist das das Fenster nicht vorhanden ist.

Der Ansatz um z.B. festzstellen ob das Fenster aufplopt wäre über WMI. Du könntest zuerst im WMI dir über dne Scope ein Event feuern lassen wenn das Programm dass das Fenster beinhaltet gestartet wird. Und dann mal schauen ob es eine WMI Nachricht gibt auf die du dann ein Event für WM_CREATE findest. Wenn es keine WMI dafür gibt hast du ja durch die erste WMI Abfrage herausgefunden dass Programm gestartet ist und könntest nun über das MainWindowHandle das über de ermittelden Prozess herausfindest mit SubClassing versehen. Das geht sehr eifnach mit NativeWindow und der Funktion Assert(hwnd). Hier bekämst du alle WindowsNachrichten herein und könntest nun auf WM_CREATE immer schauen ob das Fenster das gerade in diesen Prozess erstellt wird, dein gesuchtes fenster ist und weiter wie gehabt vorgehen. Du kannst auch versuchen über C++ z.B. einen Klassischen Hook zu schreiben fals NativeWindow aus irgendwelchen Sicherheitsgründen heraus (sollte aber gehen) nicht funktioniert. Nutze dafür in C++ nicht SetWindowsHookEx für den WndProc Hook sondern so merkwürdig es klingt, SetWindowLong somit spaarst dir das unterjubeln eines Dll in einen Fremden Prozess die evtl. sogar durch Allocate Heap gelöscht wird (ach habs vergessen wie man das schreibt). Evtl, geht SetWindowLong auch in C# aber darauf verlassen würde ich mich nicht.

Hrm, aber versuchs wie gesagt mit NativeWindow, geht bestimmt.

08.05.2008 - 10:51 Uhr

Erstmal Entschuldigung, mein Posting war etwas zu schnell getippselt und zu wenig nachgedacht... was du überhaupt machen möchtest 🙂

Zu erstens: lParam habe ich mit wParam vertauscht, das passiert mir ständig...

Zu zweitens: Habe dir das falsche an Info gegeben, hatte total überlesen das Tastenkombinationen versenden möchtest.

Dafür wirst du wirst eine Stufe tiefer gehen müssen und zwar mit der WIN API User32 Funktion keybd_event.

SHIFT+TAB Simulation.


 keybd_event( VK_SHIFT, Mapvirtualkey(VK_SHIFT, 0), 0, 0 );
 keybd_event( VK_TAB, MapVirtualKey( VK_TAB,0), 0, 0);
 keybd_event( VK_TAB, MapVirtualKey( VK_TAB,0), KEYEVENTF_KEYUP, 0);
 keybd_event( VK_SHIFT, Mapvirtualkey(VK_SHIFT, 0), KEYEVENTF_KEYUP, 0 );

/ps hier die VK's kannst auch System.Windows.Forms.Keys verwenden.

Sorry nochmal 🙂

07.05.2008 - 15:28 Uhr

HrHallo dila71,

um Windowsnachrichten an ein externes Programm zu senden nutze die WIN 32 API Funktion PostMessage, sende die Windowsnachricht WM_KEYDOWN = 0x100 über lParam übergibst du die Taste die gedrückt werden soll z.B. new IntPtr((int) Keys.F1), siehe hierzu www.pinvoke.net

Dein Hintergrundprogramm kannst du ja unterschiedlich erstellen, als Dienst oder was schöner ist z.b eine Tray Anwendung - hierzu gibt es einen schönen Artikel.