PeterBelow
Members-
Content Count
508 -
Joined
-
Last visited
-
Days Won
13
Everything posted by PeterBelow
-
How to Create dll with callback or event functions?
PeterBelow replied to ChrisChuah's topic in RTL and Delphi Object Pascal
Create a COM dll, Delphi has a wizard for that. Google for "C# com interop" to find examples for how to use such a thing from the .NET side. -
Keep func/proc declaration in sync with implementation
PeterBelow replied to Diego Simonini's topic in Delphi IDE and APIs
ModelMaker Code Explorer (MMX) can do this, as well as a lot of other things. Could not live without it... See https://www.mmx-delphi.de/ It is free and maintained. -
Install Raize components 6.1.10 in Delphi 10
PeterBelow replied to AndrewHoward's topic in General Help
The script is looking at the wrong version of the rtl package. 17.0 is not 10.2 Tokyo, that would be 19.0. Check the pathes used in the script or the dproj files it refers to. 17.0 is 10.0 Seattle if memory serves. -
The error message looks like the designer tries to read values from a dfm file into a component that has not been created yet. Was this other project created with the same Delphi version? Does it open and compile in Delphi Alexandria? Does the form you are trying to use in the new project use any self-written or 3rd-party components you are not yet using in forms of the new project?
-
If you used the button OnClick handler from the link you gave it will not work unless uncomment the Application.ProcessMesssages call.
-
The source of your problem is probably the line TImage1.Picture.Assign(Image); Should'nt that be Image1.Picture.Assign(Image);
-
Encoding an n-dimensional array given dimensions and a list of items.
PeterBelow replied to MarkShark's topic in Algorithms, Data Structures and Class Design
unit Unit1; interface uses system.Generics.Collections, system.Typinfo, system.sysutils; type TDynamicArrayFormatter<T> = class strict private FData: TArray<T>; FDimensions: TArray<cardinal>; FIndices: TArray<cardinal>; FType: PTypeInfo; strict protected procedure AddValue(aBuilder: TStringBuilder); function CalcLinearIndex: Integer; function GetText: string; procedure ProcessDimension(aDimension: Cardinal; aBuilder: TStringBuilder); public constructor Create(const aDimensions: array of cardinal; const aDataArray: TArray<T>); class function Execute(const aDimensions: array of cardinal; const aDataArray: TArray<T>): string; end; implementation constructor TDynamicArrayFormatter<T>.Create(const aDimensions: array of cardinal; const aDataArray: TArray<T>); begin inherited Create; SetLength(FDimensions, Length(aDimensions)); Move(aDimensions[0], FDimensions[0], Length(FDimensions) * Sizeof(Cardinal)); FData := aDataArray; FType:= TypeInfo(T); SetLength(FIndices, Length(FDimensions)); end; procedure TDynamicArrayFormatter<T>.AddValue(aBuilder: TStringBuilder); var LValue: T; N: Integer; S: string; begin N:= CalcLinearIndex; LValue := FData[N]; case FType.Kind of tkInteger: S:= Pinteger(@LValue)^.ToString; tkUnicodeString: S:= PPChar(@LValue)^; else S:= 'unknown type of T'; end; aBuilder.Append(S); end; function TDynamicArrayFormatter<T>.CalcLinearIndex: Integer; var I, N: Integer; begin Result := 0; N:= 1; for I := High(FDimensions) downto Low(FDimensions) do begin Inc(Result, N * Pred(FIndices[I])); N := N * FDimensions[I]; end; end; class function TDynamicArrayFormatter<T>.Execute(const aDimensions: array of cardinal; const aDataArray: TArray<T>): string; var LInstance: TDynamicArrayFormatter<T>; begin LInstance := TDynamicArrayFormatter<T>.create(aDimensions, aDataArray); try Result := LInstance.GetText; finally LInstance.Free; end; end; function TDynamicArrayFormatter<T>.GetText: string; var LBuilder: TStringBuilder; begin LBuilder := TStringBuilder.Create; try ProcessDimension(1, LBuilder); Result := LBuilder.ToString; finally LBuilder.Free; end; end; procedure TDynamicArrayFormatter<T>.ProcessDimension(aDimension: Cardinal; aBuilder: TStringBuilder); var I: Cardinal; LAddValues: Boolean; begin aBuilder.Append('{'); LAddValues := integer(aDimension) = Length(FDimensions); for I := 1 to FDimensions[Pred(aDimension)] do begin FIndices[aDimension-1] := I; if LAddValues then begin if I > 1 then aBuilder.Append(','); AddValue(aBuilder); end else ProcessDimension(Succ(aDimension), aBuilder); end; aBuilder.Append('}'); end; end. Usage like var S: string; begin S:= TDynamicArrayFormatter<string>.execute([1,2,2], ['one','two','three','four']); WriteLn(S); end; -
In addition to Anders' reply: note that (VCL) buttons have two useful properties for dialog boxes: Default - if you set that to true the button will "click" if the user hits the Enter or Return key, regardless of whether the button has focus or not. Cancel - if that is set to true the ESC key will click the button. If the button's ModalResult is set to mrCancel that will close the dialog.
-
Reorganize a class / Set Of ..
PeterBelow replied to PatV's topic in Algorithms, Data Structures and Class Design
My test code was a bit different and what I cited was what error insight displayed in the Structure pane; I did not try to compile it. -
Form.OnKeyUp(key:word) = Get ASCII code of Special character(è)
PeterBelow replied to gioma's topic in General Help
buf is declared as a single Widechar but you tell ToUnicodeEx that it can hold 255 Widechars. A good way to ruin your call stack. -
Reorganize a class / Set Of ..
PeterBelow replied to PatV's topic in Algorithms, Data Structures and Class Design
The error message makes no sense since it gives the impression that the code would work if T is constraint to class or interface. That is of course not the case. -
Form.OnKeyUp(key:word) = Get ASCII code of Special character(è)
PeterBelow replied to gioma's topic in General Help
Like Remy said this would be much easier to handle if you transmit the whole input string after the user has entered it. There are ways to figure out which character would be created from a virtual key code and the current state of the modifier keys (Shift, Alt, Ctrl), see the MapVirtualKeyEx Windows API function, but this pointless if you have to deal with accented characters or other composites that are created by a sequence of keystrokes, or Alt+numpad input. Let Windows do this work for you and use the OnKeyPress event; it gives you the character directly. -
A TDBGrid is a kind of virtual grid. It shows rows from a dataset and does not know how many rows the dataset contains (the dataset itself may not know that, in fact). So it scrolls the active row in the dataset, not the rows in the grid; the selected row in the grid corresponds to the active record in the dataset. The grid actually contains only enough rows to fill the visible area, which get reused for new content as the dataset is scrolled.
-
Reorganize a class / Set Of ..
PeterBelow replied to PatV's topic in Algorithms, Data Structures and Class Design
I tried something like that and the compiler does not accept the "set of T" declaration, moaning about T not having a class or interface constraint. Which makes no sense at all in this case. -
Reorganize a class / Set Of ..
PeterBelow replied to PatV's topic in Algorithms, Data Structures and Class Design
Sets have their use but they also have limitations, e. g. they are not supported with generics as far as I know, so a "set of T" does not work. If you could replace the set with a list you could turn the class into a generic base class with the generic T: record parameter for the enumeration that the set is now defined with. Of course a check for "x in set" is much faster than a check for "x in list". The compiler (11.1) accepts something like type TWrapper<T: record> = class private FSet: TList<T>; end; TEnum = (one, two, three); TEnumWrapper = class(TWrapper<TEnum>) end; But you still cannot apply functions like Ord to T in methods of TWrapper, nor cast it to Byte. The constraint system for generics is too limited here since you cannot specify T as an ordinal type. -
Delete unicode non-breaking space
PeterBelow replied to Fons N's topic in RTL and Delphi Object Pascal
You are approaching this from the wrong angle. The data you showed pasted into notepad looks like a semicolon-separated CSV format. To dissect this you can use TStringlist. Something like this: var LText, LLine: TStringlist; i: integer; begin LText := TStringlist.Create; try LText := Clipboard.AsText; // This splits the data into lines LLine := TStringlist.Create; try LLine.StrictDelimiter := true; LLine.Delimiter := ';'; for i:= 0 to LText.Count - 1 do begin LLine.DelimitedText := LText[i]; if i = 0 then ProcessHeaderLine(LLine) else ProcessDataLine(LLine); end; finally LLine.Free; end; finally LText.Free; end; end; Untested, just typed into the post directly. The two Process routines are something you would write yourself. For each the passed stringlist should hold 5 lines, the column captions for the header and the column values for the data. If you really want to replace a non-breaking Unicode space it is a single character with the code #$00A0, not a two-character string. Your hex viewer probably pastes the clipboard content as ANSI text, while Notepad pastes it as Unicode (UTF-16). -
The System.IOUtils unit contains a number of helpers to work with files in general. The TPath record has methods to build a path, dissect a path, find system folders etc.
-
Can undefined function result point to valid/used data in memory?
PeterBelow replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
A function return value of type string as well as other compiler-managed types (e.g. dynamic arrays) is actually implemented as an additional Var parameter, so your function would be equivalent to procedure SwitchCase(const aStr: string; var Result:string); The compiler initializes the string variable passed for Result at the point of call, so it will always be valid. It is not guaranteed to be nil (string.empty), though. The compiler may reuse another hidden local variable used previously in the calling method. Such things are documented in the Delphi Language guide, see https://docwiki.embarcadero.com/RADStudio/Sydney/en/Program_Control_(Delphi) -
Is this for a multi-user application, where several users may request a new code/number combination for the same code concurrently? That may pose a problem unless you can figure out a way to avoid or at least detect collisions. On a database level sequences (or generators, nomenclature differs between databases) were introduced to solve such issues, but in your case you would need one sequence per code. A unique index on the table storing the code+number values would at least give you a way to detect collisions if you simply use a SELECT max(value) FROM <table> WHERE value like :code+'%' to get the last value used.
-
The VCL controls do not implement a default handling of the mouse wheel, unless a Windows control implements it on the API level. TScrollbox is not based on an API control, so you have to code this yourself. You only have to do this once, though: create a descendant of TScollbox that implements the behaviour you want and the use that. Note that when creating a component you do not use the parent component's events, those are for the component user. Instead you overwrite the virtual or dynamic methods that fire the events.
-
Hard to say with the info you give us. A scrollbox (VCL) sets its range automatically based on the position and dimensions of the controls it contains. If it is empty or the content is aligned alClient there is nothing to scroll. If all content fits in the client area of the scrollbox there is nothing to scroll either.
-
I don't know much about the US legal system, other than that it is weird by german standards and have no actual case I could point to. But in my opinion a known safety problem like the one this discussion is about would be a quality issue. Of course if the client decides to use such an unsafe installation folder and the possible risk is spelled out in the installation guide then it is his problem. As far as I'm aware (and i'm definitely not a lawyer) in Germany software is treated like other products (hardware) now as far as consumer protection legislation and liability is concerned, so damage caused by faulty software could be reason for a (private) lawsuite. In this particular case it would probably boil down to how much knowlege of the risk involved can be reasonably expected of the user installing the software...
-
Are you also aware of the legal repercussions that may have? It's of course OK if you only use the program on your own computers, but if you sell it to clients it opens you up to litigation. If the program is infected on the client's computer and then causes damage there the client could sue you, since the program does not follow accepted safety standards for software. Depends on your countries legislation, of course.
-
That requires write access for the user account to the folder the program is in, and that makes it vulnerable to malware attacks.
-
Delphi 11.1 IDE - Control + Click doesn't open FireDAC units
PeterBelow replied to Michael Riley's topic in Delphi IDE and APIs
I just checked my Pro installations and both 10.4 and 11.1 only have the three source files you listed. For the other FireDac units only the DCUs are there. The latest Feature Matrix lists full FireDac source code as Enterprise /Architect edition only.