Solved

Drawing with GDIplus and double buffering

Posted on 2011-03-04
20
1,123 Views
Last Modified: 2012-06-21
Drawing with GDIplus and double buffering:
0
Comment
Question by:pgmerLA
20 Comments
 
LVL 7

Expert Comment

by:JimBeveridge
ID: 35039322
Please update this topic with the body of your question, otherwise delete the question.
0
 
LVL 9

Expert Comment

by:JohnGaby
ID: 35039331
Could you be more specific.  Are you asking how to double buffer your paints using GDI++?  If so, you can create a Bitmap of the same size as the region you want to paint:

http://msdn.microsoft.com/en-us/library/ms534420%28v=VS.85%29.aspx

Then you can a Graphics object based on that bitmap:

http://msdn.microsoft.com/en-us/library/ms534453%28v=VS.85%29.aspx

You can then paint into the bitmap using the methods of the Graphics class.

Finally, you can create a Graphics object for the DC into which you want to paint and then paint the Bitmap onto that DC using that second Graphics object.
0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35039439
Ok for the next step we would like to actually begin drawing something , wouldn't we?
Find the function WndProc and in there the WM_PAINT case, this is where all the drawing occurs...
Now if we where to draw directly on the window surface, and the drawing would change frequently, we would see a "flickering" effect (very un-pretty) so to overcome that we will commence all the drawing into a bitmap in memory and then copy this entire bitmap to the window surface at once.
So... After the line that says BeginPaint... put:

int width = ps.rcPaint.right - ps.rcPaint.left;
int height = ps.rcPaint.bottom - ps.rcPaint.top;
Bitmap memoryBitmap(width, height);
Graphics(&memoryBitmap);

Open in new window


Now we have the graphics object which we will use to draw everything so let's draw a simple rectangle...

gr.Clear(Color::White);		// Clear to white background
Pen pen(Color::Red);		// This is the pen we will use to draw
gr.DrawRectangle(&pen, 10,10,100,100); // Draw rectangle from 10,10 to 110,110

Open in new window


Now that we drawn something on our memory bitmap it's time to copy it to the actual window surface.
To do so we will create another Graphics object from the HDC of the window that the BeginPaint function created for us:
Graphics grScreen(hdc);

Open in new window

Now just draw the memory bitmap on this new graphics object:
grScreen.DrawImage(&memoryBitmap, 0,0);

Open in new window


That's it if you now run the application this is what you should see:

 Step 2
Now if you'll try to resize the window now you will see that there is still flickering on the rectangle this is happening because window send the WM_ERASEBACKGROUND message prior to painting and erases the window to white, so we need to tell windows that we are handling the erase ourself. To do so add another case statement to the select where the WM_PAINT is located like this:
case WM_ERASEBKGND:
return TRUE;
break;

Open in new window


Now that tells window that the message is received and handled by us...
Try resizing the window now, voila , no flickering.

I am not posting the entire code intentionally since I want you to learn from this and not just blindly copy and paste, how ever if you run into trouble with this I'll post the entire code.

If everything works , on to the next step: "Reading the file and drawing the grid"
0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35039467
Unfortunately I am not aware of any other means of communicating here but the comments... Also sorry it takes time to answer each question, part of it is because of our time difference... (10 hours I believe)
0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35082289
Hey pgmerLA,
Are you stuck? Do you need more help?
0
 

Author Comment

by:pgmerLA
ID: 35104516
Hi SunnyDark,
I am actually stuck in step 1.
I have tried to do it by myself and I am running into trouble.

I have few questions that seems so basic, they are embarrassing to ask.
1.When I create a project, should I click on/off "Precompiled header"?

2.how do I open the stdafx.h file and how do I find "#define WIN32_LEAN_AND_MEAN"?

3.you said to comment it. what do you mean by it?

4. how do I find the InitInstance function?

Thanks for the help.

0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35107075
OK ,
When you create the project choose:
Application type: Windows application
Leave everything else as it is...
All the necessary files will be created for you.

If you followed the instructions and created a new project in Visual Studio 2008 you should heve the following project structure:
 sample
 
As you can see on the left (the location of solution explorer may be different for you) there are the project files... One of them is stdafx.h , you can see it opened in the editor.
On line 10 you can see the following:
#define WIN32_LEAN_AND_MEAN

