?? wmcal.cpp
字號(hào):
// 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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -