Jump to content

TiGü

Members
  • Content Count

    39
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by TiGü

  1. var IsCrossPlatformDebuggerPresent: Boolean; begin IsCrossPlatformDebuggerPresent := System.DebugHook <> 0; end;
  2. Do you use Windows 10? Why not increase the DPI for the current Monitors? You can use a 1920 x 1200 Monitor with a 125%, 150% or 175% scaling. Source: https://www.tenforums.com/tutorials/5990-change-dpi-scaling-level-displays-windows-10-a.html
  3. Have a look to Microsofts Team Foundation Server: https://en.wikipedia.org/wiki/Team_Foundation_Server
  4. TiGü

    Caching with class variables

    Hi Primož, that's a nice piece of code, but i notice in my Delphi Tokyo, that the ens-Result for the TEnumSet (for valid values) is empty. But if you add a untyped Move, than it works: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.TypInfo, System.Rtti, System.SysUtils; resourcestring SValueLiesOutsideAllowedRange = 'Value %d lies outside allowed range for %s (%d .. %d)'; type TypeInfoCache<T> = class class var FMinIntVal: Integer; FMaxIntVal: Integer; FIsSet: Boolean; public class constructor Create; class property MaxIntVal: Integer read FMaxIntVal; class property MinIntVal: Integer read FMinIntVal; class property IsSet: Boolean read FIsSet; end; Range<T> = record private class function MaxIntVal: Integer; static; inline; class function MinIntVal: Integer; static; inline; class procedure RaiseException(const Value: Integer); static; public class function Check(const Value: Integer): T; static; end; { Range<T> } class function Range<T>.Check(const Value: Integer): T; begin if (Value < MinIntVal) or (Value > MaxIntVal) then RaiseException(Value); if TypeInfoCache<T>.IsSet then begin Move(Value, Result, SizeOf(T)); // here is the magic end; end; class function Range<T>.MaxIntVal: Integer; begin Result := TypeInfoCache<T>.MaxIntVal; end; class function Range<T>.MinIntVal: Integer; begin Result := TypeInfoCache<T>.MinIntVal; end; class procedure Range<T>.RaiseException(const Value: Integer); begin raise Exception.CreateFmt(SValueLiesOutsideAllowedRange, [Value, PTypeInfo(TypeInfo(T)).Name, MinIntVal, MaxIntVal]); end; { TypeInfoCache<T> } class constructor TypeInfoCache<T>.Create; var ti: PTypeInfo; typeData: PTypeData; i: Integer; begin ti := TypeInfo(T); FIsSet := ti.Kind = tkSet; if FIsSet then ti := GetTypeData(ti).CompType^; typeData := GetTypeData(ti); FMinIntVal := typeData.MinValue; if FIsSet then begin FMaxIntVal := 0; for i := typeData.MinValue to typeData.MaxValue do FMaxIntVal := FMaxIntVal or (1 shl i); end else FMaxIntVal := typeData.MaxValue; end; type TEnum = (en1, en2, en3); TEnumSet = set of TEnum; var en: TEnum; ens: TEnumSet; begin try try en := Range<TEnum>.Check(0); en := Range<TEnum>.Check(2); en := Range<TEnum>.Check(3); except on E: Exception do Writeln('Expected exception: ', E.ClassName, ' ', E.Message); end; try ens := Range<TEnumSet>.Check(0); ens := Range<TEnumSet>.Check(2); ens := Range<TEnumSet>.Check(7); ens := Range<TEnumSet>.Check(8); except on E: Exception do Writeln('Expected exception: ', E.ClassName, ' ', E.Message); end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; if DebugHook <> 0 then Readln; end.
  5. TiGü

    Embarcadero DocWiki for Rio

    OT: I liked the depressive design, it fit well with the daily frustrating experience with the IDE. 👿
  6. TiGü

    Debugging multiple DLLs simultaneously

    I guess it will have a good reason/requirement why he needs to use an application with multiple DLLs.
  7. TiGü

    Debugging multiple DLLs simultaneously

    program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Winapi.Windows; procedure Main; var I: Integer; begin Writeln('Start'); while not IsDebuggerPresent do begin Writeln('I''m waiting for you!'); Sleep(100); end; for I := 1 to 1000 do Writeln(' I:', I); Writeln('End'); end; begin try Main; Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Try the good old While-Not-IsDebuggerPresent-Trick!
  8. They aren't necessary. Unfortunately, you can't hide them with Delphi Tools. https://stackoverflow.com/questions/24718716/delphi-xe6-dll-unwanted-export-tmethodimplementationintercept
  9. Wow, it could be easier. You have to set the Converter.Options after casting to the EarsivWebService interface. Then they are not reset and you can avoid the AfterExecute handler. unit Earsiv.View; interface uses System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, EarsivWebService1, Soap.SOAPHTTPClient, Soap.OpConvertOptions; type TForm5 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private FRIO: THTTPRIO; FEarsivWebService: EarsivWebService; public end; var Form5: TForm5; implementation {$R *.dfm} procedure TForm5.FormCreate(Sender: TObject); begin FRIO := THTTPRIO.Create(nil); FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService'; FEarsivWebService := (FRIO as EarsivWebService); FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; end; procedure TForm5.Button1Click(Sender: TObject); var Request: faturaOlustur; Response: faturaOlusturResponse; begin Request := nil; Response := nil; Request := faturaOlustur.Create(); Request.input := 'Hello'; Request.fatura := belge.Create(); Request.fatura.belgeFormati := belgeFormatiEnum.PDF; try Response := FEarsivWebService.faturaOlustur(Request); finally if Assigned(Response) then begin if Assigned(Response.return) then begin ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText); end; Response.Free; end; Request.Free; end; end; end.
  10. Hm, after the first request, the Converter.Options are fine and included soDocument and soLiteralParams...so there is room for improvement (calling MyHTTPRIO1AfterExecute only once and disconnect it afterwards from FRIO.OnAfterExecute or something).
  11. Hi @ertank! I play with your code and do some debugging in the depths of the Delphi SOAP sources. As you can see in the TOPToSoapDomConvert.ProcessResponse (Line 2037 in Tokyo 10.2.3) it calls a inline class helper function IsBareLiteral. Making long story short: Set every time the THTTPRIO.Converter.Options (see Unit Soap.OpConvertOptions) and the Response will be filled. Try this: unit Earsiv.View; interface uses System.SysUtils, System.Classes, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, EarsivWebService1, Soap.SOAPHTTPClient, Soap.OpConvertOptions; type TForm5 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private FRIO: THTTPRIO; WS: EarsivWebService; procedure MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream); public end; var Form5: TForm5; implementation {$R *.dfm} procedure TForm5.Button1Click(Sender: TObject); var Request: faturaOlustur; Response: faturaOlusturResponse; begin if not Assigned(FRIO) then begin FRIO := THTTPRIO.Create(nil); FRIO.OnAfterExecute := MyHTTPRIO1AfterExecute; FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService'; // the following line are not enough, see MyHTTPRIO1AfterExecute FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; WS := (FRIO as EarsivWebService); end; Request := nil; Response := nil; Request := faturaOlustur.Create(); Request.input := 'Hello'; Request.fatura := belge.Create(); Request.fatura.belgeFormati := belgeFormatiEnum.PDF; try Response := WS.faturaOlustur(Request); finally if Assigned(Response) and Assigned(Response.return) then begin ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText); end; Request.Free; Response.Free; end; end; procedure TForm5.MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream); begin FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams]; end; end.
×