P/Invoke GradientFill

  • Thread starter Thread starter Ron Lemire
  • Start date Start date
R

Ron Lemire

Hi,

I'm trying to paint a gradient on a form by overriding the Paint handler
with GradientFill(
HDC hdc,
PTRIVERTEX pVertex,
ULONG nVertex,
PVOID pMesh,
ULONG nCount,
ULONG ulMode
);

The .NET Framework supports Graphics.GetHdc but the .NET Compact Framework
does not.

Any ideas on how to get the Device Context Handle to use with GradientFill?

Thanks...Ron Lemire
 
Just read my post and I'm not overriding the Paint handler, just using
GradientFill in the Paint message handler.
 
Hi,

I am away from my work PC right now so forgive me if this
is not completely accurate but you can do something like
this - I will verify Monday morning with the full
P/Invoke code if needed:

In the Control on which you want to draw...
this.Catpure = true;
P/Invoke GetCapture(); // returns HWND
this.Capture = false;

P/Invoke GetDC(hwnd); // returns DC from HWND above

Geoff Schwab
Program Manager
Excell Data Corporation
http://msdn.com/mobility

This posting is provided "AS IS" with no warranties, and
confers no rights.
 
Geoff,

Thanks I'll give it a try.
I was looking in the help and 2 other functions might also get it:
HWND GetActiveWindow(void);followed byHDC GetWindowDC(
HWND hWnd
); Thanks again. I appreciate you help...Ron Lemire
 
Hi Geoff,
Tried both methods (GetDC and GetWindowDC) and get 2 different int values so
there must be a difference.
Anyway I've tried GradientFill and get a 'NotSupportedException' with both.
I think I'm doing something wrong.
Have you ever got GradientFill to work? If so, can you spot what's wrong
with my code (see below).
Thanks...Ron

=========================================================================
public struct TRIVERTEX
{
public long x;
public long y;
public int Red;
public int Green;
public int Blue;
public int Alpha;
}

public struct GRADIENT_RECT
{
public long UpperLeft;
public long LowerRight;
}

[DllImport("Coredll.dll", EntryPoint="GetCapture")]
private static extern long GetCapture();

[DllImport("Coredll.dll", EntryPoint="GetDC")]
private static extern long GetDC(long hWnd);

[DllImport("Coredll.dll", EntryPoint="GradientFill")]
public static extern void GradientFill(long hdc, TRIVERTEX[] pVertex,
long dwNumVertex, GRADIENT_RECT pMesh, long dwNumMesh,
long dwMode);

