Version:0.9 StartHTML:0000000105 EndHTML:0000078245 StartFragment:0000001037 EndFragment:0000078229 mXScriptasHTML
{**********************************************************************
 * Project  : LED BOX System Arduino Function Overview
 * App Name : 301_LED_Arduino3.txt, delphi_leds.pde :loc's = 571 
 * Purpose  : Demonstrates cPort COM with Arduino
 * Date     : 09/25/2012  -  17:07
 * History  : convert CPort Library to maXbox Aug 2011
 *          : system save data looger for mX3.9.2, finished yet!!
            : communicates with COM Ports to USB arduino LED lights;
 **********************************************************************}

Program Arduino_LED_3;

{@BOOL WINAPI MessageBeep(
  __in  UINT uType  );}
//TThreadFunction = function(P: Pointer): Longint; stdcall;
//Procedure ExecuteThread(afunc: TThreadFunction; var thrOK: boolean);


function MessageBoxTimeOut(hWnd: HWND; lpText: PChar; lpCaption: PChar; uType: UINT;
                wLanguageId: WORD; dwMilliseconds: DWORD): Integer;
             external 'MessageBoxTimeoutA@user32.dll stdcall';
  
procedure TForm1_FormClose(Sender: TObject; var action: TCloseAction); forward;
  
Const
  BACKMAP = 'examples\images\bmp47.bmp';
  //BACKMAP = 'examples\images\bmp33.bmp';
  BITMAP1 = 'examples\images\empty.bmp';
  SAVEPATH = 'examples\treeview_300.txt';
  
type
  TByteArr = array of byte;
  
var
  except_state, execute_state: string;  
  mytimestamp: TDateTime;
  osType: TIdWin32Type;
  //logfrm: TForm;
  

procedure getMaxBoxIni;
var Ini: TIniFile;   
begin
  Ini:= TIniFile.Create(ExePath+'maxboxdef.ini');
  try
    except_state:= Ini.ReadString('Form', 'EXCEPTIONLOG','');
    execute_state:= Ini.ReadString('Form', 'EXECUTESHELL','');
  finally
    writeln('inifile sysdata test: '+(except_state)+ ' '+(execute_state))
    ini.Free;
  end;
end;

procedure PrintList(Value: TStringList);
var
  I, Line, Pagenum: Integer;
begin
  //let's print
  //if Assigned(FOnBeginPrint) then
    //FOnBeginPrint(Self);
  line := 0;
  Printer.BeginDoc;
  Pagenum := 1;
  for I := 0 to Value.Count - 1 do begin
    //if Assigned(FOnProgress) then
      //FOnProgress(Self, I + 1, Value.Count);
    Line := Line + Printer.Canvas.TextHeight(Value[I]);
    if Line + Printer.Canvas.TextHeight(Value[I]) > Printer.PageHeight then begin
      Line := Printer.Canvas.TextHeight(Value[I]);
      Printer.NewPage;
      Inc(PageNum);
      //if Assigned(FOnNextPage) then
        //FOnNextPage(Self, PageNum);
    end;
    Printer.Canvas.TextOut(0, Line, Value[I]);
  end;
  Printer.EndDoc;
  //if Assigned(FOnFinishedPrint) then
    //FOnFinishedPrint(Self);
end;


//*******************************Data Logger*****************************//
var FLogFileName:string;
    JvLogFile1: TJvLogFile;
    btnStart, btnShow, btnReset: TButton;
    lblActive, lblInactive: TLabel;


procedure TJvLog_StopLogging;
begin
  btnStart.Tag:= 0;
  lblActive.Visible := false;
  lblInactive.Visible := true;
  btnStart.Caption := '&Start';
  JvLogFile1.SaveToFile(FLogFileName);
end;

procedure TJvLog_ResetLogging;
begin
  TJvLog_StopLogging;
  DeleteFile(FLogFileName);
  JvLogFile1.Clear;
end;

procedure TJvLog_StartLogging;
begin
  if FileExists(FLogFileName) then
    JvLogFile1.LoadFromFile(FLogFileName);
  btnStart.Caption := '&Stop';
  btnStart.Tag := 1;
  lblActive.Visible := true;
  lblInactive.Visible := false;
end;

procedure TJvLogFMainForm_FormCreate(Sender: TObject);
begin
  FLogFileName:= ChangeFileExt(Application.ExeName,'.log');
end;

procedure TJvLogFMainForm_btnStartClick(Sender: TObject);
begin
  if btnStart.Tag = 0 then
    TJvLog_StartLogging
  else
    TJvLog_StopLogging;
end;

procedure TJvLogFMainForm_btnShowClick(Sender: TObject);
begin
  if btnStart.Tag = 1 then
    //btnStart.Click; // stop logging
    TJvLogFMainForm_btnStartClick(self);
  JvLogFile1.ShowLog('Mouse Move Log');
end;

procedure TJvLogFMainForm_FormMouseMove(Sender: TObject; Shift:TShiftState; X,Y: Integer);
begin
  if btnStart.Tag = 1 then
    JvLogFile1.Add(DateTimeToStr(Now),'Mouse Move',Format('X:%d, Y:%d',[X,Y]));
  writeln(Format('JvLogFile Demo - X:%d, Y:%d',[X,Y]));
end;

procedure TJvLogFMainForm_btnResetClick(Sender: TObject);
begin
  TJvLog_ResetLogging;
end;


//*******************************COM Port Arduino*****************************//
var 
    btn_connect, btn_Setup, btn_loop: TBitBtn;
    ComPort1: TComPort;
    StatusBar1: TStatusBar;
    chk_led1, chk_led2, chk_led3, chk_led4, chk_led5: TCheckBox;
    comFrm: TForm;
    
procedure TForm1_btn_connectClick(Sender: TObject);
begin
  if ComPort1.Connected then begin
     btn_connect.Caption:= 'Connect';  // Toggle the caption of Connection Button
     btn_Setup.Enabled:= True;         // If not connected, lets enable the Setup Button
     btn_loop.Enabled:= false;         // Knight Rider demo button is disabled at first

      // This block resets the state of all Leds to Off
      // According to Arduino Code the Chars A,B,C,D,E are used
      // to set Digital Pins (2-6) to LOW
      comport1.WriteStr('A');
      comport1.WriteStr('B');
      comport1.WriteStr('C');
      comport1.WriteStr('D');
      comport1.WriteStr('E');
      //-----------------------------------------------
      // This block resets the state of all Check Boxes to Unchecked
      chk_led1.Checked:=false;
      chk_led2.Checked:=false;
      chk_led3.Checked:=false;
      chk_led4.Checked:=false;
      chk_led5.Checked:=false;
      //-----------------------------------------------
      ComPort1.Close;              // COM Port in use is closed

      statusbar1.Panels[1].Text:='Disconnected';  // Status bar is set to display connection info
      // This block disables the check boxes
      // so the user cannot change them if COM Port is disconnected
      chk_led1.Enabled:=false;
      chk_led2.Enabled:=false;
      chk_led3.Enabled:=false;
      chk_led4.Enabled:=false;
      chk_led5.Enabled:=false;
      //------------------------------------------------
     end else begin
      btn_connect.Caption:='Disconnect';        // Toggle the caption of Connection Button
      btn_Setup.Enabled:=False;                 // If not connected, lets disable the Setup Button
      btn_loop.Enabled:=true;                   // Now that conection Rider demo button is enabled
      ComPort1.Open;                            // COM Port in use is finally opened
      statusbar1.Panels[1].Text:='Connected';   // Status bar is set to display connection info

      // This block enables the check boxes
      // so the user can change them to set LED states when COM Port is connected
      chk_led1.Enabled:=true;
      chk_led2.Enabled:=true;
      chk_led3.Enabled:=true;
      chk_led4.Enabled:=true;
      chk_led5.Enabled:=true;
      //------------------------------------------------
    end
end;

procedure TForm1_btn_SetupClick(Sender: TObject);
begin
 comport1.ShowSetupDialog;                                   // Opens the predefined Setup Dialog (part of ComPort component)
 statusbar1.Panels[0].Text:= 'Port in use ' + comport1.Port;  // Status bar is set to display Port in use after setup dialog
end;

procedure TForm1_FormCreateCom(Sender: TObject);
begin
 comport1:= TComport.Create(self);
  with comport1 do begin
    BaudRate:= br9600;
    Port:= 'COM1';
    Parity.Bits:= prNone;
    StopBits:= sbOneStopBit;
    DataBits:= dbEight;
    Events:= [evRxChar, evTxEmpty, evRxFlag, evRing, evBreak, evCTS, evDSR, evError, evRLSD, evRx80Full]
    FlowControl.OutCTSFlow:= False;
    FlowControl.OutDSRFlow:= False;
    FlowControl.ControlDTR:= dtrDisable;
    FlowControl.ControlRTS:= rtsDisable;
    FlowControl.XonXoffOut:= False;
    FlowControl.XonXoffIn:= False;
  end;
  writeln('debug: com frm create ');
   
 statusbar1.Panels[0].Text:='Port in use ' + comport1.Port;  // Status bar is set to display predefined Port in use at begining of program execution

  if comport1.Connected=true then
    statusbar1.Panels[1].Text:='Connected'                  // Status bar is set to display connection info at begining of program execution
    else
    statusbar1.Panels[1].Text:='Disconnected'
  end;

// Next are the procedures to turning ON and OFF each led using the variables
// defined on both Arduino code and delphi code.
// Sending the predifined vars thru serial comm (on byte at the time)
// Ports 2,3,4,5,6 are turned ON by sending it corresponding var 1,2,3,4,5
// and they are turned OFF by sending it corresponding var A,B,C,D,E

procedure TForm1_chk_led1Click(Sender: TObject);
begin
  if chk_led1.Checked=true then
    comport1.WriteStr('1')
    else
    comport1.WriteStr('A');
    writeln('debug com led 1');
 end;

procedure TForm1_chk_led2Click(Sender: TObject);
begin
    if chk_led2.Checked=true then
    comport1.WriteStr('2')
    else
    comport1.WriteStr('B')
end;

procedure TForm1_chk_led3Click(Sender: TObject);
begin
    if chk_led3.Checked=true then
    comport1.WriteStr('3')
    else
    comport1.WriteStr('C')
end;

procedure TForm1_chk_led4Click(Sender: TObject);
begin
    if chk_led4.Checked=true then
    comport1.WriteStr('4')
    else
    comport1.WriteStr('D')
end;

procedure TForm1_chk_led5Click(Sender: TObject);
begin
    if chk_led5.Checked=true then
    comport1.WriteStr('5')
    else
    comport1.WriteStr('E')
end;

// Here ends the ON/OFF procedures for each led

procedure TForm1_FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if ComPort1.Connected then begin
      comport1.WriteStr('A');     // If the application is closed, its good to leave
      comport1.WriteStr('B');     // everything as we found it at start.
      comport1.WriteStr('C');     // So we reset all the leds to OFF
      comport1.WriteStr('D');
      comport1.WriteStr('E');
      ComPort1.Close;
    end
end;

procedure TForm1_btn_loopClick(Sender: TObject);
begin
// We turn off all Led Check Boxes to allow a clean state before and after Knight Rider mode
      chk_led1.Checked:=false;
      chk_led2.Checked:=false;
      chk_led3.Checked:=false;
      chk_led4.Checked:=false;
      chk_led5.Checked:=false;

// Here begins the rough mode of Knight Rider Demo ;)
  comport1.WriteStr('1'); Sleep(50);
  comport1.WriteStr('A'); Sleep(50);
  comport1.WriteStr('2'); Sleep(50);
  comport1.WriteStr('B'); Sleep(50);
  comport1.WriteStr('3'); Sleep(50);
  comport1.WriteStr('C'); Sleep(50);
  comport1.WriteStr('4'); Sleep(50);
  comport1.WriteStr('D'); Sleep(50);
  comport1.WriteStr('5'); Sleep(50);
  comport1.WriteStr('E'); Sleep(50);
  comport1.WriteStr('4'); Sleep(50);
  comport1.WriteStr('D'); Sleep(50);
  comport1.WriteStr('3'); Sleep(50);
  comport1.WriteStr('C'); Sleep(50);
  comport1.WriteStr('2'); Sleep(50);
  comport1.WriteStr('B'); Sleep(50);
  comport1.WriteStr('1'); Sleep(50);
  comport1.WriteStr('A'); Sleep(50);
end;

procedure InitComPortForm;
begin
 comFrm:= TForm.create(self);
 with comFrm do begin
   //FormStyle := fsStayOnTop;
   Position:= poScreenCenter;
   caption:='COM Port meets Arduino LED - DblClick to Save Outline';
   //color:= clsilver;
   width:= 700;
   height:= 550;
   //Canvas.Pen.mode:= pmNotXor;
   //onMouseMove:= @FormMouseMove;
   //onMouseDown:= @FormMouseDown;
   //onDblClick:= @DblClickButton;
   //onCreate:= @TForm1_FormCreate;        
   onClose:=  @TForm1_FormClose;
   Show;
   canvas.brush.bitmap:= getBitmapObject(Exepath+'examples\images\bmp47.bmp');
   Canvas.FillRect(Rect(600,400,210,100));
 end;
 btn_Setup:=  TBitBtn.create(comfrm);
 with btn_Setup do begin
   parent:= comfrm;
   setbounds(500,440,150,55)
   font.size:= 12;
   glyph.LoadFromResourceName(HINSTANCE,'ledbulbon'); //Knownfile
   mXButton(05,05,width, height,12,12,handle);
   caption:= '&Settings';
   onClick:= @TForm1_btn_SetupClick;
 end;
 btn_connect:= TBitBtn.create(comfrm);
 with btn_connect do begin
   Parent:= comfrm;
   setbounds(180,440,150, 55);
   caption:= 'C&onnect Node';
   font.size:= 12;
   glyph.LoadFromResourceName(getHINSTANCE,'CL_MPNEXT');
   mXButton(05,05,width, height,12,12,handle);
   onClick:= @TForm1_btn_connectClick;
 end;
 btn_Loop:= TBitBtn.create(comfrm);
 with btn_loop do begin
   Parent:= comfrm;
   setbounds(340,440,150, 55);
   Hint:= 'Do a loop thru all the leds on and off'
   ShowHint:= True;
   caption:= '&Knight Rider';
   font.size:= 12;
   glyph.LoadFromResourceName(getHINSTANCE,'CL_MPSTOP');
   mXButton(05,05,width, height,12,12,handle);
   onClick:= @TForm1_btn_loopClick;
 end;
 
 with TDateTimePicker.Create(self) do begin
    parent:= comfrm;
    //color
    date;
    //time:= now;
    top:= 190;
    left:= 15;
    calalignment:= albottom;
  end;
  chk_led1:= TCheckBox.create(self)
    with chk_led1 do begin
    parent:= comfrm;
    SetBounds(16,42,57,17)
    Caption:= 'Led 1';
    Enabled:= False;
    //TabOrder = 3
    OnClick:= @TForm1_chk_led1Click;
  end;
   chk_led2:= TCheckBox.create(self)
    with chk_led2 do begin
    parent:= comfrm;
    SetBounds(16,66,57,17)
    Caption:= 'Led 2';
    Enabled:= False;
    //TabOrder = 3
    OnClick:= @TForm1_chk_led2Click;
  end;
  chk_led3:= TCheckBox.create(self)
    with chk_led3 do begin
    parent:= comfrm;
    SetBounds(16,90,57,17)
    Caption:= 'Led 3';
    Enabled:= False;
    //TabOrder = 3
    OnClick:= @TForm1_chk_led3Click;
  end;
 chk_led4:= TCheckBox.create(self)
    with chk_led4 do begin
    parent:= comfrm;
    SetBounds(16,114,57,17)
    Caption:= 'Led 4';
    Enabled:= False;
    //TabOrder = 3
    OnClick:= @TForm1_chk_led4Click;
  end;
  chk_led5:= TCheckBox.create(self)
    with chk_led5 do begin
    parent:= comfrm;
    SetBounds(16,138,57,17)
    Caption:= 'Led 5';
    Enabled:= False;
    //TabOrder = 3
    OnClick:= @TForm1_chk_led5Click;
  end;
  
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(80,42,39,13)
    Caption:= '<--------->'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(80,66,39,13)
    Caption:= '<--------->'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(80,90,39,13)
    Caption:= '<--------->'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(80,114,39,13)
    Caption:= '<--------->'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(80,138,39,13)
    Caption:= '<--------->'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
     setBounds(16,12,69,13)
     Caption:= 'LED Control';
     Font.Charset:= DEFAULT_CHARSET;
     Font.Color:= clMaroon;
     Font.Size:= 13;
     Font.Name:= 'MS Sans Serif';
     Font.Style:= [fsBold];
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
     setBounds(155,12,69,13)
     Caption:= 'Arduino PIN';
     Font.Charset:= DEFAULT_CHARSET;
     Font.Color:= clNavy;
     Font.Size:= 13;
     Font.Name:= 'MS Sans Serif';
     Font.Style:= [fsBold];
  end;

  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(156,42,38,13)
    Caption:= 'Digital 2'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(156,66,38,13)
    Caption:= 'Digital 3'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(156,90,38,13)
    Caption:= 'Digital 4'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(156,114,38,13)
    Caption:= 'Digital 5'
  end;
  with TLabel.create(self) do begin
    parent:= comfrm;
    SetBounds(156,138,38,13)
    Caption:= 'Digital 6'
  end;

  statusbar1:= TStatusBar.create(self);
  with statusbar1 do begin
    parent:= comFrm;
    //simplepanel:= true;
    //align:= alleft;
    showhint:= true;
    hint:= 'this is a led box';
     Panels.add;
     panels.items[0].width:= 200;
     panels.items[0].text:= '200';
     Panels.add;
     panels.items[1].width:= 150;
     panels.items[1].text:= '150';
  end;
  TForm1_FormCreateCom(self); 
