How to send files from two different location with one TCP-Server? - file

How to send files from two different locations via only one TCP-Server, I managed to send files from one location only.
This the code to send from one directory ...
procedure TForm1.Timer1Timer(Sender: TObject);
var
fs: TFileStream;
fn: string;
sr: TSearchRec;
I: integer;
begin
I := 0;
if FindFirst('C:/*.jpg', faAnyFile, sr) = 0 then
begin
with StringGrid1 do
begin
ListBox1.Items.Add('C:/' + sr.Name);
while FindNext(sr) = 0 do
begin
ListBox1.Items.Add('C:/' + sr.Name);
Inc(I);
if I = 7 then
Break;
end;
FindClose(sr);
idTCPClient1.Connect;
for fn in ListBox1.Items do
begin
fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
try
idTCPClient1.IOHandler.WriteLn(ExtractFileName(fn));
idTCPClient1.IOHandler.Write(fs, 0, True);
idUDPClient1.Send(lbLatitude.Text + ',' + lbLongitude.Text);
Finally
fs.Free;
end;
end;
end;
end;
end;

All you have to do (without completely re-writing your code, like DavidH suggested) is simply fill your ListBox with paths from all of the different directories that you want, eg:
procedure TForm1.Timer1Timer(Sender: TObject);
var
fs: TFileStream;
fn: string;
sr: TSearchRec;
I : integer;
begin
I := 0;
if FindFirst('C:/*.jpg', faAnyFile, sr) = 0 then
begin
repeat
ListBox1.Items.Add('C:/' + sr.Name);
Inc(I);
if I = 7 then Break;
until FindNext(sr) <> 0;
FindClose(sr);
end;
if I < 7 then
begin
if FindFirst('C:/Some Other Folder/*.jpg', faAnyFile, sr) = 0 then
begin
repeat
ListBox1.Items.Add('C:/Some Other Folder/' + sr.Name);
Inc(I);
if I = 7 then Break;
until FindNext(sr) <> 0;
FindClose(sr);
end;
end;
idTCPClient1.Connect;
for fn in ListBox1.Items do
begin
fs := TFileStream.Create(fn, fmOpenRead or fmShareDenyWrite);
try
IdTCPClient1.IOHandler.WriteLn(ExtractFileName(fn));
IdTCPClient1.IOHandler.Write(fs, 0, True);
...
finally
fs.Free;
end;
end;
end;

Related

Is there a way to switch components mid-loop?

