473,226 Members | 1,442 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,226 software developers and data experts.

Difference between 'this.CreateGraphics()' and 'Graphics.FromHdc(hDC);'

Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !

Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?

A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);

B)
Graphics g = this.CreateGraphics();

You have my thanks and full attention,
James Randle.

Dec 4 '06 #1
8 12713
The code i am looking at (if this helps) is attached below (from
http://www.codeproject.com/cs/combob...ears_flat.asp).

In the WM_NC_PAINT message handler, a graphics object is already
created, but then SendPrintClientMsg() is called which seems to do the
same work again (in reverse - getting the hDC from
this.CreateGraphics). Is this mad, or more likely, am i missing
something?

....

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

namespace DrawFlat
{
[ToolboxBitmap(typeof(System.Windows.Forms.ComboBox ))]
public class FlatComboBox: ComboBox
{
#region ComboInfoHelper
internal class ComboInfoHelper
{
[DllImport("user32")]
private static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref
ComboBoxInfo info);

#region RECT struct
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
#endregion

#region ComboBoxInfo Struct
[StructLayout(LayoutKind.Sequential)]
private struct ComboBoxInfo
{
public int cbSize;
public RECT rcItem;
public RECT rcButton;
public IntPtr stateButton;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
#endregion

public static int GetComboDropDownWidth()
{
ComboBox cb = new ComboBox();
int width = GetComboDropDownWidth(cb.Handle);
cb.Dispose();
return width;
}
public static int GetComboDropDownWidth(IntPtr handle)
{
ComboBoxInfo cbi = new ComboBoxInfo();
cbi.cbSize = Marshal.SizeOf(cbi);
GetComboBoxInfo(handle, ref cbi);
int width = cbi.rcButton.Right - cbi.rcButton.Left;
return width;
}
}
#endregion

public const int WM_ERASEBKGND = 0x14;
public const int WM_PAINT = 0xF;
public const int WM_NC_PAINT = 0x85;
public const int WM_PRINTCLIENT = 0x318;
private static int DropDownButtonWidth = 17;

[DllImport("user32.dll", EntryPoint="SendMessageA")]
public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr
wParam, object lParam);

[DllImport("user32")]
public static extern IntPtr GetWindowDC (IntPtr hWnd );

[DllImport("user32")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );

static FlatComboBox()
{
DropDownButtonWidth = ComboInfoHelper.GetComboDropDownWidth() + 2;
}

public FlatComboBox()
: base()
{
this.SetStyle(ControlStyles.DoubleBuffer, true);
}

protected override void OnSelectedValueChanged(EventArgs e)
{
base.OnSelectedValueChanged (e);
this.Invalidate();
}

protected override void WndProc(ref Message m)
{
if (this.DropDownStyle == ComboBoxStyle.Simple)
{
base.WndProc(ref m);
return;
}

IntPtr hDC = IntPtr.Zero;
Graphics gdc = null;
switch (m.Msg)
{
case WM_NC_PAINT:
hDC = GetWindowDC(this.Handle);
gdc = Graphics.FromHdc(hDC);
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClientMsg(); // send to draw client area
PaintFlatControlBorder(this, gdc);
m.Result = (IntPtr) 1; // indicate msg has been processed
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();

break;
case WM_PAINT:
base.WndProc(ref m);
// flatten the border area again
hDC = GetWindowDC(this.Handle);
gdc = Graphics.FromHdc(hDC);
Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control),
2);
gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3,
this.Height-3));
PaintFlatDropDown(this, gdc);
PaintFlatControlBorder(this, gdc);
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();

break;
default:
base.WndProc(ref m);
break;
}
}
private void SendPrintClientMsg()
{
// We send this message for the control to redraw the client area
Graphics gClient = this.CreateGraphics();
IntPtr ptrClientDC = gClient.GetHdc();
SendMessage(this.Handle, WM_PRINTCLIENT, ptrClientDC, 0);
gClient.ReleaseHdc(ptrClientDC);
gClient.Dispose();
}

private void PaintFlatControlBorder(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
if (ctrl.Focused == false || ctrl.Enabled == false )
ControlPaint.DrawBorder(g, rect, SystemColors.ControlDark,
ButtonBorderStyle.Solid);
else
ControlPaint.DrawBorder(g, rect, Color.Black,
ButtonBorderStyle.Solid);
}
public static void PaintFlatDropDown(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(ctrl.Width-DropDownButtonWidth, 0,
DropDownButtonWidth, ctrl.Height);
ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
}

protected override void OnLostFocus(System.EventArgs e)
{
base.OnLostFocus(e);
this.Invalidate();
}

protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
this.Invalidate();
}
protected override void OnResize(EventArgs e)
{
base.OnResize (e);
this.Invalidate();
}

}
}

