The Graphic Device Interface for the MFC

Here we are at the third article. After revising the way Windows works through two of the most used Visual Studio tools for MFC programmers, it is time to learn something concrete. Throughout this article, the object discussed will be the GDI (Graphic Device Interface). Here we can expect to learn about the following things: printing text to the client area, some mouse input-related information, and the CPen and CBrush classes.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 3
March 12, 2008
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

The world is our property. We can do anything with a little sacrifice and devotion. I can say that if you've arrived here, then you are already one step closer to achieving your goals and dreams. However, if you haven’t read the first two segments, I strongly recommend suspending this reading session and searching for the articles that describe the basic things required to continue our journey in the world of the Microsoft Foundation Class library They were also published here in the ASP Free, so finding them shouldn’t be a problem.

As promised, we will get some real MFC code. But before that, we need to go over the concept of a device: how it works, and how we can use it to our benefit. It will only be the basic knowledge. Advanced devices are beyond the purpose of this article.

General Concepts of the GDI

Windows is a graphic operating system, so it shouldn’t surprise you that everything is drawn to the screen, even the text. To simplify this process, Windows has implemented a library of functions that allow for different usage of the “graphical pictures” in a multitude of ways. As everything is an image for Windows, you must call for every modification on the screen in one of the GDIs.

Beyond the functions required for transferring the data to the screen, a GDI interface also holds a set of objects for the drawing process. This is made up of the following components:

Device context – A set of attributes that define the surface on which the images and the objects are shown.

Pen – Object for driving a line.

Brush – An object for filling a contour present on the screen.

Font – Doha, Character style…

Bitmap – One object containing an image is coming up.

Palette – Another object containing a set of colors that will be used for showing an image on the screen.

All of these help create the final image drawn to your screen. Therefore, we can conclude that a device context is a collection of attributes that will, eventually, determine the way images are shown within a window. A DC (device context) has lots of attributes, but most of them aren’t related to your trouble because when you get the DC, Windows automatically initializes them.

Of course, you can change them manually. For example, the color of the Pen will always be black. If you want to write text with a purple color, you will have to change this attribute. It can easily be done because, as I said before, all is created for you. Should you want to customize its particularities, then that’s your only task.

A DC must always have a full set of instruments; you can’t eliminate some instruments from it. But you can switch between them. So when you want to go back to the default GDI object, all you do is change it with the default instrument. Also a DC represents the borders of a specific window. Each time you draw outside of it, Windows automatically makes a fast resize to avoid this “drawing outside the box” scenario. This way you are limited only to drawing in the client area, not outside of it.

This entire GDI story is integrated in a series of classes for the sole purpose of simplifying its usage. The biggest of them is the CDC class. The MFC library derives a few classes from it:

CClientDC – Context for assuring access to the client area of a window. This should be used as a response to any of the messages, excluding one: the WM_PAINT message.

CPaintDC - The reason for the prior exception is this class, as this was designed for that individual message, so it must be used only for it.

CMetaFileDC - A context that holds a metafile and is under Windows. It is a file that contains a list of commands for the fast reproduction of a picture.

CWindowDC – The context that gives you access to the entire window, not just the client area.

We’ve just finished the necessary theoretical knowledge! Should you have trouble understanding the DCs, have no fear, as everything will become clear with the example presented on the next page; we’ll learn to write text on the client area.

Practice and Text

In this section, as I promised, we're going to learn how to write a particular text on the client area. Before we begin, let's clarify something. Each time you use a Device context, you should create it. This can be done by declaring a new device context that is linked to the client area you wish to use. Some of the functions that are addressed towards a message map already carry one of these control devices. As a result, in these cases you don't have to create it yourself.

These are the functions that you will obviously and explicitly use like the WM_DRAW message present in any view class under the OnDraw name. The WM_DRAW message is dispatched towards the program at any time the window’s content needs to be updated — redrawn. If you passed through the first two segments of this article series, then you should have created the MFC_example named application. In its view class (CMFC_exampleView), the OnDraw function looks like this:


void CMFC_exampleView::OnDraw(CDC* /*pDC*/)

{

CMFC_exampleDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if (!pDoc)

return;


// TODO: add draw code for native data here

}


After this, the device creation is commented as the /*pDC*/ part, but after we remove this comment, we can use it without borders. Now we can call one of the many functions that a DC context has. For example, drawing a rectangle can be accomplished in the following line:

pDC->Rectangle( 100, 120, 400, 500);

To exemplify, we’ll create a rectangle from the upper right coordinates (100,120) and the lower right coordinates (400,500). The functions present in a DC are massive, so search for them in the MSDN help files or in an MFC bible. But if you want to use a DC in a function where it doesn’t comes so swiftly, you can declare it with the following line:

CClientDC clientDC(this);

We create a CClientDC device context that is called clientDC (you could also call it my_cat, but for standard coding and for easy understanding, this name suits it the most). This DC is assigned to the current view area. This is realized by calling it for the this pointer. The device can be initialized in other ways too, but this is the most useful because we don’t need to worry about its destruction. As a rule of C programming, all local variables are destroyed at the end of a function.

Enough said! Let’s take a look at the attached code below. It contains many new things; each of them will be covered right after this code snippet.


void CMFC_exampleView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call a // default

CClientDC clientDC(this); // we create a DC that will be used

 

COLORREF color = clientDC.GetTextColor();

if(color == RGB (0, 0, 0)) // if the background color is black

