Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
4.43/5 (3 votes)
See more:
INTRODUCTION AND RELEVANT INFORMATION:

I have a complex painting to implement in my main window’s WM_PAINT handler.

I have submitted a picture bellow to illustrate it:
http://pbrd.co/18fNYYp[^]

Main window has static controls, instead of buttons, which have style SS_NOTIFY.
When user clicks on them, certain actions occur in program, which are irrelevant for now.

The following picture shows where static controls in the main window are:
http://pbrd.co/18fOkya[^]

Map on the orange panel is an EMF file ,top left and right logos are PNG files, and other pictures are bitmaps.

Visual Styles are enabled via #pragma directive. I also use GDI+ along with the GDI.

Project was created as empty project and I have coded everything from “scratch”.

In order to implement this task, I have decided to draw the entire picture in WM_PAINT, and to put transparent static controls over the images on the picture that correspond them.

In order to keep my code clean and simple, I have made functions that implement the above, so my WM_PAINT handler can be as small as possible.

Gradient brushes were made with the usage of GradientFill(...) API.

I work on Windows XP, using MS Visual Studio C++ 2008 Express Edition and pure Win32 API.

One note: since Express edition of VS doesn't have resource editor, resource file and resource header were created using ResEdit from here:
http://www.resedit.net/.[^]

UPDATE #1( updated on December 17th, 2013 ):

In order to make things easier for those trying to help, here is the single source file with minimal code that illustrates the problem: http://pastebin.com/BeAVHViC[^]

PROBLEM:

In order to avoid flickering, I have used double buffering, which I have learned from Paul Watt’s articles, Charles Petzold’s Programming Windows 5th edition and Forger’s WIN32 tutorial.

Theoretically speaking, everything is OK, and my code compiles without any errors.

I have pasted the code here:
http://pastebin.com/zSYT1i8L[^]

My English is not good enough to accurately describe the problems that I face ( all I can say is that edges of the main window and static control's redraw “slow” and they flicker ) so I have created a demo application that demonstrates them:
http://www.filedropper.com/geotermistgrafika[^]

MY EFFORTS TO SOLVE THE PROBLEM:

I have handled WM_ERASEBKGND ( returned (LRESULT)1 ), and I have excluded styles CS_VREDRAW and CS_HREDRAW from my window class-therefore flickering should not be caused because of this.

My window doesn’t have WS_CLIPCHILDREN style because part of the desktop picture is seen where static controls are.

In my WM_SIZE handler I have :
1. Repositioned static controls using SetWindowPos(...) API and reduced flickering by adding the SWP_NOCOPYBITS flag.

2. Invalidated the entire window with the InvalidateRect( hWnd, NULL, FALSE ), so this API does not send WM_ERASEBKGND when invalidating ( 3rd parameter is FALSE ), but even if I try with TRUE the effect is the same.

I have implemented double buffering for WM_PAINT handler like in the examples found in the above books/articles/tutorials ( by doing everything in the memory DC and do BitBlt(...) on screen DC in order to avoid flickering ).

I didn’t handle WM_SIZING, nor WM_WINDOWPOSCHANGING, or WM_MOVING message.

I have used the tool GDIView ( http://www.nirsoft.net/utils/gdi_handles.html[^] ) to track down GDI leaks.
Each time I resize/maximize my window, GDIView shows +4 in column for regions, which should mean that I leak regions but I can’t figure out how is this possible, since I do not use API’s that manipulate with regions, and have double checked everything.

In my opinion everything should be fine and maybe this is irrelevant, but I just thought to mention it, in case it is important.

If I add WS_EX_COMPOSITED style to the main window, the performance does not improve.

I have tried to find online example that would help me to solve my problem but all the tutorials are simple and do not cover this type of complex pictures.

IMPORTANT NOTE:

Before improving this question, I got two solutions suggested, one of them advising me to do as much as I can in WM_ERASEBKGND.

After leaving my WM_PAINT handler empty and calling onPaint function in WM_ERASEBKGND with the device context obtained with GetDC(..) API, the flickering disappeared, but during the resizing, redrawing of the window was “spiky” and the problem with the edges of the main window was not solved.
Still, this is much better improvement than the original code.

UPDATE ( December, 17th 2013 ):

After removing the call drawImages( hdc, MemDC, r ); from onPaint, the flickering of the edges occurs again.

It seems less, and the number of regions GDIView detects as leaked is reduced by one.

QUESTION:

How to get rid of the problems demonstrated in my demo application, provided above?

I hereby thank anyone who invests its time and efforts to try to help me.

Best regards.
Posted
Updated 17-Dec-13 10:33am
v8
Comments
The_Inventor 10-Dec-13 1:19am    
Hi ALNS! Put all the code that you have written for your WM_PAINT function and put it into an overridden OnDraw function. The fact that you are using WM_PAINT to do all that is causing your flicker problems to begin with. WM_PAINT is best used to redraw a small part of the screen image that is active. Using the OnDraw function is faster, and better.

Just call all the routines that you have already written, modify your onPaint function a little. What happens is that you get the whole screen in memory before it is drawn, so that when you move or resize, overrides that you need handle, and need to reflect the OnDdraw called in the proper place in the main function, and in the case statements of your window messages.
AlwaysLearningNewStuff 10-Dec-13 8:35am    
Thank you so much for the advice!

That is a bit unclear for me, since as a beginner, I do not have a concept on how to override WM_PAINT ( and I struggle to find an example of it, since I work in pure WIN32 API ).

Can you please help me with some pseudo code, or some link that has an example?

Currently I am searching for this here at CodeProject articles, but I have no luck...

Hopefully this isn't much of a problem for you...

Thank you again for your advice!

Best regards :)
CPallini 10-Dec-13 9:05am    
Without viewing your code, how can we help you?
AlwaysLearningNewStuff 10-Dec-13 9:41am    
Mr.Pallini,

The link to the code is attached in the section PROBLEM, subsection EDIT #1 ( December, 9th 2013 ) :and the demo project is attached just above, too.

Regards.

CPallini is absolutly right. Painting with WM_PAINT or the OnPaint method leads to flickering. Draw most things with the WM_ERASEBKGND message.

read some articles about "paint for beginners". Key is to avoid redrawing.

http://www.codeproject.com/search.aspx?q=paint+for+beginners&x=-1262&y=-146&sbo=kw[^]

I solve these problem via iterating: only draw one piece and if it works, i activate the next as long as it work...

Tip: dont work with controls, but check the mouse coordinates and handle it via posting messages to the windows.
 
Share this answer
 
Comments
Richard MacCutchan 10-Dec-13 13:26pm    
Very interesting comment about Draw most things with the WM_ERASEBKGND message. I must give it a try sometime.
The_Inventor 11-Dec-13 0:11am    
@KarstenK : why don't you give credit where it is due. CPallini didn't make the comment, I did. If Always makes a function called OnDraw(CDC* pDC) and puts everything into 'memory' prior to 'Drawing' it, then there should be no flicker.
KarstenK 11-Dec-13 6:11am    
Problem on the edge is the typical use case for regions. Create a region only for the area you want to draw. Like here: http://www.codeproject.com/Articles/1944/Guide-to-WIN32-Regions

@The_Inventor: sorry!
AlwaysLearningNewStuff 17-Dec-13 12:42pm    
Thank you so much for your suggestions, I really appreciate it!

I have read most of the articles from that link before ( especially those from Paul Watt), so I could learn double buffering properly.

To establish "common ground" in further communication, let us divide the picture in the following sections:

1. Header
2. Middle part
3. Pictures of transparent static controls ( 4 blue ones and the ones on orange panel )
4. Footer ( or "status bar " )

From your last comment I understand that you have probably meant to first draw header in WM_ERASEBKGND, and then if it works, to add drawing of the middle part and so on, can you confirm if I have understood it right?

By the way, I have removed onPaint and left typical empty WM_PAINT handler.

I have recoded onPaint to use GetDC(..) and ReleaseDC(...) and flickering disappeared, but repainting is “slow” and the problem with the edges remained.

Thanks again for trying to help, can you suggest some improvements based on this new information I have delivered?

UPDATE ( December, 17th 2013 ) :

After removing the call drawImages( hdc, MemDC, r ); from onPaint, and trying to only draw background, the flickering of the edges occurs again.

It seems less, and the number of regions GDIView detects as leaked is reduced by one.

Best regards.
KarstenK 18-Dec-13 2:49am    
you really need to dig into "regions" and create a region of the window you want to draw. Regions are the key for your solution. ;-)

