1

I would like to use the DWMWA_ALLOW_NCPAINT to draw in the Non Client area but I cant figure out how to use it, can anyone help me?

Jakob
  • 23
  • 7

1 Answers1

0

It is a constant that you can pass it into the Win32 API function DwmSetWindowAttribute. You cannot use it with the function DwmGetWindowAttribute. It is "set-only".

To call a native function from managed code, in your case, it is DwmSetWindowAttribute, you should use P/Invoke.

In the below code, you can see how you can define the signature of native function DwmSetWindowAttribute and pass the constant DWMWA_ALLOW_NCPAINT into it.

PS: However, I don't think it is enough to use DWMWA_ALLOW_NCPAINT to draw on Non-client Area. There are many of that topic on SO. You can search it.

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace DWMWA_ALLOW_NCPAINT
{
    public partial class MainForm : Form
    {
        public Form1()
        {
            InitializeComponent();
        } 
        private IntPtr TRUE;
        private IntPtr FALSE;
  
        protected override void OnHandleCreated(EventArgs e)
        {
            TRUE = Marshal.AllocHGlobal(sizeof(int));
            Marshal.WriteInt32(TRUE, 1);
            FALSE = Marshal.AllocHGlobal(sizeof(int));
            Marshal.WriteInt32(TRUE, 0); 

            EnableNCPaint(Handle);
            //DisableNCPaint(Handle);
            base.OnHandleCreated(e);
        } 
        private void EnableNCPaint(IntPtr hwnd)
        {  
            DwmSetWindowAttribute(hwnd, (int)DWMWINDOWATTRIBUTE.DWMWA_ALLOW_NCPAINT, TRUE, sizeof(int)); 
        }
        private void DisableNCPaint(IntPtr hwnd)
        { 
            DwmSetWindowAttribute(hwnd, (int)DWMWINDOWATTRIBUTE.DWMWA_ALLOW_NCPAINT, FALSE, sizeof(int)); 
        } 
        enum DWMNCRENDERINGPOLICY
        {
            DWMNCRP_USEWINDOWSTYLE,
            DWMNCRP_DISABLED,
            DWMNCRP_ENABLED,
            DWMNCRP_LAST
        };
        [Flags]
        enum DWMWINDOWATTRIBUTE : uint
        {
            DWMWA_NCRENDERING_ENABLED = 1,
            DWMWA_NCRENDERING_POLICY,
            DWMWA_TRANSITIONS_FORCEDISABLED,
            DWMWA_ALLOW_NCPAINT,
            DWMWA_CAPTION_BUTTON_BOUNDS,
            DWMWA_NONCLIENT_RTL_LAYOUT,
            DWMWA_FORCE_ICONIC_REPRESENTATION,
            DWMWA_FLIP3D_POLICY,
            DWMWA_EXTENDED_FRAME_BOUNDS,
            DWMWA_HAS_ICONIC_BITMAP,
            DWMWA_DISALLOW_PEEK,
            DWMWA_EXCLUDED_FROM_PEEK,
            DWMWA_CLOAK,
            DWMWA_CLOAKED,
            DWMWA_FREEZE_REPRESENTATION,
            DWMWA_LAST
        };
        [DllImport("dwmapi.dll")]
        private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, IntPtr pvAttribute, int cbAttribute);

        [DllImport("dwmapi.dll")]
        private static extern int DwmSetWindowAttribute(IntPtr hwnd, int dwAttribute, IntPtr pvAttribute, int cbAttribute); 
    }
}

jtxkopt
  • 916
  • 1
  • 8
  • 21
  • What's the HGlobal for, why not just do `var TRUE = 1; DwmSetWindowAttribute(hwnd, DWMWINDOWATTRIBUTE.DWMWA_ALLOW_NCPAINT, ref TRUE, sizeof(int));` also should check return code – Charlieface Sep 11 '22 at 03:03
  • Because the parameter `pvAttribute` is type of `PVOID` which is a typedef for `void*`. The function takes the address of arbitrary type of variable. – jtxkopt Sep 11 '22 at 07:49
  • Thanks for your reply, you are right, unfortunately `DWMWA_ALLOW_NCPAINT' was not enough to draw the title bar, but I appreciated your help. – Jakob Sep 11 '22 at 08:40
  • To draw on Non-clien Area, you should also set `DWMNCRENDERINGPOLICY`. – jtxkopt Sep 11 '22 at 08:41
  • 1
    I know, but you can define an overload which takes a `in int pvAttribute`. Also if you allocate memory you must remember to free it. – Charlieface Sep 11 '22 at 08:47