MFC and VC++ EXPERIMENTS: Part II
Posted On September 14, 2006 by Ramdas S filed under
What are the various Resources in VC++?
1. Menu
2. Dialog
3. Bitmap
4. Toolbar
----------
5. Cursor
6. Icon
7. Accelerator
---------
8. String Table
9. Version.
----------
We have listed the various resources according to their order of importance. The first group is very important while the other two are less so.
Let us now see a very simple example of creating a menu and using it.
The procedure is as follows:
1. file è new è filetype è resource script;
2. We get a folder;
3. Right-click on the folder;
4. We get a context-menu
5. Select 'insert';
6. We get a list of resources like accelerator, menu, etc.;
7. Select è menu è new;
8. We get a dotted rectangle (menu1);
9. Double-click on this rectangle and give caption for 'menu1' (say) shapes;
10. We get a rectangle below menu1;
11. Double-click on this rectangle (item1);
12. Give id as '101' caption 'square';
13. A rectangle (item2) will appear below this;
14. Give id=102 and caption="circle"; and so on.
In this example, the caption of top-level menu is 'shape'. (In java, this will be:
Menu menu1;
menu1 = new Menu("shapes");
MenuItem item1,item2;
item1 = new MenuItem("square");
item2 = new MenuItem("circle");]
When we create such a menu visually, the IDE automatically creates a text file as *.rc.
How do we find out the equivalent text file thus created by the IDE?
FILE è open è *.rc
(IMPORTANT NOTE: Remember to locate the combo named 'open as' and select 'text' from the choices offered.)
The IDE will inform that the file is open in the editor and then display the text file. It will look very much like a C file with include statements, etc. But, it is not really a C file. This text file is compiled by the resource compiler and linked to the compiled source file at run-time.
The actual text file created by the IDE is given below:
IDR_MENU1 MENU DISCARDABLE
BEGIN
POPUP "shape"
BEGIN
MENUITEM "square", 101
MENUITEM "circle", 102
END
END
Having thus created the menu in the Resource editor, we have to use it in our source file.
For menu-based programs, the pattern is as given in code 6.
Code 6
declare: CMenu menu1;
int n;
define:
menu1.LoadMenu(IDR_MENU1);
SetMenu(&menu1);
n=0;
macro:
ON_COMMAND(101,job1)
ON_COMMAND(102,job2)
function:
void job1()
{
n=1; Invalidate();
}
void job2()
{ n=2; Invalidate();}
We can write suitable code in paint for n==1 and n==2, as required. Refer code 7.
Code 7
DEMO-04 // menu-events
#include <afxwin.h>
class myframe : public CFrameWnd
{
// DECLARATION
public:
CMenu menu1;
int n;
myframe() // CONSTRUCTOR
{
Create(0,"");
menu1.LoadMenu(IDR_MENU1);
SetMenu(&menu1);
}
void job1()
{
n=1; Invalidate();
}
void job2()
{
n=2; Invalidate();
}
void OnPaint() // FUNCTION
{
CPaintDC dc(this);
if(n==1) { dc.Rectangle(200,100,400,300);}
if(n==2) {dc.Ellipse(200,100,400,300);}
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(myframe,CFrameWnd)
ON_WM_CHAR()
ON_WM_PAINT() // MACRO
END_MESSAGE_MAP()
class myapp : public CWinApp
{
// as usual
};
It has been mentioned earlier that the most important resources are Menu, Dialog, Bitmap and Toolbar. We have just now seen the Menu.
The Toolbar resource is very similar to Menu. Instead of first selecting a topmenu, clicking it and then selecting the required item from the options, it is deemed to be more productive to offer direct access to the menuitem in the form of toolbar buttons.
So, we will now see how we create a toolbar using the Resource editor and connect it in code.
As in the case of creating any resource, we get at the resource folder, select it è right-click è insert è toolbar è new.
We are taken to the toolbar editor and a small square appears along with graphics tools and color palette. We can draw some figure in the square using these tools. Whatever we draw on this square immediately appears on the toolbar button. We can have as many toolbar buttons as we want. Then, we double-click on the first button. A dialog appears. Give id as 101, 102, etc. corresponding to the existing menu-event handlers. Check out code 8.
Code 8
DEMO-05 // TOOLBAR DEMO
#include <afxwin.h>
#include "resource.h"
#include <afxext.h> // IMPORTANT!
class myframe : public CFrameWnd
{
public:
CToolBar toolbar1;
int n;
myframe()
{
Create (0,"");
n=0;
}
int OnCreate(LPCREATESTRUCT S)
{
CFrameWnd::OnCreate(S);
toolbar1.Create(this);
toolbar1.LoadToolBar(IDR_TOOLBAR1);
return 0;
}
void job1()
{
n=1;
Invalidate();
}
void job2()
{
n=2;
Invalidate();
}
void OnPaint()
{
CPaintDC dc(this); if(n==1){dc.TextOut(200,200,"sunday");}
if(n==2){dc.TextOut(200,200,"monday");}
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(myframe,CFrameWnd)
ON_COMMAND(101,job1)
ON_WM_CREATE()
ON_COMMAND(102,job2)
ON_WM_PAINT()
END_MESSAGE_MAP()
class myapp : public CWinApp
{
// AS USUAL
};
myapp app;
Procedure for displaying image in MFC
Let us now take up the trickiest task for beginners in MFC, i.e. displaying an image programmatically. In VB, it is as simple as:image1.picture=loadpicture("c:\mathew.gif")
However, it is a lot more difficult in VC++.
1. Go to PAINT
2. Set Image Attribute:
WIDTH=160 (say)
HEIGHT=200 (say)
3. Draw some figure with color.
4. Save as c:\picture1.bmp
(256 COLOR BITMAP)
IN MFC,
· File è new è resource script
· We get a folder· Right-click on the folder
· We get a popup menu
· Select 'insert'
· We get a list of resources (like accelerator, bitmap, etc.)
· Select bitmap an IMPORT
· Browse to c:\picture1.bmp
· This will be now added to project as:IDB_BITMAP1
Remember! Do not forget to add this in the source file:
#include "resource.h" The important point to be noted is that we cannot directly use picture file with *.jpg, *.gif extensions. We must first convert such files into *.bmp (only 256 color bmp). We can use 'paint' or 'photo-editor' program for this purpose. We can save such 256 color bmp files as mathew256.bmp (for example).
It is also necessary to note down the original width and height of the image file. In our example, width=160 & height=200.
When we import such a file into our project, it is given a default id as 'IDB_BITMAP1'. We need not change it.
We cannot display an image file directly on the screen. First we create a device-context in memory, compatible with either CClientDC or CPaintDC. We create bmp1 of CBitmap class and load our IDB-BITMAP1 into our bmp1. Then we select bmp1 int the memory device-context.
Finally, we render the image on screen using BitBlt (bit-block-transfer) or StretchBlt (stretch-block-transfer) functions. BitBlt is used for rendering without enlarging or decreasing the size. StretchBlt is used for either enlarging or reducing the size of the picture.
We can illustrate the three modes by using key-events with the condition:
if( k='1') {dc.BitBlt(.....
if( k='2') {dc.StretchBlt(...
if( k='3') {// tiling code}
These introductory remarks should allow the reader to easily follow the full code given in code 9.
Code 9
DEMO-06 // Displaying Bitmaps
#include <afxwin.h>
#include "resource.h" // note carefully
class myframe : public CFrameWnd
{
// DECLARATION
private:
char k;
public:
myframe() // CONSTRUCTOR
{
Create(0,"");
k='z';
}
void OnChar(UINT a, UINT b, UINT c)
{
k=(char) a; // FUNCTION
Invalidate(); // go to paint
}
void OnPaint()
{
CPaintDC dc(this);
CBitmap bmp1;
bmp1.LoadBitmap(IDB_BITMAP1);
CDC mdc;
mdc.CreateCompatibleDC(&dc);
mdc.SelectObject(&bmp1);
if(k= ='1')
{
dc.BitBlt(100,100,160,200,&mdc,0,0,SRCCOPY);
}
if(k= ='2') // enlarging
{
dc.StretchBlt(100,100,200,250,&mdc,0,0,160,200,SRCCOPY);
}
if(k= = '3') // tiling
{
for(int k=0; k<600; k=k+200)
{
for( int j=0; j<800; j=j+160)
{
dc.BitBlt(j,k,160,200,&mdc,0,0,SRCCOPY)'
}
}
}
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(myframe,CFrameWnd)
ON_WM_CHAR()
ON_WM_PAINT() // MACRO
END_MESSAGE_MAP()
class myapp : public CWinApp
{
// as usual
};
myapp app;
What are the various Device-Contexts in MFC?
- CDC (parent class);
- CpaintDC (erasing context);
- CClientDC (local/non-erasing context);
- CwindowDC; and
- CmetaFileDC.
We have already given demonstrated CDC, CPaintDC and CClientDC.
What is CWindowDC?A typical window is made up of the following components:
- Title bar;
- Menu bar;
- Tool bar;
- Status bar; and
- Dialog bar (like toolbox).
Supposing that we want to print a message in the title bar itself, it cannot be done except by CWindowDC. In that case, the anchor point (origin) becomes the top-left corner of the window. The code will be as shown below:
if( k=='1')
{CWindowDC dc(this);
dc.TextOut(5,5,"hello");
dc.MoveTo(0,0);
dc.LineTo(200,200);
}
MetaFileDC is a very nice feature in MFC. We can create a shape by graphics command and draw that in metafile-context i.e. an mdc in hard disk. We can get back to this graphics after closing the program because the graphics is in the hard disk. HMETAFILE is the handle to the metafile. Using this we can redraw the graphics.
It should be observed that, this is a very powerful and elegant solution to store a graphics in file! But the syntax should be followed strictly. Check out code 10.
Code 10
DEMO-07 // MetaFileDC
#include <afxwin.h>#include <afxext.h> // IMPORTANT
class myframe : public CFrameWnd
{
public:
myframe()
{
Create(0,"");
}
void OnChar(UINT a, UINT b, UINT c)
{
char k = (char) a;
if(k=='1')
{
CMetaFileDC mdc;
mdc.Create("c:\\myfile");
mdc.Rectangle(200,100,300,200);
mdc.TextOut(50,50,"hello");
mdc.Close();
MessageBox("metafile created in hard disk");
}
if(k=='2') // retrieve the file and display
{
CClientDC dc(this);
HMETAFILE hm = GetMetaFile("c:\\myfile");
dc.PlayMetaFile(hm);
}
}
DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(myframe, CFrameWnd)
ON_WM_CHAR()
END_MESSAGE_MAP()
class myapp : public CWinApp
{
// AS USUAL
}
myapp a ;
