-
Content Count
380 -
Joined
-
Last visited
-
Days Won
4
Everything posted by Clément
-
In a delphi class, record, or form I mean.
-
Hi, I'm using another construction for simple types: iif<T>( aCond : boolean; aTrue : T; aFalse : T ) : T; function iif<T>( aCond : boolean; aTrue : T; aFalse : T ) : T; begin if aCond then Result := aTrue else Result := aFalse; end; No overloads, very easy to ready.... procedure SomeProcedure; begin a := iif<string>( aCond, 'Hello', 'World'); b := iif<integer>( aCond, 12, 0 ); end; As for ternary operators, it would be a nice addition. Couldn't it be written in ASM?
-
static array vs. dynamic array
Clément replied to FranzB's topic in Algorithms, Data Structures and Class Design
Hi, The way your types are declared you most certainly will end up writing overloads or specific methods for each! Have you considered the possibility work with only one type of array? (TPoligonA) For example: TPoligon = Array of TPoint; T4Poligon = Array [1..4] of TPoint; TPoligonA = TArray<TPoint>; TForm17 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } function NewT4 : TPoligonA; function ProcessPoligon( const aPoligon : TPoligonA ) : Boolean; end; implementation function TForm17.NewT4: TPoligonA; begin SetLength(Result,4); end; function TForm17.ProcessPoligon(const aPoligon: TPoligonA): Boolean; begin end; NewT4 will return a zero base array.. Since you will loose delphi type checking and range checking, you will need to check if the array have 4 elements. But, you will work with a unique type, which is what you asked HTH -
Hi, Since you already know the values of :TRS, :INCOME and :OUTGO you can check for nulls before entering your update. SELECT .... INTO :TRS,:INCOME,:OUTGO; IF TRS is NULL then TRS = 0; if INCOME IS NULL then INCOME = 0; if OUTGO IS NULL then OUTGO = 0; STOCK = TRS + INCOME - OUTGO; UPDATE ITEMS SET TRS= :TRS, INCOME = :INCOME, OUTGO= :OUTGO, STOCK= :STOCK WHERE ITEMNO=:ITMNO; END I haven't checked the syntax, but you get the idea.
-
How to optimize exe loading times
Clément replied to a topic in Software Testing and Quality Assurance
Since your concern is about startup time, there's a very handy way to find the culprit: Comment your code. All the objects( data modules, forms, classes ) created before the "application.run" should be checked for "legacy code not required anymore" If your project starts creating only the main form, then check the constructor and show form. And don't be shy! comment everything! even assignments (you never know what a setter might be doing) You will find out some leftovers from the past, that made perfect sense last decade, that are no longer required. The library you are using are among the best in delphi ecosystem, but... since you mention IBObjects, and FireDac, are you sure there's no query being executed at startup? DB Stuff might usually be rather slow, specially if some event's are alive during startup! -
The code: {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes, System.Diagnostics; //******************************************** // Constants to tune the benchmark performance const HexStringLength = 64; InputDataCount = 512; IterationCount = 20000; //***************************************************************** // David Heffernan's routine, with Move replace by Int64 assignment {$DEFINE ReplaceMoveWithInt64Assign} function HexToBinHeff(const HexValue: string): string; const BinaryValues: array [0..15] of string = ( '0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111' ); var HexDigit: Char; HexDigitValue: Integer; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for HexDigit in HexValue do begin case HexDigit of '0'..'9': HexDigitValue := Ord(HexDigit) - Ord('0'); 'a'..'f': HexDigitValue := 10 + Ord(HexDigit) - Ord('a'); 'A'..'F': HexDigitValue := 10 + Ord(HexDigit) - Ord('A'); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; {$IFDEF ReplaceMoveWithInt64Assign} PInt64(Ptr)^ := PInt64(BinaryValues[HexDigitValue])^; {$ELSE} Move(Pointer(BinaryValues[HexDigitValue])^, Ptr^, 4 * SizeOf(Char)); {$ENDIF} Inc(Ptr, 4); end; end; function HexToBinHeff2(const HexValue: string): string; const BinaryValues: array [0..15] of string = ( '0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111' ); var HexDigit: Char; HexDigitValue: Integer; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for var i : integer := low(HexValue) to High( HexValue ) do begin case HexValue[i] of '0'..'9': HexDigitValue := Ord(HexValue[i]) - Ord('0'); 'a'..'f': HexDigitValue := 10 + Ord(HexValue[i]) - Ord('a'); 'A'..'F': HexDigitValue := 10 + Ord(HexValue[i]) - Ord('A'); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexValue[i], HexValue]); end; {$IFDEF ReplaceMoveWithInt64Assign} PInt64(Ptr)^ := PInt64(BinaryValues[HexDigitValue])^; {$ELSE} Move(Pointer(BinaryValues[HexDigitValue])^, Ptr^, 4 * SizeOf(Char)); {$ENDIF} Inc(Ptr, 4); end; end; //************************ // Mahdi Safsafi's routine {$DEFINE ReplaceMoveWithInt64Assign} function HexToBinMahdi(const HexValue: string): string; type TChar4 = array [0 .. 3] of Char; PChar4 = ^TChar4; const Table1: array ['0' .. '9'] of TChar4 = ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001'); Table2: array ['a' .. 'f'] of TChar4 = ('1010', '1011', '1100', '1101', '1110', '1111'); var HexDigit: Char; P: PChar4; begin SetLength(Result, Length(HexValue) * 4); P := PChar4(Result); for HexDigit in HexValue do begin case HexDigit of '0' .. '9': P^ := Table1[HexDigit]; 'a' .. 'f': P^ := Table2[HexDigit]; 'A' .. 'F': P^ := Table2[Chr(Ord(HexDigit) xor $20)]; else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Inc(P); end; end; function HexToBinMahdi2(const HexValue: string): string; type TChar4 = array [0 .. 3] of Char; PChar4 = ^TChar4; const Table1: array ['0' .. '9'] of TChar4 = ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001'); Table2: array ['a' .. 'f'] of TChar4 = ('1010', '1011', '1100', '1101', '1110', '1111'); var HexDigit: Char; P: PChar4; begin SetLength(Result, Length(HexValue) * 4); P := PChar4(Result); for var i: integer := low(HexValue) to high( HexValue ) do begin case HexValue[i] of '0' .. '9': P^ := Table1[HexValue[i]]; 'a' .. 'f': P^ := Table2[HexValue[i]]; 'A' .. 'F': P^ := Table2[Chr(Ord(HexValue[i]) xor $20)]; else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexValue[i], HexValue]); end; Inc(P); end; end; {$IFDEF CPUX86} //*********************** // Kas Ob's asm32 version procedure CharToBin_ASM32(HexChar: Char; HexBuffer: PChar); asm push edi mov edi,edx // Get the decimal value of one Hex Char (= half byte) movzx eax, HexChar mov ecx, 57 sub ecx, eax sar ecx, 31 and ecx, 39 neg ecx add eax, ecx add eax, - 48 // Produce 4 Chars presenting 4 bits of HexChar xor ecx,ecx mov dx,$1 test al,4 cmovne cx,dx shl ecx,16 test al,8 cmovne cx,dx add ecx,$00300030 mov [edi],ecx xor ecx,ecx test al,1 cmovne cx,dx shl ecx,16 test al,2 cmovne cx,dx add ecx,$00300030 mov [edi+4],ecx pop edi end; function HexToBinAsm32(const HexValue: string): string; var HexDigit: Char; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for HexDigit in HexValue do begin case HexDigit of '0'..'9','a'..'f','A'..'F': CharToBin_ASM32(HexDigit, Ptr); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Inc(Ptr, 4); end; end; function HexToBinAsm322(const HexValue: string): string; var HexDigit: Char; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for var i: integer := low(HexValue) to High( HexValue ) do begin case HexValue[i] of '0'..'9','a'..'f','A'..'F': CharToBin_ASM32(HexValue[i], Ptr); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Inc(Ptr, 4); end; end; //********************* // Kas Ob's xmm version procedure CharToBin_XMM(HexChar: Char; HexBuffer: PChar); const DEC_TO_BIN_WORD_MASK: array[0..7] of UInt16 = ($01, $02,$00,$00, $04, $08, $00, $00); DEC_TO_BIN_FF_TO_CHARONE_DISTANCE: array[0..7] of UInt16 = ($FFCF, $FFCF, $FFCF, $FFCF, $FFCF, $FFCF, $FFCF, $FFCF); DEC_TO_BIN_REVERSE_MASK: array[0..15] of Byte = (10, $80, 8, $80, 2, $80, 0, $80, $80, $80, $80, $80, $80, $80, $80, $80); asm movzx eax, HexChar mov ecx, 57 sub ecx, eax sar ecx, 31 and ecx, 39 neg ecx add eax, ecx add eax, - 48 // Produce 4 Chars presenting 4 bits of HexChar movd xmm0, eax pxor xmm1, xmm1 movdqu xmm2, DEC_TO_BIN_FF_TO_CHARONE_DISTANCE movdqu xmm3, DEC_TO_BIN_WORD_MASK movdqu xmm4,DEC_TO_BIN_REVERSE_MASK punpckldq xmm0, xmm0 packssdw xmm0, xmm0 pand xmm0, xmm3 pcmpeqw xmm0, xmm1 psubw xmm0, xmm2 PSHUFB xmm0, xmm4 // reverse the result movq qword ptr[HexBuffer], xmm0 end; function HexToBinXmm(const HexValue: string): string; var HexDigit: Char; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for HexDigit in HexValue do begin case HexDigit of '0'..'9','a'..'f','A'..'F': CharToBin_XMM(HexDigit, Ptr); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexDigit, HexValue]); end; Inc(Ptr, 4); end; end; function HexToBinXmm2(const HexValue: string): string; var HexDigit: Char; Ptr: PChar; begin SetLength(Result, Length(HexValue) * 4); Ptr := Pointer(Result); for var i : integer := low( HexValue ) to high( HexValue) do begin case HexValue[i] of '0'..'9','a'..'f','A'..'F': CharToBin_XMM(HexValue[i], Ptr); else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexValue[i], HexValue]); end; Inc(Ptr, 4); end; end; {$ENDIF} //*************** // Benchmark code function RandomHexDigit: Char; var Ordinal: Integer; begin Ordinal := Random(16); case Ordinal of 0..9: Result := Chr(Ord('0') + Ordinal); 10..15: Result := Chr(Ord('a') + Ordinal - 10); else raise Exception.Create(''); end; end; function RandomHexString(Length: Integer): string; var Index: Integer; begin SetLength(Result, Length); for Index := 1 to Length do Result[Index] := RandomHexDigit; end; procedure TestCorrectness; var Index: Integer; HexStr, BinStr: string; begin for Index := 0 to $fffff do begin HexStr := IntToHex(Index, 6); BinStr := HexToBinHeff(HexStr); if BinStr<>HexToBinMahdi(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinMahdi2(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinHeff2(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinAsm32(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinAsm322(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinXmm(HexStr) then raise Exception.Create('incorrect implementation'); if BinStr<>HexToBinXmm2(HexStr) then raise Exception.Create('incorrect implementation'); end; end; procedure Benchmark; var Index, Iteration: Integer; sw: TStopwatch; HexStrings: TArray<string>; binaryString: string; begin SetLength(HexStrings, InputDataCount); for Index := 0 to InputDataCount-1 do HexStrings[Index] := RandomHexString(HexStringLength); sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinHeff(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('Pascal lookup (Heff): ', sw.ElapsedMilliseconds); sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinMahdi(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('Pascal lookup (Mahdi): ', sw.ElapsedMilliseconds); {$IFDEF CPUX86} sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinAsm32(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('asm32: ', sw.ElapsedMilliseconds); sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinXmm(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('xmm: ', sw.ElapsedMilliseconds); {$ENDIF} sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinHeff2(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('Pascal lookup (Heff2): ', sw.ElapsedMilliseconds); sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinMahdi2(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('Pascal lookup (Mahdi2): ', sw.ElapsedMilliseconds); {$IFDEF CPUX86} sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinAsm322(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('asm32 2: ', sw.ElapsedMilliseconds); sw := TStopwatch.StartNew; for Iteration := 0 to IterationCount-1 do for Index := 0 to InputDataCount-1 do begin binaryString := HexToBinXmm2(HexStrings[Index]); binaryString := ''; // force a reallocation of the string every iteration of this loop end; Writeln('xmm 2: ', sw.ElapsedMilliseconds); {$ENDIF} end; begin try Randomize; TestCorrectness; Benchmark; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end. The output: Pascal lookup (Heff): 5416 Pascal lookup (Mahdi): 5097 asm32: 8073 xmm: 6325 Pascal lookup (Heff2): 4487 Pascal lookup (Mahdi2): 4179 asm32 2: 7260 xmm 2: 5658
-
Hi, Just would like to say thank you for this thread!!!! If I might just add my 0.00002c..... The "for in" syntax is not optimization friendly ... I ran the benchmark in my very slow machine with the following modification in Mahdi code: function HexToBinMahdi2(const HexValue: string): string; type TChar4 = array [0 .. 3] of Char; PChar4 = ^TChar4; const Table1: array ['0' .. '9'] of TChar4 = ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001'); Table2: array ['a' .. 'f'] of TChar4 = ('1010', '1011', '1100', '1101', '1110', '1111'); var HexDigit: Char; P: PChar4; begin SetLength(Result, Length(HexValue) * 4); P := PChar4(Result); for var i: integer := low(HexValue) to high( HexValue ) do begin case HexValue[i] of '0' .. '9': P^ := Table1[HexValue[i]]; 'a' .. 'f': P^ := Table2[HexValue[i]]; 'A' .. 'F': P^ := Table2[Chr(Ord(HexValue[i]) xor $20)]; else raise EConvertError.CreateFmt('Invalid hex digit ''%s'' found in ''%s''', [HexValue[i], HexValue]); end; Inc(P); end; end; Pascal lookup (Heff): 5391 Pascal lookup (Mahdi): 5072 Pascal lookup (Mahdi2): 4184 asm32: 8067 xmm: 6369 I know the test is about the conversion, but since "for in" is very slow, it might help straight things up a little extra bit
-
Embarcadero should revisit their SKU matrix. Professional SKU is not satisfactory for DB Access, and some basic "Enterprise" software integration SOAP, REST etc Enterprise SKU is great for DB Access, but lack support for standard enterprise solution. Support for SOAP,REST, Encryption is very weak in native Enterprise SKU, and to offer a solution as good as native competition SKU you have to buy expensive 3rd party library. .NET offers such wide range of very good written library. This makes delphi ecosystem expensive. In Brazil we still have a very large base of Delphi Developers, they need a _good_ Professional SKU as most of them are ISV and don't have budget to buy an enterprise SKU especially if they won't use all the enterprise matrix features. This is also true for Managers in small companies. They won't spend money on features they won't need/use. Not an easy solution.
-
Reading fields with different lenghts
Clément replied to AndrewHoward's topic in Delphi IDE and APIs
Hi, Showing some code always helps us give accurate answers. Anyway.... If you can read Sizeof(TMyData) in one peace, you could use a record like type TMyData = record bSTX : Byte; bSep1: byte; Field1: Array[0..1] of byte; bSep2 : Byte; Field2 : Array[0..5] of byte; bSep3: Byte; Field3 : Array[0..2] of byte. Field4 : Array[0..4] of byte; bsep4 : Byte; bETX : Byte; bLRC : byte; end; var MyData : TMyData; begin fillchar( MyData, Sizeof(TMyData) , 0 ); move( DataFromCOM[0], MyData[0], Sizeof(TMyData) ); // Use the data MyData.Field1; MyData.Field2; end; Always check if you are receiving the expected number of bytes. Check the values of STX, ETX and the separators to see if at least those are Ok. If this routine will be called "a lot", I suggest creating MyData as a class field, to be use as long as the class is not destroyed. -
Hi, I'm revisiting the application I wrote to help me manage my applications localization, but after seeing all the nice work done in better translation manager... I'm puzzled.. Should I continue with my interface, or move to BTM? So here I am....I need to know how I can duplicate some features my implementation has. Basically my application generates a global class (glbLocalization) that I include in my projects. I can access all the localization properties I require. For example: glbLocalization.FormLogin.btnLogin.caption( aLanguageID : Cardinal = 0 ) When LanguageID is 0, the user default kicks in, which means, can be windows language, or any other language the user wants to be its default. There is a feature that my customers are very used too: Multi language UI. Basically this features allows the user to do whatever localization combination he likes: * The application remains in the main language, reports can be generated in any other languages. * Any form can be opened in different languages. Ex: All the user interface is in portuguese. The reports can be viewed in portuguese and mailed to a Brazilian manager, switch to any other supported language and email the report directlly The user might need to share some information available on his form with another user in LA, He opens another form in Spanish and share the contents. The implementation became trivial since I just have pass the LanguageID as the parameter ( to a form, report, etc) and everything is retrieved from the corresponding resource. To achieve this I generate a single resource file (.RC) with all the supported languages and translation. Given the LanguageID, it's a matter to go the corresponding section and get the string. Delphi's RTL resources (aka ResourceString) are not translated, it's a feature I would like to add in this new version. Back in Borland era, when I studied delphi translation features, I haven't found a way to implement the above features. Is there a way to use BTM (or delphi native localization) to mimic the above feature?
-
Localization inquery
Clément replied to Clément's topic in Algorithms, Data Structures and Class Design
Hi, I finally reached a Beta version of the utility I'm rewriting to help me manage my application localization. Since I talked about it here, I thought I could share some screens to give you an idea of this tool. I'm using mustache templates to generate the output, in theory the utility can generate code for any language. The generation process creates a JSON containing the translations that is merged with the templates. For the .RC and Delphi I using the following templates: .RC: {{#constants}} #define {{name}} {{value}} {{/constants}} {{#resources}} STRINGTABLE LANGUAGE {{language}}, {{subLanguage}} BEGIN {{#stringTable}} {{{name}}} "{{{value}}}" {{/stringTable}} END {{/resources}} .PAS (part of it): unit app.localization; interface uses WinAPI.Windows; const {{#languages}} {{constantName}} = {{languageID}}; {{/languages}} // --------------- {{#constants}} {{name}} = {{value}}; {{/constants}} function _( const StringID : DWORD; aLanguageID : DWORD = 0 ) : String; procedure SetDefaultLanguage( aLanguageID : DWord ); implementation {$R {{outputRES}}} var gDefaultLanguage : DWord; procedure SetDefaultLanguage( aLanguageID : DWord ); begin gDefaultLanguage := aLanguageID; end; function StringTableRes(hInstLib: Cardinal; idString: DWORD; wLang: Word): String; This is the generate .PAS: unit app.localization; interface uses WinAPI.Windows; const _EN_US = 1033; _PT_BR = 1046; _EL_GR = 1032; // --------------- GLOBAL_CPTN_BTN_OK = 1; GLOBAL_CPTN_BTN_APPLY = 2; GLOBAL_CPTN_BTN_CANCEL = 3; GLOBAL_CPTN_BTN_PRINT = 4; GLOBAL_CPTN_BTN_EXPORT = 5; GLOBAL_CPTN_BTN_FILTER = 6; GLOBAL_CPTN_GB_SAMPLEDATA = 7; GLOBAL_TXT_SAMPLE_DESCRIPTION = 8; FORMLOGIN_CPTN_WELCOME = 9; function _( const StringID : DWORD; aLanguageID : DWORD = 0 ) : String; procedure SetDefaultLanguage( aLanguageID : DWord ); implementation {$R teste.res} var gDefaultLanguage : DWord; procedure SetDefaultLanguage( aLanguageID : DWord ); begin gDefaultLanguage := aLanguageID; end; Let me show you the result: The code: implementation uses app.localization; {$R *.dfm} procedure TForm1.DoLocalize; begin GroupBox1.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _EN_US ); GroupBox2.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _PT_BR ); GroupBox3.Caption := _( GLOBAL_CPTN_GB_SAMPLEDATA, _EL_GR ); btnOK.Caption := _( GLOBAL_CPTN_BTN_APPLY, _EN_US ); btnOk1.Caption := _( GLOBAL_CPTN_BTN_APPLY, _PT_BR ); btnOk2.Caption := _( GLOBAL_CPTN_BTN_APPLY, _EL_GR ); btnCancel.Caption := _( GLOBAL_CPTN_BTN_CANCEL, _EN_US ); btnCancel1.Caption := _( GLOBAL_CPTN_BTN_CANCEL, _PT_BR ); btnCancel2.Caption := _( GLOBAL_CPTN_BTN_CANCEL, _EL_GR ); label1.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _EN_US ); label2.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _PT_BR ); label3.caption := _( GLOBAL_TXT_SAMPLE_DESCRIPTION, _EL_GR ); end; procedure TForm1.DoShow; begin DoLocalize; inherited; end; And the generator -
Best type for data buffer: TBytes, RawByteString, String, AnsiString, ...
Clément replied to Rollo62's topic in Algorithms, Data Structures and Class Design
TBytes and pointers! Either love or hate them! Can you avoid allocation if you work with one large chuck of data (eg: 1 or 2MBytes) ? -
Localization inquery
Clément replied to Clément's topic in Algorithms, Data Structures and Class Design
I liked BTM but I was afraid you would say that. I will have to keep my interface then. Anyway, thanks for that great tool! -
Hi, I'm finalizing the modernization of my old translation IDE, and I need to update some features, like automated translation. The app is still using old API call. And at that time they were free. Before writing a Google or Microsoft API I would like to check if there's a better option for us developers. Is there any API you would recommend? Is there a more suitable API that translates better small application texts ( like button captions, form captions, etc ) Clément
-
Thank for the tips. Very nice job with BTM! I know how hard it is to manage a translation tool. When I decided to reinvent the wheel, there was no BTM, only the one provided by Inprise, or maybe Borland. I will look the source for inspiration, and as soon as mine is functional, I will post here some pictures, and hopefully you will help me with your invaluable insight. Clément
-
Hi, Usually IT departments install a lot of stuff to prevent infection, but once you're infected is another ball game. Check if your firewall is up and running. If you can install ( user permission wise ) a software in your machine, I strongly recommend you to download malwarebytes https://www.malwarebytes.com/ (Personal edition will be just fine ) from a clean machine, copy the installer to a pen-drive and install and run it in your machine. Let it run. Hopefully most of those nasty fellows can be removed. Unfortunately there's no "one antivirus to rule them all", so you might need some other antivirus software to clean it up. If your firewall is NOT active. turn off your machine at once. Don't waste time trying to put it back online, especially if you are in a LAN and have access to other machine in the network. Once windows reboots, your firewall should be up and running again. Don't use your machine without a firewall. If your firewall is deactivated again, shut it down for good and let the IT department deal with it HTH, Clément
-
Just updated from 10.4 with Patch 1,2,3 applied. (WebInstall). No problems so far
-
I got a [pgpopen@foxmail.com].pgp that forced me to reformat my machine. I have successfully installed 10.4, installed all components and libraries... loaded my project and ... I'm missing some VCL styles 😥 What happened to : [BRCC32 Error] dhsPinger.vrc(71): file not found: C:\Users\Public\Documents\Embarcadero\Studio\21.0\Styles\AquaLightSlate2.vsf [BRCC32 Error] dhsPinger.vrc(73): file not found: C:\Users\Public\Documents\Embarcadero\Studio\21.0\Styles\Glossy2.vsf [BRCC32 Error] dhsPinger.vrc(76): file not found: C:\Users\Public\Documents\Embarcadero\Studio\21.0\Styles\ZirconSE.vsf I installed all VCL Styles (GetIt Manager), went to DelphiStyles.com, search Embarcadero Blogs, CodeRage... where are those styles? Clément
-
Hi, I'm still looking for the styles... I found this link, they are free, and yet nowhere to be found.. Shouldn't they be included in 10.4? I installed 10.2 and 10.3. The styles are not there ... They should be a free download in the getit manager... https://community.embarcadero.com/article/16642-getit-october-2018
-
Calling an "application" from windows service
Clément posted a topic in RTL and Delphi Object Pascal
Hi, I wrote a Windows Service (REST HTTP Server) does a lot of stuff 😎. Several users (hopefully) will be connected and each might need to call this "app" from their own thread. Well, I would like to avoid compiling those modules into the main Service, because they will get changed a lot more often than the service itself. Some modules are specific to some users. A few details about this app: No form, no console no user interaction are required. I just need to pass a command line with some parameters ( 4 or 5 actually) and the "app" should run, do the thing, and return to the service. My options are: 1) Small executable with the required modules: ... just a log file to guide me (or my user). Will be called from the service with the required parameters (command line) 2) Write a DLL and load and unload it when there's an update (don't like the idea, but it works) 3) Write another Windows Service with the required modules. As both services share the same machine, communication between them should not be a problem. 4) Mix options 3 and 1 to build a powerfull architecture ( not required right now ). Do you guys have another option? A preferred one? TIA, Clément -
Well... yes... I mean, my computer has RDP activated in another port. So basically the ISP router forward the requests from a non-default RDP port to a non-default RDP local port. My computer is not working 24/7. But it can start itself everyday at 8:00 am, and I turn it off when I'm done. So it can stay on from 8:00 to 17:00, or sometimes 23h00. I still have to understand how he managed to create a local account. As far as I can tell, ha managed to overcome 3 firewalls. My ISP Router, my server, and my machine. So he manage to discover the exact ports and his timing was perfect. Or this attack didn't happened all at once. I might have been infected by some virus a few weeks back that remained inactive, or was unable to take action, up until "something" happened and made the hacking possible. Since it's my working machine, I only open my customer email. There's no navigating to suspicious sites or downloading illegal content. The fact is that "somehow" he manage to create a local user account using RDP. And Windows Defender kicked in only after I dropped his connection. If one more minute has passed it would be terrible! I would required a lot more than those 3 VCL Skins... And by the way... this kind of ransomware uses RSA with AES to encrypt contents, the encryption takes place by scanning folders and file alphabetically. I have my Images (Glyphs and Icons) stored in "Images" Folder ( Several GBytes of recoverable data ) that delayed that virus long enough. Just a few folder from my Projects... It ignores executables and any file with less than 5kb . The only thing left unencrypted is a text file with "directions" to contact them. Well, finally I manage to recover all my projects. My most recent backup was from 11/08 the attack took place 12th. In my backup server, my readonly folder tree was unaffected. The problem I had was some files are not included in my backup (like some VCL Skins, Icons, RC files, configurations files, Delphi settings, thirdparty components, etc.. ) A lot of work to rebuild my machine since I have a really hard time believing the antivirus got rid of that virus. I just feel safer destroying partitions and reformatting everything. Brand new Windows 10 installation with Delphi and all its ecosystem.
-
There are a few things I learned from this experience. There was a lot strange traffic in my firewall. I already wrote a batch that will block those traffics automatically. But that wasn't the main issue. When I was remotely accessing my machine, I noticed it was slower than it should. I start searching for processes that were eating all my resources CPU and memory. My antivirus was "normal", all my usual processes were "normal" but yet something was eating over 70% of CPU and 80% memory... I was in task manager and click the Users.. To my surprise, there was another user logged in. Very unusual name something like "yyz==Twe". I never would have created a user like that one. The moment I killed the connection the machine start working normally. The Antivirus warned me there was a Ransomware running asked to run an offline scan, and I restarted the machine. Windows 10 was up to date. How this fellow managed to create a local user in my machine through RDP is beyond me.
-
LOL!! Don't worry I have precedence ... I founded DHS when I was still in high school,Turbo Pascal and Turbo C++ ruled the world ( a long time ago , in a galaxy far away... ) ...
-
I already check GetIt manager. It's not there. I installed from the WebInstaller.. Maybe ISO installer has more styles
-
Windows share that's created by the backup application only when the backup is ready to be copied. This was a full backup copy day, so it took longer to copy. What saved me was 2 things actually. 1) A folder that only a windows user (usrBackup) has write access to it. Every other domain user has read only access 2) A rather large glyph collection. My drive C was completelly lost.