⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmcal.cpp

📁 wince (windows mobile)绘制的很好实例,可以作为视频开发的参考
💻 CPP
字号:
// Caleidoscope for Windows Mobile
// coded by dzolee - demeter_z@freemail.hu
// http://dzolee.blogspot.com


#include "stdafx.h"
#include "wmcal.h"
#include <windows.h>
#include "timer.h"
#include "..\zgfx\zgfx.h"

// Global Variables:
HINSTANCE g_hInst;			//current instance
HWND g_hWnd;				//window handle
ZGfx g_gfx;
int g_focus;
bool g_running;
int g_screen_w, g_screen_h;
int g_frames;
//displayed gems.
gem g_gems[NUMBER_OF_GEMS];

//////////////////////////////////////////////////////////////////////////
ATOM			MyRegisterClass(HINSTANCE, LPTSTR);
BOOL			InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);

//////////////////////////////////////////////////////////////////////////
//initialize gem colors and positions.
void RandomizeGems()
{
int i;

	for(i=0; i<NUMBER_OF_GEMS; i++)	
	{
		g_gems[i].x=rand() % (g_screen_w/2);
		g_gems[i].y=rand() % (g_screen_h/2);
		switch(rand()%3)
		{
			case 0:
			{
				g_gems[i].color=RGB_TO_565(rand(), 10, 10);
				break;
			}
			case 1:
			{
				g_gems[i].color=RGB_TO_565(10, 10, rand());
				break;
			}
			case 2:
			{
				g_gems[i].color=RGB_TO_565(10, rand(), 10);
				break;
			}
		}

		g_gems[i].color=RGB_TO_565(rand(), rand(), rand());
	}
}

