Share via


How can I implement IDeviceContext?

The VisualStyleRenderer APIs take an IDeviceContext, for which you can normally pass a graphics object. However if there is something you want to change in GDI before passing onto the VisualStyleRenderer, you can explicitly implement IDeviceContext, and pass in your custom object to the VisualStyleRenderer.

The example below shows how to SelectObject a font into a device context before calling into the VisualStyleRenderer.

public partial class Form1 : Form {
public Form1() {
InitializeComponent();
this.Font = SystemFonts.IconTitleFont;

}

protected override void OnPaint(PaintEventArgs e) {

VisualStyleRenderer vsr = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.CheckedHot);
using (MyDeviceContext dc = new MyDeviceContext(e.Graphics)) {
vsr.DrawText(dc, new Rectangle(10,10,200,20), "Whoops! Bad font");

dc.SelectedFont = this.Font;
vsr.DrawText(dc, new Rectangle(10, 30, 200, 20), "Correct font!");

}

}

public class MyDeviceContext : IDeviceContext {
private Graphics graphics;
private IntPtr hdc = IntPtr.Zero;
private Font selectedFont = null;
private IntPtr hfont = IntPtr.Zero;

public MyDeviceContext(Graphics g) {
this.graphics = g;
}
#region IDeviceContext Members

public Font SelectedFont {
get {
return selectedFont;
}
set {
if (selectedFont != value) {
selectedFont = value;

if (selectedFont != null) {
hfont = selectedFont.ToHfont();
IntPtr prevGDIObject = UnsafeNativeMethods.SelectObject(new HandleRef(this, GetHdc()), new HandleRef(this, hfont));
if (prevGDIObject != IntPtr.Zero) {
UnsafeNativeMethods.DeleteObject(new HandleRef(this, prevGDIObject));
}
}
else if (hfont != IntPtr.Zero) {
UnsafeNativeMethods.DeleteObject(new HandleRef(this, hfont));
}

}

}
}
public IntPtr GetHdc() {
if (hdc == IntPtr.Zero) {
hdc = this.graphics.GetHdc();
}
return hdc;
}

public void ReleaseHdc() {
SelectedFont = null;
if (this.hdc != IntPtr.Zero) {
this.graphics.ReleaseHdc();
hdc = IntPtr.Zero;
}
}

#endregion

#region IDisposable Members

void IDisposable.Dispose() {
ReleaseHdc();
}

#endregion

private class UnsafeNativeMethods {

[DllImport("Gdi32", SetLastError = true, ExactSpelling = true, EntryPoint = "SelectObject", CharSet = CharSet.Auto)]
public static extern IntPtr SelectObject(HandleRef hdc, HandleRef obj);

[DllImport("Gdi32", SetLastError = true, ExactSpelling = true, EntryPoint = "DeleteObject", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern bool DeleteObject(HandleRef hObject); }
}
}