Dec 4 '06 #2
"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@79g2000cws.googlegro ups.com...
The code i am looking at (if this helps) is attached below (from
http://www.codeproject.com/cs/combob...ears_flat.asp).

In the WM_NC_PAINT message handler, a graphics object is already
created, but then SendPrintClientMsg() is called which seems to do the
same work again (in reverse - getting the hDC from
this.CreateGraphics). Is this mad, or more likely, am i missing
something?
I don't know. The whole thing does look kind of odd to me...presumably, the
code is like this because some of the code was originally unmanaged? I
can't imagine writing C# code like this from scratch.

From http://msdn2.microsoft.com/en-us/library/ms535950.aspx it's apparent to
me that FromHdc does what you'd think: it just wraps a device context handle
with a Graphics object.

I don't know how CreateGraphics works, but presumably it calls either GetDC
or GetWindowDC. Okay, I admit it could call CreateDC but that seems less
likely for screen drawing. Whether it calls GetDC or GetWindowDC probably
depends on whether the Control and/or Form class always uses an "own DC" for
the window.

So yes, it does kind of look like the same DC may be getting handed back and
forth to multiple Graphics objects, and yes it does seem to me that would be
wasteful.

Ain't legacy code great? :)

Pete
Dec 4 '06 #3
CreateGraphics will get you a Graphics object based on the client area of
the window.

FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.

You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !

Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?

A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);

B)
Graphics g = this.CreateGraphics();

You have my thanks and full attention,
James Randle.

Dec 4 '06 #4
Peter, Bob,

Thankyou both for your replies.

Bob,
If i might ask, why do you think the author of the above code used this
method? I am about to read the GDI+ FAQ, but are there some appropriate
questions i should be asking that would hasten my successful completion
of a similar control?

Bob Powell [MVP] wrote:
CreateGraphics will get you a Graphics object based on the client area of
the window.

FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.

You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !

Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?

A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);

B)
Graphics g = this.CreateGraphics();

You have my thanks and full attention,
James Randle.
Dec 4 '06 #5
Bob (again!),
Hi. I've had a read through the GDI+ FAQ. Am i correct in the following
suggestions?
1) do WM_PAINT control painting in overridden OnPaint() event (after
base.OnPaint(e))
2) WM_NC_PAINT still needs to be handled in WndProc as it uses 'fancy
stuff'

I just read that the combobox has no 'non-client' area so can i discard
WM_NC_PAINT all together?

Thanks and thanks again,
James Randle.
Bob Powell [MVP] wrote:
CreateGraphics will get you a Graphics object based on the client area of
the window.

FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.

You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !

Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?

A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);

B)
Graphics g = this.CreateGraphics();

You have my thanks and full attention,
James Randle.
Dec 4 '06 #6
I just tried to call the drawing functions from an overriden OnPaint()
and the combo has reverted to its 3d appearance. Does this mean i have
to break the rules, or am i doing something wrong?

Arrggghhh!
James Randle.

pigeonrandle wrote:
Bob (again!),
Hi. I've had a read through the GDI+ FAQ. Am i correct in the following
suggestions?
1) do WM_PAINT control painting in overridden OnPaint() event (after
base.OnPaint(e))
2) WM_NC_PAINT still needs to be handled in WndProc as it uses 'fancy
stuff'

I just read that the combobox has no 'non-client' area so can i discard
WM_NC_PAINT all together?

Thanks and thanks again,
James Randle.
Bob Powell [MVP] wrote:
CreateGraphics will get you a Graphics object based on the client area of
the window.

FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.

You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.

"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !
>
Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?
>
A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);
>
B)
Graphics g = this.CreateGraphics();
>
You have my thanks and full attention,
James Randle.
>
Dec 4 '06 #7
Problem solved!

placing

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint,
true);

in the constructor (UserPaint being the important bit) has restored the
missing paint event, and the draw flat button code can be called from
an overriden onpaint().

Thanks to anyone half writing a reply as i write mine, and again thanks
to Bob for pointing me in the right direction.

James Randle.

pigeonrandle wrote:
I just tried to call the drawing functions from an overriden OnPaint()
and the combo has reverted to its 3d appearance. Does this mean i have
to break the rules, or am i doing something wrong?

Arrggghhh!
James Randle.

pigeonrandle wrote:
Bob (again!),
Hi. I've had a read through the GDI+ FAQ. Am i correct in the following
suggestions?
1) do WM_PAINT control painting in overridden OnPaint() event (after
base.OnPaint(e))
2) WM_NC_PAINT still needs to be handled in WndProc as it uses 'fancy
stuff'

I just read that the combobox has no 'non-client' area so can i discard
WM_NC_PAINT all together?

Thanks and thanks again,
James Randle.
Bob Powell [MVP] wrote:
CreateGraphics will get you a Graphics object based on the client area of
the window.
>
FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.
>
You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.
>
--
Bob Powell [MVP]
Visual C#, System.Drawing
>
Ramuseco Limited .NET consulting
http://www.ramuseco.com
>
Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm
>
Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm
>
All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
>
>
>
"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !

Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?

A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);

B)
Graphics g = this.CreateGraphics();

You have my thanks and full attention,
James Randle.
Dec 4 '06 #8
Err...Problem created.

