Autor Beitrag
Sh4dY-
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 22.10.11 10:54 
Hallo Leute,

ich bin ziemlich neu bei C# und habe jetzt ein kleines Problem: Ich will in einer Win-Forms-Anwendung eine kleine
Benutzeroberfläche erstellen. Das klappt soweit auch ganz gut, nur mit der "aktualisierung" meines Programms habe ich noch Probleme.
Und zwar benutze ich einmal
protected override void OnMouseMove(MouseEventArgs e)
an dessen Ende ich Invalidate() benutze, weil dort bestimmte sachen ausgerechnet werden müssen.
Und ich benutze einen Timer, an dessen Ende auch Invalidate() benutzt wird.

Problem: Wenn ich jetzt meinen Timer starte und gleichzeitig die Maus bewege, dann werden zwar die Aktionen in "OnMouseMove"
ausgeführt, aber nicht die Aktionen meines Timers. Wenn ich jetzt das Invalidate() aus OnMouseMove lösche, dann funktioniert
der Timer wunderbar.
Ich habe es inzwischen auch geschafft eine Lösung für mein Problem zu finden: Ich lösche das Invalidate() aus meinem Timer
und aus OnMouseMove und erstelle einen neuen Timer der mit einem Intervall, von zB 15, Invalidate() aufruft. Dadurch funktioniert
das ganze zwar, aber es geht doch bestimmt schöner??

Ich hoffe ihr versteht mein Problem und könnt mir helfen...
lg Sh4dY-
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4809
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 22.10.11 11:16 
Hallo und :welcome:

bitte zeige mal deinen (relevanten) Code für die genannten Methoden.
Eigentlich sollte der Code einwandfrei auch ohne den zusätzlichen Timer funktionieren.
Welches Intervall hat denn deine erste Timer-Methode?
Und benutzt du in OnMouseMove() auch den Aufruf der Basisklassenmethode?
Sh4dY- Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Sa 22.10.11 11:32 
Die Klasse MainForm abgeleitet von Form:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
    public class MainForm : Form
    {
        private static MainForm     main;
        private        TabManager   tabMng;

        public static MainForm      MainF      { get { return main; } }

        public MainForm()
        {
            Text = "Browser";
            FormBorderStyle = FormBorderStyle.FixedSingle;
            WindowState = FormWindowState.Maximized;
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);

            Paint += new PaintEventHandler(OnPaint);

            main = this;
            tabMng = new TabManager(5, 50, 250, 700);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            tabMng.MouseDown(e);
            Invalidate();
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            tabMng.MouseMove(e);
            Invalidate();
        }

        private void OnPaint(Object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            tabMng.Draw(g);
        }

        [STAThread]
        private static void Main()
        {
            Application.Run(new MainForm());
        }
    }


und die Klasse TabManager (hier wird der Timer ausgeführt):
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
    public class TabManager
    {
        private Timer selectionTimer;

        public Timer SelectionTimer  { get { return selectionTimer; } }

        public TabManager(int x, int y, int w, int h)
        {
            ...
            selectionTimer = new Timer();
            selectionTimer.Interval = 15;
            selectionTimer.Tick += new EventHandler(OnRunSelectionTimer);
        }

        private void OnRunSelectionTimer(object sender, EventArgs e)
        {
            ... Berechnungen
            MainForm.MainF.Invalidate();
        }

        public void SelectTab(Tab t)
        {
            ...
            selectionTimer.Start();
        }

        public void MouseDown(MouseEventArgs e)
        {
            ... Berechnungen
        }

        public void MouseMove(MouseEventArgs e)
        {
            ... Berechnungen
        }

        public void Draw(Graphics g)
        {
            ... Zeichnen von Rectangles und Images
        }
    }


Moderiert von user profile iconChristian S.: Code- durch C#-Tags ersetzt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4809
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 22.10.11 12:07 
Hallo,