tips: + Try to make global instancess like the pens.
+ MoveToEx/LineTo are "slow" (consider using a bitmap)
Here is what I did with it. I left the drawImages function for you to rewrite.
You should be able to use CBitmap and CBitmap* without breaking your code.

C++
#include "resource.h"
#include <windows.h>
#include <afxwin.h>
#include <windowsx.h> // for TransparentBlt()
#include <commctrl.h>
#include <gdiplus.h>
#pragma comment( linker, "/manifestdependency:\"type='win32' \
                         name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
                         processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
                         language='*'\"")
#pragma comment( lib, "comctl32.lib")
#pragma comment( lib, "Msimg32.lib" ) // for TransparentBlt()
#pragma comment( lib, "Gdiplus.lib" )
using namespace Gdiplus;
// variable for storing the instance
static HINSTANCE hInst; 
// icons
static HICON hIcon, // main window's icon
hiAdmin; // icon in the left corner of the status bar
// Images for logos
Image *image, // left logo on main window's top banner
     *image1, // right logo on main window's top banner
     *btn5; // map for the orange static control
// variables for painting the window

static HBRUSH hbPozadina, // gray background brush for grid on the top
              BlueFrame, // needed to frame blue static controls
			  hbr; // orange brush for orange panel

static HBITMAP bmpBTN1, // image for top left blue static control
               bmpBTN2, // image for top right blue static control
			   //============ these two make one image =========== //
			   bmpBTN3, // left image for bottom left blue static control
			   bmpBTN3a, // right image for bottom left blue static control
			   //==================================================//
			   bmpBTN4, // image for bottom right blue static control
			   bmpSimbol, // middle logo on the main window's top banner
			   bmpInfo, // top left image for child window of the 1st orange static control
			   bmpLink, // top left image for child window of the 3rd orange static control
			   bmpHelp; // top left image for child window of the 2nd orange static control
/****************************** helper functions for WM_PAINT **************************/
// Fills triangle with gradient brush
void GradientTriangle( CDC* MemDC, LONG x1, LONG y1, LONG x2, LONG y2, LONG x3, LONG y3, 
                      COLORREF top, COLORREF bottom )
{
        TRIVERTEX vertex[3];
        vertex[0].x     = x1;
        vertex[0].y     = y1;
        vertex[0].Red   = GetRValue(bottom) << 8;
		vertex[0].Green = GetGValue(bottom) << 8;
		vertex[0].Blue  = GetBValue(bottom) << 8;
		vertex[0].Alpha = 0x0000;
		vertex[1].x     = x2;
		vertex[1].y     = y2;
		vertex[1].Red   = GetRValue(top) << 8;
		vertex[1].Green = GetGValue(top) << 8;
		vertex[1].Blue  = GetBValue(top) << 8;
		vertex[1].Alpha = 0x0000;
		vertex[2].x     = x3;
		vertex[2].y     = y3; 
		vertex[2].Red   = GetRValue(bottom) << 8;
		vertex[2].Green = GetGValue(bottom) << 8;
		vertex[2].Blue  = GetBValue(bottom) << 8;
		vertex[2].Alpha = 0x0000;
// Create a GRADIENT_TRIANGLE structure that
// references the TRIVERTEX vertices.
        GRADIENT_TRIANGLE gTriangle;
		gTriangle.Vertex1 = 0;
		gTriangle.Vertex2 = 1;
		gTriangle.Vertex3 = 2;
// Draw a shaded triangle.
        GradientFill( MemDC, vertex, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);
}
// draws the background for the part of the window between header and footer
void drawBackground( HDC MemDC, RECT r )
{
        /******************** main window's gradient background ***************/
	GradientTriangle( MemDC, r.right, r.bottom - r.top - 30, r.left, r.bottom - r.top - 30,
	          r.left, r.top + 120, RGB( 0x95, 0xB3, 0xD7 ), RGB( 0xDB, 0xE5, 0xF1 ) );
	GradientTriangle( MemDC, r.right, r.bottom - r.top - 30, r.right, r.top + 120,
	          r.left, r.top + 120, RGB( 0x95, 0xB3, 0xD7 ), RGB( 0xDB, 0xE5, 0xF1 ) );
}

