Can I mix GDI and GDI+ drawing in my application?
You can mix GDI and GDI+ drawing operations in the same code path. The article INFO: Interoperability Between GDI and GDI+ (Q311221) discusses some caveats to keep in mind when you are writing code that allows GDI and GDI+ to interoperate. See also the FAQ ‘How to create my own hatch styles for brushes’ for an example how to use GDI bitmaps with GDI+. The most prominent functions for mixing GDI and GDI+ are the GetHdc and ReleaseHdc methods of the Graphics class.
How to load and display a cursor from a resource manifest
System.IO.Stream strm = null; try { string curName = ‘WindowsApplication1.Cursor1.cur’; strm = this.GetType().Assembly.GetManifestResourceStream(curName); this.Cursor = new Cursor(strm); } catch(Exception ex) { MessageBox.Show(ex.Message.ToString()); } finally { if(strm != null) strm.Close(); }
How to create my own hatch styles for brushes
GDI+ features a TextureBrush that lets you draw repeating patterns. You can specify any bitmap to be drawn repeatedly. In this example we create bitmaps using code and attach them to a TextureBrush. static object[] patternSpecs = new object[] { new short[] { 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 }, // horizontal new short[] { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, // vertical new short[] { 0x77, 0xbb, 0xdd, 0xee, 0x77, 0xbb, 0xdd, 0xee }, // \\\ Down new short[] { 0xee, 0xdd, 0xbb, 0x77, 0xee, 0xdd, 0xbb, 0x77 }, // /// Up new short[] { 0xee, 0x00, 0xee, 0xee, 0xee, 0x00, 0xee, 0xee }, // +++ } public static Bitmap CreateBitmapFromPattern(int pattern) { Bitmap patternBitmap; IntPtr hBitmap = NativeMethods.CreateBitmap(8, 8, 1, 1, (short[]) patternSpecs[pattern]); if (hBitmap != IntPtr.Zero) patternBitmap = Image.FromHbitmap(hBitmap); NativeMethods.DeleteObject(hBitmap); return patternBitmap; } public static void FillRectangle(Graphics g, Rectangle r, int pattern, Color foreColor, Color backColor) { Bitmap bm = CreateBitmapFromPattern(pattern); FillRectangle(g, r, bm, foreColor, backColor); } public static void FillRectangle(Graphics g, Rectangle r, Bitmap bm, Color foreColor, Color backColor) { if (bm != null) { Size size = bm.PhysicalDimension.ToSize(); TextureBrush br = new TextureBrush(bm, new Rectangle(new Point(0, 0), size), ia); br.WrapMode = WrapMode.Tile; g.FillRectangle(br, r); br.Dispose(); } } public class NativeMethods { [DllImport(‘gdi32’, CharSet=CharSet.Auto, ExactSpelling=true)] extern public static IntPtr CreateBitmap(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel, [MarshalAs(UnmanagedType.LPArray)] short[] lpvBits); [DllImport(‘gdi32’)] extern public static bool DeleteObject(IntPtr hObject) ; }
How to set the rendering origin for hatch brushes
The Graphics.RenderingOrigin property lets you specify a Point structure that represents the dither origin for 8-bits-per-pixel and 16-bits-per-pixel dithering and is also used to set the origin for hatch brushes. The following example shows how to use RenderingOrigin: namespace Scrollable1 { using System; using System.Collections; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; /// /// Summary description for ScrollableControl1. /// public class ScrollableControl1 : System.Windows.Forms.ScrollableControl { private void InitializeComponent () { } public ScrollableControl1() { InitializeComponent (); this.AutoScrollMinSize = new Size(500, 500); } protected override void OnPaint(PaintEventArgs pe) { pe.Graphics.RenderingOrigin = AutoScrollPosition; HatchBrush br = new HatchBrush(HatchStyle.ForwardDiagonal, Color.Blue, Color.White); pe.Graphics.FillRectangle(br, ClientRectangle /*or pe.ClipRectangle*/); br.Dispose(); } } }
How can I supply a list of values to be chosen from a dropdown list at runtime for a specific type similar to enums?
You have to implement a TypeConverter for your class and override the GetStandardValues and GetStandardValuesSupported method. In your override of GetStandardValuesSupported you have to return true. In your override of GetStandardValues you should return the list of values. Optionally you can override GetStandardValuesExclusive and allow the user to specify values that are not in the value list. Note: The standard values collection can be initialized at runtime depending on the context of the instance object. public class GridCellValueTypeConverter: TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { if (sourceType == typeof(System.String)) return true; return base.CanConvertFrom(context,sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value is System.String) { if (((string) value) != ”) return Type.GetType((string) value); else return null; } return base.ConvertFrom(context,culture,value); } // no string conversion public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof(String)) { Type type = (Type) value; if (type == null) return String.Empty; else if (type.Namespace == ‘System’) return type.ToString(); else { return String.Concat(type.FullName, ‘,’, type.AssemblyQualifiedName.Split(’,’)[1]); } } return base.ConvertFrom(context,culture,value); } public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { return svc; } public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { return false; } public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { return true; } // Fields static GridCellValueTypeConverter() { values = new string[] { ‘System.String’, ‘System.Double’, ‘System.Int32’, ‘System.Boolean’, ‘System.DateTime’, ‘System.Int16’, ‘System.Int64’, ‘System.Single’, ‘System.Byte’, ‘System.Char’, ‘System.Decimal’, ‘System.UInt16’, ‘System.UInt32’, ‘System.UInt64’, }; Array.Sort(values); Type[] types = new Type[values.Length]; for (int i = 0; i < values.Length; i++) types[i] = Type.GetType(values[i]); svc = new TypeConverter.StandardValuesCollection(types); } private static string[] values; private static TypeConverter.StandardValuesCollection svc; }