BCX is a basic language to C translator. It converts Basic code to C which can then be compiled by several C compilers. Click the link for the SourceForge page.
You can get a development package from
RJP Computing. The development package includes BCX, an editor and the PellesC compiler. This is a really nice package since it sets up everything for you. This is what I use.
The real plus with BCX is that it makes creating window apps very easy. Instead of the clunky winapi syntax, you can use a basic-like syntax for windows program. Here is an example of a parallax star field.
'********************************************************
' BCX Parallax Scrolling Star Field by Kevin Diggins
' Written for BCX version 2.99 -- Uses BCX_PSET command
'********************************************************
GUI "StarsDemo"
CONST StarCount = 200
CONST FactorX = -1
CONST FactorY = 0
CONST DirectionX = -1
CONST DirectionY = 0
SUB FORMLOAD
GLOBAL Form1 AS HWND
GLOBAL Max_X
GLOBAL Max_Y
Form1 = BCX_FORM("BCX Star Field", 0, 0, 300, 250)
BCX_SET_FORM_COLOR(Form1,0)
CENTER(Form1)
SHOW(Form1)
END SUB
BEGIN EVENTS
SELECT CASE CBMSG
CASE WM_CREATE
Max_X = 639
Max_Y = 479
CALL INIT_STARS
EXIT FUNCTION
CASE WM_SIZE
Max_X = LOWORD(lParam)
Max_Y = HIWORD(lParam)
CALL INIT_STARS
EXIT FUNCTION
CASE WM_PAINT
ProcessPlane( 1, StarCount * 0.333, 1)
ProcessPlane(71, StarCount * 0.666, 2)
ProcessPlane(141, StarCount, 3)
EXIT FUNCTION
END SELECT
END EVENTS
SUB INIT_STARS
DIM RAW I,Tmp
GLOBAL X [StarCount+1]
GLOBAL Y [StarCount+1]
FOR I = 0 TO StarCount
Tmp = RND * Max_X
X[I] = Tmp
Tmp = RND * Max_Y
Y[I] = Tmp
NEXT
END SUB
SUB ProcessPlane(Start1,End1,Speed1)
DIM LOCAL I, Tmp, Tmp1, Tmp2, T, Kol
SLEEP(20)
FOR I = Start1 TO End1
Tmp1 = X[I]
Tmp2 = Y[I]
T = FactorX * Speed1
Kol = RND * QBCOLOR(0)
BCX_PSET(Form1,Tmp1,Tmp2,Kol)
Tmp = X[I]
INCR Tmp,T
T = FactorY * Speed1
X[I] = Tmp
Tmp = Y[I]
INCR Tmp,T
Y[I] = Tmp
Tmp = X[I]
IF Tmp <= -1 THEN
X[I] = Max_X
Tmp = RND * Max_Y
Y[I] = Tmp
END IF
Tmp = X[I]
IF Tmp >= Max_X + 1 THEN
X[I] = 0
Tmp = RND * Max_Y
Y[I] = Tmp
END IF
Tmp = Y[I]
IF Tmp <= -1 THEN
Y[I] = Max_Y
Tmp = RND * Max_X
X[I] = Tmp
END IF
Tmp = Y[I]
IF Tmp >= Max_Y THEN
Y[I] = 0
Tmp = RND * Max_X
X[I] = Tmp
END IF
Tmp1 = X[I]
Tmp2 = Y[I]
Kol = RND * QBCOLOR(15)
BCX_PSET(Form1,Tmp1,Tmp2,Kol)
NEXT
END SUB
BCX is also a great way to learn C programming, since you can examine the C code and see how things are done. Here is the C output for the preceding example:
// *************************************************************
// Created with BCX -- The BASIC To C Translator (ver 5.11a)
// BCX (c) 1999 - 2006 by Kevin Diggins
// *************************************************************
// Translated for compiling with a C Compiler
// *************************************************************
#include <windows.h> // Win32 Header File
#include <windowsx.h> // Win32 Header File
#include <commctrl.h> // Win32 Header File
#include <mmsystem.h> // Win32 Header File
#include <shellapi.h> // Win32 Header File
#include <shlobj.h> // Win32 Header File
#include <richedit.h> // Win32 Header File
#include <wchar.h> // Win32 Header File
#include <objbase.h> // Win32 Header File
#include <ocidl.h> // Win32 Header File
#include <winuser.h> // Win32 Header File
#include <olectl.h> // Win32 Header File
#include <oaidl.h> // Win32 Header File
#include <ole2.h> // Win32 Header File
#include <oleauto.h> // Win32 Header File
#include <conio.h>
#include <direct.h>
#include <ctype.h>
#include <io.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <setjmp.h>
#include <time.h>
#include <stdarg.h>
#include <process.h>
// ***************************************************
// Compiler Defines
// ***************************************************
// C++
#if defined( __cplusplus )
#define overloaded
#define C_EXPORT EXTERN_C __declspec(dllexport)
#define C_IMPORT EXTERN_C __declspec(dllimport)
#else
#define C_EXPORT __declspec(dllexport)
#define C_IMPORT __declspec(dllimport)
#endif
// Open Watcom defs
#if defined( __WATCOM_CPLUSPLUS__ ) || defined( __TINYC__ )
#define atanl atan
#define sinl sin
#define cosl cos
#define tanl tan
#define asinl asin
#define acosl acos
#define log10l log10
#define logl log
#define _fcloseall fcloseall
#endif
// Borland C++ 5.5.1 defs - bcc32.exe
#if defined( __BCPLUSPLUS__ )
// ===== Borland Libraries ==========
#include <dos.h>
#pragma comment(lib,"import32.lib")
#pragma comment(lib,"cw32.lib")
// ==================================
#endif
// Microsoft VC++
#ifndef DECLSPEC_UUID
#if (_MSC_VER >= 1100) && defined ( __cplusplus )
#define DECLSPEC_UUID(x) __declspec(uuid(x))
#else
#define DECLSPEC_UUID(x)
#endif
#endif
#if !defined( __LCC__ )
// *************************************************
// Instruct Linker to Search Object/Import Libraries
// *************************************************
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"winspool.lib")
#pragma comment(lib,"shell32.lib")
#pragma comment(lib,"ole32.lib")
#pragma comment(lib,"oleaut32.lib")
#pragma comment(lib,"uuid.lib")
#pragma comment(lib,"odbc32.lib")
#pragma comment(lib,"odbccp32.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"comdlg32.lib")
#pragma comment(lib,"imagehlp.lib")
#pragma comment(lib,"version.lib")
#else
#pragma lib <winspool.lib>
#pragma lib <shell32.lib>
#pragma lib <ole32.lib>
#pragma lib <oleaut32.lib>
#pragma lib <uuid.lib>
#pragma lib <odbc32.lib>
#pragma lib <odbccp32.lib>
#pragma lib <winmm.lib>
#pragma lib <imagehlp.lib>
#pragma lib <version.lib>
// *************************************************
// End of Object/Import Libraries To Search
// *************************************************
#endif
// *************************************************
// User Defined Constants
// *************************************************
#define StarCount 200
#define FactorX -1
#define FactorY 0
#define DirectionX -1
#define DirectionY 0
// *************************************************
// User Global Variables
// *************************************************
static HFONT BcxFont;
static float BCX_ScaleX;
static float BCX_ScaleY;
static HINSTANCE BCX_hInstance;
static HWND BCX_hwndMDIClient;
static WNDCLASSEX BCX_WndClass;
static BOOL BCX_GUI_Init;
static char BCX_ClassName[2048];
static HWND Form1;
static int Max_X;
static int Max_Y;
static int X[StarCount+1];
static int Y[StarCount+1];
// *************************************************
// Standard Macros
// *************************************************
#define DefaultFont ((BcxFont==0)?GetStockObject(DEFAULT_GUI_FONT):BcxFont)
#define Show(Window)RedrawWindow(Window,0,0,0);ShowWindow(Window,SW_SHOW);
// *************************************************
// Standard Prototypes
// *************************************************
void BCX_SetMetric (char *);
void BCX_RegWnd (char *, WNDPROC);
void BCX_InitGUI (void);
HWND BCX_Form(char*,int=0,int=0,int=250,int=150,int=0,int=0);
void BCX_Set_Form_Color (HWND,COLORREF);
COLORREF BCX_Pset (HWND,int,int,int=0,HDC=0);
int qbcolor (int);
void Center (HWND,HWND=0,HWND=0);
float rnd (void);
// *************************************************
// User Prototypes
// *************************************************
void FormLoad (void);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
void INIT_STARS (void);
void ProcessPlane (int, int, int);
// **********************************
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR CmdLine,int CmdShow)
{
MSG Msg;
strcpy(BCX_ClassName,"StarsDemo");
BCX_SetMetric("");
BCX_InitGUI();
BCX_hInstance = hInst;
BCX_WndClass.hIcon = LoadIcon(NULL,IDI_WINLOGO);
BCX_RegWnd( BCX_ClassName, WndProc );
// ******************************************
FormLoad();
// ******************************************
while(GetMessage(&Msg,NULL,0,0))
{
HWND hActiveWindow = GetActiveWindow();
if(!IsWindow(hActiveWindow) || !IsDialogMessage(hActiveWindow,&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
return Msg.wParam;
}
// *************************************************
// Runtime Functions
// *************************************************
float rnd (void)
{
return (float)rand()/RAND_MAX;
}
void Center (HWND hwnd, HWND Xhwnd, HWND Yhwnd)
{
RECT rect, rectP;
int x, y, width, height;
int screenwidth, screenheight;
if(Xhwnd==0)
{
RECT DesktopArea;
RECT rc;
SystemParametersInfo(SPI_GETWORKAREA,0,&DesktopArea,0);
GetWindowRect(hwnd,&rc);
SetWindowPos(hwnd,HWND_TOP,
((DesktopArea.right-DesktopArea.left)-(rc.right-rc.left))/2+
DesktopArea.left,((DesktopArea.bottom-DesktopArea.top)-
(rc.bottom-rc.top))/2 + DesktopArea.top,0,0,SWP_NOSIZE);
return;
}
GetWindowRect (hwnd,&rect);
GetWindowRect (Xhwnd,&rectP);
width = rect.right-rect.left;
x = ((rectP.right-rectP.left)-width)/2 + rectP.left;
if(Yhwnd==NULL)
{
height = rect.bottom-rect.top;
y = ((rectP.bottom-rectP.top)-height)/2 + rectP.top;
}
else
{
GetWindowRect(Yhwnd,&rectP);
height = rect.bottom-rect.top;
y = ((rectP.bottom-rectP.top)-height)/2+rectP.top;
}
screenwidth = GetSystemMetrics(SM_CXSCREEN);
screenheight = GetSystemMetrics(SM_CYSCREEN);
if ((x<0)) x=0;
if ((y<0)) y=0;
if ((x+width>screenwidth)) x = screenwidth-width;
if ((y+height>screenheight)) y = screenheight-height;
MoveWindow (hwnd, x, y, width, height, FALSE);
}
HWND BCX_Form(char *Caption,int X,int Y,int W,int H,int Style,int Exstyle)
{
if(!Style)
{
Style= WS_MINIMIZEBOX | WS_SIZEBOX | WS_CAPTION |
WS_MAXIMIZEBOX | WS_POPUP | WS_SYSMENU;
}
HWND A = CreateWindowEx(Exstyle,BCX_ClassName,Caption,Style,
X*BCX_ScaleX,Y*BCX_ScaleY,(4+W)*BCX_ScaleX,(12+H)*BCX_ScaleY,
NULL,(HMENU)NULL,BCX_hInstance,NULL);
SendMessage(A,(UINT)WM_SETFONT,(WPARAM)DefaultFont,(LPARAM)MAKELPARAM(FALSE,0));
return A;
}
void BCX_Set_Form_Color (HWND hWnd, COLORREF Kolor)
{
HBRUSH hbr=CreateSolidBrush(Kolor);
DeleteObject((HBRUSH)SetClassLong(hWnd,GCL_HBRBACKGROUND,(DWORD)hbr));
InvalidateRect (hWnd,NULL,TRUE);
}
COLORREF BCX_Pset (HWND Wnd,int x,int y,int Pen,HDC DrawHDC)
{
COLORREF a;
int b=0;
HPEN hOPen;
HPEN hNPen=CreatePen(PS_SOLID,1,Pen);
if(!DrawHDC) DrawHDC=GetDC(Wnd),b=1;
hOPen=(HPEN)SelectObject(DrawHDC,hNPen);
a = SetPixelV(DrawHDC,x,y,Pen);
DeleteObject(SelectObject(DrawHDC,hOPen));
if(b) ReleaseDC(Wnd,DrawHDC);
return a;
}
int qbcolor (int N)
{
switch (N)
{
case 0 : return RGB(0,0,0);
case 1 : return RGB(0,0,128);
case 2 : return RGB(0,128,0);
case 3 : return RGB(0,128,128);
case 4 : return RGB(196,0,0);
case 5 : return RGB(128,0,128);
case 6 : return RGB(128,64,0);
case 7 : return RGB(196,196,196);
case 8 : return RGB(128,128,128);
case 9 : return RGB(0,0, 255);
case 10 : return RGB(0,255,0);
case 11 : return RGB(0,255,255);
case 12 : return RGB(255,0,0);
case 13 : return RGB(255,0,255);
case 14 : return RGB(255,255,0);
case 15 : return RGB(255,255,255);
case 16 : return RGB(164,164,164);
case 17 : return RGB(128,160,255);
case 18 : return RGB(160,255,160);
case 19 : return RGB(160,255,255);
case 20 : return RGB(255,160,160);
case 21 : return RGB(255,160,255);
case 22 : return RGB(255,255,160);
case 23 : return RGB(212,212,212);
case 24 : return RGB(180,180,180);
case 25 : return RGB(188,220,255);
case 26 : return RGB(220,255,220);
case 27 : return RGB(220,255,255);
case 28 : return RGB(255,220,220);
case 29 : return RGB(255,220,255);
case 30 : return RGB(255,255,220);
case 31 : return RGB(228,228,228);
}
return 0;
}
void BCX_SetMetric (char *metric)
{
if(!BCX_GUI_Init)
{
BCX_InitGUI();
}
if(stricmp(metric,"PIXELS")==0)
{
BCX_ScaleX=1;
BCX_ScaleY=1;
}
else
{
RECT rc={0,0,4,8};
MapDialogRect(NULL,&rc);
BCX_ScaleX=rc.right/2;
BCX_ScaleY=rc.bottom/4;
}
}
void BCX_RegWnd (char *classname, WNDPROC Form_WndProc)
{
if(classname[0]==0)
{
MessageBox (GetActiveWindow(),"Empty String For BCX_ClassName NOT Allowed","Empty ClassName",0);
fflush(stdout);
ExitProcess(1);
}
if(GetClassInfoEx( BCX_hInstance, classname, &BCX_WndClass)!=0)
{
if(!Form_WndProc)
{
UnregisterClass(classname,BCX_hInstance);
}
return;
}
if(!BCX_GUI_Init)
{
BCX_InitGUI();
}
if(BCX_ScaleX==0&&BCX_ScaleY==0)
{
BCX_SetMetric("Pixels");
}
strcpy(BCX_ClassName,classname);
BCX_WndClass.lpfnWndProc=Form_WndProc;
BCX_WndClass.hInstance=BCX_hInstance;
BCX_WndClass.lpszClassName=classname;
RegisterClassEx(&BCX_WndClass);
}
void BCX_InitGUI (void)
{
INITCOMMONCONTROLSEX iccex;
if(BCX_GUI_Init)
{
return;
}
RECT rc={0,0,4,8};
MapDialogRect(NULL,&rc);
BCX_ScaleX=rc.right/2;
BCX_ScaleY=rc.bottom/4;
BCX_hInstance=GetModuleHandle(NULL);
BCX_hwndMDIClient=NULL;
BCX_WndClass.cbSize=sizeof(BCX_WndClass);
BCX_WndClass.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
BCX_WndClass.cbClsExtra=0;
BCX_WndClass.cbWndExtra=0;
BCX_WndClass.hIcon= LoadIcon(NULL,IDI_WINLOGO);;
BCX_WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
BCX_WndClass.hbrBackground=(HBRUSH)(COLOR_BTNFACE+1);
BCX_WndClass.lpszMenuName=NULL;
BCX_WndClass.hIconSm=NULL;
iccex.dwSize=sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC=ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_BAR_CLASSES | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_PROGRESS_CLASS | ICC_USEREX_CLASSES | ICC_DATE_CLASSES;
InitCommonControlsEx(&iccex);
BCX_GUI_Init=TRUE;
}
// ************************************
// User Subs and Functions
// ************************************
void FormLoad (void)
{
Form1=BCX_Form("BCX Star Field",0,0,300,250);
BCX_Set_Form_Color(Form1,0);
Center(Form1);
Show(Form1);
}
LRESULT CALLBACK WndProc (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
while(1)
{
if(Msg==WM_CREATE)
{
Max_X=639;
Max_Y=479;
INIT_STARS();
return 0;
}
if(Msg==WM_SIZE)
{
Max_X=LOWORD(lParam);
Max_Y=HIWORD(lParam);
INIT_STARS();
return 0;
}
if(Msg==WM_PAINT)
{
ProcessPlane(1,StarCount*.333,1);
ProcessPlane(71,StarCount*.666,2);
ProcessPlane(141,StarCount,3);
return 0;
}
break;
}
if(Msg==WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,Msg,wParam,lParam);
}
void INIT_STARS (void)
{
int I;
int Tmp;
for(I=0; I<=StarCount; I+=1)
{
Tmp=rnd()*Max_X;
X[I]=Tmp;
Tmp=rnd()*Max_Y;
Y[I]=Tmp;
}
}
void ProcessPlane (int Start1, int End1, int Speed1)
{
static int I;
memset(&I,0,sizeof(I));
static int Tmp;
memset(&Tmp,0,sizeof(Tmp));
static int Tmp1;
memset(&Tmp1,0,sizeof(Tmp1));
static int Tmp2;
memset(&Tmp2,0,sizeof(Tmp2));
static int T;
memset(&T,0,sizeof(T));
static int Kol;
memset(&Kol,0,sizeof(Kol));
Sleep(20);
for(I=Start1; I<=End1; I+=1)
{
Tmp1=X[I];
Tmp2=Y[I];
T=FactorX*Speed1;
Kol=rnd()*qbcolor(0);
BCX_Pset(Form1,Tmp1,Tmp2,Kol);
Tmp=X[I];
Tmp+=(T);
T=FactorY*Speed1;
X[I]=Tmp;
Tmp=Y[I];
Tmp+=(T);
Y[I]=Tmp;
Tmp=X[I];
if(Tmp<=-1)
{
X[I]=Max_X;
Tmp=rnd()*Max_Y;
Y[I]=Tmp;
}
Tmp=X[I];
if(Tmp>=Max_X+1)
{
X[I]=0;
Tmp=rnd()*Max_Y;
Y[I]=Tmp;
}
Tmp=Y[I];
if(Tmp<=-1)
{
Y[I]=Max_Y;
Tmp=rnd()*Max_X;
X[I]=Tmp;
}
Tmp=Y[I];
if(Tmp>=Max_Y)
{
Y[I]=0;
Tmp=rnd()*Max_X;
X[I]=Tmp;
}
Tmp1=X[I];
Tmp2=Y[I];
Kol=rnd()*qbcolor(15);
BCX_Pset(Form1,Tmp1,Tmp2,Kol);
}
}