Okay, ich hatte die Antwort etwas arg hingesudelt.
Ich gebe nun erstmal nur die Antwort auf die Frage von davor.
Erstelle zwei Formulare, das erste wo das Grid angezeigt werden soll, ich nenne es mal <GridForm> und ein zweites das dein Wartefenster sein soll, daher <WaitForm>. In deinen <WaitForm> erstellst du ein neues Delegate: public delegate void mydelegate(Grid e). Dann ein passendes Event dazu public event mydelegate MyEvent;
Als nächstes, erstellst du ein einen Thread im <WaitForm>, am besten startest diesen nach der initialisierung der Komponenten. In der Methode des Threads wird ein neues Grid initialisiert.
Das Grid füllst du dann mit deinen Daten. Wenn das Grid gefüllt wurde, rufst du zuerst MyEvent(<Grid>) auf, danach rufst du die Close Methode auf.
So normalerweise würde jetzt ein Fehler auftreten in der <Waitform> überschreibe die bisherige Close Methode mit diesen Beispiel.
public new void Close()
{
if (this.InvokeRequired) this.Invoke(new MethodInvoker(this.Close));
else { base.Close();}
}
Jetzt gehst du in das <GridForm> das dass Grid anzeigt, dort erstellst du einen Thread der das <WaitForm> initialisiert und ebenso das <WaitForm. MyEvent> aufruft. Dann rufst du die Methode Threads Application.Run(<WaitForm>) auf. Fertig ist der Thread.
Wenn nun das <WaitForm> beendet wird, wird dein <WaitForm>MyEvent ausgelöst und das Formular auf dem dein Grid anzeigen möchtest bekommt als Parameter das volle Grid. Denke nur daran, das dein Grid wenn es angezeigt werden soll, wieder invoked werden muss.
Soo das war die reine Antwort auf deine Frage, nur sollte man davon die Finger lassen. Mal davon abgesehen erscheint es mir selbst nicht mal klar für was das Waitformular brauchst?
Kurzum, mach es lieber anders. Sollte deine Datenquelle eine SQL Datenbank sein, nutze DataAdapter Fill und / oder nutze Datasourcen um deine Daten an eine Quelle zu binden die diese dann auch anzeigt.
Aber ich habe halt keine Ahnung was da genau machen möchtest, willst du Benutzereingaben ebenso blockieren und darum das Formular Disablen oder ein Waitform?
Starte einen Thread aus deinem Main GUI und starte dort mit Application.Start(new Form WaitFenster). Starte dann im WaitFenster einen weiteren Thread indem du die Daten abarbeitest und in einen lokalen Member speicherst (idealfall als Grid). Wenn der Thread stirbt dann, invoke delegate Event von WaitForm indem du an MainForm die Daten von Grid übergibst.
[Pure Vermutung]
Und wenn dir eher dannach liegt mehr performance rauszuholen, füllst du die Daten SQL seitig ohne sie in C# nochmals zu bearbeiten, bleib auf der Datenbankebene und arbeite mit Datensourcen. Mal 20-60 Sekunden zu warten wegen 20.000 Datensätzen muss nicht sein. Wenn aber keine andere Wahl hast, gibt es noch mehr Möglichkeiten mit Threads zu arbeiten. Du kannst dir auch mal UserWorkItem / WaitHandels mal ansehen.
Hrm, konnte das Problem nicht nachvollziehen.
Mal ein kleines Testprojekt, egal ob int, bool ich musste nichts dran ändern.
Naja wenn die OnPaint Methode überschreibst in deiner PictureBox dann ist der zu zeichnete Rasterbereich (GraphicPath) größer als der Clientbereich (ClientSize) der PictureBox, oder hast du dass berücksichtigt?
Uh.. du hast recht, hätte mal besser nachschauen sollen ob ListView.DataSource überhaupt exestiert. Was mich ehrlich gesagt wundert, das es keines gibt.
Naja bei CodeProject gibt es eines: Link
Achso, na dann.
Wenn mehrere Child zu einen Parentcontrol hinzugefügt werden, solltest du die SuspendLayout Methode vor dem initalisieren der hinzuzufügenden Childcontrols aufrufen. Das heisst innerhalb deiner Childcontrols die du aufrufst sollten ebenso vor der initalisierung die SuspendLayout und die ResumeLayout Methode aufgerufen worden sein. Um dann das Parentcontrol wieder mit ResumeLayout nach der initalisierung der Chidlcontrols zu schließen. Aber so wie ich dich verstanden habe machst du das bereits.
Also, vermute ich nur mal, das Child-Chidlcontrols zur Laufzeit hinzugefügt werden, so das die SuspendLayout und ResumeLayout bei diesen Controls erneut aufgerufen werden. In dem fall würde ich bei diesen Child-Childcontrols, von diesen beiden Initalisierungsmethoden absehen (normalerweise sollte das überhaupt kein Problem darstellen sie dennoch darzustellen). Da es sich hierbei nur um performance verbesserungen für die Zeichenroutine handelt. Um ehrlich zu sein, bei vielen Controls nutze ich das nicht einmal... Nur bei denen vom VS-Designer generierten.
Also eigentlich sollte das kein Problem sein... Wenn du das hier meinst:
this.SuspendLayout();
<ControlA>.SuspendLayout();
<ControlB>.SuspendLayout();
<Control...>.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(<ControlA>)).BeginInit();
((System.ComponentModel.ISupportInitialize)(<ControlB>)).BeginInit();
((System.ComponentModel.ISupportInitialize)(<Control...>)).BeginInit();
// eigenschaften setzen this, Control A / B usw..
((System.ComponentModel.ISupportInitialize)(<ControlA>)).EndInit();
((System.ComponentModel.ISupportInitialize)(<ControlB>)).EndInit();
((System.ComponentModel.ISupportInitialize)(<Control...>)).EndInit();
this.ResumeLayout(false);
<ControlA>.ResumeLayout();
<ControlB>.ResumeLayout();
<Control...>.ResumeLayout();
Oder zielt deine Frage auf etwas anderes ab?
Okay, das ist noch leichter, selber machen ist eh die bessere Idee 🙂
Evtl. hast du vergessen beim malen deines Rasters die Region zu aktualisieren.
Einfach bei der OnPaint wenn das Raster malst this.Region = new Region(<Raster_GraphicPath>) aktualisieren. Wenn das nicht klappt fürchte ich wirst etwas mehr reinposten müssen bzw. zumindest die stelle wo deine PictureBox mit deinen Raster füllst bzw auch die stelle mit der AutoScroll Zuweisung.
/PS
Ich vermute nur mal das deine Rastergröße hinzeichnest ohne das die Region des Controls mitberücksichtigt wird. Soll aber die Region beibehalten werden weil dein parentcontrol nicht die PictureBox in seiner größe einschränkt (was weis ich, Dockstyles usw..) dann musst ne Region erstellen an die sich deine Scrolleiste(zusätzliches Control) ausrichten kann.
Mach einfach nen Databinding von der Listview auf dein Array, geht schneller als mit Add das ganze zu füllen und deine CPU wird weniger belastet.
Ok, bei einen ActiveX Control sieht das ganze wieder anders aus. Aber stellt dennoch kein Problem dar.
Leichteste weg, du schaust dir das OnClick Event an. entweder sieht die Methode auf die gezeigt wird wie folgt aus.
private void OnClick(EventArgs e)
Dann siehst dir anhand eines kleinen Brakepoints mal an ob EventArgs e nicht dem Typen MouseEventArgs entspricht wenn ja, machst folgendes.
private void OnClick(EventArgs e)
{
if(e is MouseEventArgs)
{
MouseEventArgs args = e asMouseEventArgs;
<MenüDing>.Show(args.Location);
}
}
Wenn das nicht der fall sein sollte, kannst du anhand vom ParentControl (dein UserControl) die Position über Click oder OnMouseDown erhalten oder wenn irgendwas dazu führen sollte das dass nicht geht mach folgendes:
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point lpPoint);
// du weist das geklickt wurde aber nicht wo die maus steht also holst dir die mouse Koordinaten
private void OnClick(EventArgs e)
{
Point bla = Point.empty;
GetCursorPos(out bla)
<MenüDing>.Show(bla);
}
Also, GetCursorPos gibt die den ScreenPoint zurück evtl. solltest noch PointToClient nutzen, glaube aber brauchst das nicht.
/ps
Im Quellcode könnten Tippfehler sein, aus dem Kopf heraus und mit ner Flasche Whisky in der Hand lässt sich schlecht was tippen..
Eigentlich haben dir die bisherigen Antworten auf die Frage Lösungswege zu diesen Problem aufgezeig? - Du möchtest doch entweder Systemweit alle Dateien sichtbar oder unsichtbar machen oder nur bestimmte Dateien?
Und was dir Melone sagen wollte ist das hier:
Start->Ausführen->cmd und:
%windir%\system32\rundll32.exe user32, UpdatePerUserSystemParameters ,1 ,True
Aktualisiert den Desktop bzw. auch den Explorer. Was dir z.B Helfen würde nachdem du die Registry Einträge geändert hast zum aktualisieren.
Hrm, nur ne Idee keine Ahnung ob das klappt.
using (Process _ps = new Process())
{
_ps.StartInfo.FileName = ("Access.exe");
_ps.StartInfo.CreateNoWindow = true;
_ps.Start();
using (StreamWriter _sw = _ps.StandardInput.BaseStream)
{
// entschlüsselten Stream in streamwriter übergeben
// dbconnection aufbauen usw..
}
}
[RunInstaller(true)]
public class CInstaller : Installer
{
private ServiceInstaller m_ThisService;
private ServiceProcessInstaller m_ThisServiceProcess;
public CInstaller()
{
m_ThisService = new ServiceInstaller();
m_ThisServiceProcess = new ServiceProcessInstaller();
m_ThisServiceProcess.Account = ServiceAccount.NetworkService; //<-- genau da
m_ThisService.ServiceName = "Simple Test Service";
m_ThisService.StartType = ServiceStartMode.Manual;
Installers.Add(m_ThisService);
Installers.Add(m_ThisServiceProcess);
}
}
Siehe Artikel
Gerne hier ein Prima Artikel dazu: Artikel
/PS
Wenn VS2003 benutzt, scroll bei dem Artikel nach ganz unten 🙂
Original von sbertl000
Encoding.ASCII.GetString(),Aber nur so am Rande, wie kann man das .NET FW auf der PSP laufen lassen?
Das würde ich auch gerne wissen, poste das mal rein wenn es keine Probleme damit gibt stigge =)
Original von Bibi1911
Oder muss ich das aus zwei verschiedenen Controls zusammenbauen?
Danke im Voraus.
Jup genau das machst dann.
Du erstellst erst ein Control für die Urhzeit. Z.B eine DigitalUhr da diese kaum Aufwendig sind. Indemman einfach ein Label oder TextEditControl.Text den DateTime.ToString(<format>) übergibt und einen System.Windows.Form.Timer benutzt der jede 1 Sekunden Tickt um dein Control zu aktualisieren. Oder du zeichnest selbst eine Uhr (was lange geht um was schönes hinzubekommen). Dann nimmst nen UserControl und legst dein ZeitControl wie ein DateTimePicker drauf. Und fertig ist dein eigenes Zeit&KalenderControl (Naja Properties Events usw. kannst du dann ja gestallten wie du möchtest) 🙂
Hrm, wenn nur ein File ändern möchtest oder mehrere warum nicht so?
FileInfo tt = new FileInfo(@"C:\GeheimRezeptVonTanteEmmasSpätze.txt");
tt.Attributes = FileAttributes.Normal;
tt.Attributes = FileAttributes.Hidden;
Wenn es Systemweit ändern möchtest dann.. hrm..gebe keine Garantie darauf das es funktioniert.
Start>Run>Regedit>OK
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\
Advanced\Folder\Hidden\SHOWALL]
0x00000001(1) // Verstecken
0x00000002(2) // Anzeigen
So zum Beispiel:
using (XmlDocument doc = new XmlDocument())
{
XmlNode myRoot, myNode;
XmlAttribute myAttribute;
myRoot = doc.CreateElement("AppendChild");
doc.AppendChild(myRoot);
myNode = doc.CreateElement("Child1");
myNode.InnerText = "Text1";
myAttribute = doc.CreateAttribute("Attribute1");
myAttribute.InnerText = "AttributeText1";
myNode.Attributes.Append(myAttribute);
myAttribute = doc.CreateAttribute("Attribute2");
myAttribute.InnerText = "AttributeText2";
myNode.Attributes.Append(myAttribute);
myRoot.AppendChild(myNode);
myRoot.AppendChild(doc.CreateElement("Child2")).InnerText = "Text2";
myRoot.SelectSingleNode("Child2").Attributes.Append
(doc.CreateAttribute("Attribute2")).InnerText = "AttributeText2";
doc.Save(@"c:\AttributeNodes.xml");
}
Ok, das ist ein eindeutiges Threading Thema.
Damit dein GUI-Thread wegen der enormen abfrage an Datensätzen nicht blockiert wird, erstelle einen Thread der dir deine Generische- Liste füllt. Im Forum gibt es viele ähnliche Threads such einfach mal unter Threads oder schau dir folgenden Artikel an.
Denk dran, schön ist eine Progressbar die den Status mit angibt wie weit das Einlesen der Daten vorrangeschritten ist. Also beschäftige dich gleich mal mit Invoke();.
Also, es gibt mehrere Lösungen eigentlich viele 😉
Die meisten Controls haben das Propertie <Control>.ContextMenu oder <Control>.ContextMenuStrip. Hast du nun ein Control das diese Eigenschaft nicht hat oder du unbedingt das <UserControl1>MenüControl verwenden möchtest oder irgend eine andere Schikane vorhast so kannst du auch folgendes angehen.
protected override void OnMouseDown(MouseEventArgs e)
{
if (l<ControlA>.Region.IsVisible(e.Location))
{
<MenüDing>.Show(e);
}
if (l<ControlB>.Region.IsVisible(e.Location))
{
<MenüDing>.Show(e);
}
if (l<ControlUsw..>.Region.IsVisible(e.Location))
{
<MenüDing>.Show(e);
}
base.OnMouseDown(e);
}
Wenn du irgend ein selbstzusammengemaltes UserControl hast, dann ersetze <Control> durch this.Region.IsVisible(e.Location). Solltest du "Nur" OnPaint überschreiben und rumzeichnen bitte this.Region(myGraphicPath) immer mit angeben (und nicht nur wegen den Clicks).
/ps Die Schleifen sind nur vereinfacht dargestelt zur verdeutlichung.
Original von Haggy
ich denke er hat ein eigenständiges control.So müsste das control ja immer auf dem parent container gezeichnet werden (falls vorhanden).
Weil sonst der Hintergrund des UserDefined controls immer noch nciht echt duchsichtigwäre
Hrm, da hast du keinesfalls unrecht... 🙁
Nur was besseres viel mir dazu sonst nicht ein.
Mit der Windows API sollte da auch was möglich sein, aber wird wahrscheinlich um einiges aufwendiger.
Wenn es mit der Win API mal versuchen möchtest, es müsste etwas mit dem device context zu tun haben. Schlüsselwörter, MSDN, WinAPI bzw. Pinvoke.net
GetDc();
GetDcEx();
SelectObject();
ReleaseHdc();
BitBlt();
Ansonsten, selbst malen.. Ist halt aufwendig, vielleicht gibt es noch leichtere Lösungen...
Probiere das mal aus:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// hier alle daten binden
// editControl 1
textBox2.DataBindings.Add("Text",bs,"Firma",true);
// editControl 2
// editControl usw..
}
Hrm, da gibt es was, ich hoffe was ich dir da nun hintippe stimmt.
Ist leider aus dem Kopf heraus - ich hatte grad kein VS offen...
Der Alpha-Wert gibt die Transparenz an und bedenke das den Backcolor entsprechend deiner gewünschten Farben einstellen musst. Etwas ausprobieren wird dir ebenso wenig erspaart bleiben.
[Edit]
Groß und Kleinschreibung bei SupportsTransparentBackColor bin ich mir grade nicht sicher..
public <UserControlName>()
{
this.InitalizeComponents();
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.Opaque, true);
this.BackColor = Color.FromArgb(0, 0, 0, 0);
}
protected override CreateParams CreateParams
{
get
{
this.CreateParams clCreateParams = base.CreateParams;
clCreateParams .ExStyle |= 0x00000020;
return cp;
}
}
Hrm, naja der schnellste Weg wäre folgendes:
1.) FormBorderStyle.None setzen.
2.) Backgroundcolor = <wiederliche Farbe>
3.) TransparencyKey = <wiederliche Farbe>
4.) Region = new Region(myNewGraphicPath) <- z.b. ein Formular mit Runden Kanten. Die neue Region verhindert Events, die sonst ausgelöst würden wenn man auf die Abgeflachten Kanten klickt.
5.) Dann legst deine Bilder auf das Formular drüber bzw. die Controls die die darauf abgebildet haben möchtest. Denk nur daran, diese dürfen nicht die <wiederliche Farbe> Farbe besitzen.
6.) Contextmenü wie Schließen, Minimieren und Maximieren nicht vergessen.
Das ganze kannst dann auch auf Controls anwenden, die du verändert haben möchtest.
Aber ich betohne nochmals, der Effekt der damit Erziehlt wird ist OK, nur sauber programmiert ist das sicher nicht. Wenn man sich noch etwas mehr Mühe machen möchte, würde ich dir vorschlagen schau das deine Effekte zumindest bei (in) den Controls dann selbst manipulierst bei: protected override void OnPaint(PaintEventArgs e).
/ps
Tippfehler dienen der allgemeinen Unterhalltung... 😜
Ich kenne das Steuerelement nicht, aber vielleicht solltest den <shockwave>.OCX via regsvr32 regestrieren. Das Problem ist nur das auch dran denken musst das manche kostenpflichtig sind und wenn das Programm herausgibst, muss das Steuerelement auf jeden Client regestriert werden.
Ich denke da gibt es sicher noch bessere Möglichkeiten das zu handhaben.
Ich sollte in den Feierabend gehen, bin immer zu langsam...
Die System.Timer Classe ist nicht Threadsicher. Wenn direkt in der Aufgerufenen Funktion ChangeTimer irgendwas an deinem GUI machst, wird es das GUI blokieren, es sei du führst Invoke aus oder nutzt andere Techniken. Wenn dass nicht der Fall sein sollte, musst genaueres erklären.
System.Timer wird hauptsächlich für ServerApplicationen verwendet ohne GUI.
Ich denke die Frage zielt darauf ab was mit den Controls dann bei Veränderung der Formgröße passiert.
Weil mit form1.size = new Size(800,600) hast du bereits die Lösung selbst offenbart. Leider passieren dann grauen erregende Dinge mit deinen Controls auf der Form. Um das zu verhindern gibt es zwei Lösungen Layouts oder this.Scale(new Size(<breite>, <höhe>);.
Die Frage zum Button das ist dann button1.Location = new Point(<x>,<y>);
Hallo fab84,
in der Main Methods kannst die übergabeparameter z.B. wie folgt auslesen.
In der MSDN Hilfe kannst das ebenso nochmals genauer nachlesen was genau da alles möglich ist.
Hier ein Beispiel:
[STAThread]
static void Main(string[] bla)
{
foreach (string dumdidum in bla)
MessageBox.Show(bla);
Application.Run();
}
Ok herbivore ist ein Tippmonster 😉
Hallo csharpstarter, erstelle eine Member Variable in der du dir merkst ob die Funktion schon einmal gestartet wurde.
private m_bCanUse = true
private void MeineFunktion()
{
this.m_bCanUse = false;
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (this.m_bCanUse) this.MeineFunktion();
base.OnKeyDown(e);
}
Allerdings gibts da noch ein paar Möglichkeiten das schöner zu gestallten.
/PS Da war wer schneller 😉
Vorweg, ich kenne mich mit Windows Presentation Forms (WPF)zwar noch nicht aus aber ich glaube damit sollte so etwas auch möglich sein.
Aber wenn dergleichen selber Programmieren möchtest unter .NET 2.0 dann überschreibst dafür die entsprechenden Client Non Border Areas in der WndProc (Stichwort Appearance). Dann werden Grafiken nicht wie üblich darüber gelegt/gezeichnet sondern in den entsprechenden display device context reingemalt. Was einen enormen stress bereitet, da man nicht gerade wenige Windows API Funktionen benötigt (magic number 174 🤔 ) die wiederum bei den verschiedenen Windowssystemen Probleme bereiten können (nutze ich coredll oder win32?). Außerdem sollte man nicht den Fehler begehen ein Control mit einen Skin zu erstellen, auf dem wiederum andere draufgeklatscht sind. Sondern das man wirklich jedes Control eigenständig behandelt und stattdessen auf ein Zentrales Layout geht (LookAndFeel) das man dann ändern kann (genial ist das dann zur Laufzeit).
Ich empfehle dir WPF mal anzusehen oder wenn alles nichts hilft, es gibt Anbieter die solche Skin Controls / Forms Techniken verkaufen. Im Forum gibt es für WPF extra eine neue Rubrik GUI: WPF und Silverlight.
Was ansonsten noch geht, tricksen, das Formular misshandeln indem man Grafiken drüberlegt, dran rumschnippelt es transparent macht oder drüberzeichnet. Hat nur den netten Nebeneffekt das man größtenteils alles selbst berechnen muss.
Aber vielleicht kennt jemand anderes noch bessere Lösungen.
Super vielen Dank, ich werd versuchen ob ich via Bit-Operation nur die relevanten Styles rausbekomme 🙂
Hier das Ergebniss:
[Flags]
public enum WindowStyles : uint
{
.....
WS_DIALOG = WS_DLGFRAME |DS_MODALFRAME | WS_POPUP
}
private bool EnumWindows(IntPtr hWnd, int lParam)
{
uint nProcessId = 0;
// search only thread owner dialogs
if (CWin32.GetWindowThreadProcessId(hWnd, out nProcessId) > 0 && CWin32.GetCurrentProcessId() == nProcessId)
{
int nStyle = CWin32.GetWindowLong(hWnd, (int)CWin32.WindowLong.GWL_STYLE);
CWin32.WindowStyles eWindowStyles = (CWin32.WindowStyles)nStyle;
eWindowStyles = eWindowStyles & CWin32.WindowStyles.WS_DIALOG;
if (eWindowStyles == CWin32.WindowStyles.WS_DIALOG)
return false;
}
return true;
}
Nicht schön aber selten 😜
Scheint auch wirklich ohne Probleme zu funktionieren - auch bei den CustomDialogs der Hauptanwendung.
Hallo Community,
ich suche eine bessere Lösung für das finden von Dialog Fenstern.
Hierzu habe ich folgende Ausgangssituation, ich schreibe derzeit eine TAPI Schnittstelle für ein Hauptprodukt, das TAPI PopUp Fenster läuft in einen separaten Thread und wird dort gehalten, so das die Hauptanwendung unabhängig des PopUp Fensters arbeitet. Durch verschiedene Aktionen wird vom PopUp Fenster das Hauptprogramms angesteuert und Daten werden übertragen oder MDI Fenster werden angezeigt. Mein Problem besteht nun darin das Absprünge auf das Hauptprogramm nur zulässig sein sollen, wenn ‚kein’ Dialog Fenster das PopUp Fenster oder Hauptprogramm blockiert. Modale Fenster dagegen sollen ignoriert werden.
Soweit so gut, bisher habe ich folgenden Ansatz dafür verwendet der zwar ohne Probleme Funktioniert aber alles andere als schön ist:
Ich gehe derzeit über die WIN32 API EnumWindows über alle aktiven Fensterhandels (Controls usw.) dannach hole ich mir über die WIn32 API GetWindowThreadProcessId die Prozess ID der Fensterhandels und vergleiche sie mit der eigenen Prozess ID. Wenn diese übereinstimmer suche ich über die WIN32 API Funktion GetWindowLong den Fensterstyle (GWL_STYLE) dannach vergleiche ich die Fensterstyles mit den für die Hauptanwendung typischen Fensterstyles für Dialoge.
Ich bin mit dem Ansatz nicht wirklich zufrieden, da Dialoge evtl. auch unterschiedliche Styles verwenden könnten. Gibt es irgendwie einen besseren Ansatz oder kann ich geziehlt nach einen Style suchen - statt nur die Bitweise verkettung der gesammten Styles die ich mit WindowLong.GWL_STYLE zurück bekomme?
private bool EnumWindows(IntPtr hWnd, int lParam)
{
uint nProcessId = 0;
// only process owner dialogs
if (CWin32.GetWindowThreadProcessId(hWnd, out nProcessId) > 0
&& CWin32.GetCurrentProcessId() == nProcessId)
{
int _nStyle = CWin32.GetWindowLong(hWnd, (int)CWin32.WindowLong.GWL_STYLE);
CWin32.WindowStyles eWindowStyles = (CWin32.WindowStyles)_nStyle;
if (((uint)eWindowStyles == 0x94C800CC) // dialog ex.
|| ((uint)eWindowStyles == 0x96cc20c4)) // normal dialog
return false; // abort
}
return true; // next handle
}
Danke für jeden Tipp 🙂
Hrm, du kannst die Abfrage von Melone verwenden, dann erstellst eine View [1] in der die Werte erstmal zwischen Speicherst. Dannach ließt den Row Count der View[2] aus, woraufhin wieder eine View [2] erstellst und beim Create den Row Count der View [1] verwendest um die Anzahl der Spalten in View [2] zu erstellen. Dannach fügst mit einen kleinen Stored Prozedure mit einer Schleife in die View[2] ein. Vergiss nicht ein declare auf eine Hilfsvariable zu erstellen. Diese gibt von 0 bis x an gezählt die spalte von View [2] wieder. Du kannst dir dann überlegen ob dann den gesammten Prozess in einer Stored Prozedure zusammenfasst und vergiss nicht die Views dannach wieder zu zerstören wenn sie nicht mehr brauchst.
[C# Code]
Mach einfach das select von Melone und halt sie dir im C# Code und schreibe dann eine View, Table oder wohin diese brauchst. Denke das ist einfacher als der reine SQL Ansatz.
/PS
Wer Tippfehler findet, darf sie behalten ;)
Hrm, ich würde das in etwa so gestallten.
Wie die DialogForm dann gestalltest (ContextMenu, Taskbar visible usw..) bleibt dir überlassen 🙂
/PS
Runterzählen des Warteintervalls dreh die Sache einfach für die Anzeige um.
Ich habe leider hochgezählt 1-2-3-4... statt 60-59-58... usw.
Mit der WIN32 API kommst auch wie folgt an die Cursor Possition. (Zwar hier nicht nötig aber vielleicht nicht schlecht zu wissen)
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Point lpPoint);
Dieser Artikel ist wirklich für jeden Einsteiger geeignet, prima Leistung 👍
[Flags]
public enum WindowsMessages
{
WM_SYSCOMMAND = 0x112
}
[Flags]
public enum SystemCommands
{
SC_MINIMIZE = 0xF020,
SC_MAXIMIZE = 0xF030,
SC_CLOSE = 0xF060,
SC_RESTORE = 0xF120,
}
// für das implementieren der windows api erforderlicher namespace
using System.Runtime.InteropServices;
[DllImport("User32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hwnd, int message, IntPtr wParam, IntPtr lParam);
// in funktion für den close button
SendMessage(this.Handle, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
// in funktion für den minimieren button
SendMessage(this.Handle, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MINIMIZE, IntPtr.Zero);
// schreibe ne abfrage ob der status des formulars gerade maximiert ist oder nicht um evtl einen restore auszulösen ( kannst ja dabei auch die grafik des buttons ändern
int nSc = (WindowState == FormWindowState.Maximized) ? (int)SystemCommands.SC_RESTORE : (int)SystemCommands.SC_MAXIMIZE;
SendMessage(this.Handle, (int)WindowsMessages.WM_SYSCOMMAND, (IntPtr)nSc, IntPtr.Zero);
Die Moving Funktionalität kommt gleich, ich bin grade bei Naruto schauen 😉
/PS
Wenn es aber komplett richtig machen möchtest, schau dir diesen Artikel an: KlickMich
Oki, wäre SetWindowLong gewesen.
Aber es geht doch einfacher.
Hier ein Code Project dazu http://www.codeproject.com/cs/miscctrl/taskbarnotifier.asp
Na ja, dachte dabei eher an die Popup Eigenschaft.
War nur etwas zu faul nachzusehen ob man diese bei SetWindowLong oder bei SetWindowPos setzen konnte.
Also, was natürlich sehr schick ist das ganze mit einen Windows Dienst zu koppeln.
Der dann einen andere Prozess (evtl. Parametrisiert / Datenbank / XML ) startet wenn die Bedingung erfüllt ist. Hat eben den Vorteil dass deine Anwendung was auch immer sie überwacht oder triggern soll, ständig dafür bereit steht.
Es gibt dafür sehr interessante Einstiegsartikel in diesem Forum.
/Ps
Wenn keinen Dienst dafür nutzen möchtest schau das ohne zu tricksen die Sache angehst. Dafür gibt es die Möglichkeiten mit CallBacks und Polling zu arbeiten.
Auch interessant ist ein solcher Vorgang (Q: Microsoft)
Gibt eine menge 'schöner' Ansätze dafür 🙂
using System;
using System.Threading;
// Eine Klasse, die verwendet wird, um Daten an DisplayMessage zu übergeben,
// wenn sie durch den Thread-Pool ausgeführt wird.
public class MessageInfo {
private int iterations;
private string message;
// Konstruktor, der die Konfigurationseinstellungen für den Thread übernimmt.
public MessageInfo(int iterations, string message) {
this.iterations = iterations;
this.message = message;
}
// Eigenschaften, um die Konfigurationseinstellungen zu ermitteln.
public int Iterations { get { return iterations; } }
public string Message { get { return message; } }
}
public class ThreadPoolExample {
// Eine Nachricht im Konsolenfenster ausgeben.
public static void DisplayMessage(object state) {
// Statusparamter in ein MessageInfo-Objekt casten.
MessageInfo config = state as MessageInfo;
// Falls der Konfigurationsparameter null ist, wurden der
// ThreadPool.QueueUserWorkItem-Methode keine Parameter übergeben;
// dann die Standardwerte verwenden.
if (config == null) {
// Eine vordefinierte Nachricht dreimal im Konsolenfenster ausgeben.
for (int count = 0; count < 3; count++) {
Console.WriteLine("Ein Thread-Pool-Beispiel.");
// Sleep nur für Demonstrationszwecke. Vermeiden Sie das Aussetzen des Threads
// mit Sleep in echten Anwendungen!
Thread.Sleep(1000);
}
} else {
// Die angegebene Nachricht entsprechend oft ausgeben.
for (int count = 0; count < config.Iterations; count++) {
Console.WriteLine(config.Message);
// Sleep nur für Demonstrationszwecke. Vermeiden Sie das Aussetzen des Threads
// mit Sleep in echten Anwendungen!
Thread.Sleep(1000);
}
}
}
public static void Main() {
// Erstellen einer Delegaten-Instanz, um zu erlauben, die DisplayMessage-Methode
// dem Thread-Pool zwecks Ausführung hinzuzufügen.
WaitCallback workMethod =
new WaitCallback(ThreadPoolExample.DisplayMessage);
// Ausführen von DisplayMessage unter Verwendung des Thread-Pools und ohne Paramerter.
ThreadPool.QueueUserWorkItem(workMethod);
// DisplayMessage unter Verwendung des Thread-Pools und mit der Möglichkeit
// zur Übergabe eines MessageInfo-Objektes, das DisplayMessage übergeben wird, ausführen.
MessageInfo info =
new MessageInfo(5, "Ein Thread-Pool-Beispiel mit Parametern.");
ThreadPool.QueueUserWorkItem(workMethod, info);
// Auf weitere Ausführung warten.
Console.WriteLine("Hauptmethode beendet. Drücken Sie Return zum Beenden.");
Console.ReadLine();
}
}
Also über SetWindowLong / SetWindowPos der Win32 API (www.pinvoke.net) gibt es eine Möglichkeit das ganze zu lösen.
Aber vielleicht kennt jemand einen leichteren Weg 🤔
Hallo Andreas,
denk dran Windows Themes zu verhindern, der Code dazu steht etwas weiter oben 🙂
Hrm, schau dir einfach für den vorgang mal Design Pattern an.
Im Link habe ich ein kleines Beispiel dafür drinnen, bzw. von Dragon geklaut 😉
Also, du kannst dort auch mit System.windows.Forms arbeiten. Aber lass die Finger davon. Trenne immer sauber Basisklassen von Nebenklassen und Hauptklassen.
Wenn du in einer Nebenklasse nun den Text der TextBox benötigst, so kannst du diesen Wert über den Konstruktor, über eine Methode oder über ein Propertie der Nebenklasse übergeben.
Nur erklär bitte genauer was du vorhast, denn es gibt viele Möglichkeiten etwas komfortabler zu gestallten.
Hrm, habe mich mit den Settings noch nicht beschäftigt aber denke das er sich die minimierte Position merkt und dann versucht an 0;0 das Formular mit Größe usw. 0;0 hin zu zeichnen. Wirst es denke ich daher nicht angezeigt bekommen. Frage einfach beim Save vorher mal das WindowState ab ob das Formular Minimiert ist und Speichere dann die Settings nicht weg.
Wenn dann das Formular erscheint kannst du dir ja überlegen wie du ab dann vorgehen möchtest.
Hrm, wäre nicht schlecht wenn noch ca. erklärst wie das ganze intern abläuft.
Hier mal ein paar Bilder dazu.
Hier erkennt man das es sich um keinen typischen WindowsBorder handelt und auch die Breite nicht dem eines WindowsBorder entspricht.
Und hier das gleiche als Überblick:
Das einzige was man dazu ergänzen muss, passt gut auf bei MDI Childs dort muss man etwas verändern bei PointToScreen.
Was in deinem Code noch fehlt, ist das verhinden von Windows Themes welches man mit folgenden Codeschnipsel verhindert.
[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int SetWindowTheme(IntPtr hwnd, String pszSubAppName,
String pszSubIdList);
Einfach beim entsprechenden Formular die OnHandleCreated Methode überschreiben bzw. ergänzen um die Windows Themes zu verhinden.
protected override void OnHandleCreated(EventArgs e)
{
SetWindowTheme(this.Handle, "", "");
base.OnHandleCreated(e);
}