Windows.Forms - Problem z oknem bez ramki

0

Witam,
mam następujący problem. Stworzyłem na potrzeby aplikacji taki mini-framework gui. Okna mają swoje własne wyglądy, przyciski zamknij, minimalizuj itp. W związku z tym wszystkie okna mają ustawione
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
Jest jedno główne okno, na którym jest panel CenterPanel z ustawionym tłem:
this.CenterPanel.BackgroundImage = Styl.Obraz("CenterPanel");
Pozostałe okna aplikacji mają zaimplementowaną własną obsługę przesuwania i zmiany rozmiaru (ponieważ nie mają standardowej ramki). Na przykład obsługa przesuwania okna odbywa się na zasadzie, że obsługujemy zdarzenie przesuwania myszki na górnym panelem takiego okna (pełniącym rolę własnej "belki" z przyciskami i tytułem okna) z jednoczesnym naciśnięciem przycisku lewego myszy nad nim, czyli mniej więcej tak:

        /// <summary>
        /// Zdarzenie naciśnięcia przycisku myszy na górnym panelu okna (pasku)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void TopPanel_MouseDown(object sender, MouseEventArgs e)
        {
            this.Focus();

            if (e.Button == MouseButtons.Left)
            {
                this.Przesun = true;
                this.PrzesunPunkt = new Point(e.X, e.Y);
            }
        }


        /// <summary>
        /// Zdarzenie puszczenia wciśniętego przycisku myszy na górnym panelu okna (pasku)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void TopPanel_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Przesun = false;
            }
        }


        /// <summary>
        /// Zdarzenie zmiany położenia kursora myszy na górnym panelu okna (pasku)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void TopPanel_MouseMove(object sender, MouseEventArgs e)
        {
            this.Focus();
            try
            {
                if (this.Przesun && this.WindowState == FormWindowState.Normal && e.Button == MouseButtons.Left)
                {
                    MainWindow oknoGlowne = this.Owner as MainWindow;   // Referencja do okna głównego
                    Point aktualne = PointToScreen(e.Location);         // Aktualna pozycja kursora myszy

                    // Określamy wstępne, nowe położenie okna
                    Int32 X, Y;
                    X = aktualne.X - this.PrzesunPunkt.X;
                    Y = aktualne.Y - this.PrzesunPunkt.Y;

                    // W poniższych warunkach sprawdzamy, czy wystąpiło zetknięcie przesuwanego okna
                    // z krawędzią panelu głównego (centralnego) okna głównego,
                    // uwzględniając mechanizm przyciągania do krawędzi

                    // Krawędź lewa
                    if (X <= oknoGlowne.ObszarRoboczy.Left + WindowController.SnapToEdgeDistance)
                        X = oknoGlowne.ObszarRoboczy.Left;

                    // Krawędź górna
                    if (Y <= oknoGlowne.ObszarRoboczy.Top + WindowController.SnapToEdgeDistance)
                        Y = oknoGlowne.ObszarRoboczy.Top;

                    // Krawędź prawa
                    if (X + this.Width >= oknoGlowne.ObszarRoboczy.Right - WindowController.SnapToEdgeDistance)
                        X = oknoGlowne.ObszarRoboczy.Right - this.Width;

                    // Krawędź dolna
                    if (Y + this.Height >= oknoGlowne.ObszarRoboczy.Bottom - WindowController.SnapToEdgeDistance)
                        Y = oknoGlowne.ObszarRoboczy.Bottom - this.Height;

                    // Zmieniamy położenie okna
                    this.Location = new Point(X, Y);
                }
            }
            catch { }
        }

No i teraz problem. Gdy przesuwamy takie okno nad oknem głównym (zawierającym ten panel z tłem jpg), panel ten (okna głównego) się nie odświeża za dobrze, to znaczy w miejscach, w których znajdowało się okno przesuwane, pozostają prostokąty jednolite (w kolorze okna głównego) i wygląda to bardzo nieładnie. Natomiast, gdy przesuwane okno uczynimy standarowym z ramką (np. FormBorderStyle.FixedSingle) i zaczniemy je przesuwać na głównym oknem "ciągnąc" za standardową belkę, główne okna odświeża się prawidłowo.

Czy ktoś ma pojęcie, co może być przyczyną. Przypuszczam, że domyślny mechanizm przesuwanie okien może wysyłać jakiś komunikat do okna głównego (może do wszystkich innych okien w systemie), ale w sumie analizowałem wysyłane komunikaty w obu przypadkach przeładowując metodę WndProc okna głównego i wszystko jest raczej tak samo.

Będę wdzięczny za pomoc, bo walczę z tym od tygodnia... Z góry dzięki za odpowiedzi.

0

hmm.. brzmi troche jak nieodpalany repaint nonclient.. ale musialbym na to zerknac i sprawdzic na Twoim kodzie.. teraz nie mam czasu niestety:/

zaraz.. ktore okno Ci sie nie odrysowuje? to ktore przesuwasz zy to ktore lezy pod nim? to glupoty gadam.. panel lezy w obszarze klienckim, wiec nie wiem czemu mialby sie nie odrysowac.. jezeli okno-z-ponad przesuwasz, to okno ponizej dostalo Invalidate okrytego regionu, prawda? sprawdz to

0

nie odrysowuje się to które leży pod spodem (a konkretnie jego panel CenterPanel z ustawionym tłem JPG). Ponadto, jeśli ustawie dla tego panelu zwykłe, jednolite tło zamiast JPG, to wszystko jest ok, nie ma tego "migotania". Myślałem dlatego, że to problem powiedzmy wydajnościowy, że program nie nadąża w takim tempie odrysować sporego JPG-a (60kB), ale potem ustawiłem dla tych okienek przesuwanych standardowe FormBorderStyle i przesuwając za standardową belkę okna nie ma tego problemu, więc doszedłem do wniosku że nie tu leży problem. Dzięki za odpowiedź, spróbuje coś pokombinować wg Twojej sugestii.

0

invalidate(Rectangle) + update() wykonane na centralnym panelu okna głównego po każdej zmianie położenia okna, które przesuwamy pomogło!!!

nie jest jeszcze idealnie, zostaje zawsze jeden nieodrysowany, ostatni prostokąt (wcześniej zostawały wszystkie z każdego poprzedniego położenia przesuwanego okna), ale jest nieporównywalnie lepiej. Będę jeszcze kombinował dalej, ale dziękuję bardzo!

0

no to swietnie, zawsze to lepsze niz nic.
jest tylko drobny problem, ze jakkolwiek pamiec mi szwankuje i platformy mieszaja, to jestem pewien, ze jak okno przesuwasz, to system operacyjny do widocznych okien pod spodem powinien byl niezzwlocznie invalidate wyslac (a nie Ty recznie!), albo odtworzyc ich zawartosc z no wlasnie, czego.. doublebuffer moze. nie mniej, dziwne. moglbys rzucic jakims mikrosamplem ktory by to obrazowal?

0

mikro samplem kodu czy mikro samplem exe? :) tak czy inaczej wyśle ci na mejla jeśli chcesz, tylko powiedz co...

0

wklej kod na pastebina, po co mam reflectora wlaczac:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1