Laden...

Fenster wird gerade verschoben.

Erstellt von userid14268 vor 13 Jahren Letzter Beitrag vor 13 Jahren 3.855 Views
U
userid14268 Themenstarter:in
1.578 Beiträge seit 2009
vor 13 Jahren
Fenster wird gerade verschoben.

Hi,

Es geht darum, ich habe ein PleaseWait Fenster welches der User verschieben kann.
Dieses Fenster wird vom Code heraus aufgerufen und auch wieder geschlossen (versteckt). Der User kann das Fenster selber nicht schließen.

Nun kann es aber Passieren das das Fenster versteckt wird während der User es verschiebt, sobald das Passierte und das Fenster wieder angezeigt wird, kann es nicht mehr verschoben werden.

Gibt es irgendwie eine Möglichkeit zu ermitteln ob ein Fenster gerade verschoben wird?

LG
CSL

L
862 Beiträge seit 2006
vor 13 Jahren

Eine Möglichkeit gibt es bestimmt. Allerdings muss man zuerst einmal definieren wann denn ein Fesnter 'verschoben' wird. Wird es verschoben wenn der Window-Header den Mauscapture hat? Ich denke mal nicht unbedingt da dieser ja auch gedrückt sein kann wenn der Benutzer einen Doppel-Klick darauf macht um es zu maximieren (auch wenn das nicht geht).
Vielleicht solltest du die Left und Top-Eigenschaft des Windows überwachen. Wenn sich diese Werte ändern dann hat sich das Fenster verschoben.
Nun stellt sich die Frage wann die Verschiebe-Aktion aufhört? Hier könnte man sagen nachdem der Benutzer die Maustaste losgelassen hat. Ein anderer Ansatz wäre es nach einer Verschiebeaktion eine gewisse Zeit zu warten und nach z.B. 1 Sekunde die Verschiebung als abgeschlossen zu betrachten.

Ein Standard-Flag 'IsWindowMoving' gibt es leider nicht. Du wirst dir wohl aus meinen Ideen oben selbst was basteln müssen.

S
489 Beiträge seit 2007
vor 13 Jahren

Warum hidest Du das Fenster nur? Da einfachste ist sicherlich immer wieder ein neues zu erstellen.

Ich habe es nicht noch mal ausprobiert, aber so weit ich weiß feuert das Event SizeChanged beim Verschieben. Oder Du baust Dir was über die MouseDown, MouseMove und MouseUp Events zusammen.

151 Beiträge seit 2009
vor 13 Jahren

Hallo CSL,

generell gibt es diese Möglichkeit schon, das hängt dann aber auch mit der Implementation zusammen.
Ich hatte einmal ein Boolean eingebaut, um zu erkenn ob ein Dragging stattfindet oder nicht. Was anderes hab ich diesbezüglich bisher nicht unternommen.

Grüßle
Jéré

Edit: das ähnelt wohl eher SeboStones zweitem Vorschlag 😃

U
userid14268 Themenstarter:in
1.578 Beiträge seit 2009
vor 13 Jahren

>> MouseDown[Up][Move]
Das Fenster hat aber eine Titlelleiste, dort wird das [Preview]MouseDown etc. nicht gesendet, das kommt nur wenn man in den Client bereich ist.

>> SizeChanged
Und was bringt mir ein SizeChanged? Das wird abgesetzt wenn es gerade verschoben wurde, man weiß dadurch nicht ob es noch beim verschieben ist, ein SizeChanging gibt es ja nicht.

private _isDragging;
private OnSizeChanged()
{
    _isDragging = true; // or false?
    // when _isDragging can set to false or true?
}

>>Warum hidest Du das Fenster nur?

  1. Erhaltung der Letzten Position und Größe,
  2. Beim erstellen des Fensters muss einiges gemacht werden, sei es TextBoxen, ProgressBars, [De]Abonnieren diverser Events bis hin zum erstellen eines DispatcherTimers.
    Manche Aktionen können von 0.5 sek bis 5 Tage andauern, d.h. es kann problemlos dazu kommen das das Fenster mindestens 10x pro Sekunde zerstört und wieder erstellt werden muss.

Darum gibt es nur ein PleaseWait Fenster über die gesamte Programmlaufzeit.

L
862 Beiträge seit 2006
vor 13 Jahren

Evtl. kannst du per WinAPI irgendwie mitkriegen wenn der Benutzer mit der Maus auf die Titel-Leiste drückt. Das ist zwar kein sauberer Weg (ich würds auch nicht machen) aber die einzige Möglichkeit das mitzubekommen (ausser du programmierst deinen eigenen WindowHeader).