//////////////////////////////////////////////////////////////////////////
//create caleidoscope effect by mirroring.
void DoMirror()
{
register int x, y, maxx, maxy, ypitch, line_size;
register unsigned short *psrc, *pdest;
GfxRetval gr;

	//get YPitch
	g_gfx.GfxGetBufferYPitch(&ypitch);
	//divide by 2, so we can add this to a WORD pointer
	ypitch>>=1;

	//mirror upper-left quarter to upper-right
	maxx=g_screen_w/2;
	maxy=g_screen_h/2;

	//get address of upper-left corner
	gr=g_gfx.GfxGetPixelAddress(0, 0, &psrc);
	if(gr==GfxOK)
	{
		//get address of last pixel in the first row.
		gr=g_gfx.GfxGetPixelAddress(g_screen_w-1, 0, &pdest);
		if(gr==GfxOK)
		{
			//copy pixels from left quarter to right quarter, with a mirroring
			for(y=0; y<maxy; y++)
			{
				for(x=0; x<maxx; x++)
				{
					*pdest--=*psrc++;
				}
				pdest+=maxx;
				pdest+=ypitch;
				psrc-=maxx;
				psrc+=ypitch;
			}
		}
	}

	//mirror upper half to bottom
	maxy=g_screen_h/2;
	line_size=g_screen_w*2;

	//get address of pixel at (0,0)
	gr=g_gfx.GfxGetPixelAddress(0, 0, &psrc);
	if(gr==GfxOK)
	{
		//get address of the last row on the screen
		gr=g_gfx.GfxGetPixelAddress(0, g_screen_h-1, &pdest);
		if(gr==GfxOK)
		{
			//copy line by line, with mirroring
			for(y=0; y<maxy; y++)
			{
				memcpy((void *)pdest, (void *)psrc, line_size);
				psrc+=ypitch;
				pdest-=ypitch;
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////
//this function is called periodically to render a frame.
void DrawFrame(double frametime)
{
register int i, gem_size, gem_step;
GfxRect rect;

	//increment frames counter
	g_frames++;
	//re-randomize the gem positions every 10 seconds.
	if(0==g_frames%(FRAMES_PER_SECOND * 10))
	{
		RandomizeGems();
		g_gfx.GfxClearScreen(false);
	}

	//calculate gem size and movement speed based on resolution
	gem_size=g_screen_w/48;
	gem_step=g_screen_w/96;

	//move & display gems
	for(i=0; i<NUMBER_OF_GEMS; i++)
	{
		//random replacing
		if(0==rand()%128)
		{
			g_gems[i].x=rand() % (g_screen_w/2);
			g_gems[i].y=rand() % (g_screen_h/2);
		}
		//gems can move in 8 directions (left, right, up, down, up-left, etc)
		switch(rand()%7)
		{
			case 0:
			{
				//check boundaries
				if(g_gems[i].x>gem_step)
				{
					g_gems[i].x-=gem_step;
				}
				break;
			}
			case 1:
			{
				//check boundaries
				if(g_gems[i].x>gem_step && g_gems[i].y>gem_step)
				{
					g_gems[i].x-=gem_step;
					g_gems[i].y-=gem_step;
				}
				break;
			}
			case 2:
			{
				//check boundaries
				if(g_gems[i].y>gem_step)
				{
					g_gems[i].y-=gem_step;
				}
				break;
			}
			case 3:
			{
				//check boundaries
				if(g_gems[i].y>gem_step && g_gems[i].x<g_screen_w/2)
				{
					g_gems[i].y-=gem_step;
					g_gems[i].x+=gem_step;
				}
				break;
			}
			case 4:
			{
				//check boundaries
				if(g_gems[i].x<g_screen_w/2)
				{
					g_gems[i].x+=gem_step;
				}
				break;
			}
			case 5:
			{
				//check boundaries
				if(g_gems[i].x<g_screen_w/2 && g_gems[i].y<g_screen_h/2)
				{
					g_gems[i].x+=gem_step;
					g_gems[i].y+=gem_step;
				}
				break;
			}
			case 6:
			{
				//check boundaries
				if(g_gems[i].y<g_screen_h/2)
				{
					g_gems[i].y+=gem_step;
				}
				break;
			}
			case 7:
			{
				//check boundaries
				if(g_gems[i].x>gem_step && g_gems[i].y<g_screen_h/2)
				{
					g_gems[i].x-=gem_step;
					g_gems[i].y+=gem_step;
				}
				break;
			}
		}

		//draw rectangle in upper-left quarter
		rect.h=rect.w=gem_size;
		rect.x=g_gems[i].x;
		rect.y=g_gems[i].y;
		g_gfx.GfxFillRect(rect, g_gems[i].color);
		//draw mirror of this rectangle, but still in upper-left quarter.
		//as a result it will seem as if there were 8 directions, while in fact there are only 4.
		rect.x=g_gems[i].y;
		rect.y=g_gems[i].x;
		g_gfx.GfxFillRect(rect, g_gems[i].color);
	}

	//perform mirroring
	DoMirror();

	//finally update screen - copy sw buffer to the video memory
	g_gfx.GfxUpdateScreen();
}

//////////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
MSG msg;
RECT rc;
MEMORYSTATUS memory;
double lastupdate, passed;
GfxRetval gr;
GfxSubsys gs;

	//check available memory
	memory.dwLength=sizeof(MEMORYSTATUS);
	GlobalMemoryStatus(&memory);
	if(memory.dwAvailVirtual<5*1024*1024)
	{
		MessageBox(0,L"Not enough free memory.\nFree up some memory by closing other applications and try again.",L"Error",MB_OK|MB_ICONSTOP);
		return 0;
	}

	//init focus counter
	g_focus=0;

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

	//get screen dimensions
	g_screen_h=GetSystemMetrics(SM_CYSCREEN);
	g_screen_w=GetSystemMetrics(SM_CXSCREEN);

	//set fullscreen
	SHFullScreen(g_hWnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON);

	//resize window to cover screen
	SetRect(&rc, 0, 0, g_screen_w, g_screen_h);
	MoveWindow(g_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, false);

	//use a rectangle instead of the whole screen
	if(g_screen_w != g_screen_h)
	{
		if(g_screen_w > g_screen_h)
		{
			g_screen_w=g_screen_h;
		}
		else
		{
			g_screen_h=g_screen_w;
		}
	}

	//init graphics
	gr=g_gfx.GfxCreateSurface(g_hWnd, g_screen_w, g_screen_h, &gs);

	if(gr!=GfxOK)
	{
		MessageBox(0,L"Could not initialize graphics. Your device might be incompatible with this program.",L"Error",MB_OK|MB_ICONSTOP);
		return 0;
	}

	//clear background
	g_gfx.GfxFillHWBuffer(RGB_TO_565(150, 150, 200));

	//init gem positions
	RandomizeGems();

	//init timer routines
	TimerInit();

	//init random number generator
	srand(GetTickCount());

	//prepare for the main loop
	lastupdate=0;	//last frame draw time in double
	g_running=true;

	// Main message loop:
	PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
	while(msg.message!=WM_QUIT && g_running)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			//if focus got
			if(g_focus>0)
			{
				passed=TimerGetDouble();				//how much time passed since last update
				passed-=lastupdate;
				if(passed>1.0/FRAMES_PER_SECOND)		//limit framerate
				{
					lastupdate=TimerGetDouble();
					DrawFrame(passed);					//render frame
				}
			}
		}
	}
	return (int) msg.wParam;							//that's it
}

//////////////////////////////////////////////////////////////////////////
//this is a wizard-generated initialization function.
//it performs stuff required by Windows applications.
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
	WNDCLASS wc;

	wc.style         = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc   = WndProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WMCAL));
	wc.hCursor       = 0;
	wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = 0;
	wc.lpszClassName = L"WMCaleidoscope";

	return RegisterClass(&wc);
}