clientDC.SetTextColor( RGB(255,0,0)); //change it


//we set the Background of the text to transparent

//so windows will draw out only the text, ignoring the BK

clientDC.SetBkMode( TRANSPARENT );

//add some extra character depending upon X coordinates

clientDC.SetTextCharacterExtra(point.x/10);

 


//create a pen

int width =3;

CPen newPen (PS_SOLID, width, color);

CPen* oldPen = clientDC.SelectObject( &newPen);

//create a brush

CBrush newBrush( HS_CROSS, RGB(0,0,255) );

//select for usage the newly created Brush, replacing the old

CBrush* oldBrush = clientDC.SelectObject( &newBrush);


//Click = Dong at that coordinate

clientDC.TextOutW( point.x, point.y,CString("Dong"));

//and an ellipse just below our click

clientDC.Ellipse( point.x + 30, point.y+ 50, point.x +100,point.y + 150);


//change back tom the old Brush

clientDC.SelectObject(oldBrush);

clientDC.SelectObject(oldPen);


CView::OnLButtonDown(nFlags, point);

}


The upper code writes out Dong where we left click and an ellipse right below it. If you don’t comprehend the code, then the next paragraphs were written for you. They hold some valuable extra information.

Practice and Text continued

MFC has a few classes that are very useful. For example, look at the CString class. It is just like STL’s string. It replaces the char arrays, but this allocates its memory dynamically. It has some additional advantages also. But going into the depths of it is, unfortunately, beyond the purpose of this article.

Notwithstanding, let’s start from the beginning. At first, we create the necessary DC to allow us to draw to the client area. This is followed by declaring a 24-bit color to be the current text color. Now, if that is black — the default — then we will change it to red. The RGB color is made out of the three basic colors, using the following scheme: RedGreenBlue (Red amount, Green amount, Blue amount).

The amount can be a value between 0 and 255. Now the RGB (0, 0, 0) stands for the black color, while the RGB (255, 255, 255) represents the white. For a text, the background can be either TRANSPARENT or OPAQUE. The transparent attribute ignores the background color and only the text itself will be drawn.

There are many other really advanced text functions and as a foretaste, I’m presenting you the Spacing one. Basically, it adds extra spaces between the characters. As for the text part, we’ll only need to call the TextOutW (only TextOut for Visual Studios prior to the .Net platform). The first two parameters are the starting coordinates from where the code will be drawn, while the third parameter holds the content. The text is in a CString type variable.

I’ve added some other dedicates. The CPen class is for the line style along with what the DC is drawing to the client area. The CBrush holds the pattern, which helps fill in the contour. The constructors each have a style and a color parameter, then there's the CPen and extra width parameter. Here I showed you how you can replace the customized settings.

The SelectObject function replaces the assigned object and returns a pointer to the old object. Now if we choose to save this, we can later make a switch back to the old settings so that when we are writing a program, we always have the default settings. This way we might prevent those irritating situations where we are expecting one thing, but thanks to some of our changes at a different place in the code, we are dealing with a different situation.

Just another remark: since we have written this code on the OnLButtonDown section and not in the OnDraw function, when the window requires a redraw (e.g.; minimizing the application), the previous image in its entirety will disappear. To solve this problem we should implement a saving/serializing algorithm and make the drawing part in the OnDraw function.

We can force a redraw of the client area by calling the Invalidate() function first. This will result in the repainting of the client area at the next WM_PAINT message. Now we will also send a message, specifically a WM_PAINT one. We can individually send any message, but think about the results before you do. The combo will look like this:


Invalidate ();

const char *Msg = "The sent message";

SendMessage(WM_PAINT, 0, (LPARAM)(LPCTSTR)Msg);

Conclusion

Below you can find our application attached, so you can start it up at any time.

 

It is official. We have reached the end of the third part. The timing is perfect for a brief review of everything we just learned. This segment was dedicated to the Device Interfaces and some real-world code. At this point, you should have a picture of MFC in your head.

In the next part, we are going to learn how to handle common, or standard, controls. Also, we’ll get a look at the image handling process. Yes, image handling. The reason for that is because nowadays every application uses some kind of image to give it a sense of style and user-friendliness.

An image is worth more than a thousand words and with the high quality pictures present, we can easily shape our little application into a more attractive one. But for more about this, you will have to return for the next part.

Until then, as usual, have an amazing day and don't go too far because the next article is coming up soon. You'll find it here on ASP Free as soon as it goes live. However, in the mean time, if there are any further questions or unresolved issues that are related to this article or to IT in general, visit the friendly, ever-growing community at DevHardware Forums.

blog comments powered by Disqus
BRAINDUMP ARTICLES

- Microsoft Windows 8 Committed to Cloud Compu...
- Independent Developers Favor Windows Phone 7
- Dell Introduces VMware-based Cloud
- Microsoft and Skype Agree to Acquisition Deal
- Transfer Contacts in Microsoft Outlook
- Zune`s Next Steps
- Safari Books Online Review
- Does Microsoft Get Touch Screens Now?
- Microsoft`s Record Quarterly Earnings Not En...
- Basic Operations and Registers in Assembly
- Assembly Coding within Visual C/C++ IDE
- New Microsoft Office Coming with a Twist
- Microsoft`s FUSE Labs Unveils Spindex Social...
- HP Slate with Windows 7: Dead or Alive?
- Windows Phone 7 Mobile OS to Rival Android a...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 7 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials