Что приводит к сбою приложения C ++ / CLI без полей при переопределении WndProc? - PullRequest
1 голос
/ 25 декабря 2010

Я использую форму с рамкой НЕТ.Мне нужно переопределить WndProc для изменения размера и перемещения формы.Однако, используя этот код, мое приложение аварийно завершает работу!

 static const int WM_NCHITTEST = 0x0084;
 static const int HTCLIENT = 1;
 static const int HTCAPTION = 2;

 protected: virtual void Form1::WndProc(System::Windows::Forms::Message %m) override 
 {        
     switch (m.Msg)
     {
         case WM_NCHITTEST:
             if (m.Result == IntPtr(HTCLIENT))
             {
                 m.Result = IntPtr(HTCAPTION);
             }
             break;
     }
     Form1::WndProc(m);
 }       


virtual System::Windows::Forms::CreateParams^ get() override
{

    System::Windows::Forms::CreateParams^ cp = __super::CreateParams;
    cp->Style |= 0x40000; 
    return cp;
}

Как я могу исправить свой код, чтобы он не зависал, но все же позволял перемещать и изменять размер моей формы?

Ответы [ 2 ]

3 голосов
/ 25 декабря 2010

Вы должны вызвать метод WndProc базового класса first , чтобы для m.Result было установлено правильное значение.Размещенный вами код не вызывает его до тех пор, пока end .

Кроме того, вы пытаетесь вызвать базовый класс с помощью Form1::WndProc, который фактически вызывает current реализация класса WndProc класса.Вот почему ваше приложение «падает» каждый раз, когда вы пытаетесь запустить его с StackOverflowException - ваш код в методе WndProc вызывает себя рекурсивно.Прямой вызов реализации суперкласса (как вы сделали в свойстве CreateParams) с ключевым словом __super работает просто отлично.

Итак, вам нужно переписать этот метод следующим образом:

virtual void Form1::WndProc(System::Windows::Forms::Message %m) override 
{
    __super::WndProc(m);

    switch (m.Msg)
    {
    case WM_NCHITTEST:
        if (m.Result == IntPtr(HTCLIENT))
        {
            m.Result = IntPtr(HTCAPTION);
        }
        break;
    }
}
1 голос
/ 25 декабря 2010

Проверьте предупреждения, которые вы получаете по этому коду:

предупреждение C4717: 'cpptemp5 :: Form1 :: WndProc': рекурсивно для всех путей управления, функция вызовет переполнение стека во время выполнения

Вот почему ваш код падает с этим именем сайта.Это могло быть немного больше, чем предупреждение.Исправление:

 Form::WndProc(m);

Или используйте ключевое слово __super.Прежде чем изменить возвращаемое значение, его следует вызвать.


предупреждение C4490: «переопределить»: неправильное использование спецификатора переопределения;'cpptemp5 :: Form1 :: get' не соответствует методу базового класса ссылки

, который препятствует работе вашей попытки переопределения, форма все еще имеет границы.Лучшей мышеловкой является назначение свойства FormBorderStyle в конструкторе:

    Form1(void)
    {
        InitializeComponent();
        this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
    }

Хотя обычно вы делаете это с конструктором, используя окно свойств.Для полноты, переопределение не работает, потому что вы сделали его функцией, а не свойством.Правильный синтаксис:

protected:
    property System::Windows::Forms::CreateParams^ CreateParams {
        virtual System::Windows::Forms::CreateParams^ get() override {
            System::Windows::Forms::CreateParams^ cp = __super::CreateParams;
            cp->Style |= 0x40000;
            return cp;
        }
    }

Но не достаточно хорош, чтобы сделать форму без полей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...