Ich denke die einfachste/schnellste Methode ist wenn du einfach beim Top/Left-Changed davon ausgehst jetzt bewegt sich das Fenster und eine kurze Zeitspanne danach den Status wieder auf NotMoving setzt.

L
416 Beiträge seit 2008
vor 13 Jahren

Wäre es nicht vielleicht einfacher herauszufinden warum das Fenster wenn es beim Verschieben versteckt wird dannach nicht mehr verschoben werden kann. Oder hast du da schon sehr viel Zeit investiert ohne Erfolg?

U
userid14268 Themenstarter:in
1.578 Beiträge seit 2009
vor 13 Jahren

Wäre es nicht vielleicht einfacher herauszufinden warum das Fenster wenn es beim Verschieben versteckt wird dannach nicht mehr verschoben werden kann. Oder hast du da schon sehr viel Zeit investiert ohne Erfolg?

Bisher habe ich da nur sehr wenig Zeit investiert, bisher leben wir einfach damit.
> Ich habe kein Ansatz wie ich das Debuggen könnte, das ist ein ganz normales Windows ohne eine Modifikation.

Eine Idee?

S
489 Beiträge seit 2007
vor 13 Jahren

Debuggen kannste vergessen, meiner Meinung nach. Aber Du kannst mit Snoop schauen was für Properties sich in den Controls des Fensters "abnormal" geändert haben, vielleicht hilft das schon weiter.

5.742 Beiträge seit 2007
vor 13 Jahren

Hallo CSL,

ich würde mal einen Connect Eintrag aufsetzen, wenn sich das tatsächlich reproduzieren lässt. Das hilft zwar nur langfristig, aber trotzdem.

Ansonsten wirst du wohl als Workaround mit ein paar WindowsMessages herumspielen müssen...
Vielleicht kann man sogar durch gezieltes Senden von bestimmten Messages das Fenster wieder bewegbar machen.

U
userid14268 Themenstarter:in
1.578 Beiträge seit 2009
vor 13 Jahren

Ich konnte das Problem reproduzieren und habe für euch eine kleine Demo Applikation:

http://downloads.my-libraries.de/MovingFailDemo.zip

Sobald die Applikation Startet wird ein Fenster für 3 Sekunden angezeigt, dann zerstört und das Hauptfenster erscheint.

Wenn man das Fenster verschiebt während es zerstört wird, ist das Hauptfenster dann nicht mehr benutzbar. Bei mir geht es sogar soweit das ich die Windows Startleiste und VS nicht mehr anklicken kann.

  • Applikation Starten
  • Das Kleine Fenster so lange verschieben bis es verschwindet
  • Versuchen das Hauptfenster zu bedienen.

Der Code besteht nur aus zwei einfachen Fenstern ohne Besonderheit, und die Startprozedur ich folgende:

public partial class App : Application
{
	private DispatcherTimer _waitTimer;
	private DemoWindow _window;

	public App()
	{
		ShutdownMode = ShutdownMode.OnExplicitShutdown;

		_waitTimer = new DispatcherTimer();
		_waitTimer.Interval = TimeSpan.FromSeconds(3);
		_waitTimer.Tick += new EventHandler(Timer_Tick);
	}

	protected override void OnStartup(StartupEventArgs e)
	{
		_window = new DemoWindow();
		_waitTimer.Start();
		_window.ShowDialog();
		base.OnStartup(e);
	}

	private void Timer_Tick(object sender, EventArgs e)
	{
		_waitTimer.Stop();
		_window.Close();
		new MainWindow().ShowDialog();
		Shutdown();
	}
}

Jemand eine Idee?

U
userid14268 Themenstarter:in
1.578 Beiträge seit 2009
vor 13 Jahren

Habs.

Das ist ein Problem des Message Loops, Hide und ShowDialog(); werden im EventHandler aufgerufen, und das Fenster kann erst korrekt zerstört werden bis alle Messages abgearbeitet sind, also erst sobald ShowDialog fertig ist, ist der EventHandler am ende.

Lösung:

public partial class App : Application
{
    private DispatcherTimer _waitTimer;
    private DemoWindow _window;

    public App()
    {
        ShutdownMode = ShutdownMode.OnExplicitShutdown;

        _waitTimer = new DispatcherTimer();
        _waitTimer.Interval = TimeSpan.FromSeconds(3);
        _waitTimer.Tick += new EventHandler(Timer_Tick);
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        _window = new DemoWindow();
        _waitTimer.Start();
        _window.ShowDialog();
        base.OnStartup(e);
    }

    private void Timer_Tick(object sender, EventArgs e)
    {
        _waitTimer.Stop();
        _window.Close();
        Dispatcher.BeginInvoke(new Action(delegate
        {
            new MainWindow().ShowDialog();
            Shutdown();
        }));
    }
}

//Tag vergessen