Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ Win32 GDI+
I am using GDI+ to draw png image with transparency.
 
after sometime I want to draw same image with some rotation. but I am not able to remove The previous image date. So my rendered window is a series of old images.
 
void CBusyWnd::drawImage	( )
{
	if (mImage)
	{
		Gdiplus::Graphics gdip(mWnd);
		gdip.ResetTransform();
		gdip.TranslateTransform((Gdiplus::REAL)(mImage->GetWidth())/2.0f,(Gdiplus::REAL)(mImage->GetHeight())/2.0f);
		gdip.RotateTransform(mAngle=mAngle>360?0:mAngle+1);
		gdip.TranslateTransform(-1.0f*(Gdiplus::REAL)(mImage->GetWidth())/2.0f,-1.0f*(Gdiplus::REAL)(mImage->GetHeight())/2.0f);
		gdip.DrawImage(mImage, 0, 0, mImage->GetWidth(), mImage->GetHeight());
		gdip.Flush();
	}
	InvalidateRect(mWnd, NULL, FALSE);
}
please find image at http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/825a5243-9441-4abc-be30-e5598ccc9872[^]
 
my registered window class is:-
 
outWndClass.style		= CS_HREDRAW | CS_VREDRAW;
outWndClass.lpfnWndProc		= wndProc; 
outWndClass.hInstance		= GetModuleHandle(NULL);
outWndClass.hCursor		= LoadCursor(NULL, IDC_APPSTARTING);
outWndClass.hbrBackground	= (HBRUSH)GetStockObject(HOLLOW_BRUSH);//(HBRUSH)(COLOR_WINDOW + 1);
outWndClass.lpszClassName	= L"BusyWnd";
 
outWndClass.hIcon		= LoadIcon(outWndClass.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
 

if (!RegisterClass(&outWndClass))
{
	if (GetLastError() != 0x00000582) // already registered)
	{
		OutputDebugString(L"Unable to register class BusyWnd\n");
		return false;
	}
}
 
 
Can anyone help give me some pointer.
 
I tried following code for clearing the window before each draw. but Code is too slow and the is no way to set transparency.
 
HDC hdc = GetDC(mWnd); // Get the DC from that HWND
for( UINT i = 0 ; i < mImage->GetWidth() ; i++ )
	for( UINT j = 0 ; j < mImage->GetHeight() ; j++ )
		SetPixel(hdc, i,j, RGB(255,255,255)); // SetPixel(HDC hdc, int x, int y, COLORREF color)
ReleaseDC(mWnd, hdc); // Release the DC
DeleteDC(hdc); // Delete the DC
Posted 25-Apr-13 2:16am
Comments
enhzflep at 25-Apr-13 7:42am
   
I just handle the WM_ERASEBKG message. Though only do this, so that I can erase the background or not, depending on whether or not the image has an alpha channel. Though, you possibly don't need to go that far. As it stands, your call to InvalidateRect passes false for the 3rd param - if you change this to true, the WM_ERASEBKG message gets sent. I'm not familiar with mfc, so don't know if that will do the trick, or if you'll have to handle it yourself. Also, I noticed a background brush of HOLLOW_BRUSH - think you'll have to set that to a colour for it to work.
saurabh saini at 25-Apr-13 8:18am
   
Thanks for your reply.
Sending True or False to InvalidateRect doesn't make any difference right now and I have no code in WM_ERASEBKG.
Can u tell me which brush to use for alpha and what code to write in WM_ERASEBKG.
enhzflep at 25-Apr-13 8:37am
   
No worries.
I use this code in a class that subclasses static controls and draws transparent pngs in em.
So, the background brush is whatever is the default for the control. If it's hollow, then the dialog colour will be shown, I guess.
 
LRESULT CALLBACK CStaticImg::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
RECT myRect;
PAINTSTRUCT ps;
HBRUSH mBrush;
switch (uMsg)
{
case WM_PAINT:
BeginPaint(hWnd, &ps);
displayImage();
EndPaint(hWnd, &ps);
return false;
case WM_ERASEBKGND:
GetClientRect(hWnd, &myRect);
mBrush = (HBRUSH) GetWindowLong(hWnd, GCL_HBRBACKGROUND);
if (isBkgTransparent)
FillRect((HDC)wParam, &myRect, mBrush);
return true;
}
return CallWindowProc(mOldWndProc, hWnd, uMsg, wParam, lParam);
}
saurabh saini at 25-Apr-13 9:45am
   