Now the drop down is a solid black color, and none of the text is
displayed. I now see why the contrived method was used in the first
place ...
it allowed user painting of some of the control whilst letting the text
drawing continue as expected.

Is there a way to accomplish this properly? To be honest, i dont want
to have to write loads of drawing code (that is already there) just
because i want to draw a flat button and flat border which wouldnt
obscure the text anyway.

Any comments?
James Randle
pigeonrandle wrote:
Problem solved!

placing

this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint,
true);

in the constructor (UserPaint being the important bit) has restored the
missing paint event, and the draw flat button code can be called from
an overriden onpaint().

Thanks to anyone half writing a reply as i write mine, and again thanks
to Bob for pointing me in the right direction.

James Randle.

pigeonrandle wrote:
I just tried to call the drawing functions from an overriden OnPaint()
and the combo has reverted to its 3d appearance. Does this mean i have
to break the rules, or am i doing something wrong?

Arrggghhh!
James Randle.

pigeonrandle wrote:
Bob (again!),
Hi. I've had a read through the GDI+ FAQ. Am i correct in the following
suggestions?
1) do WM_PAINT control painting in overridden OnPaint() event (after
base.OnPaint(e))
2) WM_NC_PAINT still needs to be handled in WndProc as it uses 'fancy
stuff'
>
I just read that the combobox has no 'non-client' area so can i discard
WM_NC_PAINT all together?
>
Thanks and thanks again,
James Randle.
>
>
Bob Powell [MVP] wrote:
CreateGraphics will get you a Graphics object based on the client area of
the window.

FromHdc using the handle from GetWindowDC will return a graphics object
based on the whole window including the non-client area. This DC is normally
only used by the system unless you want to do clever stuff like override the
non client drawing.

You should really use niether. See the GDI+ FAQ for how and when to get a
Graphics object.

--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.



"pigeonrandle" <pi**********@hotmail.comwrote in message
news:11**********************@80g2000cwy.googlegro ups.com...
Hi,
Please pity me, i am on a dial-up connection for the first time in 5
years :( !
>
Does anyone know how the resulting Graphics objects differ ...? What i
really mean is can someone explain it to me please?
>
A)
[DllImport("user32.dll")] protected static extern IntPtr GetWindowDC
(IntPtr hWnd );
hDC = GetWindowDC(this.Handle);
g_dc = Graphics.FromHdc(hDC);
>
B)
Graphics g = this.CreateGraphics();
>
You have my thanks and full attention,
James Randle.
>
Dec 4 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Glenn | last post by:
We use GDI code to do some drawing with R2_MASKPEN (because there doesn't seem to be a GDI+ way of doing it). We're getting the HDC from a Graphics object passed in to the method. This works fine...
1
by: Brian Keating EI9FXB | last post by:
Hello there, I've been playing with custom draw and am having a bit of difficulty, Namely the graphics function in this function throws invalid arg exception. Im pretty sure this is correct cause...
6
by: Chuck Bowling | last post by:
Does the device context handle for a graphics device change during the lifetime of the underlying object? I'm asking because I ran across some code that stores the hDC in the class rather than...
3
by: Andreas | last post by:
Hi NG, i encountered a problem during developing some activex control with c#. I read an article that it is possible to expose windows forms as activex controls. So I tried it and it worked...
3
by: Girish | last post by:
Hi , I am migrating from VC 6.0 to VC 7.0 with ( windows Control Lib option in vc dot net ) where I want to draw an image using StretchDIBits. I am not able to get the HDC of the Window....
8
by: MyAlias | last post by:
Can't solve this CallBack returning structures Error message: An unhandled exception of type 'System.NullReferenceException' occurred in MyTest.exe Additional information: Object reference not...
6
by: JoeC | last post by:
I have been working on my maze program and this line is failing: class space{ char gchar; graphic *gr; graphic *grDefault; player * play; bool seen;
2
by: Lloyd Dupont | last post by:
In my .NET application I have some text rendered through GDI. It draws and print nicely. Now I would like to implement image export. So I create a new System.Drawing.Bitmap(width, height) then...
6
by: NvrBst | last post by:
Hello. I can pInvoke "GetDC" with NULL or "IntPtr.Zero" and get the hDC for the entire screen. I can use the hDC for stuff like "GetPixel" and it works fine. When I try to do the... ...
1
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
0
by: veera ravala | last post by:
ServiceNow is a powerful cloud-based platform that offers a wide range of services to help organizations manage their workflows, operations, and IT services more efficiently. At its core, ServiceNow...
0
by: VivesProcSPL | last post by:
Obviously, one of the original purposes of SQL is to make data query processing easy. The language uses many English-like terms and syntax in an effort to make it easy to learn, particularly for...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: fareedcanada | last post by:
Hello I am trying to split number on their count. suppose i have 121314151617 (12cnt) then number should be split like 12,13,14,15,16,17 and if 11314151617 (11cnt) then should be split like...
1
by: davi5007 | last post by:
Hi, Basically, I am trying to automate a field named TraceabilityNo into a web page from an access form. I've got the serial held in the variable strSearchString. How can I get this into the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.