I've put double forward slash to comment it out (this is how you comment a line in c++, just start it with double forward slashes).

Now if you open the file GDIGraph.cpp (provided you named the project GDIGraph) you should be able to find the InitInstance function inside that file:
The function definition looks like this:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
.....
}

You may also use the find function (in edit menu) to find things in your solution.
0
 

Author Comment

by:pgmerLA
ID: 35123125
Hi SunnyDark,

I have completed the first step, but I am still getting lost of error code: c4430,c2440, c2146 etc...(104 in total)
// GDIGraph.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "GDIGraph.h"
#pragma comment(lib,"gdiplus.lib")
#include<gdiplus.h>
using namespace Gdiplus;

#define WIN32_LEAN_AND_MEAN  //WHAT TYPE OF COMMENT WOULD BE APPROPRIATE HERE?
#define MAX_LOADSTRING 100


// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR	gdiplusToken;


// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_GDIGRAPH, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIGRAPH));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	GdiplusShutdown(gdiplusToken);
	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDIGRAPH));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_GDIGRAPH);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   GdiplusShutdown(gdiplusToken);
   
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

Open in new window

0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35123745
Ok , Here is what you need to fix,
Remove the line
#define WIN32_LEAN_AND_MEAN
From this file.
This is already defined in stdafx.h on line 10.
When I say to comment something OUT it means to make this line a comment or imply put, just erase it. So open stdafx.h go to line 10, find #define WIN32_LEAN_AND_MEAN and erase it (or make it a comment , that is what I meant from the beginning).
0
 

Author Comment

by:pgmerLA
ID: 35124217
got it. step 1 accomplished!
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 8

Expert Comment

by:SunnyDark
ID: 35124273
Nice,
You already have step 2 right here (this question), so you may move right to it.
0
 

Author Comment

by:pgmerLA
ID: 35124299
Can you tell me what part of the code I am making a mistake?
I can't compile it.
// GDIGraph.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "GDIGraph.h"
#pragma comment(lib,"gdiplus.lib")
#include<gdiplus.h>
using namespace Gdiplus;


#define MAX_LOADSTRING 100


// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR	gdiplusToken;


// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_GDIGRAPH, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIGRAPH));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	GdiplusShutdown(gdiplusToken);
	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDIGRAPH));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_GDIGRAPH);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   GdiplusShutdown(gdiplusToken);
   
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: Add any drawing code here...
		int width = ps.rcPaint.right - ps.rcPaint.left;
		int height = ps.rcPaint.bottom - ps.rcPaint.top;
		Bitmap memoryBitmap(width, height);
		Graphics(&memoryBitmap);
		gr.Clear(Color::White);		// Clear to white background
		Pen pen(Color::Red);		// This is the pen we will use to draw
		gr.DrawRectangle(&pen, 10,10,100,100); // Draw rectangle from 10,10 to 110,110
		Graphics grScreen(hdc);
		grScreen.DrawImage(&memoryBitmap, 0,0);
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_ERASEBKGND:
	return TRUE;
	break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

Open in new window

0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35124306
You are calling GdiplusShutdown in InitInstance (line 126) instead of GdiplusStartup
0
 

Author Comment

by:pgmerLA
ID: 35124369
do you know how to make line number appear in MS VS2008?
0
 

Author Comment

by:pgmerLA
ID: 35124395
for the GdiplusStartup(), how can I know what arguments to put in?  line 126.
0
 

Author Comment

by:pgmerLA
ID: 35169465
Hi SunnyDark,

Are you still interested in teaching me?
I hope you are :)
0
 
LVL 8

Expert Comment

by:SunnyDark
ID: 35169673
Sure , I somehow missed your comments...
So to make line numbers to appear look at the screen cast.
 SunnyDark-434444.flv

Now for the gdistartup function, it was actually my fault , in the original answer for the first step the line with gdistartup somehow "mysteriously" disappeared from the post...
The line should be:
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

Open in new window

0
 

Author Comment

by:pgmerLA
ID: 35172519
Hi SunnyDark,
I have attached my code.
I can't compile it. Could you tell me where I made a mistake?
Thanks.
Matt


 error C2040: 'memoryBitmap' : 'Gdiplus::Graphics &' differs in levels of indirection from 'Gdiplus::Bitmap'
