A humble attempt to explain GDI stock objects…
So what are stock objects? “Stock” as the name says means goods in hand, which a shop keeper always has as a backup. In the same way GDI also keep a set of backup of objects which it creates during initialization and these are known as stock objects. Let’s think of a case like this… you are creating a fancy brush but somehow the creation fails, so what will be your backup policy, mine would be to use a stock brush, for e.g. BLACK_BRUSH since these objects are always available. Think of a case where you have to quickly create a black brush, I would go for stock object BLACK_BRUSH.
Following are the stock objects that I know, taken straight out of MSDN…
Value | Meaning |
---|---|
BLACK_BRUSH | Black brush. |
DKGRAY_BRUSH | Dark gray brush. |
DC_BRUSH | Windows 2000/XP: Solid color brush. The default color is white. The color can be changed by using the SetDCBrushColor function. For more information, see the Remarks section. |
GRAY_BRUSH | Gray brush. |
HOLLOW_BRUSH | Hollow brush (equivalent to NULL_BRUSH). |
LTGRAY_BRUSH | Light gray brush. |
NULL_BRUSH | Null brush (equivalent to HOLLOW_BRUSH). |
WHITE_BRUSH | White brush. |
BLACK_PEN | Black pen. |
DC_PEN | Windows 2000/XP: Solid pen color. The default color is white. The color can be changed by using the SetDCPenColor function. For more information, see the Remarks section. |
NULL_PEN | Empty pen. |
WHITE_PEN | White pen. |
ANSI_FIXED_FONT | Windows fixed-pitch (monospace) system font. |
ANSI_VAR_FONT | Windows variable-pitch (proportional space) system font. |
DEVICE_DEFAULT_FONT | Windows NT/2000/XP: Device-dependent font. |
DEFAULT_GUI_FONT | Default font for user interface objects such as menus and dialog boxes. This is MS Sans Serif. Compare this with SYSTEM_FONT. |
OEM_FIXED_FONT | Original equipment manufacturer (OEM) dependent fixed-pitch (monospace) font. |
SYSTEM_FONT | System font. By default, the system uses the system font to draw menus, dialog box controls, and text.Windows 95/98 and Windows NT: The system font is MS Sans Serif.Windows 2000/XP: The system font is Tahoma |
SYSTEM_FIXED_FONT | Fixed-pitch (monospace) system font. This stock object is provided only for compatibility with 16-bit Windows versions earlier than 3.0. |
DEFAULT_PALETTE | Default palette. This palette consists of the static colors in the system palette. |
If you look at above table, we can see that almost all GDI object classes (exceptions are regions and bitmaps) has a backup stock object, mainly to act as a fallback method just in case of a failure IMO.
To use retrieve a stock object we call function GetStockObject. The good thing about working with a stock object is that we don’t have to delete it, since we didn’t create it. Now think how easy it’s to create a black pen, or black brush. No overheads to delete/free them. It’s definitely faster too.
There is a brush called NULL_BRUSH, a pen called NULL_PEN which are quite useful to draw a hollow rectangle without any fill, instead of selecting a brush equivalent to background window color to simulate drawing a rectangle without any fill.
CDC class of MFC has a very easy to use function for stock object. It’s CDC::SelectStockObject. I’m going nuts for this function. 😉 Take a look at these calls….
// Select a black brush CDC ClientDC; ClientDC.Attach( ::GetDC( m_hWnd )); const int RestorePoint = ClientDC.SaveDC(); // Select a black brush ClientDC.SelectStockObject( BLACK_BRUSH ); // Select a black pen ClientDC.SelectStockObject( BLACK_PEN ); // Select existing font ClientDC.SelectStockObject( <strong>DEVICE_DEFAULT_FONT</strong> ); ClientDC.RestoreDC( RestorePoint );
See how easy it’s to use these stock objects. No overhead of creating or freeing them, but as I already said these are just for backup action purpose. For fancy stuff you of course have to go for other functions.
So bottom line is stock objects are just to avoid cases were you end up with no brush to paint or no pen to write. 🙂
Making many drawing calls using just one API call!
Use Polyxxxx set of functions. Some of the functions that I know are listed below
- PolyPolyline
- PolyTextOut
- PolylineTo
- PolyDraw
- PolyBezier
- PolyBezierTo
From MSDN:
These functions exploit the fact that many drawing calls use identical attributes, and so multiple items can be drawn in a single call once the brushes, pens, colors, and fonts have been selected. For example, the console window uses PolyTextOut. This change significantly reduces scrolling time in a console window.
Retrieving current text color of a DC!
Use GetTextColor! Function signature is as follows…
// MFC COLORREF GetTextColor() const; // SDK COLORREF GetTextColor( HDC hdc ); // handle to DC
Retrieving face name of font selected into a DC!
Use GetTextFace function! Function signature is as follows…
// MFC int GetTextFace( CString& rString ) const; // SDK int GetTextFace( HDC hdc, // handle to DC              int nCount, //length of typeface name buffer                 LPTSTR lpFaceName // typeface name buffer               );
Retrieving graphics objects selected into a DC!
Felt the need to retrieve current brush or pen or palette selected into a DC? Sometime back a friend of mine asked me this question, as an answer I gave him a better solution, but the question was a valid one!
So are there any windows api’s that helps us in the regard? Well the answer is yes, use GetCurrentObject and GetObject in tandem to retrieve details of graphics object selected into a dc.
GetCurrentObject signature
HGDIOBJ GetCurrentObject( HDC hdc, // handle to DC UINT uObjectType // object type );
Lookup MSDN for possible values of uObjectType.
GetObject signature
int GetObject( HGDIOBJ hgdiobj, // handle to graphics object int cbBuffer, // size of buffer for object information LPVOID lpvObject // buffer for object information );
Lookup MSDN for possible values of lpvObject in GetObject. Here is an example of how to use these functions!
// Use GetCurrentObject to get current brush selected in to a DC HBRUSH hCurrentDCBrush = GetCurrentObject( hDC, OBJ_BRUSH ); // Get brush details LOGBRUSH lCurrentBrushDetails = { 0 }; GetObject( hCurrentDCBrush, sizeof( lCurrentBrushDetails ), &lCurrentBrushDetails );
Drawing outlined text!
How to draw text like this!
Looks interesting right! Well this is done using plain window’s GDI functions, here is a function which does this!
// Thanks to Charles Petzold! void CCanvas::DrawOutlineText( CDC& dc, const CString& Text ) {  const int RestorePoint = dc.SaveDC(); // Create new font  CFont NewFont;  NewFont.CreatePointFont( 700, TEXT( "Verdana" ), &dc ); // Use this font  dc.SelectObject( &NewFont ); // Brush for pen  LOGBRUSH lBrushForPen = { 0 };  lBrushForPen.lbColor = RGB( 200, 150, 100 );  lBrushForPen.lbHatch = HS_CROSS;  lBrushForPen.lbStyle = BS_SOLID;  // New pen for drawing outline text  CPen OutlinePen;  OutlinePen.CreatePen( PS_GEOMETRIC | PS_SOLID, 2, &lBrushForPen, 0, 0 );  // Use this pen  dc.SelectObject( &OutlinePen );  dc.SetBkMode( TRANSPARENT ); dc.BeginPath();  // This text is not drawn on screen, but instead each action is being  // recorded and stored internally as a path, since we called BeginPath  dc.TextOut( 20, 20, Text );  // Stop path  dc.EndPath();  // Now draw outline text  dc.StrokePath();  dc.RestoreDC( RestorePoint ); }
How to get color of a pixel from any Bitmap?
It’s easy to get color of a pixel from a bitmap. Here is a function which does this…
#include
#include
// Returns Pixel color from bitmap
COLORREF GetPixelValueFromBitmap( const int x, const int y, CBitmap& bmp )
{
// DC for desktop
CDC dcDesktop;
dcDesktop.Attach( ::GetDC( GetDesktopWindow() ));
// Create a DC compatible with desktop or any other existing window
CDC dc;
dc.CreateCompatibleDC( &dcDesktop );
// Save the DC settings here, so that we can restore it later
const int nRestorePoint = dc.SaveDC();
// Select the bitmap into the DC
dc.SelectObject( &bmp );
// Now get the pixels value from the DC
const COLORREF clr = dc.GetPixel( x, y );
// Restore DC settings
dc.RestoreDC( nRestorePoint );
// Return pixel value/color
return clr;
}// End GetPixelValueFromBitmap
// main function
int main()
{
// initialize MFC and print an error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
std::cerr << _T("Fatal Error: MFC initialization failed") << std::endl;
return 1;
}
// Prepare a bitmap
CBitmap bmp;
// Provide your own bitmap id
bmp.LoadBitmap( IDB_BITMAP1 );
// Get color of given pixel from given bitmap
COLORREF clr = GetPixelValueFromBitmap( 0, 2, bmp );
// Split up the colors and see
const int Red = GetRValue( clr );
const int Green = GetGValue( clr );
const int Blue = GetBValue( clr );
return 0;
}// End main[/sourcecode]