end; 
   

begin   //main of LED BOX
   //InifileRead;
   //ProcessMessagesOFF;
   getMaxBoxIni;
   writeln('Thread ID :'+intToStr(CurrentThreadID))
   writeln('Process ID :'+intToStr(CurrentProcessID))
   writeln('machine name is: '+getHostName)
   writeln('user name is: '+getUserName)
   osType:= Win32Type;
   writeln('OS Type is: '+intToStr(ord(osType)));
   mytimestamp:= GetFileCreationTime(exepath+'maxbox3.exe')
   writeln(DateTimeToStr(mytimestamp)+' for maXbox3 file')
   //SearchAndOpenDoc(ExtractFilePath(ParamStr(0))+'docs\maxbox_starter16.pdf')
   //ExecuteCommand('cmd','/k dir *.*')
   
    with TComport.Create(self) do begin   //TestCase
      //cleanupinstance;
      Open;
      writeln('com handle '+inttostr(handle));
      codepage;
      buffer;
      writeln('of com port '+getnamepath);
      if connected then writeln(' com connect on');
      Close;
      Free;
    end;
  
    InitComPortForm; 
    maxform1.mxNavigator.color:= clyellow;
    //JvFormLog
    with TJvLogFile.Create(self) do begin
      add('first','second','third');
      //showlog('maXbox logger');
      Free;
    end;
    //printimage(getbitmapObject(Exepath+backmap),bscentered); 
    //getEnvironmentInfo;
End. 


type
  TJvLogFileMainForm = class(TForm)
    JvLogFile1: TJvLogFile;
    btnStart: TButton;
    btnShow: TButton;
    lblActive: TLabel;
    btnReset: TButton;
    lblInactive: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
    procedure btnShowClick(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure btnResetClick(Sender: TObject);
  private
    { Private declarations }
    FLogFileName:string;
    procedure StartLogging;
    procedure StopLogging;
    procedure ResetLogging;
  end;
  
//-----------------------------------------------------------------------
  * Controls the state (ON/OFF) of 5 LEDs connected to an Arduino Board
  * on Digital Pins 2,3,4,5,6 thru the serial comm
 *
 * Created April 02 2009
 * copyleft 2009 Roberto Ramirez <beta@thepenguincult.com>
 * Full Source code at http://www.thepenguincult.com/proyectos/arduino-delphi-control/
 *
 *}

/*
 * Delphi LEDs Control
 * -----------------
 * Turns on and off 5 light emitting diodes(LED) connected to digital  
 * pins 2 thru 6. The LEDs will be controlled using check boxes on Delphi
 * that sends serial data to Arduino Board.
 *
 * IMPORTANT!!: Don't forget to download the Delphi PC Example that controls the leds connected to arduino board.
 *
 * Created April 02 2009
 * copyleft 2009 Roberto Ramirez <beta@thepenguincult.com>
 * Full Source code at http://www.thepenguincult.com/proyectos/arduino-delphi-control/
 * 
 */

int val = 0;       // variable to store the data from the serial port
int ledPin1 = 2;   // LED connected to digital pin 2
int ledPin2 = 3;   // LED connected to digital pin 3
int ledPin3 = 4;   // LED connected to digital pin 4
int ledPin4 = 5;   // LED connected to digital pin 5
int ledPin5 = 6;   // LED connected to digital pin 6

void setup() {

  pinMode(ledPin1,OUTPUT);    // declare the LED's pin as output
  pinMode(ledPin2,OUTPUT);    // declare the LED's pin as output
  pinMode(ledPin3,OUTPUT);    // declare the LED's pin as output
  pinMode(ledPin4,OUTPUT);    // declare the LED's pin as output
  pinMode(ledPin5,OUTPUT);    // declare the LED's pin as output

  Serial.begin(9600);        // connect to the serial port
}

void loop () {
  val = Serial.read();      // read the serial port

  
  if (val !=-1){

    if (val=='1'){
      digitalWrite(ledPin1,HIGH);
    }
    
    else if (val=='A'){
      digitalWrite(ledPin1,LOW);
      }
    
    if (val=='2'){
      digitalWrite(ledPin2,HIGH);
    }

    else if (val=='B'){
      digitalWrite(ledPin2,LOW);
      }

    if (val=='3'){
      digitalWrite(ledPin3,HIGH);
    }

    else if (val=='C'){
      digitalWrite(ledPin3,LOW);
      }

    if (val=='4'){
      digitalWrite(ledPin4,HIGH);
    }

    else if (val=='D'){
      digitalWrite(ledPin4,LOW);
      }

    if (val=='5'){
      digitalWrite(ledPin5,HIGH);
    }

    else if (val=='E'){
      digitalWrite(ledPin5,LOW);
      }
   
    //Serial.println();
  }
}
----------------------------------------------------------------------
//----------------------------------Code Notes------------------------
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, CPort, CPortCtl, Menus;
  
  
------------------------------------------------
Windows crashed again. I am the Blue Screen of Death. No one hears your screams.
Three things are certain: Death, taxes, and lost data. Guess which has occurred.
There is no place like 127.0.0.1 

http://en.wikipedia.org/wiki/Sneakers_%281992_film%29


procedure RotateBitmap(var htmpBitmapDC: TBitmap; var lWidth : Longint;
                            var lHeight : Longint; lRadians : real; origmap: TBitmap);
var
         I,J : Longint;               // loop counter
         //htmpBitmapDC : Longint;    // DC of the new bitmap
         lSine,lCosine : extended;          // sine,cosine used in rotation
         X1,X2,X3,Y1,Y2,Y3 : Longint;     // used in calculating new bitmap dimensions
         lMinX,lMaxX,lMinY,lMaxY: Longint;  
         lNewWidth,lNewHeight : Longint;  // width of new bitmap
         lSrcX,lSrcY  : Longint;   // x,y pixel coord we are blitting from the source image
         myrect: TRect;