// draws the header of the main window
void drawHeader( CDC* MemDC, RECT rect, HBRUSH hbPozadina )
{
     FillRect( MemDC, &rect, hbPozadina);  // draw grid on the banner background
     LOGBRUSH lbPozadina;
     HGDIOBJ hPenPozadina = NULL, hOldPenPozadina;
     lbPozadina.lbColor = RGB( 216, 216, 216 );
     lbPozadina.lbHatch = 0;
     lbPozadina.lbStyle = BS_SOLID;
     hPenPozadina = ExtCreatePen( PS_COSMETIC | PS_SOLID, 1, &lbPozadina, 0, NULL); 
     hOldPenPozadina = SelectObject( MemDC, hPenPozadina); // needed for cleanup
     for( int i = rect.left + 12; i< rect.right; i += 12)
     {
		MoveToEx( MemDC, i, rect.top, NULL );
		LineTo( MemDC, i, rect.bottom - rect.top + 1 );
	 }

     for( int i = rect.top + 12; i< rect.bottom; i += 12)
     {
         MoveToEx( MemDC, rect.left, i, NULL );
         LineTo( MemDC, rect.right - rect.left + 1, i );
     }
        // perform proper cleanup
     SelectObject( MemDC, hOldPenPozadina);
     DeleteObject(hPenPozadina);
/********* draw a line at the bottom of the top banner ******/
     LOGBRUSH lb;
     HGDIOBJ hPen = NULL, hOldPen;
     lb.lbColor = RGB( 0, 0, 0 );
     lb.lbHatch = 0;
     lb.lbStyle = BS_SOLID;
     hPen = ExtCreatePen( PS_COSMETIC | PS_SOLID, 1, &lb, 0, NULL); 
     hOldPen = SelectObject( MemDC, hPen ); // needed for proper cleanup
     MoveToEx( MemDC, rect.left, rect.top + 120, NULL );
     LineTo( MemDC, rect.right - rect.left + 1, rect.top + 120 );
     // perform proper cleanup
     SelectObject( MemDC, hOldPen );
     DeleteObject(hPen);
}
// fills rectangle with gradient brush
void GradientRectangle( CDC* MemDC, LONG x1, LONG y1, LONG x2, LONG y2, COLORREF top, COLORREF bottom )
{
// vertexes for static's gradient color
        TRIVERTEX vertexS[2];
        vertexS[0].x     = x1;
        vertexS[0].y     = y1;
        vertexS[0].Red   = GetRValue(top) << 8;
        vertexS[0].Green = GetGValue(top) << 8;
        vertexS[0].Blue  = GetBValue(top) << 8;
        vertexS[0].Alpha = 0x0000;
        vertexS[1].x     = x2;
        vertexS[1].y     = y2; 
        vertexS[1].Red   = GetRValue(bottom) << 8;
        vertexS[1].Green = GetGValue(bottom) << 8;
        vertexS[1].Blue  = GetBValue(bottom) << 8;
        vertexS[1].Alpha = 0x0000;
        // Create a GRADIENT_RECT structure that 
        // references the TRIVERTEX vertices.
        GRADIENT_RECT gRect;
        gRect.UpperLeft  = 0;
        gRect.LowerRight = 1;
        // Draw a shaded rectangle. 
        GradientFill( MemDC, vertexS, 2, &gRect, 1, GRADIENT_FILL_RECT_V );
}
// fills the "button" with blue gradient and frames it with blue brush
void FillButton( CDC* MemDC, RECT rect, HBRUSH BlueFrame )
{
        // fill upper half of the rectangle
        GradientRectangle( MemDC, rect.left, rect.top, rect.right, rect.top + ( rect.bottom - rect.top ) / 2,
		RGB( 0x95, 0xB3, 0xD7 ), RGB( 0x4F, 0x8B, 0xBD ) );
        // fill bottom half of the rectangle
        GradientRectangle( MemDC, rect.left, rect.top + ( rect.bottom - rect.top ) / 2, 
		rect.right, rect.bottom, RGB( 0x4F, 0x8B, 0xBD ), RGB( 0x95, 0xB3, 0xD7 ) );
		FrameRect( MemDC, &rect, BlueFrame );
}
// draws the "status bar" at the bottom of the main window
void drawFooter( CDC* MemDC, RECT r, COLORREF top, COLORREF bottom )
{
// down triangle
	GradientTriangle( MemDC, r.right, r.bottom, ( r.right - r.left ) / 2, r.bottom - r.top - 15,
	                r.left, r.bottom, top, bottom );
// upper triangle
	GradientTriangle( MemDC, r.right, r.bottom - r.top - 30, ( r.right - r.left ) / 2, r.bottom - r.top - 15,
	                r.left, r.bottom - r.top - 30, top, bottom );
// left triangle
	GradientTriangle( MemDC, r.left, r.bottom, ( r.right - r.left ) / 2, r.bottom - r.top - 15,
	                r.left, r.bottom - r.top - 30, top, bottom );
// right triangle
    GradientTriangle( MemDC, r.right, r.bottom - r.top - 30, ( r.right - r.left ) / 2, r.bottom - r.top - 15, 
	                r.right, r.bottom, top, bottom );
// draw icon
	DrawIconEx( MemDC, r.left, r.bottom - r.top - 30, hiAdmin, 30, 30, NULL, NULL, DI_NORMAL );
}
// draw orange panel on which map and 3 static controls will be drawn
void drawOrangePanel( CDC* MemDC, RECT r, COLORREF top, COLORREF bottom )
{
 // down triangle
	GradientTriangle( MemDC, r.right, r.bottom, r.left + ( r.right - r.left ) / 2, r.top + ( r.bottom - r.top ) / 2,
	                r.left, r.bottom, top, bottom );
 // upper triangle
    GradientTriangle( MemDC, r.right, r.top, r.left + ( r.right - r.left ) / 2, r.top + ( r.bottom - r.top ) / 2,
					r.left, r.top, top, bottom );
// left triangle
    GradientTriangle( MemDC, r.left, r.bottom, r.left + ( r.right - r.left ) / 2, r.top + ( r.bottom - r.top ) / 2,
	                r.left, r.top, top, bottom );
// right triangle
    GradientTriangle( MemDC, r.right, r.top, r.left + ( r.right - r.left ) / 2, r.top + ( r.bottom - r.top ) / 2, 
	                r.right, r.bottom, top, bottom );
}