//////////////////////////////////////////////////////////////////////////
//this is a wizard-generated initialization function.
//it performs stuff required by Windows applications.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

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

    //If it is already running, then focus on the window, and exit
    hWnd = FindWindow(L"WMCaleidoscope", L"WMCaleidoscope");	
    if (hWnd) 
    {
        // set focus to foremost child window
        // The "| 0x00000001" is used to bring any owned windows to the foreground and
        // activate them.
        SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
        return 0;
    } 

    if (!MyRegisterClass(hInstance, L"WMCaleidoscope"))
    {
    	return FALSE;
    }

    hWnd = CreateWindow(L"WMCaleidoscope", L"WMCaleidoscope", WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
        return FALSE;
    }

	g_hWnd=hWnd;

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

    return TRUE;
}

//////////////////////////////////////////////////////////////////////////
//this is the message loop.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) 
	{
		case WM_LBUTTONDOWN:			//exit if key pressed or screen tapped
		case WM_KEYDOWN:
		{
			g_running=false;
			break;
		}
		case WM_SETFOCUS:				//redraw screen if focus gotten
		{
			if(g_gfx.GfxIsInitialized())
			{
				g_gfx.GfxResume();
				g_gfx.GfxClearHWBuffer();	//redraw screen
				g_gfx.GfxUpdateScreen();
			}
			g_focus++;
			break;
		}
		case WM_KILLFOCUS:				//suspend graphics if focus lost (eg. low battery popup)
		{
			g_focus--;
			g_gfx.GfxSuspend();
			break;
		}
		case WM_PAINT:					//handle windows painting messages.
		{
			if(g_gfx.GfxIsInitialized())
			{
				ValidateRect(hWnd, 0); //no repaint - validate the entire window.
			}
			else
			{
				//gfx not yet inited, let windows draw
				return DefWindowProc(hWnd, message, wParam, lParam);
			}
			break;
		}
		case WM_DESTROY:
		{
			PostQuitMessage(0);
			break;
		}
		default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -