имеем пример работы графического движка на с++ для wince
как его можно переделать на pascal
думаю такой пригодился бы каждому кто хочет писать на wince
есть кто может перевести ?
может у кого нибудь есть уже готовый пример на подобие ?
- Код: Выделить всё
// Test0.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <aygshell.h>
#include <gx.h>
//////////////////////////////////////////////////////////////////////////////////////
#define SCRTYPE_UNKNOWN 0
#define SCRTYPE_QVGA 1
#define SCRTYPE_VGA 2
#define SCRMODE_NONE 0
#define SCRMODE_GAPI_QVGA 1
#define SCRMODE_RAW_VGA 1
//////////////////////////////////////////////////////////////////////////////////////
// Global Variables:
HINSTANCE g_hInst; // The current instance
HWND g_hMainWindow; // Main window handle
// Физические размеры и ориентация экрана
int g_phscreen_type;
int g_phscreen_dx;
int g_phscreen_dy;
int g_phscreen_orient;
// Размеры фреймбуфера
int screen_dx;
int screen_dy;
int screen_size;
int screen_mode;
// Прямоугольник вывода
RECT crect_fullscreen;
// Копия фреймбуфера
LPWORD shadow_buffer;
// координаты мыши (стилуса)
int stylus_down = 0;
int stylus_last_x = 0;
int stylus_last_y = 0;
// переменные нашей главной картинки
int main_x = 50; // координаты картинки
int main_y = 50; //
int main_sdx = 10; // её размеры
int main_sdy = 11; //
// собственно сама картинка - каждый WORD это один пиксель - как видно это
// одномерный массив всего-лишь ...
const WORD main_sprite [11*10] = {
0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000,
0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0x0000,
0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000,
0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0x0000,
0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0x0000, 0xFFFF, 0x0000,
0x0000, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0x0000,
0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0x0000,
0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0x0000, 0x0000, 0x0000,
0x0000, 0xFFFF, 0xFFFF, 0x5555, 0x5555, 0x5555, 0x5555, 0xFFFF, 0xFFFF, 0x0000,
0xFFFF, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0xFFFF
};
// название класса и окна ...
const TCHAR * g_sWindowClass = L"WC_TEST0_CLASS1\0";
const TCHAR * g_sTitle = L"Test0\0";
////////////////////////////////////////////////////////////////////////////////////
// Инициализируем графику
//
BOOL InitGfx ( void )
{
GXDisplayProperties dispprop;
// размеры фреймбуфера зададим фиксированные 240 х 320
screen_dx = 240;
screen_dy = 320;
screen_size = screen_dx * screen_dy;
screen_mode = SCRMODE_NONE;
// границы для вывода на полный экран
crect_fullscreen.left = 0;
crect_fullscreen.right = 240;
crect_fullscreen.top = 0;
crect_fullscreen.bottom = 320;
// инициализируем дисплей
if (GXOpenDisplay(g_hMainWindow, GX_FULLSCREEN) == 0) {
MessageBox(g_hMainWindow, L"GAPI: Unable to init display.", L"ERROR", MB_OK);
return FALSE;
}
dispprop = GXGetDisplayProperties();
// проверяем графические параметры
if ((dispprop.cBPP != 16) || (dispprop.cxWidth != (unsigned int)screen_dx) || (dispprop.cyHeight != (unsigned int)screen_dy))
{
GXCloseDisplay();
MessageBox(g_hMainWindow, L"GAPI: Unable to init 240x320 16bpp mode.", L"ERROR", MB_OK);
return FALSE;
}
// ок, все нормально, режим работы - qvga gapi фреймбуфер
screen_mode = SCRMODE_GAPI_QVGA;
shadow_buffer = (LPWORD) malloc(screen_size*sizeof(WORD));
return TRUE;
}
// Освобождаем ресурсы gapi и прочее
//
void DeinitGfx ( void )
{
if (screen_mode == SCRMODE_GAPI_QVGA) GXCloseDisplay();
free(shadow_buffer);
}
// Выводим копию фреймбуфера на актуальный экран
//
void DrawShadowBuffer ( LPWORD buf )
{
if (screen_mode == SCRMODE_GAPI_QVGA) {
LPWORD framebuffer = (LPWORD) GXBeginDraw();
memcpy(framebuffer, buf, screen_size*sizeof(WORD));
GXEndDraw();
return;
}
}
// Рисуем картинку из массива (spr_data) в буфер (fbuf, копию фреймбуфера шириной 240 пикс.)
//
void draw_sprite( LPWORD fbuf, int x, int y, RECT clip_rect, LPWORD spr_data, int sdx, int sdy )
{
int __x, __y;
int sx, sy;
int ddx, ddy;
LPWORD spraddr, bufaddr;
int i, j;
WORD d;
// проверяем не вылезли ли координаты за ограничивающую область так что рисовать совсем ничего уже и не надо
__x = x; if ((__x >= clip_rect.right) || ((__x + sdx) <= clip_rect.left)) return;
__y = y; if ((__y >= clip_rect.bottom) || ((__y + sdy) <= clip_rect.top)) return;
// проверяем не вылезли ли координаты за ограничивающую область так что рисовать придется не весь спрайт, а его кусок
sx = 0; if (__x<clip_rect.left) { sx = (clip_rect.left-__x); __x = clip_rect.left; }
sy = 0; if (__y<clip_rect.top) { sy = (clip_rect.top-__y); __y = clip_rect.top; }
ddx = sdx - sx; if ((clip_rect.right - __x) < ddx) ddx = (clip_rect.right - __x);
ddy = sdy - sy; if ((clip_rect.bottom - __y) < ddy) ddy = (clip_rect.bottom - __y);
// указатели на начало отображения в буфере экрана и начало в спрайтовом буфере
spraddr = &((spr_data)[sy*sdx+sx]);
bufaddr = &(fbuf[__y*screen_dx+__x]);
for (j=0; j<ddy; j++) {
for (i=0; i<ddx; i++) {
d = spraddr[i];
if (d != 0) bufaddr[i] = d;
}
spraddr += sdx;
bufaddr += 240;
}
}
// Обрабатываем события мыши (стилуса то есть)
//
void OnMouseDown ( int mx, int my )
{
stylus_down = 1;
stylus_last_x = mx;
stylus_last_y = my;
}
void OnMouseUp ( int mx, int my )
{
stylus_down = 0;
stylus_last_x = mx;
stylus_last_y = my;
}
void OnMouseMove ( int mx, int my )
{
stylus_down = 1;
stylus_last_x = mx;
stylus_last_y = my;
}
// Функция вызывающаяся по таймеру где собственно мы всё и рисуем на экран
//
void TimerTick ( void )
{
// управление картинкой
if (stylus_down == 1) {
main_x = stylus_last_x - 4;
main_y = stylus_last_y - 5;
}
// заполняем буфер цветом
memset(shadow_buffer, 0x33, screen_size*sizeof(WORD));
// рисуем нашу картинку
draw_sprite(shadow_buffer, main_x, main_y, crect_fullscreen, (LPWORD)main_sprite, main_sdx, main_sdy);
// рисуем (копируем) буфер на экран (во фреймбуфер)
DrawShadowBuffer(shadow_buffer);
}
// переводим координаты мыши в координаты QVGA с началом в левом верхнем углу
//
void AdjustMouseMessage ( LPARAM * lp )
{
int x, y;
x = LOWORD(*lp);
y = HIWORD(*lp);
// Здесь необходимо проверить как поворот экрана влияет на координаты стилуса для
// разных КПК и разных режимов работы - пока я не стал включать сюда код, требуется
// ещё провести тестирование ... пока оставим пустой
// тут эта строка нужна будет если программа будет работать в настоящем vga-режиме
// то есть ресурсы программы содержат CEUX, HI_RES_AWARE, иначе даже на vga-устройствах координаты
// мыши один фиг будут в qvga
if (g_phscreen_type == SCRTYPE_VGA) { x = x >> 1; y = y >> 1; }
*lp = (y << 16) | (x & 0xFFFF);
}
// Processes messages for the main window.
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
// выходим из программы если нажали где-то в левом верхнем углу экрана
if ((lParam == 0) || (lParam == 1)) { PostQuitMessage(0); return 0; }
AdjustMouseMessage(&lParam);
OnMouseDown(LOWORD(lParam), HIWORD(lParam));
break;
case WM_LBUTTONUP:
AdjustMouseMessage(&lParam);
OnMouseUp(LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOUSEMOVE:
AdjustMouseMessage(&lParam);
OnMouseMove(LOWORD(lParam), HIWORD(lParam));
break;
case WM_KEYDOWN:
break;
case WM_ACTIVATE:
break;
case WM_SETTINGCHANGE:
break;
case WM_TIMER:
TimerTick();
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPCTSTR 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_ICON1));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
// Saves instance handle and creates main window
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
int wx;
// If it is already running, then focus on the window
g_hMainWindow = FindWindow(g_sWindowClass, g_sTitle);
if (g_hMainWindow)
{
// set focus to foremost child window
// The "| 0x01" is used to bring any owned windows to the foreground and
// activate them.
SetForegroundWindow((HWND)((ULONG) g_hMainWindow | 0x00000001));
MessageBox(g_hMainWindow, L"Already running.", L"WARNING", MB_OK);
return 0;
}
// Register class
if (!MyRegisterClass(hInstance, g_sWindowClass)) {
MessageBox(g_hMainWindow, L"Unable to register class.", L"ERROR", MB_OK);
return FALSE;
}
// Получаем реальные физические размеры экрана КПК
g_phscreen_dx = GetSystemMetrics(SM_CXSCREEN);
g_phscreen_dy = GetSystemMetrics(SM_CYSCREEN);
g_phscreen_type = SCRTYPE_UNKNOWN;
if ((g_phscreen_dx == 480) || (g_phscreen_dy == 480)) { g_phscreen_type = SCRTYPE_VGA; wx = 640; }
if ((g_phscreen_dx == 240) || (g_phscreen_dy == 240)) { g_phscreen_type = SCRTYPE_QVGA; wx = 320; }
if (g_phscreen_type == SCRTYPE_UNKNOWN) {
// Error handling for unknown screen resolution ...
}
// Получаем текущую ориентацию экрана (портретная, ландшафтная ...)
DEVMODE sDevMode = {0};
sDevMode.dmSize = sizeof(DEVMODE);
sDevMode.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &sDevMode, NULL, CDS_TEST, NULL);
g_phscreen_orient = sDevMode.dmDisplayOrientation;
// Создаем квадратное окно - чтобы при поворотах экрана в процессе работы нашей программы - оно все равно закрывало весь экран
g_hMainWindow = CreateWindow(g_sWindowClass, g_sTitle, WS_VISIBLE, 0, 0, wx, wx, NULL, NULL, hInstance, NULL);
if (!g_hMainWindow) {
MessageBox(g_hMainWindow, L"Unable to create main window.", L"ERROR", MB_OK);
return FALSE;
}
// окно должно быть поверх всех остальных окон в системе - чтобы нажатия мыши система не вздумала передать другим окнам!
SetWindowPos(g_hMainWindow, HWND_TOPMOST, 0, 0, wx, wx, 0);
ShowWindow(g_hMainWindow, nCmdShow);
UpdateWindow(g_hMainWindow);
// прячем разные не нужным нам кнопки, значок клавиатуры, кнопку "start" и т.д.
SHFullScreen(g_hMainWindow, SHFS_HIDETASKBAR);
SHFullScreen(g_hMainWindow, SHFS_HIDESIPBUTTON);
SHFullScreen(g_hMainWindow, SHFS_HIDESTARTICON);
return TRUE;
}
//
// Entry point
//
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
MSG msg;
// Store instance handle in our global variable
g_hInst = hInstance;
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) return FALSE;
// Init graphics engine
if (!InitGfx()) return FALSE;
// Устанавливаем таймер на 50мс или 1/20сек.
SetTimer(g_hMainWindow, 1, 50, NULL);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Убираем, удаляем, чистим ...
DeinitGfx();
return 0;
}