einen konkreten Fehler kann ich hier nicht entdecken, jedoch könntest du noch einige Verbesserungen an deinem Programm vornehmen:
- anstatt der "static MainForm" verwende besser in TabManager eine Referenz (bzw. verwende ein Ereignis, so daß du gar nicht vom TabManager auf die MainForm direkt zugreifen mußt)
- wie schon oben geschrieben, in OnMouseDown/Move etc. die Basisklassenmethode aufrufen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
protected override void OnMouseDown(MouseEventArgs e)
{
  base.OnMouseDown(e);
  // ...
}

- Invalidate() auch nur dann aufrufen, wenn es wirklich eine Änderung gibt, evtl. sogar über Invalidate(Rectangle) den Bereich einschränken (damit nicht immer alles neu gezeichnet werden muß)
- evtl. das Timer-Intervall erhöhen (denn 15ms sind ja eine FPS von 1000/15 = 66,7) - so schnell kann ein User die Änderungen sowieso nicht nachvollziehen (ok, bei meinem Spiel FastDriver habe ich eine so hohe Aktualisierungsrate, aber da kommt es auch auf Geschwindigkeit an ;-)

Und wie viele Objekte zeichnest du denn in deiner Draw-Methode?

Du kannst dir auch mal meinen Artikel Kommunikation von 2 Forms durchlesen.
Sh4dY- Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 24.10.11 13:41 
Okay also das hat nicht geholfen... ich will vielleicht mein Problem nochmal verdeutlichen:

- Ich benutze einmal einen Timer, der an einem bestimmten Zeitpunkt gestartet wird und dann immer wieder Invalidate() aufruft.
- Ich benutze OnMouseMove, wo auch Invalidate() aufgerufen wird.
- Wenn ich jetzt meinen Code teste dann klappt zunächst alles wunderbar. Wenn jetzt der Timer startet und ich gleichzeitig die Maus bewege (also OnMouseMove wird aufgerufen) dann werden die Aktionen im Timer nichtmehr aufgerufen, d.h. OnMouseMove funktioniert zwar noch, aber mein Timer wird einfach "pausiert", also es passiert nichts mehr. Wenn ich die Maus nicht bewege dann läuft der Timer wunderbar.
=> Anscheinend hab ich hier irgendeine überschneidung vom Invalidate() aus OnMouseMove und aus meinem Timer. Wenn ich nämlich zB das Invalidate aus OnMouseMove und aus meinem Timer lösche und stattdessen einen zweiten Timer erstelle (dieser läuft von Anfang an bis zum Ende) und dort Invalidate() aufrufe, dann funktioniert es perfekt. Das ist jetzt natürlich eine ziemlich "hässliche" Lösung....
Hat jemand ne Idee?

lg Sh4dY-
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4809
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mo 24.10.11 16:34 
Hallo,

du hast meine Frage nach der Anzahl der gezeichneten Objekte noch nicht beantwortet.

Evtl. kannst du ja mal dein Projekt hier als Anhang (ZIP) hochladen...
Sh4dY- Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 24.10.11 17:20 
Oh das hab ich glatt übersehen, also es werden ca. 20-30 Linien, Images und Rectangles gezeichnet. Aber das sollte doch kein Problem sein...?

Hab die Datei unten angehängt, ich arbeite mit Visual Studio, aber man sollte es auch so öffnen können. Hoffentlich kannst du, oder sonst jemand, mir weiterhelfen... wäre echt cool :)

Wichtig sollte eigentlich nur MainForm und ein Teil von TabManager sein...
Einloggen, um Attachments anzusehen!
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4809
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Di 25.10.11 18:04 
Hallo,

ich habe mir mal dein Projekt angeschaut (auch wenn ich zuerst die Bilder faken mußte).

Also ich habe bei mir unter Win XP keine Probleme mit dem Timer im TabManager, sobald ich dort ein Invalidate() noch ausführe (den anderen Timer im MainForm habe ich komplett rausgenommen).

Auch die Maus kann ich dann bewegen, ohne irgendwelche Probleme (der entsprechende Tab-Button wird dann auch bei Überfahren korrekt aktiviert angezeigt).

Einzig wie schon geschrieben, sollte man am besten jedoch nicht immer Invalidate() aufrufen, sondern am besten mittels eines Rechtecks auf den tatsächlich geänderten Bereich einschränken.