void drawStrings( CDC* MemDC, RECT r )
{
// rectangle for header
	RECT rect, baner; // needed for proper positioning
    SIZE sBaner; // needed for proper positioning
    HFONT hf, hfOld;
    long lfHeight;
    rect.left = r.left;
    rect.top = r.top;
    rect.right = r.right;
    rect.bottom = 120;
/************************ middle orange text ************************/
// set font size below via function's first argument 
    lfHeight = -MulDiv( 14, GetDeviceCaps( MemDC, LOGPIXELSY), 72 );
    hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial Black" );
    SetBkMode( MemDC, TRANSPARENT );
    SetTextColor( MemDC, RGB( 255, 163, 94 ) ); // orange
    hfOld = (HFONT)SelectObject( MemDC, hf ); // needed for cleanup
    GetTextExtentPoint32( MemDC, L"ГЕОТЕРМАЛНИ ИНФОРМАЦИОНИ СИСТЕМ ГРАДА БЕОГРАДА-ГЕОТЕРМИСТ",
	    wcslen(L"ГЕОТЕРМАЛНИ ИНФОРМАЦИОНИ СИСТЕМ ГРАДА БЕОГРАДА-ГЕОТЕРМИСТ"), &sBaner );
// proper positioning
        baner.left = r.left + 60;  baner.right = r.right - r.left - 60;
        baner.top = r.top + 15;    baner.bottom = r.top + sBaner.cy;
        DrawTextEx( MemDC, L"ГЕОТЕРМАЛНИ ИНФОРМАЦИОНИ СИСТЕМ ГРАДА БЕОГРАДА-ГЕОТЕРМИСТ",
           wcslen(L"ГЕОТЕРМАЛНИ ИНФОРМАЦИОНИ СИСТЕМ ГРАДА БЕОГРАДА-ГЕОТЕРМИСТ"), &baner,
           DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK, 0 );
        SelectObject( MemDC, hfOld ); // proper cleanup
        DeleteObject( hf );
/******************************* top left text ************************/
//position it properly
        baner.left = r.left + 90;
        baner.top = r.top + sBaner.cy + 28;
        baner.right = 460;
        baner.bottom = r.bottom;
        lfHeight = -MulDiv( 8, GetDeviceCaps( MemDC, LOGPIXELSY), 72 );
        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial Black" );
        SetTextColor( MemDC, RGB( 0, 0, 0 ) );
        hfOld = (HFONT)SelectObject( MemDC, hf ); // needed for proper cleanup
        DrawTextEx( MemDC, L"УПРАВА ГРАДА БЕОГРАДА\nСЕКРЕТАРИЈАТ ЗА КОМУНАЛНЕ И СТАМБЕНЕ ПОСЛОВЕ\nУПРАВА ЗА ЕНЕРГЕТИКУ",
	        wcslen(L"УПРАВА ГРАДА БЕОГРАДА\nСЕКРЕТАРИЈАТ ЗА КОМУНАЛНЕ И СТАМБЕНЕ ПОСЛОВЕ\nУПРАВА ЗА ЕНЕРГЕТИКУ"), 
			&baner, DT_CENTER | DT_NOCLIP | DT_WORDBREAK, 0 );
/*************************** top right text *************************/
// position it properly
        baner.top = r.top + sBaner.cy + 28;
        baner.left = r.right - 350;
        baner.right = r.right - 100;
        baner.bottom = r.bottom;
        DrawTextEx( MemDC, L"УНИВЕРЗИТЕТ У БЕОГРАДУ\nРУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nДЕПАРТМАН ЗА ХИДРОГЕОЛОГИЈУ",
			wcslen(L"УНИВЕРЗИТЕТ У БЕОГРАДУ\nРУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nДЕПАРТМАН ЗА ХИДРОГЕОЛОГИЈУ"), 
			&baner, DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK, 0 );
        SelectObject( MemDC, hfOld ); // proper cleanup
        DeleteObject( hf );
//========= draw right text in status bar =============//
        lfHeight = -MulDiv( 8, GetDeviceCaps( MemDC, LOGPIXELSY), 72 );
        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, L"Arial Black" );
        hfOld = (HFONT)SelectObject( MemDC, hf ); // needed for proper cleanup
        GetTextExtentPoint32( MemDC, L"ЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ",
			wcslen(L"ЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ"), &sBaner );
// position it properly
        rect.bottom = r.bottom;
        rect.right = r.left + sBaner.cx + 30;
        rect.left = r.left + 30;
        rect.top = r.bottom - r.top - 30;
// draw it to the back buffer
        DrawTextEx( MemDC, L"РУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ",
                wcslen(L"РУДАРСКО ГЕОЛОШКИ ФАКУЛТЕТ\nЦЕНТАР ЗА ОБНОВЉИВЕ ВОДНЕ ЕНЕРГЕТСКЕ РЕСУРСЕ"), 
                &rect, DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK, 0 );
        SelectObject( MemDC, hfOld ); // proper cleanup
        DeleteObject( hf );
