Position eines Forms wird nach OnShown-Event zurückgesetzt

Fabsch

Erfahrenes Mitglied
Hallo,

nachdem ich nun seit über einer Stunde hier im Forum und auch vorher bei Google danach gesucht habe, poste ich das hier mal ;)

Also: Ich habe ein Form, das im OnLoad-Event an der rechten Seite des Bildschirms Platz reserviert.
Aber das geht ja, nur ein anderes Problem: Ich setze die Position des Forms, nachdem ich den Platz reserviert habe, (auch im OnLoad-Event) dahin, wo eben der reservierte Platz ist.
Und wenn ich das Projekt jetzt erstelle und ausführe, wird der Platz rechts reserviert, die Position des Forms gesetzt und beim Anzeigen wird die Position zurückgesetzt, also bei Manual auf 0, 0.
Hab deswegen die Position im OnShown-Event erst gesetzt, aber das gleiche.
Dann habe ich noch im OnShown-Event nach dem setzen der Position ein Thread.Sleep(800) reingemacht..
So bleibt das Form für 800ms an der richtigen Position, und wenn er dann weiterkommt, ist das Form wieder an Position 0, 0 :suspekt:
StartPosition des Forms ist Manual.

Und hier der Code:
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;

namespace Test
{
    /// <sumary>
    /// Beinhaltet Information über die Application Bar.
    /// Eine ausführliche Beschreibung finden Sie in MSDN APPBARDATA Dokumentation.
    /// </sumary> 
    [StructLayout(LayoutKind.Sequential)]
    public struct APPBARDATA
    {
        public uint cbSize;
        public IntPtr hWnd;
        public uint uCallbackMessage;
        public uint uEdge;
        public RECT rc;
        public int lParam;
    }
    /// <sumary>
    /// Speichert Größe und Position der AppBAr.
    /// </sumary>
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    public partial class Form2 : Form
    {
        const int ABM_NEW = 0x00000000;
        const int ABM_REMOVE = 0x00000001;
        const int ABM_SETPOS = 0x00000003;
        const int ABM_QUERYPOS = 0x00000002;

        const int ABE_LEFT = 0x00000000;
        const int ABE_TOP = 0x00000001;
        const int ABE_RIGHT = 0x00000002;
        const int ABE_BOTTOM = 0x00000003;

        [DllImport("shell32.dll")]
        static extern IntPtr SHAppBarMessage(uint dwMessage,
           ref APPBARDATA pData);
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern uint RegisterWindowMessage(string lpString);

        APPBARDATA abd;

        public Form2()
        {
            InitializeComponent();
            //FormBorderStyle = FormBorderStyle.None;
        }
        
        
        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        
        private void Form2_Shown(object sender, EventArgs e)
        {
            //this.Location = new Point(abd.rc.left, abd.rc.top);
            //Thread.Sleep(800);
        }

        
        private void Form2_Load(object sender, EventArgs e)
        {
            abd = new APPBARDATA();
            abd.cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA));
            abd.hWnd = this.Handle;
            abd.uCallbackMessage = RegisterWindowMessage(Guid.NewGuid().ToString());

            // AppBar beim System registrieren.
            SHAppBarMessage(ABM_NEW, ref abd);

            // Größe und Position festlegen
            abd.rc = new RECT();

            abd.uEdge = ABE_RIGHT;
            abd.rc.top = 0;
            abd.rc.left = Screen.PrimaryScreen.WorkingArea.Width - this.Width;
            abd.rc.bottom = this.Height;
            abd.rc.right = this.Width;

            // Die Gröse und Position der AppBar prüfen.
            // Wenn diese nicht gültig sind, werden die 
            // korrigierte Werte zurückgegeben.
            SHAppBarMessage(ABM_QUERYPOS, ref abd);
            // Größe und Position der AppBarsetzen
            SHAppBarMessage(ABM_SETPOS, ref abd);
            // Größe und Position des Anwendungsfenster im AppBar-Bereich positionieren
            this.Location = new Point(abd.rc.left, abd.rc.top);


            this.Size = new Size(abd.rc.right, abd.rc.bottom);
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            APPBARDATA abd = new APPBARDATA();
            abd.cbSize = (uint)Marshal.SizeOf(typeof(APPBARDATA));
            abd.hWnd = this.Handle;

            SHAppBarMessage(ABM_REMOVE, ref abd);
        }
    }
}

MfG
Fabsch
 
Hi,

ist nur ein fixer Workaround und keine richtig Lösung: Hast du mal versucht, statt eine Handler-Methode für das normale Shown-Event die "OnShown"-Methode des Forms zu überschreiben? Wenn du nur das Event behandelst, werden durch das Event ja noch andere Methoden ausgelöst...

C#:
protected void OnShown(EventArgs e)
{
    base.OnShown(e); // WICHTIG!
    // Hier die Position setzen.
}

Geht aber sicher auch eleganter, wenn man die Ursache für diesen Effekt kennt. ;)

Grüße, D.
 
Hallo,
ich hatte das vorher so gehabt und jetzt eben so probiert, weil es durch das Überschreiben der Methoden eben nicht ging ;)

MfG
Fabsch
 
Hallo,

die Eigenschaft StartPosition wird in der Methode InitializeComponent auf Manual gesetzt, das ist ja im Konstruktor.
Edit: Ok dann mach ich das ganze, was im OnLoad-Event steht in den Konstruktor, ich editiere später dann meinen Beitrag nochmal!
Edit2: Jetzt steht der gesamte Code zum Platz reservieren im Konstruktor, aber gleiches Problem immer noch.

MfG
Fabsch
 
Zuletzt bearbeitet:
Hi

Wie mir scheint muss du die Position in diesem Fall ebenfalls über die WindowsAPI setzen.
Da ich nicht mehr weiß, wo ich es her hab, häng ich das Projekt mit dem Beispiel mal an.
 

Anhänge

Hallo,

hab die Position nun auch über die WinAPI gesetzt (im Konstruktor) nur wird die Position wieder auf 0, 0 zurückgesetzt.

Wenn ich aber einen Timer benutze, den ich in der OnShown-Methode starte und der nach 10ms tickt und die Position setzt, mache, dann bleibt das Form auf der richtigen Stelle.
Nur ist das mit einem Timer nicht so gut.

MfG
Fabsch
 
Zuletzt bearbeitet:
Zurück