// GAPI1.cpp
//
// GAPI Ļ.
// Ļɫ϶
// һ.

#include "stdafx.h"
#include "GAPI1.h"
#include
#include
#include

#include "gx.h"

#define MAX_LOADSTRING 100

// ȫֱ:
HINSTANCE	hInst;	// ǰʾ
HWND 		hwndCB;	// 

// ȫGAPI :
GXDisplayProperties gx_displayprop;
GXKeyList gx_keylist;

// ȫֱ(ֻ)
int x1=10,x2=100,y1=40,y2=80, dx1=4,dy1=-4, dx2=3,dy2=3;
static SHACTIVATEINFO s_sai;

// ڱģаǰĺ:
ATOM MyRegisterClass (HINSTANCE, LPTSTR);
BOOL InitInstance (HINSTANCE, int);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable;

// ִгʼ:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_GAPI1);

// Ϣѭ:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,
MAKEINTRESOURCE(IDI_GAPI1));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;

return RegisterClass(&wc);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd = NULL;
TCHAR szTitle[MAX_LOADSTRING]; 		// ı
TCHAR szWindowClass[MAX_LOADSTRING]; 	// 

hInst = hInstance; // ǵȫֱд洢ʾ
// ʼȫַ
LoadString(hInstance, IDC_GAPI1, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

//Уѡд
hWnd = FindWindow(szWindowClass, szTitle);
if (hWnd)
{
SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
return 0;
}

MyRegisterClass(hInstance, szWindowClass);

RECT rect;
GetClientRect(hWnd, &rect);

hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//ò˵ĸ߶CW_USEDEFAULT ʱ
// ûпǴһ). ڴµĳߴ
// һ˵
{
RECT rc;
GetWindowRect(hWnd, &rc);
rc.bottom -= MENU_HEIGHT;
if (hwndCB)
MoveWindow(hWnd, rc.left, rc.top, rc.right, rc.bottom, FALSE);
}

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

// GAPI Stuff

// Ļ
if (GXOpenDisplay(hWnd, GX_FULLSCREEN) == 0)
return FALSE;
// ȡʾ
gx_displayprop = GXGetDisplayProperties();

// 16 bitɫʾ
if (gx_displayprop.cBPP != 16)
{
// ֻڱд16 bitɫ
GXCloseDisplay();
MessageBox(hWnd,L"Sorry, only supporting 16bit color",L"Sorry!", MB_OK);
return FALSE;
}

// ť
GXOpenInput();

// ȡĬϰť/µ.
gx_keylist = GXGetDefaultKeys(GX_NORMALKEYS);

return TRUE;
}

// ƻһظýڴַ,ɫ,x  y co-ords
void PlotPixel(unsigned short *buffer, int x, int y, int r, int g, int b)
{

int address = (x * gx_displayprop.cbxPitch>>1) + (y * gx_displayprop.cbyPitch>>1);

unsigned short PixelCol;

if (gx_displayprop.ffFormat & kfDirect565)
{
PixelCol = (unsigned short) (r & 0xff) << 11 | (g & 0xff) << 6 | (b & 0xff);
}
else
{
PixelCol = (unsigned short) (r & 0xff) << 10 | (g & 0xff) << 5 | (b & 0xff);
}
*(unsigned short *)(buffer+address) = PixelCol;
}

// 㷨. See Foly, vanDam, Feiner, Hughes
void DrawLine(unsigned short *buffer, int x0, int y0, int x1, int y1, int r, int g,
int b)
{

int x;

if (x0>x1) {x=x1; x1=x0; x0=x;}
if (y0>y1) {x=y1; y1=y0; y0=x;}

float dx,dy,y,m;

dy=y1-y0;
dx=x1-x0;
m=dy/dx;
y=y0;
for (x=x0; x<x1; x++)
{
PlotPixel(buffer,x,(int)y,r,g,b);
y+=m;
}
}



// Ļú,,ֵɫ
void ClearScreen(int r, int g, int b)
{
// GX ȡĻ.
unsigned short * buffer = (unsigned short *) GXBeginDraw();
unsigned short * line_buffer = buffer;

if (buffer == NULL) return;

// r,g,b ɫ.
unsigned short PixelCol;

if (gx_displayprop.ffFormat & kfDirect565)
{
PixelCol = (unsigned short) (r & 0xff) << 11 | (g & 0xff) << 6 | (b & 0xff);
}
else
{
PixelCol = (unsigned short) (r & 0xff) << 10 | (g & 0xff) << 5 | (b & 0xff);
}

// ѭӶñҪɫĻ
for (unsigned int y=0; y<gx_displayprop.cyHeight; y++)
{

unsigned short * pixel = buffer;

for (unsigned int x=0; x<gx_displayprop.cxWidth; x++)
{
*pixel = PixelCol;
pixel += gx_displayprop.cbxPitch >> 1;
}

buffer += gx_displayprop.cbyPitch >> 1;
}


// һСĶͼ.
// ʹClearScreen±дԽܻ
// ΪΪҪ,
// ȡGXBeginDraw.

DrawLine(line_buffer,x1,y1,x2,y2,0,0,0);

x1+=dx1; if (x1<2 || x1>238) dx1=-dx1;
x2+=dx2; if (x2<2 || x2>238) dx2=-dx2;
y1+=dy1; if (y1<2 || y1>328) dy1=-dy1;
y2+=dy2; if (y2<2 || y2>328) dy2=-dy2;

// ƴ
GXEndDraw();
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{

switch (message)
{

case WM_CREATE:
SetTimer(hWnd,1,100,NULL);
break;

case WM_TIMER:
ClearScreen(rand(),rand(),rand());

break;

case WM_KEYDOWN:

if (wParam == (unsigned) gx_keylist.vkUp)
{

SendMessage(hWnd,WM_CLOSE,0,0);
}

break;

case WM_DESTROY:

KillTimer(hWnd,1);

GXCloseInput();
GXCloseDisplay();

PostQuitMessage(0);
break;

case WM_KILLFOCUS:
GXSuspend();
break;

case WM_SETFOCUS:
GXResume();
break;

case WM_SETTINGCHANGE:
SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
break;
  
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

