Почему панель управления заставки не убивает мою форму, когда она умирает?

Используя код, который я нашел на CodeProject, я создал заставку. Следующая форма — это крошечная форма, которую я показываю в Панели управления, когда пользователь выбирает мою заставку.

Кажется, все работает нормально; форма правильно изменяет размеры и рисуется (пустая) в нужном месте панели управления, перемещается вместе с CP и т. д. Но когда панель управления закрывается (или заменяет мою форму мини-предварительным просмотром другой заставки), мое приложение не умри. Просто врезается в память.

Моя форма не получает сообщений о закрытии/закрытии формы, изменениях видимости и т. д. Я неправильно устанавливаю родительские права здесь?

Вот соответствующий код. Все импортированные вызовы WinAPI возвращают ожидаемые значения, а GetLastError всегда возвращает ноль, так что думаю проблема не в этом...

    private void miniControlPanelForm_Load(object sender, EventArgs e)
    {

        // note that iphWnd is a class variable, passed to us by windows

        // set our window style to WS_CHILD, so that our window is
        // destroyed when parent window is destroyed.

        // get the current window style, but with WS_CHILD set
        IntPtr ip = new IntPtr();
        int index = (int)NativeMethods.WindowLongFlags.GWL_STYLE | 0x40000000;   
        ip = NativeMethods.GetWindowLongPtr(this.Handle, index);
        int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

        // set that value as our current Style
        object ohRef = new object();
        HandleRef hRef = new HandleRef(ohRef, this.Handle);
        IntPtr ip2 = new IntPtr();
        int index2 = (int)NativeMethods.WindowLongFlags.GWL_STYLE;
        ip2 = NativeMethods.SetWindowLongPtr(hRef, index2, ip);
        error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

        // set the passed preview window as the parent of this window
        IntPtr newOldParent = NativeMethods.SetParent(this.Handle, iphWnd);
        error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

        //set our window's size to the size of our window's new parent
        Rectangle ParentRect = new Rectangle();
        NativeMethods.GetClientRect(iphWnd, ref ParentRect);
        this.Size = ParentRect.Size;

        //set our location at (0, 0)
        this.Location = new Point(0, 0);
    }

У меня есть Application.Exit в различных обработчиках событий «форма закрывается», но они никогда не вызываются...


person Cardinal Fang    schedule 25.08.2014    source источник
comment
Связанный (хотя и не очень полезный): заголовок stackoverflow.com/questions/21967757/   -  person Blorgbeard    schedule 25.08.2014
comment
Связано (и на самом деле очень полезно): stackoverflow.com/questions/12203577/   -  person Blorgbeard    schedule 25.08.2014


Ответы (1)


Все эти проблемы исчезнут, если вы правильно сделаете форму дочерней по отношению к окну панели управления. Вот как я это делаю сейчас, и это работает во всех случаях.

В форме добавьте это, что заставит стиль окна формы WS_CHILD во время создания:

    /// <summary>
    /// Override CreateParams property so we can add "WS_CHILD" to
    /// the Style each time it is queried during window creation.
    /// </summary>
    protected override CreateParams CreateParams
    {
        get
        {
            // get the base params and modify them
            CreateParams cp = base.CreateParams;
            cp.Style |= NativeMethods.WindowStyles.WS_CHILD;
            return cp;
        }
    }

В коде, который получает hWnd для панели управления и создает форму, используйте SetParent, чтобы сделать форму дочерней по отношению к панели управления:

    /// <summary>
    /// Show the form in the little control panel preview window.
    /// </summary>
    /// <param name="hWnd">hwnd passed to us at launch by windows</param>
    static void ShowMiniPreview(IntPtr hWnd)
    {
        if (NativeMethods.IsWindow(hWnd))
        {
            miniControlPanelForm preview = new miniControlPanelForm(hWnd);
            IntPtr newParent = NativeMethods.SetParent(preview.Handle, hWnd);

            // Set the size of the form to the size of the parent window (using the passed hWnd).
            System.Drawing.Rectangle ParentRect = new System.Drawing.Rectangle();
            bool fSuccess = NativeMethods.GetClientRect(hWnd, ref ParentRect);

            // Set our size to new rect and location at (0, 0)
            preview.Size = ParentRect.Size;
            preview.Location = new System.Drawing.Point(0, 0);

            // Show the form
            preview.Show();

            // and run it
            Application.Run(preview);
        }
    }

Обратите внимание, что «NativeMethods» — это мой класс с различными методами и константами Win32, объявленными как PInvokes:

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    public static class WindowStyles
    {
        public static readonly Int32
        WS_CHILD = 0x40000000;
    }

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern bool GetClientRect(IntPtr hWnd, ref Rectangle rect);
person Cardinal Fang    schedule 25.08.2014