I have tried this code, The background is not transparent after the Call of FillRect. moreover it started flickering.
Jochen Arndt at 25-Apr-13 8:33am
   
To erase rectangular areas, you can use the GDI FillRect() function passing a brush or one of the standard Windows system colors. This will be much faster than using SetPixel() inside a loop.
saurabh saini at 25-Apr-13 9:43am
   
I was just trying with SetPixel. but SetPixel doesn't support alpha value.
I have tried FillRect. I think I am not able to find right brush. moreover my animation start to flicker after FillRect.
Jochen Arndt at 25-Apr-13 10:00am
   
Flickering is a common problem with GDI. To avoid it, use double buffering. That is perform drawing using a memory DC and then BitBlt (copy) the complete image to the window DC so that it is shown on the screen.
 
I did not had a look on your link before but saw now what you want. When using only one layer and drawing your symbol over the picture, you can not restore the bits below the symbol. You must redraw the whole image. A solution is to use multiple layers. One for the picture, and one for the symbol where both use a memory DC. When one of it must be changed, update it in memory and BitBlt all layers to the window DC afterwards.
saurabh saini at 25-Apr-13 10:38am
   
I able to understand what you are saying. But I am new to win32 programing, I found some code of transparent splash screen and modified that, plus tried to add some animation in it, that's where the problem started.
It will be better for me, if you can give some kind a code or pseudo code or some link how to do the things you saying in win32.
If you want I can provide you with the header and cpp of my class.
Jochen Arndt at 26-Apr-13 3:33am
   
I did not have code or specific links myself.
 
A good beginners artice is
http://www.codeproject.com/Articles/1988/Guide-to-WIN32-Paint-for-beginners
 
To have a list of articles here at CodeProject, see
http://www.codeproject.com/search.aspx?q=gdi+c%2b%2b+win32&doctypeid=1
 
You may repeat the search removing 'win32' because code using MFC with GDI can be often simply ported to Win32 and shows at least how specific operations can be performed.
 
Additional search keywords (not only here but also using a web search) are 'animation' and 'sprites'.
 
The basic operations are:
- Create a memory DC for the picture using size of picture and color depth of screen
- Create a memory DC for the symbol using same size and color depth or optional a smaller size
- Load picture into first DC
- Draw symbol into second
- BitBlt (copy) picture to screen
- BitBlt the transparent symbol to the screen
- Repeat above 3 steps to change the symbol
 
If there is still flickering, perform the above operations into another memory DC and finally copy that to the screen.

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Right now what your code is doing is its not clearing the previous position of .png image. What you need to do is every time you need to reload the background image and then position your .png .
  Permalink  
Comments
saurabh saini at 25-Apr-13 9:25am
   
thanks for your reply.
Sorry but I am not able to understand what and how to do that. I am bit new to win32 and GDI.

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

  Print Answers RSS
0 OriginalGriff 215
1 George Jonsson 175
2 Kornfeld Eliyahu Peter 159
3 PIEBALDconsult 110
4 Richard MacCutchan 85
0 OriginalGriff 6,080
1 DamithSL 4,648
2 Maciej Los 4,087
3 Kornfeld Eliyahu Peter 3,624
4 Sergey Alexandrovich Kryukov 3,294


Advertise | Privacy | Mobile
Web02 | 2.8.141220.1 | Last Updated 25 Apr 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100