begin
   // create a compatible DC from the one just brought
   // compute the sine/cosinse of the radians used to // rotate this image
   lSine := Sin(lRadians);
   lCosine := Cos(lRadians);
   // compute the size of the new bitmap being created
   X1 := Round(-lHeight * lSine);
   Y1 := Round(lHeight * lCosine);
   X2 := Round(lWidth * lCosine - lHeight * lSine);
   Y2 := Round(lHeight * lCosine + lWidth * lSine);
   X3 := Round(lWidth * lCosine);
   Y3 := Round(lWidth * lSine);
   // figure out the max/min size of the new bitmap
   lMinX := Min(0, Min(X1, Min(X2, X3)));
   lMinY := Min(0, Min(Y1, Min(Y2, Y3)));
   lMaxX := Max(X1, Max(X2, X3));
   lMaxY := Max(Y1, Max(Y2, Y3));
   // set the new bitmap width/height
   lNewWidth:= lMaxX - lMinX;
   lNewHeight:= lMaxY - lMinY;
   // create a new bitmap based upon the new width/height of the // rotated bitmap
   //hNewBitmap := CreateCompatibleBitmap(hBitmapDC, lNewWidth, lNewHeight);
   htmpBitmapDC.height:= lNewHeight;
   htmpBitmapDC.width:= lNewWidth;
   //myRect:= Rect(0,0,lwidth,lheight); 
   //bfrm.Canvas.BrushCopy(MyRect, Image1.Picture.Bitmap, MyRect, clred);
   For I:= 0 To lNewWidth do begin
     For J:= 0 To lNewHeight do begin
       lSrcX:= Round((J + lMinX) * lCosine + (I + lMinY) * lSine);
       lSrcY:= Round((I + lMinY) * lCosine - (J + lMinX) * lSine);
       If (lSrcX >= 0) And (lSrcX <= lWidth) And
          (lSrcY >= 0) And (lSrcY <= lHeight) Then begin
         BitBlt(htmpBitmapDC.canvas.handle,J,I,lnewheight,lnewwidth,origmap.canvas.handle,
                                 lSrcX,lSrcY, SRCCOPY);
        end;
     end;
  end;
  //Image1.Refresh; 
  lWidth:= htmpBitmapDC.width;
  lHeight:= htmpBitmapDC.height;
End;
      

procedure maXCalc_demo;
begin
  printF('this is %.6f',[maXcalc('ln(2)+fact(388)+2!')]); 
  printF('this is %.6f',[maXcalc('(4!)^(3!)')]); 
  printF('this is %.6f',[maXcalc('4!+4!')]); 
  printF('this is %.6f',[maXcalc('log(22)')]); 
  printF('this is logN %.6f',[maXcalc('2%256')]);
  writeln('ln(e): '+floattostr(maXcalc('ln(e)')))
  writeln(floattostr(maXcalc('e+10^6')))
  printF('addition theorem %.18f ',[maXcalc('sin(2.5/2)')])
  printF('addition theorem %.18f ',[maXcalc('sqrt(1/2*(1-cos(2.5)))')])
  printF('addition theorem2 %22.18f ',[maXcalc('cos(2.5/2)')])
  printF('addition theorem2 %22.18f ',[maXcalc('sqrt(1/2*(1+cos(2.5)))')])
  maXcalcF('2%256+2^10');
end; 

50000  = 0.693137180659968
100000 = 0.693142180584982
500000 = 0.693146180561005
10^6   = 0.693146680560255
5*10^6 = 0.693147080560068
50*10^6= 0.693147170560399    //Runtime: 0:28:22.422
ln(2)  = 0.693147180559945

(* zeta:= 0;
     for i:= 1 to 50000 do 
       if i mod 2 = 0 then
         zeta:= zeta - 1/i else
         zeta:= zeta + 1/i;
       writeln('harmonic alternate to ln(2): '+floattostr(zeta))  
       writeln(floattostr(maxcalc('ln(2)')))
       writeln(floattostr(ln2))    *)
   
http://www.hitekdev.com/delphi/BITMAPANIMATION.html