|
|
|
The General Winforms Interview Questions consists the most frequently
asked questions in Winforms. This list of 100+ questions guage your familiarity
with the Winforms platform. The q&a have been collected over a period
of time from various blogs, forums and other similar Winforms sites
|
38. GDI from GDI
|
| 38.1 How does text drawing
differ between GDI+ and GDI?
|
| 38.2 How do I do
XOR-type-drawing (SetROP2-Function in MFC) in GDI+?
|
| 38.3 Can I mix GDI and GDI+
drawing in my application?
|
| 38.4 How do the Win32 System
Colors map to the colors provided by System.Drawing.SystemColors?
|
38.1 How does text drawing differ between GDI+ and GDI?
|
|
GDI+ text layout is resolution independent, and forms built with GDI+ text look
the same at all resolutions and when printed. The GDI+ APIs DrawString and
MeasureString lay out text independent of device resolution, so a paragraph of
text takes the same number of lines, no matter what the display device.
|
38.2 How do I do XOR-type-drawing (SetROP2-Function in MFC) in GDI+?
|
|
GDI+ doesn't support ROP codes like XOR. To use XOR drawing mode, interop with
GDI.
|
38.3 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.
|
|
38.4 How do the Win32 System Colors map to the colors provided by
System.Drawing.SystemColors?
|
|
The following table lists all Win32 System Colors and the corresponding name in
System.Drawing.SystemColors type:
|
GetSysColor(n) SystemColors.
COLOR_ACTIVEBORDER ActiveBorder
COLOR_ACTIVECAPTION ActiveCaption
COLOR_CAPTIONTEXT ActiveCaptionText
COLOR_APPWORKSPACE AppWorkspace
COLOR_3DFACE Control
COLOR_3DSHADOW ControlDark
COLOR_3DDKSHADOW ControlDarkDark
COLOR_3DLIGHT ControlLight
COLOR_3DHIGHLIGHT ControlLightLight
COLOR_BTNTEXT ControlText
COLOR_DESKTOP Desktop
COLOR_GRAYTEXT GrayText
COLOR_HIGHLIGHT Highlight
COLOR_HIGHLIGHTTEXT HighlightText
COLOR_HIGHLIGHT HotTrack
COLOR_INACTIVEBORDER InactiveBorder
COLOR_INACTIVECAPTION InactiveCaption
COLOR_INACTIVECAPTIONTEXT InactiveCaptionText
COLOR_INFOBK Info
COLOR_INFOTEXT InfoText
COLOR_MENU Menu
COLOR_MENUTEXT MenuText
COLOR_SCROLLBAR ScrollBar
COLOR_WINDOW Window
COLOR_WINDOWFRAME WindowFrame
COLOR_WINDOWTEXT WindowText
COLOR_3DHILIGHT ControlLightLight
COLOR_BTNHIGHLIGHT ControlLightLight
COLOR_BTNHILIGHT ControlLightLight
COLOR_BACKGROUND Desktop
|
33.5 How can I programmatically create a bitmap?
|
|
Since .NET uses it's own format that is not compatible with the
EnhancedMetafile format you will have to use reflection to achieve this. (From
a posting in the microsoft.public.dotnet.framework.drawing newsgroup)
|
[C#]
using System.Runtime.InteropServices;
using System.Reflection;
public const uint CF_METAFILEPICT = 3;
public const uint CF_ENHMETAFILE = 14;
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool CloseClipboard();
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern IntPtr GetClipboardData(uint format);
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern bool IsClipboardFormatAvailable(uint format);
//Pasting into PictureBox
if (OpenClipboard(this.Handle))
{
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
IntPtr ptr = GetClipboardData(CF_ENHMETAFILE);
if (!ptr.Equals(new IntPtr(0)))
{
Metafile metafile = new Metafile(ptr,true);
//Set the Image Property of PictureBox
this.pictureBox1.Image = metafile;
}
}
CloseClipboard();
}
|
33.6 How can I swap colors in a bitmap or icon?
|
|
You use ImageAttributes, adding a ColorMap that swaps the colors. Here is a
code snippet.
|
Bitmap originalBMP = (Bitmap) Image.FromFile(@"c:\circle.bmp");
//make a copy so original will still be available
Bitmap swappedBMP = new Bitmap(originalBMP);
Graphics g = Graphics.FromImage(swappedBMP);
// Create a color map.
ColorMap[] colorSwapper= new ColorMap[2];
colorSwapper[0] = new ColorMap();
colorSwapper[1] = new ColorMap();
colorSwapper[0].OldColor = Color.Red; //red changes to yellow
colorSwapper[0].NewColor = Color.Yellow;
colorSwapper[1].OldColor = Color.Blue;//blue changes to green
colorSwapper[1].NewColor = Color.Green;
// Create an ImageAttributes object, and call SetRemapTable
ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetRemapTable(colorSwapper);
//overdraw the bitmap with swapped colors
g.DrawImage(swappedBMP, new Rectangle(0, 0,
swappedBMP.Width, swappedBMP.Height),0, 0, swappedBMP.Width,
swappedBMP.Height, GraphicsUnit.Pixel, imageAttr);
pictureBox1.Image = swappedBMP;
|
|
Here is similar code that wraps this technique in a method that swaps a single
color.
|
protected void DrawMyBitmap(Graphics gph, Color oldColor, Color newColor,
Bitmap baseImage, Rectangle rect)
{
ImageAttributes imgattr = new ImageAttributes();
ColorMap[] clrmap = new ColorMap[1]{ new ColorMap() };
clrmap[0].OldColor = oldColor;
clrmap[0].NewColor = newColor;
imgattr.SetRemapTable(clrmap);
gph.DrawImage(baseImage,rect,0,0,rect.Width,
rect.Height,GraphicsUnit.Pixel,imgattr);
}
|
33.7 How do I create a new image off a base image with certain portions of the
base image modified, in code?
|
|
To delete a tabpage, you use the tabControl1.Controls.Remove method. To add a
new page as the last tab, use the tabControl1.Controls.Add method. Here is some
sample code.
|
//remove the selected tab
tabControl1.Controls.Remove(tabControl1.SelectedTab);
//add a new tabpage as the last tab
tabControl1.Controls.Add(new TabPage("new Page"));
|
|
There does not appear to be support in the framework for inserting a tab at a
particular position. A work around might be to save the current tabpage
controls, clear the Controls collection, and then add the saved controls back
to the Controls collection inserting a new tab. Here is some code that does
this.
|
private void InsertTab(int tabNumber, ref TabControl tabControl)
{
int limit = tabControl.Controls.Count;
if(tabNumber < 0 || tabNumber > limit)
{
tabControl.Controls.Add(new TabPage("new Page"));
return;
}
int target = tabControl.SelectedIndex;
//save the existing pages & clear the controls
Control [] c = new Control[limit];
tabControl.Controls.CopyTo(c, 0);
tabControl.Controls.Clear();
//add the earlier pages
for (int i = 0; i < target; ++i)
tabControl.Controls.Add(c[i]);
//insert the page
tabControl.Controls.Add(new TabPage("new Page"));
//add the later pages
for (int i = target; i < limit; ++i)
tabControl.Controls.Add(c[i]);
//select the new page
tabControl.SelectedIndex = target;
}
|
33.8 How do I extract a Bitmap from an icon of a specific size?
|
Icon icoClose;
// Initialize this icoClose from the resource (for example). Code omitted.
… … …
// Now create a new icon off this base icon with the required size (18 X 18) in
this case.
Icon icoClose18By18 = new Icon(icoClose, 18, 18);
// Create a bitmap off this icon.
Bitmap bmpClose = icoClose.ToBitmap();
|
33.9 How to draw a shadow for a given transparent image?
|
|
The following method will draw a shadow of the supplied image at the specified
location. The general usage pattern is to call this method first to draw a
shadow at a (2,2) offset from where the original image will be drawn and then
draw the original image itself.
|
public static void DrawShadow(Graphics g, Image iconImage, int left, int top)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = 0;
cm.Matrix11 = 0;
cm.Matrix22 = 0;
cm.Matrix33 = 0.25f;
ia.SetColorMatrix(cm);
g.DrawImage(iconImage, new Rectangle(left, top, iconImage.Width,
iconImage.Height), 0, 0, iconImage.Width, iconImage.Height,
GraphicsUnit.Pixel, ia);
}
|
33.10 How to draw a faded image?
|
|
The trick is to use an alpha component while drawing the image.
|
// transparency should be in the range 0 to 1
protected void DrawScrollImage(Graphics g, Rectangle rect, Image image, float
transparency)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = 1;
cm.Matrix11 = 1;
cm.Matrix22 = 1;
cm.Matrix33 = transparency;
ia.SetColorMatrix(cm);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height,
GraphicsUnit.Pixel, ia);
}
|
33.11 How do I overlay one bitmap over another?
|
|
You can create a Graphics object from the base bitmap, and then use this
Graphics object to draw the second bitmap with a transparent color that allows
the base bitmap to show through.
|
Bitmap Circle = (Bitmap)Image.FromFile(@"c:\circle.bmp");
Bitmap MergedBMP = (Bitmap)Image.FromFile(@"c:\cross.bmp");
Graphics g = Graphics.FromImage(Circle);
MergedBMP.MakeTransparent(Color.White);
g.DrawImage(MergedBMP,0,0);
g.Dispose();
pictureBox1.Image = Circle;
|
33.12 How do I get the color of a pixel in my bitmap?
|
|
Use the Bitmap.GetPixel method.
|
[C#]
Color c = myBitmap.GetPixel( xPos, yPos);
[VB.NET}
Dim c as Color = myBitmap.GetPixel( xPos, yPos)
|
33.13 How do I capture a bitmap of my form?
|
|
You can import the BitBlt API to handle this problem. Here is a solution
offered by Simon Murrell and Lion Shi in the
microsoft.public.dotnet.windows.forms newsgroup. The number used below,
13369376, is Int32 SRCCOPY = 0xCC0020;
|
You can use Gdi32 dll. You can define the BitBlt method found within the Gdi32
dll with the code below.
[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
ntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);
And you can then use the copy below in a button click event to save the form to
an image.
Graphics g1 = this.CreateGraphics();
Image MyImage = new Bitmap(this.ClientRectangle.Width,
this.ClientRectangle.Height, g1);
Graphics g2 = Graphics.FromImage(MyImage);
IntPtr dc1 = g1.GetHdc();< BR >
IntPtr dc2 = g2.GetHdc();
BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1,
0, 0, 13369376);
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);
MyImage.Save(@"c:\Captured.bmp", ImageFormat.Bmp);
You will need to use the System.Drawing.Imaging namespace.
|
|
Here is VB code posted by Armin Zingler in the
microsoft.public.dotnet.languages.vb newsgroup.
|
33.14 How do I automatically resize the Form when the screen resolution changes
between design-time and runtime?
|
|
Public Class Win32
Public Declare Function BitBlt Lib "gdi32" Alias "BitBlt" _
(ByVal hDestDC As Integer, ByVal x As Integer, _
ByVal y As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Integer, ByVal hSrcDC As Integer, _
ByVal xSrc As Integer, ByVal ySrc As Integer, _
ByVal dwRop As Integer) As Integer
Public Declare Function GetWindowDC Lib "user32" Alias "GetWindowDC" _
(ByVal hwnd As Integer) As Integer
Public Declare Function ReleaseDC Lib "user32" Alias "ReleaseDC" _
(ByVal hwnd As Integer, ByVal hdc As Integer) As Integer
Public Const SRCCOPY As Integer = &HCC0020
End Class
Public Class Hardcopy
Public Shared Function CreateBitmap( _
ByVal Control As Control) _
As Bitmap
Dim gDest As Graphics
Dim hdcDest As IntPtr
Dim hdcSrc As Integer
Dim hWnd As Integer = Control.Handle.ToInt32
CreateBitmap = New Bitmap(Control.Width, Control.Height)
gDest = gDest.FromImage(CreateBitmap)
hdcSrc = Win32.GetWindowDC(hWnd)
hdcDest = gDest.GetHdc
Win32.BitBlt( _
hdcDest.ToInt32, 0, 0, Control.Width, Control.Height, _
hdcSrc, 0, 0, Win32.SRCCOPY _
)
gDest.ReleaseHdc(hdcDest)
Win32.ReleaseDC(hWnd, hdcSrc)
End Function
End Class
'In your Form:
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim bmp As Bitmap
bmp = Hardcopy.CreateBitmap(Me)
bmp.Save("c:\test.bmp")
End Sub
|
33.15 How do I create a new bitmap with a new size based on an existing bitmap?
|
|
You can simply specify the new size in the Bitmap constructor as follows:
|
[C#]
Bitmap bmp = new Bitmap("exisiting.bmp");
// Create a new bitmap half the size:
Bitmap bmp2 = new Bitmap(bmp, bmp.Width*0.5, bmp.Height*0.5);
this.BackgroundImage = bmp2;
[VB.Net]
Dim bmp As New Bitmap( "exisiting.bmp")
' Create a new bitmap half the size:
Dim bmp2 As New Bitmap( bmp, bmp.Width * 0.5, bmp.Height * 0.5)
Me.BackgroundImage = bmp2
|
|
If you have to specify a particular Interpolation mode while resizing use the
following code:
|
[C#]
Bitmap bmp = new Bitmap("exisiting.bmp");
// Create a new bitmap half the size:
Bitmap bmp2 = new Bitmap( bmp.Width*0.5, bmp.Height*0.5,
Imaging.PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp2);
// Set interpolation mode
g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// Draw image using specified interpolation mode.
g.DrawImage(bmp, 0, 0, bmp2.Width, bmp2.Height);
this.BackgroundImage = bmp2
[VB.Net]
Dim bmp As New Bitmap( "existing.bmp")
Dim bmp2 As New Bitmap( bmp.Width * 0.5, bmp.Height * 0.5,
Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(bmp2)
' Set interpolation mode
g.InterpolationMode =
<
BR > Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
' Draw image using specified interpolation mode.
g.DrawImage(bmp, 0, 0, bmp2.Width, bmp2.Height)
Me.BackgroundImage = bmp2
|
33.16 How can I read individual frames from an animated image?
|
|
GDI+ has direct support for reading and outputting animated images.
To get at the individual frames, you can use the image's FrameDimensionList,
and then call SelectActiveFrame, by passing in the dimension and the zero based
frame index.
First, create a new FrameDimension object:
|
FrameDimension dimension = new
System.Drawing.Imaging.FrameDimension(myImage.FrameDimensionsList[0]);
|
|
Once you have the dimension, you can get the frame count:
|
|
int frameCount = myImage.GetFrameCount(dimension);
|
|
Now, that you know the frame count of the image, you can call SelectActiveFrame
by passing in the dimension and the frame index (zero based).
|
|
myImage.SelectActiveFrame(dimension,1);
|
|