//============== right text in the status bar ==================//
        lfHeight = -MulDiv( 10, GetDeviceCaps( MemDC, LOGPIXELSY), 72 );
        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, L"Arial" );
        hfOld = (HFONT)SelectObject( MemDC, hf ); // needed for proper cleanup
        GetTextExtentPoint32( MemDC, L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана",
                wcslen(L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана"), &sBaner );
// position it properly
        rect.bottom = r.bottom;
        rect.right = r.right - 10;
        rect.left = r.right - r.left - sBaner.cx - 10;
        rect.top = r.bottom - r.top - sBaner.cy;
// draw it to the back buffer
        DrawTextEx( MemDC, L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана",
			wcslen(L" Дејан Миленић & Ана Врањеш © 2013 сва права задржана"), 
			&rect, DT_CENTER | DT_VCENTER | DT_NOCLIP | DT_WORDBREAK | DT_NOPREFIX, 0 );
        // perform proper cleanup
        SelectObject( MemDC, hfOld );
        DeleteObject(hf);
/****************** draw static control's background ******************/
//=============== top left blue static control ================//
//position it properly
        rect.left = ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 230 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
        // draw text
        // set font size below via function's first argument 
        lfHeight = -MulDiv( 8, GetDeviceCaps( MemDC, LOGPIXELSY ), 72);
        hf = CreateFont( lfHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, L"Arial Black");
        hfOld = (HFONT)SelectObject( MemDC, hf );
        DrawTextEx( MemDC, L"УНОС ПОДАТАКА", wcslen(L"УНОС ПОДАТАКА"),
                &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
//================= top right blue static control =====================//
//position it properly
        rect.left = 150 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 230 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 300 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
// draw text
        DrawTextEx( MemDC, L"ПРЕГЛЕД ПОДАТАКА", wcslen(L"ПРЕГЛЕД ПОДАТАКА"),
	        &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
//================= bottom left blue static control =====================//
//position it properly
        rect.left = ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 380 + 2 * ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
// draw text
        DrawTextEx( MemDC, L"ИЗВЕШТАЈ", wcslen(L"ИЗВЕШТАЈ"),
        &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
//================= bottom right blue static control =====================//
//position it properly
        rect.left = 150 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 380 + 2 * ( r.bottom - r.top - 450 ) / 3;
        rect.right = 300 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
        // draw text
        DrawTextEx( MemDC, L"ПРЕТРАГА", wcslen(L"ПРЕТРАГА"),
        &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK, 0 );
        SelectObject( MemDC, hfOld );
        DeleteObject(hf);
//================ text for orange static controls =============//
// first one
        rect.left = 3 * ( r.right - r.left ) / 4 + 10;
        rect.top = r.top + 160;
        rect.right = r.right - r.top - 50;
        rect.bottom = r.top + 180;
 //============= draw text ======//
        lfHeight = -MulDiv( 10, GetDeviceCaps( MemDC, LOGPIXELSY ), 72);
        hf = CreateFont(lfHeight, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0,L"Arial Unicode MS");
        hfOld = (HFONT)SelectObject( MemDC, hf );
        DrawTextEx( MemDC, L"ИНФОРМАЦИЈЕ", wcslen(L"ИНФОРМАЦИЈЕ"), &rect, 
                DT_VCENTER | DT_LEFT | DT_SINGLELINE, 0 );
// second one
        rect.left = 3 * ( r.right - r.left ) / 4 + 10;
        rect.top = r.top + 200;
        rect.bottom = r.top + 220;
//====== draw text ======//
        DrawTextEx( MemDC, L"ПОМОЋ", wcslen(L"ПОМОЋ"), &rect, 
		        DT_VCENTER | DT_LEFT | DT_SINGLELINE, 0 );
// third one
        rect.left = 3 * ( r.right - r.left ) / 4 + 10;
        rect.top = r.top + 240;
        rect.bottom = r.top + 260;
        //====== draw text ======//
        DrawTextEx( MemDC, L"КОРИСНИ ЛИНКОВИ", wcslen(L"КОРИСНИ ЛИНКОВИ"), &rect, 
                DT_VCENTER | DT_LEFT | DT_SINGLELINE, 0 );
        // font is no longer needed, so do cleanup
        SelectObject( MemDC, hfOld );
        DeleteObject(hf);
}
 /*  
void drawImages( HDC hdc, CDC* MemDC, RECT r ) 
{
        HDC hdcMemImg = CreateCompatibleDC(hdc); // back buffer for bitmaps
        RECT rect = { 0, 0, 0, 0 }; // needed for proper positioning
        //******************* top middle logo ******************
        BITMAP b;
        memset( &b, 0 , sizeof(BITMAP) );
        GetObject( bmpSimbol, sizeof(BITMAP), &b );
        // needed for proper cleanup
        // ( we select a bitmap from resource file )
        HBITMAP oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpSimbol );
        // draw bitmap to the back buffer
     TransparentBlt( MemDC, ( r.right - r.left - 64 ) / 2, r.top + 45, 64, 64, 
              hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 0, 0, 0) );

		TransparentBlt(int xDest, int yDest, int nDestWidth,
			int nDestHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth,
			int nSrcHeight, UINT crTransparent)
        SelectObject( hdcMemImg, oldBmp ); // proper cleanup

//=============== top left blue static control ================//
//position it properly
        rect.left = ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpBTN1, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpBTN1 );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left + 20, rect.top + 10, rect.right - rect.left - 30, 
                rect.bottom - rect.top - 40, 
                hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 0, 0, 0 ) );
        SelectObject( hdcMemImg, oldBmp );
//================= top right blue static control =====================//
//position it properly
        rect.left = 150 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 300 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpBTN2, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpBTN2 );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left + 15, rect.top + 10, rect.right - rect.left - 30, 
                rect.bottom - rect.top - 40, hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 255, 0, 255 ) );
        SelectObject( hdcMemImg, oldBmp );
//================= bottom left blue static control =====================//
//position it properly
        rect.left = ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 270 + 2 * ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpBTN3, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpBTN3 );
        // draw left bitmap on back buffer
        TransparentBlt( MemDC, rect.left + 5, rect.top + 20, ( rect.right - rect.left) / 2, 
	         rect.bottom - rect.top - 60, hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 0, 0, 0 ) );
        SelectObject( hdcMemImg, oldBmp );
        // draw right bitmap on back buffer
        memset( &b, 0 , sizeof(BITMAP) );
        GetObject( bmpBTN3a, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpBTN3a );
        TransparentBlt( MemDC, rect.left + ( rect.right - rect.left) / 2 + 5, rect.top + 20, 
                ( rect.right - rect.left) / 2 - 5, rect.bottom - rect.top - 60, 
                hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 0, 0, 0 ) );
        SelectObject( hdcMemImg, oldBmp );
        //position it properly
        rect.left = 150 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 270 + 2 * ( r.bottom - r.top - 450 ) / 3;
        rect.right = 300 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpBTN4, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpBTN4 );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left + 25, rect.top + 10, rect.right - rect.left - 50, 
         rect.bottom - rect.top - 40, hdcMemImg, 0, 0, b.bmWidth, b.bmHeight, RGB( 0, 0, 0 ) );
        SelectObject( hdcMemImg, oldBmp );
        //================= static controls on orange panel ==================//
        // first one
        rect.left = 3 * ( r.right - r.left ) / 4 - 30;
        rect.top = r.top + 150;
        rect.right = r.right - r.top - 50;
        rect.bottom = r.top + 180;
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpInfo, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpInfo );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left, rect.top, 30, 30, hdcMemImg, 0, 0, 
                b.bmWidth, b.bmHeight, RGB( 255, 163, 94 ) );
        SelectObject( hdcMemImg, oldBmp );
        // second one
        rect.left = 3 * ( r.right - r.left ) / 4 - 30;
        rect.top = r.top + 190;
        rect.bottom = r.top + 220;
        //=============== draw bitmap =============//
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpHelp, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpHelp );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left, rect.top, 30, 30, hdcMemImg, 0, 0, 
                b.bmWidth, b.bmHeight, RGB( 255, 163, 94 ) );
        SelectObject( hdcMemImg, oldBmp );
        // third one
        rect.left = 3 * ( r.right - r.left ) / 4 - 30;
        rect.top = r.top + 230;
        rect.bottom = r.top + 260;
//=============== draw bitmap =============//
        memset( &b, 0, sizeof(BITMAP) );
        GetObject( bmpLink, sizeof(BITMAP), &b );
        oldBmp = (HBITMAP)SelectObject( hdcMemImg, bmpLink );
        // draw bitmap on back buffer
        TransparentBlt( MemDC, rect.left, rect.top, 30, 30, hdcMemImg, 0, 0, 
                b.bmWidth, b.bmHeight, RGB( 255, 163, 94 ) );
        SelectObject( hdcMemImg, oldBmp );
 //========= draw EMF and PNG files =========//
       Graphics graphics( MemDC );
		/******* fourth orange static control with the map ( EMF file ) ********
     // proper positioning
       rect.top = r.top + 270;
       rect.bottom = r.bottom - 60;
	   rect.left = 3 * ( r.right - r.left ) / 4 - 30;
//============= aspect ratio ================//
       UINT o_height = btn5->GetHeight(), o_width =  btn5->GetWidth();
       float scale = 0.5;  int mapPosX, mapPosY;
	   scale = (float)( rect.right - rect.left ) / o_width;
       if( (float)( rect.bottom - rect.top ) / o_height  <  scale )
	   {
            scale = (float)( rect.bottom - rect.top ) / o_height;
            int marginX = ( rect.right - rect.left ) - (int)( o_width * scale );
			int marginY = ( rect.bottom - rect.top ) - (int)( o_height * scale );
			marginX /= 2;  marginY /= 2; mapPosX = rect.left + marginX; 
			mapPosY = rect.top + marginY; 
			graphics.DrawImage( btn5, mapPosX, mapPosY, (int)( o_width * scale ),
					(int)( o_height * scale ) );
/******************** top left logo ( PNG file ) *******************
            o_height = image->GetHeight();
			o_width = image->GetWidth();
            graphics.DrawImage( image, r.left + 5, r.top + 10, o_width, o_height );
/******************** top right logo ( PNG file ) ******************
			o_height = image1->GetHeight();
            o_width = image1->GetWidth();
			graphics.DrawImage( image1, r.right - r.left - 90, r.top + 10, o_width, o_height );
        }
		DeleteDC(hdcMemImg); // release memory DC 
}
*/
void OnDraw( CDC* pDC) 
{
	RECT r; HWND hwnd;
    GetClientRect(hwnd, &r);
    CreateCompatibleDC(pDC->m_hDC); // back buffer
	CBitmap bmp = CreateCompatibleBitmap(pDC->m_hDC, r.right - r.left, r.bottom - r.top),
	CBitmap oldBmp = SelectObject(&bmp); // needed for cleanup
/*************** draw banner ******************/
// position it properly at the top
        RECT rect;
        rect.left = r.left;
        rect.top = r.top;
        rect.right = r.right;
        rect.bottom = 120;
// draw background for middle part of the window
        drawBackground( pDC, r );
//draw header with grid lines
        drawHeader( pDC, rect, hbPozadina );
// draw "status bar"
        drawFooter( pDC, r, RGB( 0x48, 0xAC, 0xC6), RGB( 0x31, 0x83, 0x99 ) );
/****************** draw static control's background ******************/
//=============== top left static control ================//
//position it properly
        rect.left = ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
// draw gradient button
        FillButton( pDC, rect, BlueFrame );
//================= top right static control =====================//
//position it properly
        rect.left = 150 + 2 * ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
        rect.right = 300 + 2 * ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
        // draw gradient button
        FillButton( pDC, rect, BlueFrame );
//================= bottom left static control =====================//
//position it properly
        rect.left = ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.top = 270 + 2 * ( r.bottom - r.top - 450 ) / 3;
        rect.right = 150 + ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
        rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
// draw gradient button
        FillButton( pDC, rect, BlueFrame );
//================= bottom right static control =====================//
//position it properly
        rect.left = 150 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
		rect.top = 270 + 2 * ( r.bottom - r.top - 450 ) / 3;
		rect.right = 300 + 2 * ( 3  * ( r.right - r.left ) / 4 - 340 ) / 3;
		rect.bottom = 420 + 2 * ( r.bottom - r.top - 450 ) / 3;
// draw gradient button
        FillButton( pDC, rect, BlueFrame );
//======================== draw orange panel =================//
//position it properly
        rect.left = 3 * ( r.right - r.left ) / 4 - 40;
        rect.top = r.top + 140;
        rect.right = rect.left + ( r.right - r.left ) / 4;
        rect.bottom = rect.top + ( r.bottom - r.top - 190 );
        drawOrangePanel( pDC, rect, RGB( 0xFF, 0xC8, 0xAA ), RGB( 0xFF, 0x96, 0x48 ) );
        // draw all the text
        drawStrings( pDC, r );
        // draw all the bitmaps and EMF files
        drawImages( hdc, MemDC, r );
        /****************** draw back buffer on the screen DC *****************/
        BitBlt(0, 0, r.right - r.left, r.bottom - r.top, pDC, 0, 0, SRCCOPY );
        /************** cleanup *******************/
        SelectObject(oldBmp );
        DeleteObject(bmp); // compatible bitmap for MemDC
}

// WinMain's procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        switch(msg)
        {
        case WM_CREATE:
			{
				image = Image::FromFile(L".\\resources\\BG.png"), // upper left logo
                image1 = Image::FromFile(L".\\resources\\RGF.png"); // upper right logo
				btn5 = Image::FromFile(L".\\resources\\BTN5.emf"); // map in the bottom of the orange button
      // load gray background brush for the top banner
                hbPozadina = CreateSolidBrush( RGB( 230, 230, 230 ) );
      // load left icon in the status bar
                hiAdmin = LoadIcon( hInst, MAKEINTRESOURCE(IDI_ICON2) );
      // bitmaps for static controls
                bmpBTN1 = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1) );
                bmpBTN2 = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP10) );
    /** these two bitmaps make one image for the bottom right blue static control **/
                bmpBTN3 = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP3) );
                bmpBTN3a = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP5) );