I am trying to animate a dropdown menu of 7 images using a for loop, using a different component to change after each iteration of the code inside the for loop. For example, the first time the loop runs: imgCourses7.Top is used, but the second time the loop runs (when I = 1) then imgCourses6.Top should be used instead.
iCoursesCount := 7;
iTotalLength := (6+41)*iCoursesCount;
imgCourses7.Top := 6;
imgCourses6.Top := 6;
imgCourses5.Top := 6;
imgCourses4.Top := 6;
imgCourses3.Top := 6;
imgCourses2.Top := 6;
imgCourses1.Top := 6;
for I := 0 to iCoursesCount -1 do
begin
while not(imgCourses7.Top = iTotalLength - 41*(I+1)) do
begin
imgCourses8.Top := imgCourses8.Top + 6;
sleep(8);
application.ProcessMessages;
if imgCourses7.Top >= iTotalLength - 41*(I+1) then
begin
imgCourses7.Top := iTotalLength - 41*(I+1);
break;
end;
end;
end;
Like #AndreasRejbrand said in a comment, you can use an array, eg:
var
Images: array[0..6] of TImage;
TargetTop: Integer;
...
...
Images[0] := imgCourses7;
Images[1] := imgCourses6;
Images[2] := imgCourses5;
Images[3] := imgCourses4;
Images[4] := imgCourses3;
Images[5] := imgCourses2;
Images[6] := imgCourses1;
iCoursesCount := Length(Images);
TargetTop := 6+(41*iCoursesCount);
for I := 0 to iCoursesCount-1 do begin
Images[I].Top := 6;
end;
for I := 0 to iCoursesCount-1 do
begin
Dec(TargetTop, 41);
while Images[I].Top <> TargetTop do
begin
Images[I].Top := Images[I].Top + 6;
Sleep(8);
Application.ProcessMessages;
if Images[I].Top >= TargetTop then
begin
Images[I].Top := TargetTop;
Break;
end;
end;
end;
That being said, you really shouldn't be using a sleeping loop that requires Application.ProcessMessages() on each iteration. You might consider using a TTimer or TThread.ForceQueue() instead. Don't block the main UI thread unnecessarily. For example:
published
procedure FormCreate(Sender: TObject);
private
Images: array[0..6] of TImage;
TargetTop: Integer;
CurrentImage: Integer;
procedure StartAnimatingMenu;
procedure StartAnimatingNextMenuItem;
procedure StepAnimateCurrentMenuItem;
...
...
procedure TMyForm.FormCreate(Sender: TObject);
begin
Images[0] := imgCourses7;
Images[1] := imgCourses6;
Images[2] := imgCourses5;
Images[3] := imgCourses4;
Images[4] := imgCourses3;
Images[5] := imgCourses2;
Images[6] := imgCourses1;
end;
procedure TMyForm.StartAnimatingMenu;
var
I: Integer;
begin
for I := Low(Images) to High(Images) do begin
Images[I].Top := 6;
end;
TargetTop := 6+(41*Length(Images));
CurrentImage := -1;
StartAnimatingNextMenuItem;
end;
procedure TMyForm.StartAnimatingNextMenuItem;
begin
Inc(CurrentImage);
if CurrentImage < Length(Images) then
begin
Dec(TargetTop, 41);
StepAnimateCurrentMenuItem;
end;
end;
procedure TMyForm.StepAnimateCurrentMenuItem;
begin
if Images[CurrentImage].Top <> TargetTop then
begin
Images[CurrentImage].Top := Images[CurrentImage].Top + 6;
TThread.ForceQueue(nil, StepAnimateCurrentMenuItem, 8);
end
else if Images[CurrentImage].Top >= TargetTop then
begin
Images[CurrentImage].Top := TargetTop;
StartAnimatingNextMenuItem;
end;
end;

How can I use an array in a procedure

This is the code I use if I'm working with one array. I want to adjust this code so that it can work with any array by using a procedure:
Var
tf: TextFile;
sWord: String;
i: Integer;
arrDurban: array of string;
begin
if Location='Durban' then
begin
i := 0;
SetLength(arrDurban, 1);
AssignFile(tf, '');
Reset(tf);
while not eof(tf) do
begin
Readln(tf, sWord);
arrDurban[i] := sWord;
Inc(i);
SetLength(arrDurban, i + 1);
end;
end;

open multiple files via shell context menu as params

