Reputation: 1520
I use a form with border NONE. I need to override WndProc for resize and move form. However, using this code, my app crashes!
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;
}
How can I fix my code not to crash but still allow my form to be moved and resized?
Upvotes: 1
Views: 1333
Reputation: 941675
Check out the warnings you get on this code:
warning C4717: 'cpptemp5::Form1::WndProc' : recursive on all control paths, function will cause runtime stack overflow
Which is why your code crashes with this web site name. That could have been a bit more than a warning. Fix:
Form::WndProc(m);
Or use the __super keyword. It should be called first, before you change the return value.
warning C4490: 'override' : incorrect use of override specifier; 'cpptemp5::Form1::get' does not match a base ref class method
Which prevents your attempt at overriding from working, the form still has borders. The better mousetrap is to assign the FormBorderStyle property in the constructor:
Form1(void)
{
InitializeComponent();
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::None;
}
Although you'd normally just do this with the designer, using the Properties window. For completeness, the override doesn't work because you made it a function, not a property. The correct syntax is:
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;
}
}
But not quite good enough to make the form borderless.
Upvotes: 1
Reputation: 244802
You have to call the base class's WndProc
method first, in order for m.Result
to be set to the correct value. The code you posted doesn't call it until the end.
Additionally, you're trying to call the base class with Form1::WndProc
, which actually calls the current class's implementation of the WndProc
method. That's why your application is "crashing" every time you try to run it with a StackOverflowException
—your code within the WndProc
method is calling itself recursively. Directly calling the superclass's implementation (like you did in the CreateParams
property) with the __super
keyword works just fine.
So, you need to re-write that method like this:
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;
}
}
Upvotes: 3