error C2530: 'memoryBitmap' : references must be initialized
 error C2065: 'gr' : undeclared identifier
error C2228: left of '.Clear' must have class/struct/union
1>        type is ''unknown-type''
error C2065: 'gr' : undeclared identifier
 error C2228: left of '.DrawRectangle' must have class/struct/union
 error C2360: initialization of 'grScreen' is skipped by 'case' label
 error C2360: initialization of 'pen' is skipped by 'case' label
error C2360: initialization of 'memoryBitmap' is skipped by 'case' label
 error C2360: initialization of 'height' is skipped by 'case' label
error C2360: initialization of 'width' is skipped by 'case' label
 error C2360: initialization of 'grScreen' is skipped by 'case' label
: error C2360: initialization of 'pen' is skipped by 'case' label
 error C2360: initialization of 'memoryBitmap' is skipped by 'case' label
error C2360: initialization of 'height' is skipped by 'case' label

error C2360: initialization of 'width' is skipped by 'case' label
 error C2361: initialization of 'grScreen' is skipped by 'default' label

 error C2361: initialization of 'pen' is skipped by 'default' label

 error C2361: initialization of 'memoryBitmap' is skipped by 'default' label



// GDIGraph.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "GDIGraph.h"
#pragma comment(lib,"gdiplus.lib")
#include<gdiplus.h>
using namespace Gdiplus;


#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;								// current instance
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR			gdiplusToken;

// Forward declarations of functions included in this code module:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

 	// TODO: Place code here.
	MSG msg;
	HACCEL hAccelTable;

	// Initialize global strings
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_GDIGRAPH, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance (hInstance, nCmdShow))
	{
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIGRAPH));

	// Main message loop:
	while (GetMessage(&msg, NULL, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	GdiplusShutdown(gdiplusToken);
	return (int) msg.wParam;
}



//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GDIGRAPH));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_GDIGRAPH);
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

	return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;

   hInst = hInstance; // Store instance handle in our global variable

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

   if (!hWnd)
   {
      return FALSE;
   }

   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND	- process the application menu
//  WM_PAINT	- Paint the main window
//  WM_DESTROY	- post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;

	switch (message)
	{
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// Parse the menu selections:
		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWnd);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
		// TODO: Add any drawing code here...
		int width = ps.rcPaint.right - ps.rcPaint.left;
		int height = ps.rcPaint.bottom - ps.rcPaint.top;
		Bitmap memoryBitmap(width, height);
		Graphics(&memoryBitmap);
		gr.Clear(Color::White); // Clear to white background
        Pen pen(Color::Red); // This is the pen we will use to draw
        gr.DrawRectangle(&pen, 10,10,100,100); // Draw rectangle from 10,10 to 110,110
		Graphics grScreen(hdc);
		grScreen.DrawImage(&memoryBitmap, 0,0);
		EndPaint(hWnd, &ps);
		break;
	case WM_ERASEBKGND:
		return TRUE;
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}

Open in new window

0
 
LVL 8

Accepted Solution

by:
SunnyDark earned 500 total points
ID: 35172541
Line 172:
Graphics gr (&memoryBitmap);

Also add "{" at line 6
and "}" at line 8 so the complete code would be :

case WM_PAINT:
          {
                hdc = BeginPaint(hWnd, &ps);
                
                // TODO: Add any drawing code here...
                int width = ps.rcPaint.right - ps.rcPaint.left;
                int height = ps.rcPaint.bottom - ps.rcPaint.top;
                Bitmap memoryBitmap(width, height);
                Graphics gr(&memoryBitmap);
                gr.Clear(Color::White); // Clear to white background
        Pen pen(Color::Red); // This is the pen we will use to draw
        gr.DrawRectangle(&pen, 10,10,100,100); // Draw rectangle from 10,10 to 110,110
                Graphics grScreen(hdc);
                grScreen.DrawImage(&memoryBitmap, 0,0);
                EndPaint(hWnd, &ps);
               }
                break;

Open in new window

0
 

Author Comment

by:pgmerLA
ID: 35172618
Step 2 accomplished!

Here is the link for step 3:
http://www.experts-exchange.com/Programming/Languages/CPP/Q_26898304.html
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now