//**********************************************************************//
                bmpBTN4 = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP4) );
                bmpSimbol = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP16) );
                bmpInfo = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP6) );
				bmpLink = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP7) );
				bmpHelp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP8) );
//******** brushes ***********//
// brush for orange panel that holds 3 static controls and a map
				hbr = CreateSolidBrush( RGB( 255, 163, 94 ) ); 
// blue frame for blue static controls
                BlueFrame = CreateSolidBrush( RGB(79, 129, 189) ); 
/*******************************************/
// get rectangle dimensions of the main window
				RECT rec;
				GetClientRect( hwnd, &rec );
  /******* main window's static controls ******/
// top left
				HWND hsUnosPodataka = CreateWindowEx( 0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 
							( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
						    120 + ( rec.bottom - rec.top - 450 ) / 3, 
						    150, 150, hwnd, (HMENU)4000, hInst, 0);
// top right
				HWND hsPregledPodataka = CreateWindowEx( 0, L"Static", L"",  WS_VISIBLE | WS_CHILD | SS_NOTIFY,
                            150 + 2 * ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
						    120 + ( rec.bottom - rec.top - 450 ) / 3, 
						    150, 150, hwnd, (HMENU)4001, hInst, 0);
// bottom left
				HWND hsIzvestaj = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 
	                        ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
						    270 + 2 * ( rec.bottom - rec.top - 450 ) / 3, 
						    150, 150, hwnd, (HMENU)4002, hInst, 0);