try
{
this.Capture = true;
long hwnd = GetCapture();
this.Capture = false;
long hdc = GetDC(hwnd);
Rectangle r = this.ClientRectangle;


GRADIENT_RECT gRect = new GRADIENT_RECT();
TRIVERTEX[] vert = new TRIVERTEX[2];

vert[0].x = r.Left;
vert[0].y = r.Top;
vert[0].Red = 0x0000;
vert[0].Green = 0x0000;
vert[0].Blue = 0xff00;
vert[0].Alpha = 0x0000;

vert[1].x = r.Right;
vert[1].y = r.Bottom;
vert[1].Red = 0x0000;
vert[1].Green = 0xff00;
vert[1].Blue = 0x0000;
vert[1].Alpha = 0x0000;

gRect.UpperLeft = 0;
gRect.LowerRight = 1;

GradientFill(hdc, vert, 2, gRect, 1, 0);
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
============================================================================
=====
 
Few notes:
Do not use "long" type with P/Invoke. Data defined as Long, LONG, or long in
SDK is Int32 or int in .NET
Arrays of structures are not marshalled in CF, hence trying to marshal
TRIVERTEX[] will fail. The workaround is to use arrays of int and perform
index arithmetics by hand
Another reason to use arrays - the structure members in CF are DWORD-aligned
(32 bit), so having Int16 members will leave holes. The worakaround is again
to use int[]
Although it is not not an error to do so, typically you will not use int for
HWND, HDC and other handles - use IntPtr instead. The reason is that
"potentially" HANDLE (which is LPVOID) can become 64 bit value and IntPtr
will handle this, while int will stay int - 32 bit value

The corrected code can be downloaded from
http://www.alexfeinman.com/download.asp?doc=GradientFill.zip

Ron Lemire said:
Hi Geoff,
Tried both methods (GetDC and GetWindowDC) and get 2 different int values so
there must be a difference.
Anyway I've tried GradientFill and get a 'NotSupportedException' with both.
I think I'm doing something wrong.
Have you ever got GradientFill to work? If so, can you spot what's wrong
with my code (see below).
Thanks...Ron

=========================================================================
public struct TRIVERTEX
{
public long x;
public long y;
public int Red;
public int Green;
public int Blue;
public int Alpha;
}

public struct GRADIENT_RECT
{
public long UpperLeft;
public long LowerRight;
}

[DllImport("Coredll.dll", EntryPoint="GetCapture")]
private static extern long GetCapture();

[DllImport("Coredll.dll", EntryPoint="GetDC")]
private static extern long GetDC(long hWnd);

[DllImport("Coredll.dll", EntryPoint="GradientFill")]
public static extern void GradientFill(long hdc, TRIVERTEX[] pVertex,
long dwNumVertex, GRADIENT_RECT pMesh, long dwNumMesh,
long dwMode);

try
{
this.Capture = true;
long hwnd = GetCapture();
this.Capture = false;
long hdc = GetDC(hwnd);
Rectangle r = this.ClientRectangle;


GRADIENT_RECT gRect = new GRADIENT_RECT();
TRIVERTEX[] vert = new TRIVERTEX[2];

vert[0].x = r.Left;
vert[0].y = r.Top;
vert[0].Red = 0x0000;
vert[0].Green = 0x0000;
vert[0].Blue = 0xff00;
vert[0].Alpha = 0x0000;

vert[1].x = r.Right;
vert[1].y = r.Bottom;
vert[1].Red = 0x0000;
vert[1].Green = 0xff00;
vert[1].Blue = 0x0000;
vert[1].Alpha = 0x0000;

gRect.UpperLeft = 0;
gRect.LowerRight = 1;

GradientFill(hdc, vert, 2, gRect, 1, 0);
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
============================================================================
=====

Geoff Schwab said:
Hi,

I am away from my work PC right now so forgive me if this
is not completely accurate but you can do something like
this - I will verify Monday morning with the full
P/Invoke code if needed:

In the Control on which you want to draw...
this.Catpure = true;
P/Invoke GetCapture(); // returns HWND
this.Capture = false;

P/Invoke GetDC(hwnd); // returns DC from HWND above

Geoff Schwab
Program Manager
Excell Data Corporation
http://msdn.com/mobility

This posting is provided "AS IS" with no warranties, and
confers no rights.
 
Much appreciated!!!

Alex Feinman said:
Few notes:
Do not use "long" type with P/Invoke. Data defined as Long, LONG, or long in
SDK is Int32 or int in .NET
Arrays of structures are not marshalled in CF, hence trying to marshal
TRIVERTEX[] will fail. The workaround is to use arrays of int and perform
index arithmetics by hand
Another reason to use arrays - the structure members in CF are DWORD-aligned
(32 bit), so having Int16 members will leave holes. The worakaround is again
to use int[]
Although it is not not an error to do so, typically you will not use int for
HWND, HDC and other handles - use IntPtr instead. The reason is that
"potentially" HANDLE (which is LPVOID) can become 64 bit value and IntPtr
will handle this, while int will stay int - 32 bit value

The corrected code can be downloaded from
http://www.alexfeinman.com/download.asp?doc=GradientFill.zip

Ron Lemire said:
Hi Geoff,
Tried both methods (GetDC and GetWindowDC) and get 2 different int
values
so
there must be a difference.
Anyway I've tried GradientFill and get a 'NotSupportedException' with both.
I think I'm doing something wrong.
Have you ever got GradientFill to work? If so, can you spot what's wrong
with my code (see below).
Thanks...Ron

=========================================================================
public struct TRIVERTEX
{
public long x;
public long y;
public int Red;
public int Green;
public int Blue;
public int Alpha;
}

public struct GRADIENT_RECT
{
public long UpperLeft;
public long LowerRight;
}

[DllImport("Coredll.dll", EntryPoint="GetCapture")]
private static extern long GetCapture();

[DllImport("Coredll.dll", EntryPoint="GetDC")]
private static extern long GetDC(long hWnd);

[DllImport("Coredll.dll", EntryPoint="GradientFill")]
public static extern void GradientFill(long hdc, TRIVERTEX[] pVertex,
long dwNumVertex, GRADIENT_RECT pMesh, long dwNumMesh,
long dwMode);

try
{
this.Capture = true;
long hwnd = GetCapture();
this.Capture = false;
long hdc = GetDC(hwnd);
Rectangle r = this.ClientRectangle;


GRADIENT_RECT gRect = new GRADIENT_RECT();
TRIVERTEX[] vert = new TRIVERTEX[2];

vert[0].x = r.Left;
vert[0].y = r.Top;
vert[0].Red = 0x0000;
vert[0].Green = 0x0000;
vert[0].Blue = 0xff00;
vert[0].Alpha = 0x0000;

vert[1].x = r.Right;
vert[1].y = r.Bottom;
vert[1].Red = 0x0000;
vert[1].Green = 0xff00;
vert[1].Blue = 0x0000;
vert[1].Alpha = 0x0000;

gRect.UpperLeft = 0;
gRect.LowerRight = 1;

GradientFill(hdc, vert, 2, gRect, 1, 0);
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
============================================================================
 
Back
Top