I want to select more than one text file in the windows explorer and open the files via context menu in my app. For one file I found the solution but for more files there some ideas but no (working) solutions.
Anyone here that has the answer?
Here is an example that i've just searched and collected from internet.
Aim: Select multiple folders in Windows Explorer and get list of these folders' names via a shell context menu item "SelectedFolders", or using SendTo menu or drag-and-drop folders from shell onto the application form.
Please put a listbox named lstSelectedFolders and a speed button named sbClearList.
The main form name is frmSelectedFolders.
Here we go.
/////////////////////////////////////////////////////////////
program selectedfolders;
uses
Windows, Messages, SysUtils, Forms,
uSelectedFolders in 'uSelectedFolders.pas' {frmSelectedFolders};
{$R *.res}
var
receiver: THandle;
i, result: integer;
s: string;
dataToSend: TCopyDataStruct;
Mutex : THandle;
begin
Mutex := CreateMutex(nil, True, 'SelectedFolders');
if (Mutex <> 0) and (GetLastError = 0) then
begin
Application.Initialize;
Application.Title := 'Selected Folders';
Application.CreateForm(TfrmSelectedFolders, frmSelectedFolders);
Application.Run;
if Mutex <> 0 then CloseHandle(Mutex);
end
else
begin
receiver := FindWindow(PChar('TfrmSelectedFolders'), PChar('Selected Folders'));
if receiver <> 0 then
begin
for i:=1 to ParamCount do
begin
s := trim(ParamStr(i));
if s <> '' then
begin
dataToSend.dwData := 0;
dataToSend.cbData := 1 + Length(s);
dataToSend.lpData := PChar(s);
result := SendMessage(receiver, WM_COPYDATA, Integer(Application.Handle), Integer(#dataToSend));
//sleep(100);
//if result > 0 then
// ShowMessage(Format('Sender side: Receiver has %d items in list!', [result]));
end;
end; // for i
end;
end;
end.
/////////////////////////////////////////////////////////////
unit uSelectedFolders;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellAPI, ActiveX, ComObj, ShlObj, Registry, Buttons;
type
TfrmSelectedFolders = class(TForm)
lstSelectedFolders: TListBox;
sbClearList: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure sbClearListClick(Sender: TObject);
private { Private declarations }
public { Public declarations }
procedure WMDROPFILES(var Message: TWMDROPFILES); message WM_DROPFILES;
procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
function GetTarget(const LinkFileName: string): string;
end;
var
frmSelectedFolders: TfrmSelectedFolders;
implementation
{$R *.dfm}
procedure RegisterContextMenuForFolders();
const
Key = 'Directory\shell\SelectedFolders\command\';
begin
with TRegistry.Create do
try
// for all users, class registration for directories
RootKey := HKEY_CLASSES_ROOT;
if OpenKey(Key, true) then
WriteString('', '"' + Application.ExeName + '" "%l"');
finally
Free;
end;
end;
procedure TfrmSelectedFolders.WMDROPFILES(var Message: TWMDROPFILES);
var
N, i: integer;
buffer: array[0..255] of Char;
s: string;
begin
try
N := DragQueryFile(Message.Drop, $FFFFFFFF, nil, 0);
for i:=1 to N do
begin
DragQueryFile(Message.Drop, i-1, #buffer, SizeOf(buffer));
s := buffer;
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
end;
finally
DragFinish(Message.Drop);
end;
end;
function TfrmSelectedFolders.GetTarget(const LinkFileName: string): string;
var
//Link : String;
psl : IShellLink;
ppf : IPersistFile;
WidePath : Array[0..260] of WideChar;
Info : Array[0..MAX_PATH] of Char;
wfs : TWin32FindData;
begin
if UpperCase(ExtractFileExt(LinkFileName)) <> '.LNK' then
begin
Result := 'NOT a shortuct by extension!';
Exit;
end;
CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, psl);
if psl.QueryInterface(IPersistFile, ppf) = 0 Then
Begin
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(LinkFileName), -1, #WidePath, MAX_PATH);
ppf.Load(WidePath, STGM_READ);
psl.GetPath(#info, MAX_PATH, wfs, SLGP_UNCPRIORITY);
Result := info;
end
else
Result := '';
end;
procedure TfrmSelectedFolders.WMCopyData(var Msg: TWMCopyData);
var
s: string;
begin
s := trim(PChar(Msg.copyDataStruct.lpData));
if s = '' then
begin
msg.Result := -1;
exit;
end;
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
msg.Result := lstSelectedFolders.Items.Count;
end;
procedure TfrmSelectedFolders.FormCreate(Sender: TObject);
var
i: integer;
s: string;
begin
RegisterContextMenuForFolders();
DragAcceptFiles(Handle, TRUE);
lstSelectedFolders.Clear;
s := ExtractFileDir(Application.ExeName);
lstSelectedFolders.Items.Add(s);
for i:=1 to ParamCount do
begin
s := trim(ParamStr(i));
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
end;
end;
procedure TfrmSelectedFolders.sbClearListClick(Sender: TObject);
begin
lstSelectedFolders.Clear;
end;
end.

Saving and loading jpeg images to database not working DELPHI

I'm trying to make a program that saves images in a database. I've pulled together some info on the net and wrote up code that I think is supposed to work, but fails in a completely unique way on either side (the saving and the loading).
Here's my code, could you tell me what I'm doing wrong?
Load from Database, gives me a memory address access violation error:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if OpenPictureDialog1.Execute then
if FileExists(OpenPictureDialog1.FileName) then
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName)
else
MessageDlg('Die lĂȘer bestaan nie!',mtError,[mbOK],1);
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+inttostr(ikode);
ADOQuery1.Open;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 1;
ADOQuery1.Insert;
TBLobfield(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
finally
S.Free;
end;
end;
Saving to the database. This code doesn't give an error as such, but it just doesn't save the image to the database:
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+inttostr(ikode);
ADOQuery1.Open;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
Image1.Picture.Graphic.LoadFromStream(S);
finally
s.Free;
end;
end;
You are calling TGraphic.LoadFromStream() but you are not initializing the TPicture.Graphic property with a valid TGraphic-derived object beforehand, so the property is likely nil, hense the crash.
Also, when saving the TPicture.Graphic to the TMemoryStream, you are skipping the first byte of the graphic when saving it to the DB. All of the bytes are important, so do not skip any of them.
Assuming your images are specifically JPEGs and nothing else (your saving code is not restricting the file type), then try this instead:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
if not (Image1.Picture.Graphic is TJpegImage) then
raise Exception.Create('Sorry, only JPG images can be saved in the DB');
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 0;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
TBlobField(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
finally
S.Free;
end;
end;
uses
..., Jpeg;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
Jpg: TJPEGImage;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
S := TMemoryStream.Create;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
Jpg := TJPEGImage.Create;
try
Jpg.LoadFromStream(S);
Image1.Picture.Assign(Jpg);
finally
Jpg.Free;
end;
finally
S.Free;
end;
end;
But if your images can be other formats besides JPEG, then you need to store the image type in the DB as well so that you can read it back and instantiate the correct TGraphic class type (TBitmap, TJpegImage, TGifImage, TPNGImage, etc) to handle it as needed, eg:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
ikode := cbxDeelnemerT4.ItemIndex + 1;
S := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(S);
S.Position := 0;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
// this is just an example, there are other ways to do this
if Image1.Picture.Graphic is TJPEGImage then
ADOQuery1.FieldByName('FotoType').AsString := 'jpg'
else if Image1.Picture.Graphic is TPNGImage then
ADOQuery1.FieldByName('FotoType').AsString := 'png'
else if Image1.Picture.Graphic is TGIFImage then
ADOQuery1.FieldByName('FotoType').AsString := 'gif'
else if Image1.Picture.Graphic is TBitmap then
ADOQuery1.FieldByName('FotoType').AsString := 'bmp'
else
raise Exception.Create('Cannot save unsupported image type to DB');
TBlobField(ADOQuery1.FieldByName('Foto')).LoadFromStream(S);
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
finally
S.Free;
end;
end;
uses
..., Jpeg, GifImg, PngImg;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TMemoryStream;
ikode : integer;
Graphic: TGraphic;
GraphicType: String;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
S := TMemoryStream.Create;
try
TBlobField(ADOQuery1.FieldByName('Foto')).SaveToStream(S);
S.Position := 0;
GraphicType := ADOQuery1.FieldByName('FotoType').AsString;
if GraphicType = 'jpg' then
Graphic := TJPEGImage.Create
ADOQuery1.FieldByName('FotoType').AsString := 'jpg'
else if GraphicType = 'png' then
Graphic := TPNGImage.Create
else if GraphicType = 'gif' then
Graphic := TGifImage.Create
else if GraphicType = 'bmp' then
Graphic := TBitmap.Create
else
raise Exception.Create('Cannot load unsupported image type from DB');
try
Graphic.LoadFromStream(S);
Image1.Picture.Assign(Graphic);
finally
Graphic.Free;
end;
finally
S.Free;
end;
end;
With that said, you should not be accessing TBlobField directly. Use the TDataSet.CreateBlobStream() method instead, let ADO give you a TStream object that is optimized for accessing ADO blob data, eg:
procedure TfrmMain.btnAddPickT4Click(Sender: TObject);
var
S : TStream;
ikode : integer;
begin
if cbxDeelnemerT4.ItemIndex < 0 then
begin
MessageDlg('Kies asseblief ''n deelnemer!',mtInformation,[mbOK],1);
Exit;
end;
if not OpenPictureDialog1.Execute then
Exit;
Image1.Picture.LoadFromFile(OpenPictureDialog1.FileName);
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = '+IntToStr(ikode);
ADOQuery1.Open;
ADOQuery1.Insert;
try
...
S := ADOQuery1.CreateBlobStream(ADOQuery1.FieldByName('Foto'), bmWrite);
try
Image1.Picture.Graphic.SaveToStream(S);
finally
S.Free;
end;
ADOQuery1.Post;
except
ADOQuery1.Cancel;
raise;
end;
end;
procedure TfrmMain.btnOpenProfileT4Click(Sender: TObject);
var
S : TStream;
ikode : integer;
Graphic: TGraphic;
begin
ikode := cbxDeelnemerT4.ItemIndex + 1;
ADOQuery1.Close;
ADOQuery1.SQL.Text := 'SELECT * FROM DEELNEMERS WHERE Kode = ' + IntToStr(ikode);
ADOQuery1.Open;
...
Graphic := ...;
try
S := ADOQuery1.CreateBlobStream(ADOQuery1.FieldByName('Foto'), bmRead);
try
Graphic.LoadFromStream(S);
finally
S.Free;
end;
Image1.Picture.Assign(Graphic);
finally
Graphic.Free;
end;
end;

Delphi - BinToHex and HexToBin : Reversal

I have an array of byte that I wish to convert into a hex string, and then back into an array of byte.
I am using the following to convert into a hex string:
function bintoHex(const bin: array of byte): String;
const HexSymbols = '0123456789ABCDEF';
var i: integer;
begin
SetLength(Result, 2*Length(bin));
for i := 0 to Length(bin)-1 do begin
Result[1 + 2*i + 0] := HexSymbols[1 + bin[i] shr 4];
Result[1 + 2*i + 1] := HexSymbols[1 + bin[i] and $0F];
end;
end;
I am unsure how to convert it back into an array of byte properly. I am shooting for something like the following:
Type TDCArray = Array of Byte;
function xHexToBin(const HexStr: String): TDCArray;
const HexSymbols = '0123456789ABCDEF';
var i: integer;
begin
SetLength(Result, ???); //Need to now get half of the length, unsure how to go about that
for i := 0 to Length(HexStr)-1 do begin
//Here convert back into an array somehow...
//Result[i] := ???
end;
end;
How would I go about doing this?
Also, I am using Delphi XE2.
Why not just use the BinToHex and HexToBin RTL functions?
{$APPTYPE CONSOLE}
uses
System.Classes,
System.SysUtils;
var
LArray : array[1..6] of Byte = (10, 11, 12, 13, 14, 15);
LText: string;
I : integer;
begin
try
SetLength(LText, Length(LArray)*2);
BinToHex(#LArray, PChar(LText), SizeOf(LArray));
//show the hex string
Writeln(LText);
//fill the array with 0
FillChar(LArray, SizeOf(LArray), #0);
//get the values from the hex string
HexToBin(PChar(LText), #LArray, Length(LArray));
//show the array values
for i := 1 to Length(LArray) do
Write(LArray[i]);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
If you want to do it yourself:
function xHexToBin(const HexStr: String): TBytes;
const HexSymbols = '0123456789ABCDEF';
var i, J: integer;
B: Byte;
begin
SetLength(Result, (Length(HexStr) + 1) shr 1);
B:= 0;
i := 0;
while I < Length(HexStr) do begin
J:= 0;
while J < Length(HexSymbols) do begin
if HexStr[I + 1] = HexSymbols[J + 1] then Break;
Inc(J);
end;
if J = Length(HexSymbols) then ; // error
if Odd(I) then
Result[I shr 1]:= B shl 4 + J
else
B:= J;
Inc(I);
end;
if Odd(I) then Result[I shr 1]:= B;
end;
2 hex chars represent 1 byte
The code i wrote earlier was pseudocode I wanted you to get the ideea. But if you need some code to paste here is the actual implementation:
program project1;
uses SysUtils,classes;
type
TByteArray = array of byte;
function StrToArray(const Hexstr: String): TByteArray ;
var
i: Integer;
begin
SetLength(Result, Length(Hexstr) div 2);
for i:=0 to (Length(Hexstr) div 2 - 1) do
Result[i]:= StrToInt('$' + Copy(Hexstr, (i * 2) + 1, 2));
end;
var
arr : TByteArray;
i : Integer;
begin
arr := StrToArray('0A0B0C0D');
for i:=0 to High(arr) do
WriteLn(arr[i]);
Readln;
end.
Btw coding is not about cuting and pasting ;)
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
SysUtils, Forms, StdCtrls, ExtCtrls, Classes;
type
{ TTextToHex_HexToBin }
TTextToHex_HexToBin = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
CheckTime: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure CheckTimeClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
end;
var
TextToHex_HexToBin: TTextToHex_HexToBin;
implementation
{$R *.lfm}
{ TTextToHex_HexToBin }
//hex to binary
function HextoBinary(const AHexStr: string):string;
var
i, j: Integer;
const
HexParts: array[0..$F] of string =
(
{0} '0000',{1} '0001',{2} '0010',{3} '0011',{4} '0100',{5} '0101',{6} '0110',{7} '0111',
{8} '1000',{9} '1001',{A} '1010',{B} '1011',{C} '1100',{D} '1101',{E} '1110',{F} '1111'
);
begin
SetLength(Result, 4 * AHexStr.Length);
j := 1;
for i := 1 to AHexStr.Length do
begin
case AHexStr[i] of
'0'..'9':
Move(HexParts[Ord(AHexStr[i]) - Ord('0')][1], Result[j], sizeof(char) * 4);
'A'..'F':
Move(HexParts[$A + Ord(AHexStr[i]) - Ord('A')][1], Result[j], sizeof(char) * 4);
'a'..'f':
Move(HexParts[$A + Ord(AHexStr[i]) - Ord('a')][1], Result[j], sizeof(char) * 4);
else
raise EConvertError.CreateFmt('Invalid hexadecimal string "%s".', [AHexStr]);
end;
Inc(j, 4);
end;
end;
procedure TTextToHex_HexToBin.Button1Click(Sender: TObject);
var
TB: TBytes;
WS: WideString;
S: string;
i: Integer;
begin
WS := Trim(Edit1.Caption);
TB := WideBytesOf(WS);
// WideString to Hexadecimal
S := '';
for i := Low(TB) to High(TB) do
S := S + IntToHex(TB[i], -1);
Edit2.Caption :=Trim(S);
// Hex to Binary
Memo1.Caption:= HextoBinary(Trim(S));
end;
procedure TTextToHex_HexToBin.CheckTimeClick(Sender: TObject);
begin
end;
procedure TTextToHex_HexToBin.FormCreate(Sender: TObject);
begin
end;
end.
[Result Show as Below]

Resources