// bottom right
				HWND hsPretraga = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY,
                            150 + 2 * ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
                            270 + 2 * ( rec.bottom - rec.top - 450 ) / 3,
                            150, 150, hwnd, (HMENU)4003, hInst, 0);
//============= static controls on the orange panel ==============//
// first one from the top
				HWND hsInfoInfo = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 
                            3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 150, 
							( rec.right - rec.left ) / 4 - 20, 30, hwnd, (HMENU)4007, hInst, 0);
// second one from the top
				HWND hsInfoHelp = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY,
                            3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 190, 
						    ( rec.right - rec.left ) / 4 - 20, 30, hwnd, (HMENU)4009, hInst, 0);
// third one from the top
				HWND hsInfoLink = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY, 
                            3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 230, 
						    ( rec.right - rec.left ) / 4 - 20, 30, hwnd, (HMENU)4008, hInst, 0);
// fourth one-it will contain a map
				HWND hsInfoKarta = CreateWindowEx(0, L"Static", L"", WS_VISIBLE | WS_CHILD | SS_NOTIFY,
	                        3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 270, 
						    ( rec.right - rec.left ) / 4 - 20, rec.bottom - rec.top - 330,
						    hwnd, (HMENU)4010, hInst, 0);
			}
			return (LRESULT)0;
		case WM_COMMAND:
			{
				switch (LOWORD(wParam))
				{
				case 4000:
				case 4001:
				case 4002:
				case 4003:
				case 4007:
				case 4008:
				case 4009:
				case 4010:
					MessageBeep(MB_ICONEXCLAMATION);
					break;
				default:
					return DefWindowProc(hwnd, msg, wParam, lParam);
				}
				break;
			}
        case WM_ERASEBKGND:
			return (LRESULT)1; // so we avoid flicker ( all painting is in WM_PAINT )
        case WM_PAINT:
			{
            // paint the picture
				CDC* pDC = GetWindowDC(hwnd);
				OnDraw(pDC);
            }
			return (LRESULT)0;
        case WM_SIZE:
            {
	            RECT rec;
                GetClientRect( hwnd, &rec );
                SetWindowPos( GetDlgItem( hwnd, 4000 ), NULL, ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
                120 + ( rec.bottom - rec.top - 450 ) / 3, 150, 150, 
                SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4001 ), NULL, 150 + 2 * ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
							120 + ( rec.bottom - rec.top - 450 ) / 3, 150, 150, SWP_NOZORDER | SWP_NOCOPYBITS);
                SetWindowPos( GetDlgItem( hwnd, 4002 ), NULL, ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
				            270 + 2 * ( rec.bottom - rec.top - 450 ) / 3, 150, 150, SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4003 ), NULL, 150 + 2 * ( 3  * ( rec.right - rec.left ) / 4 - 340 ) / 3, 
				            270 + 2 * ( rec.bottom - rec.top - 450 ) / 3, 150, 150, SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4007 ), NULL, 3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 150, 
							( rec.right - rec.left ) / 4 - 20, 30, SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4008 ), NULL, 3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 190, 
							( rec.right - rec.left ) / 4 - 20, 30, SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4009 ), NULL, 3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 230, 
							( rec.right - rec.left ) / 4 - 20, 30, SWP_NOZORDER | SWP_NOCOPYBITS );
                SetWindowPos( GetDlgItem( hwnd, 4010 ), NULL, 3 * ( rec.right - rec.left ) / 4 - 30, rec.top + 270, 
							( rec.right - rec.left ) / 4 - 20, rec.bottom - rec.top - 330, SWP_NOZORDER | SWP_NOCOPYBITS );
				InvalidateRect( hwnd, NULL, FALSE ); 
            }
			return (LRESULT)0;
		case WM_CTLCOLORSTATIC:
            return (LRESULT)( (HBRUSH)GetStockObject(NULL_BRUSH) );
		case WM_CLOSE:
			{
                DeleteObject(bmpSimbol);
                DeleteObject(bmpBTN1);
                DeleteObject(bmpBTN2);
                DeleteObject(bmpBTN3);
                DeleteObject(bmpBTN4);
                DeleteObject(bmpInfo);
                DeleteObject(bmpLink);
                DeleteObject(bmpHelp);
                DestroyIcon(hIcon);
                DestroyIcon(hiAdmin);
                DeleteObject(hbPozadina);
                DeleteObject(hbr);
                DeleteObject(BlueFrame);
                delete image;
                delete image1;
                delete btn5;
                DestroyWindow(hwnd);
			}
			return (LRESULT)0;
		case WM_DESTROY:
			{
                PostQuitMessage(0);
			}
            return (LRESULT)0;
        default:
		return DefWindowProc(hwnd, msg, wParam, lParam);
        }
        return 0;
}
// WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// store hInstance in global variable for later use
	hInst = hInstance; // load main icon
    hIcon = LoadIcon( hInst, MAKEINTRESOURCE(IDI_ICON1));
    WNDCLASSEX wc;  HWND hwnd; MSG Msg;
