Click here to Skip to main content
15,885,435 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I bit new to win32 I usually work with Qt.
I want to create a splash type window i.e. a window on different thread and rotate a image with transparent background till the main thread is busy.

I found a code of splash screen in win32. and tried to modify it. Please help me to do following task.

1) call "drawImage" method again and again to animate.
2) how to set transparency or alpha blend on. (image have transparent background).
3) how to remove previous image data.

BusyWnd.h
C++
class CBusyWnd
{
public:
	CBusyWnd	( HWND inParent = NULL );
	~CBusyWnd	( void );

public:
	void		setImage		( Gdiplus::Image&	inImage);		
	void		setWindowName	( LPCWSTR	inName );

	void		show		( );
	void		hide		( );
inline	HWND		windowHandle	( ) const{return mWnd;}

private:
	bool		regWndClass	( WNDCLASS&		outWndClass);
	void		findImagePos	( RECT&			outRect);
	void		eventLoop	( );				
	void		drawImage	( HWND			inHwnd);


static	LRESULT	CALLBACK	wndProc		( HWND		inHW, 
					  UINT		inMsg,
					  WPARAM	inWParam,
					  LPARAM	inLParam);
static	unsigned int __stdcall	threadProc	( void*		inLPParameter);

private:
	HWND				mParent;
	HWND				mWnd;
	std::wstring		mName;
	HANDLE				mEvent;
	HANDLE				mThread;
	unsigned int		mThreadID;
	Gdiplus::Image*		mImage;

	//Event Loop Data
	Gdiplus::REAL		mAngle;
};


BusyWnd.cpp

C++
CBusyWnd::CBusyWnd			(HWND inParent)
	:mParent(inParent),
	 mWnd(NULL),
	 mEvent(NULL),
	 mThread(NULL),
	 mThreadID(0),
	 mImage(NULL),
	 mAngle(0.0){}

CBusyWnd::~CBusyWnd			(void)
{
	hide();
	if(mImage)	delete mImage;
}

void CBusyWnd::setImage		( Gdiplus::Image&	inImage )
{
	if (mImage == NULL && &inImage != NULL)
		mImage = inImage.Clone();
}

void CBusyWnd::setWindowName( LPCWSTR			inName )
{
	mName = inName;
}

void CBusyWnd::show			( )
{
	if (mThread == NULL)
	{
		mEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
		mThread = (HANDLE) _beginthreadex	( NULL,
											  0,threadProc,
											  static_cast<LPVOID>(this),
											  0,&mThreadID);
		
		if (WaitForSingleObject(mEvent, 5000) == WAIT_TIMEOUT)
		{
			OutputDebugString(L"Error starting \"Busy Window\" Thread\n");
		}
	}
	else
	{
		PostThreadMessage( mThreadID, WM_ACTIVATE, WA_CLICKACTIVE, 0 );
	}
}

void CBusyWnd::hide			( )
{
	if (mThread)
	{
		PostThreadMessage(mThreadID, WM_QUIT, 0, 0);
		if ( WaitForSingleObject(mThread, 9000) == WAIT_TIMEOUT )
		{
			::TerminateThread( mThread, 2222 );
		}
		CloseHandle(mThread);
		CloseHandle(mEvent);
	}
	mThread = NULL;
}

bool CBusyWnd::regWndClass	( WNDCLASS&			outWndClass )
{
	outWndClass.style		= CS_HREDRAW | CS_VREDRAW;
	outWndClass.lpfnWndProc	= wndProc; 
	outWndClass.hInstance	= GetModuleHandle(NULL);
	outWndClass.hCursor			= LoadCursor(NULL, IDC_APPSTARTING);
	outWndClass.hbrBackground	= (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;
		}
	}
	return true;
}

void CBusyWnd::findImagePos	( RECT&				outRect )
{
	POINT point = { 0 };
	MONITORINFO mi = { sizeof(MONITORINFO), 0 };
	HMONITOR hMonitor = 0;

	::GetCursorPos( &point );
	hMonitor = ::MonitorFromPoint( point, MONITOR_DEFAULTTONEAREST );
	if ( ::GetMonitorInfo( hMonitor, &mi ) )
	{
		outRect.left = ( mi.rcMonitor.right + mi.rcMonitor.left - static_cast<long>(mImage->GetWidth()) ) /2;
		outRect.top = ( mi.rcMonitor.top + mi.rcMonitor.bottom - static_cast<long>(mImage->GetHeight()) ) /2;
	}
	else
	{
		SystemParametersInfo(SPI_GETWORKAREA, NULL, &outRect, NULL);
		outRect.left = (outRect.right + outRect.left - mImage->GetWidth())/2;
		outRect.top = (outRect.top + outRect.bottom - mImage->GetHeight())/2;
	}  
}

void CBusyWnd::eventLoop	( )
{
	SetWindowLongPtr(mWnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(this) );
	ShowWindow(mWnd, SW_SHOWNOACTIVATE);

	//Event Loop
	MSG msg;
	BOOL bRet;
	LONG timerCount = 0;

	PeekMessage(&msg, NULL, 0, 0, 0); // invoke creating message queue
	SetEvent(mEvent);

	while ((bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
	{ 
		if (bRet == -1 || msg.message == WM_QUIT)
			return;

		TranslateMessage(&msg); 
		DispatchMessage(&msg);
	}

	DestroyWindow(mWnd);
}

void CBusyWnd::drawImage	( HWND				inHwnd )
{
	if (mImage)
	{
		Gdiplus::Graphics gdip(inHwnd);
		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());	
         }
	InvalidateRect(inHwnd, NULL, TRUE);
}

unsigned int __stdcall	CBusyWnd::threadProc	( void*		inLPParameter )
{
	CBusyWnd* bWnd = static_cast<CBusyWnd*>(inLPParameter);
	if (bWnd->mImage == NULL) return 0;

	// Register your unique class name
	WNDCLASS wndcls = {0};
	if(!bWnd->regWndClass(wndcls))
		return 0;

	// try to find monitor where mouse was last time
	RECT rcArea = { 0 };
	bWnd->findImagePos(rcArea);

	//Create Window
	bWnd->mWnd = CreateWindowEx		( bWnd->mName.length()?0:WS_EX_TOOLWINDOW,
									  L"BusyWnd",
									  bWnd->mName.c_str(), 
									  WS_CLIPCHILDREN|WS_POPUP,
									  rcArea.left,
									  rcArea.top,
									  bWnd->mImage->GetWidth(),
									  bWnd->mImage->GetHeight(),
									  bWnd->mParent,
									  NULL,
									  wndcls.hInstance,
									  NULL);
	if (!bWnd->mWnd)
	{
		OutputDebugString(L"Unable to create BusyWnd\n");
		return 0;
	}

	//Call Event Loop
	bWnd->eventLoop();
	return 0;
}

LRESULT	CALLBACK		CBusyWnd::wndProc		( HWND		inHW,
						  UINT		inMsg,
						  WPARAM	inWParam,
						  LPARAM	inLParam )
{
	CBusyWnd* bWnd = reinterpret_cast<CBusyWnd*>(GetWindowLongPtr(inHW, GWL_USERDATA));
	if (bWnd == NULL)
		return DefWindowProc(inHW, inMsg, inWParam, inLParam);

	switch (inMsg)
	{
	case WM_PAINT:
		bWnd->drawImage(inHW);
		break;
	}

	return DefWindowProc(inHW, inMsg, inWParam, inLParam);
}


in this code I am not able to call my drawImage method again and again. when I call show it start a new thread and create a Image window and when I call hide it kills the thread and window.
Posted
Updated 22-Apr-13 12:01pm
v8

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