4

Okay, so I have followed the docs right down to the smallest detail, and it keeps giving me the following error when I try to debug and run (F5):

PInvokeStackImbalance was detected Message: A call to PInvoke function 'VistaControls!VistaControls.Dwm.NativeMethods::DwmExtendFrameIntoClientArea' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

I have no idea what this means, or how to fix it! Can somebody please help? Any suggestions?

I have used this before but it's not working this time. I am using VS2010 Express C# WinForms, .NET 4 (As I was before when I first used it ages ago.)

Thank you

Link: http://windowsformsaero.codeplex.com/wikipage?title=Glass%20on%20WinForms&referringTitle=Documentation

And yep, I have noticed the correction a person made down the bottom of that page, and I fixed that up, but it still doesn't work!

The Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VistaControls.Dwm;

namespace One_Stop_Management
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            e.Graphics.FillRectangles(Brushes.Black, new Rectangle[] {
        new Rectangle(0, 0, this.ClientSize.Width, 30),
        new Rectangle(this.ClientSize.Width - 30, 0, 30, this.ClientSize.Height),
        new Rectangle(0, this.ClientSize.Height - 30, this.ClientSize.Width, 30),
        new Rectangle(0, 0, 30, this.ClientSize.Height)
    });
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            VistaControls.Dwm.DwmManager.EnableGlassSheet(this);
        }
    }
}
  • 1
    It appears to be telling you that something is wrong with the P/Invoke definition for the `DwmExtendFrameIntoClientArea` function, but you'll need to post the definition you currently have in order for anyone to tell you have to fix it. My educated guess is that there's an `int` used when an `IntPtr` should have been. – Cody Gray - on strike Feb 19 '11 at 11:39
  • @Cody Gray; The issue's been solved now, but I'll post my code anyway at the bottom of my question. Thank you. –  Feb 19 '11 at 11:41

2 Answers2

6

By reverting to .NET 3.5 you just hid the problem: the stack imbalance is still present, you just don't get any exception from the Managed Debugging Assistant that is responsible for detecting correct P/Invoke calls, for a reason unknown to me.

The signature of DwmExtendFrameIntoClientArea in the "Windows Forms Aero" library is wrong.

Here is the original unmanaged signature:

HRESULT WINAPI DwmExtendFrameIntoClientArea(HWND hWnd, __in  const MARGINS *pMarInset);

Here is the signature in the library:

[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);

While it seems to match the unmanaged one at first sight, it isn't. PreserveSig = false tells the CLR to interpret the returned HRESULT and automatically throw an exception if it's corresponding to an error (see PreserveSig on MSDN). The function return type must be void and not int anymore, since the result has already been consumed from the stack by the runtime.

Change to PreserveSig = true in the library code and the stack imbalance will be gone.

Julien Lebosquain
  • 40,639
  • 8
  • 105
  • 117
  • 2
    PreserveSig = false is not a bad idea here, it automatic generates an exception when the function fails. But *do* change the return type to "void". Otherwise make sure to throw the exception yourself. – Hans Passant Feb 19 '11 at 16:50
  • You're absolutely right Hans, but the library is already checking for the return value and throwing a custom exception, so PreserveSig = true should suffice here, even if it's generally better to set it to false. – Julien Lebosquain Feb 21 '11 at 11:46
-1

Never mind. I got it. It's such a shame this doesn't work with .NET 4!

You need to go to Project Properties, and change it from .NET Framework 4 to 3.5 or lower*.