/*********** variables for GDI+ initialization *****************/
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
/************** Initialize GDI+. *************************/
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
/*************** finished GDI+ initialisation ********************/
// initialize common controls
    INITCOMMONCONTROLSEX iccex;
	iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
	iccex.dwICC = ICC_STANDARD_CLASSES ;
	InitCommonControlsEx(&iccex);
// register main window class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = hIcon;
	wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = L"Main_Window";
    wc.hIconSm = hIcon;
    if(!RegisterClassEx(&wc))
    {
	     MessageBox(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
         return 0;
	}
     // create main window
    hwnd = CreateWindowEx( 0, L"Main_Window", L"Геотермист", WS_OVERLAPPEDWINDOW,
		( GetSystemMetrics(SM_CXMAXIMIZED) - 1020 ) / 2, 
		( GetSystemMetrics(SM_CYMAXIMIZED) - 600 ) / 2, 
		1020, 600, NULL, NULL, hInstance, 0 );
    if(hwnd == NULL)
	{
		MessageBox(NULL, L"Window creation failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK);
        return 0; 
	}
	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
	{
	    TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}
        // shutdownd GDI+
    GdiplusShutdown(gdiplusToken);
	return Msg.wParam;
}


</gdiplus.h></commctrl.h></windowsx.h></afxwin.h></windows.h>
 
Share this answer
 
v3
Comments
enhzflep 11-Dec-13 7:43am    
Isn't CBitmap a part of MFC? (OP stated this a pure win32Api project with VS Express)
AlwaysLearningNewStuff 11-Dec-13 7:55am    
I was hoping that he tested his solution with the demo application I posted in my OP.

As for MFC, well, I am so desperate that I will "take whatever is offered" and try to create SDK solution on my own :)

P.S.

Are you just "visiting" or will you try to help me to deal with this "beast" ( in both cases I am glad to "see you" )?
enhzflep 11-Dec-13 8:11am    
I didn't try to compile the solution offered, so couldn't even begin to speculate.

I've seen it said that you can download the win32 DDK or SDK (I forget which) and use the MFC included in it, with VS express. Don't know if (a) it's still possible and (b) if it goes against licensing rules. Pretty sure I read about that trick here, at CP amongst other places. Something like "MFC VS Express site:codeproject.com" would possibly be a good google search.

Not sure how I would characterize my viewing of this thread. I did note that when I tried some sample code in WM_ERASEBKGND of a quick test-app of my own, that without a handler for WM_SIZE or WM_MOVE, that only part of the window was updated. (I didn't try to force an uodate - I only responded to the erase message) I didn't look into the issue further as yet. So, I'm not sure If I'm going to learn or help in this thread. Interested and wanting to help, but just not sure if I posses the skills to do so, or if I will only be able to learn from the suggestions made by other members.

Nice to 'see' you too. I always appreciate a question that clearly describes the issue being tackled and what attempts have been made to overcome it. Your questions always do both in a way that I have great respect for. Its ever so frustrating trying to come-up with a work-around/solution to a given problem, only to be bluntly told "No good" or "Already tried it" or words to that effect. Your questions are always the total opposite of that in my experience. :thumbs-up:
The_Inventor 11-Dec-13 22:00pm    
That is most likely true. I #included afxwin.h. CBitmap is in that file header. I still believe he needs to handle both the WM_SIZE and WM_MOVE messages as well. I used his previous posted code, that has the WM_SIZE handled, just the WM_MOVE to do.
AlwaysLearningNewStuff 17-Dec-13 12:58pm    
I have tried to copy and paste your code, but it failed to compile saying fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d].

After going in Project Settings->Configuration Properties->Use of MFC,, and specifying the Using MFC in a Shared DLL I get other errors.

Notice that I use PURE WIN32 and not MFC, so if you could provide pure Win32 solution I would highly appreciate it.

If you can not do it, then you could lay out your concept so maybe I could implement your solution with investment of my own effort ( I do not mind at all! ).

Thank you.

Best regards.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900