-
Content Count
1938 -
Joined
-
Last visited
-
Days Won
25
Everything posted by Attila Kovacs
-
Pitfalls of Anonymous methods and capture
Attila Kovacs replied to Lars Fosdal's topic in RTL and Delphi Object Pascal
Mhm, So avoid variables and everything should be ok in anon procs? Like that? case hType of foo: //Handler := TFoo.Create; Broker.AddHandler(TFoo.Create.OnHandle); bar: //Handler := TBar.Create; Broker.AddHandler(TBar.Create.OnHandle); end; -
Guessing the decimal separator
Attila Kovacs replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
@Rudy Velthuis I could not tell whether you agree or arguing with me. If he is running GuessDecimalseparator() on strings, and the file contains only "0" 's, it will be still treated as float 0, isn't it? Otherwise he would run GuessIntegerOrFloatOrNoneOfThem() first and then WhatNow(). -
Pitfalls of Anonymous methods and capture
Attila Kovacs replied to Lars Fosdal's topic in RTL and Delphi Object Pascal
Hi Lars, Ahm, where is Anonymous method in yor example? And I'm not sure about that for in over an enum. I'm AFK but I would test it in first place. -
I can't blame you. I have the same problem with GExperts.
-
Can't you just define defaults for those fields in the db?
-
I won't go into a conversation about good practices because I would not do anything anymore without ORM, and you would not rewrite your app from the scratch. But this could help you eventually: var CurrentConnection: TFDConnenction; CurrentConnection := LiveConnection / TestConnenction CurrentConnection.ExecSQL('whatever'); btw, what is FDCExecSQL?
-
Thanks @mael and @M.Joos. This is actually very simple with the RegisterSelectionEditor. Here is the prototype I made, I don't really have any time to make it to a "product" nor to enhance it more. First you will need a simple wizard skeleton like http://www.tempest-sw.com/opentools/simple.html Then merge this code into it. Let me know if anything is missing. TCustomPropeFilter = class(TSelectionEditor, ISelectionpropertyFilter) private // I've no clue who is managing the instance so everything static class var FFilterPane: TPanel; class var FFilterBox: TButtonedEdit; class var FFilterCombo: TComboBox; class var FFilterList: TStringList; class var FPatternList: TStringList; class var FPropertyInspector: TForm; class var FOldPropertyInspectorActivate: TNotifyEvent; class procedure OnFilterComboCloseUp(Sender: TObject); class procedure RefreshSelection; class procedure OnFilterComboKeyPress(Sender: TObject; var Key: Char); class procedure OnPropertyInspectorActivate(Sender: TObject); protected { ISelectionPropertyFilter } procedure FilterProperties(const ASelection: IDesignerSelections; const ASelectionproperties: IInterfaceList); end; constructor TSimpleWizard.Create; begin // how to unregister? RegisterSelectionEditor(TControl, TCustomPropeFilter); TCustomPropeFilter.FPropertyInspector := TForm(Application.FindComponent('PropertyInspector')); if TCustomPropeFilter.FPropertyInspector <> nil then begin TCustomPropeFilter.FOldPropertyInspectorActivate := TCustomPropeFilter.FPropertyInspector.OnActivate; TCustomPropeFilter.FPropertyInspector.OnActivate := TCustomPropeFilter.OnPropertyInspectorActivate; TCustomPropeFilter.FFilterPane := TPanel(TCustomPropeFilter.FPropertyInspector.FindComponent('FilterPane')); if TCustomPropeFilter.FFilterPane <> nil then begin TCustomPropeFilter.FFilterBox := TButtonedEdit(TCustomPropeFilter.FPropertyInspector.FindComponent('FilterBox')); // I don't like the default search box. Do you? if TCustomPropeFilter.FFilterBox <> nil then TCustomPropeFilter.FFilterBox.Visible := False; TCustomPropeFilter.FFilterCombo := TComboBox.Create(TCustomPropeFilter.FFilterPane); TCustomPropeFilter.FFilterCombo.Name := 'FilterCombo'; TCustomPropeFilter.FFilterCombo.Text := ''; TCustomPropeFilter.FFilterCombo.Margins.Left := 0; TCustomPropeFilter.FFilterCombo.Margins.Top := 3; TCustomPropeFilter.FFilterCombo.Margins.Right := 0; TCustomPropeFilter.FFilterCombo.Margins.Bottom := 0; TCustomPropeFilter.FFilterCombo.AlignWithMargins := True; // TCustomPropeFilter.FFilterCombo.Top := 100; // needed only if default search-box is visible TCustomPropeFilter.FFilterCombo.Align := alTop; TCustomPropeFilter.FFilterPane.InsertControl(TCustomPropeFilter.FFilterCombo); TCustomPropeFilter.FFilterCombo.Items.Add('Pos & Size'); TCustomPropeFilter.FFilterCombo.Items.Add('Display'); TCustomPropeFilter.FFilterCombo.Items.Add('Name'); TCustomPropeFilter.FFilterCombo.Items.Add('NewForm'); TCustomPropeFilter.FFilterCombo.OnCloseUp := TCustomPropeFilter.OnFilterComboCloseUp; TCustomPropeFilter.FFilterCombo.OnKeyPress := TCustomPropeFilter.OnFilterComboKeyPress; TCustomPropeFilter.FFilterList := TStringList.Create; TCustomPropeFilter.FPatternList := TStringList.Create; end; end; end; { TCustomPropeFilter } class procedure TCustomPropeFilter.OnFilterComboCloseUp(Sender: TObject); begin RefreshSelection; end; class procedure TCustomPropeFilter.RefreshSelection; var AList: IDesignerSelections; Designer: IDesigner; begin Designer := ActiveRoot as IDesigner; if Designer = nil then Exit; AList := CreateSelectionList; Designer.GetSelections(AList); // If the selection contains only the current form. (No controls) if (AList.Count = 1) and (AList[0] = Designer.Root) then Designer.NoSelection else Designer.ClearSelection; Designer.SetSelections(AList); end; class procedure TCustomPropeFilter.OnFilterComboKeyPress(Sender: TObject; var Key: Char); begin case Key of #13: begin RefreshSelection; Key := #0; end; #27: begin if TCustomPropeFilter.FFilterCombo.Text <> '' then begin TCustomPropeFilter.FFilterCombo.ItemIndex := -1; TCustomPropeFilter.FFilterCombo.Text := ''; RefreshSelection; end; Key := #0; end; end; end; class procedure TCustomPropeFilter.OnPropertyInspectorActivate(Sender: TObject); var CursorPos: TPoint; c: TControl; begin // This is insane but I've no better idea to avoid stealing the focus by Property Editor's OnActivate event GetCursorPos(CursorPos); c := FFilterPane.ControlAtPos(FFilterPane.ScreenToClient(CursorPos), True, True, True); if (c <> nil) and (c.Name = 'FilterCombo') then Exit; if Assigned(FOldPropertyInspectorActivate) then FOldPropertyInspectorActivate(Sender); end; procedure TCustomPropeFilter.FilterProperties(const ASelection: IDesignerSelections; const ASelectionproperties: IInterfaceList); var i, j: Integer; LSelectedItem: TPersistent; LProperty: IProperty; LPropertyName: String; MethodProperty: IMethodProperty; function PatternMatch(AList: TStringList; APropName: String): Boolean; var k: Integer; begin for k := 0 to AList.Count - 1 do if Pos(AList[k], APropName) > 0 then Exit(True); Result := False; end; begin if TCustomPropeFilter.FFilterCombo <> nil then begin // todo load the list from file or registry case TCustomPropeFilter.FFilterCombo.ItemIndex of - 1: begin if TCustomPropeFilter.FFilterCombo.Text <> '' then begin TCustomPropeFilter.FPatternList.Clear; TCustomPropeFilter.FFilterList.Text := StringReplace(TCustomPropeFilter.FFilterCombo.Text, ',', #13#10, [rfReplaceAll]); for i := TCustomPropeFilter.FFilterList.Count - 1 to 0 do if Copy(TCustomPropeFilter.FFilterList[i], 1, 1) = '*' then begin TCustomPropeFilter.FPatternList.Add(Copy(TCustomPropeFilter.FFilterList[i].ToLower, 2)); TCustomPropeFilter.FFilterList.Delete(i); end; end else Exit; end; // everything hardcoded because I'm a lazy dog 0: begin TCustomPropeFilter.FFilterList.Clear; TCustomPropeFilter.FFilterList.Add('Top'); TCustomPropeFilter.FFilterList.Add('Left'); TCustomPropeFilter.FFilterList.Add('Width'); TCustomPropeFilter.FFilterList.Add('Height'); TCustomPropeFilter.FFilterList.Add('ClientWidth'); TCustomPropeFilter.FFilterList.Add('ClientHeight'); TCustomPropeFilter.FFilterList.Add('TabOrder'); TCustomPropeFilter.FFilterList.Add('Align'); TCustomPropeFilter.FFilterList.Add('AlignWithMargins'); TCustomPropeFilter.FFilterList.Add('Margins'); end; 1: begin TCustomPropeFilter.FFilterList.Clear; TCustomPropeFilter.FFilterList.Add('Caption'); TCustomPropeFilter.FFilterList.Add('Text'); TCustomPropeFilter.FFilterList.Add('Datasource'); TCustomPropeFilter.FFilterList.Add('DataField'); end; 2: begin TCustomPropeFilter.FFilterList.Text := 'Name'; end; 3: begin TCustomPropeFilter.FFilterList.Clear; TCustomPropeFilter.FFilterList.Add('ActiveControl'); TCustomPropeFilter.FFilterList.Add('BorderIcons'); TCustomPropeFilter.FFilterList.Add('BorderStyle'); TCustomPropeFilter.FFilterList.Add('Caption'); TCustomPropeFilter.FFilterList.Add('ClientHeight'); TCustomPropeFilter.FFilterList.Add('ClientWidth'); TCustomPropeFilter.FFilterList.Add('Font'); TCustomPropeFilter.FFilterList.Add('Name'); TCustomPropeFilter.FFilterList.Add('Position'); end; end; // todo implement pattern search like in the original IDE search box for i := 0 to ASelection.Count - 1 do begin LSelectedItem := ASelection[i]; if (LSelectedItem is TControl) then for j := ASelectionproperties.Count - 1 downto 0 do begin if Supports(ASelectionproperties[j], IProperty, LProperty) then if not Supports(ASelectionproperties[j], IMethodProperty, MethodProperty) then begin LPropertyName := LProperty.GetName; if (TCustomPropeFilter.FFilterList.IndexOf(LPropertyName) = -1) and // (not PatternMatch(TCustomPropeFilter.FPatternList, LPropertyName.ToLower)) then ASelectionproperties.Delete(j); end; end; end; end; end;
-
How to "eat" the second OnMouseDown / OnMouseUp events after a DblClick?
Attila Kovacs replied to Steve Maughan's topic in VCL
We just had a similar discussion the other day. Take a look at my solution (on the bottom of the thread) and try to adopt it. Use it only on the form you really need it, but if you are going to show a modal form from the dobule-click handler there is no guarantee that the following messages are captured by your map's form but by the newly created/shown modal form. You can also try to just to call ReleaseCapture before showing the modal window. -
Guessing the decimal separator
Attila Kovacs replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
Why would you search decimal separator on integers? What formula do you think would be feasible to tell what 1.000 is? Check the first X rows, if still not obvious check another X, if still not and EOF, panic. -
Guessing the decimal separator
Attila Kovacs replied to dummzeuch's topic in Algorithms, Data Structures and Class Design
the first one from the right -
function x(const input: string; var output: string): boolean; How to defuse? Omit const? Performance penalty.
-
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
@Primož Gabrijelčič Yes, this was the original problem which I've used to solved with the wrapper. Rather more code/resource than record pointers. I like to sleep well. -
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
@Primož Gabrijelčič Nice. I like that the wrapper/forwarder is now a common thing, even if this solution has the same amount of copyrecords plus some IF handling. -
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
@Primož Gabrijelčič Yup. Still, let me know if you find an other way, I'm also interested. Especially if you can avoid the extra copyrecord's and still have the original syntax. -
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
Of course. Question is, how do you like it and how does it interfere with the existing lib. I've no clue of this lib, but this should give you some ideas wrapping the record into something. TWorkItem = class; TOmniValue = record private FOwner: TWorkItem; // <------- FOwnedObject: IAutoDestroyObject; function GetAsOwnedObject: TObject; procedure SetAsOwnedObject(const Value: TObject); public property AsOwnedObject: TObject read GetAsOwnedObject write SetAsOwnedObject; end; TWorkItem = class(TInterfacedObject, IWorkItem) strict private FResult: TOmniValue; strict protected function GetResult: TOmniValue; protected // <------------ procedure SetResult(const Value: TOmniValue); public destructor Destroy; override; property Result: TOmniValue read GetResult write SetResult; end; function TWorkItem.GetResult: TOmniValue; begin Result := FResult; Result.FOwner := Self; // <------------ end; procedure TOmniValue.SetAsOwnedObject(const Value: TObject); begin FOwnedObject := TAutoDestroyObject.Create(Value); FOwner.SetResult(Self); // <------------------- end; -
Object destroyed too soon?
Attila Kovacs replied to Primož Gabrijelčič's topic in RTL and Delphi Object Pascal
I'd say thats why: property Result: TOmniValue read GetResult write SetResult; A Record property. -
Caching with class variables
Attila Kovacs replied to Primož Gabrijelčič's topic in Tips / Blogs / Tutorials / Videos
@Kryvich Would be an improvement yes, but still too few bits. -
Caching with class variables
Attila Kovacs replied to Primož Gabrijelčič's topic in Tips / Blogs / Tutorials / Videos
Actually at 32 will already fail, because he uses integer instead of cardinal. But indeed, an "if typeData.MaxValue > 30 then raise.." would make this approach safer. -
Caching with class variables
Attila Kovacs replied to Primož Gabrijelčič's topic in Tips / Blogs / Tutorials / Videos
I've lost the thread after this line "As it turns out, we can fix both problems simply by using class variables, properties, and methods functionality of the Delphi language:" The same code follows as already above the paragraph was., instead of the declaration of "TypeInfoCache" I think. -
When I perform the OnDblClick event (Form1) to open Form2, it fires the OnCellClick event of Form2, without having clicked on the form2 grid
Attila Kovacs replied to Luiz Felipe Heemann's topic in VCL
@Schokohase I see. Yes its windows. I don't know why does it fire MouseUp after DblClick... Your version could be also strange if someone does not releases the button after the second click. I'd still go with something like this, if there are no other side effects: (Well, actually a modal window overtakes the message loop, so no effect beyond modal forms.) var WasDblClick: boolean; procedure TForm1.MyOnMessage(var Msg: TMsg; var Handled: boolean); begin case Msg.Message of WM_LBUTTONDBLCLK: WasDblClick := True; WM_LBUTTONUP: if WasDblClick then begin // v0.2 Msg.Message := WM_CANCELMODE; WasDblClick := False; { // v0.1 PostMessage(Msg.hwnd, WM_CANCELMODE, 0, 0); WasDblClick := False; Handled := True; } end; end; end; procedure TForm1.FormCreate(Sender: TObject); begin Application.OnMessage := MyOnMessage; end; -
Activity feed loads the whole posts, then it truncates them..
Attila Kovacs posted a topic in Community Management
..with a js script. Then, the whole html contains 7 lines. One of them right now is 1 million 173 thousand 457 characters long. Must be a dream for the browser to parse it. -
Activity feed loads the whole posts, then it truncates them..
Attila Kovacs replied to Attila Kovacs's topic in Community Management
There is no actual problem, I just wanted to contribute to a better user experience 🙂 It's indeed can be a bit slow if I'm loading more than 1 page of activity and there are huge comments in it. With just 3-4 clicks this one html line grows to 2-3MB. -
When I perform the OnDblClick event (Form1) to open Form2, it fires the OnCellClick event of Form2, without having clicked on the form2 grid
Attila Kovacs replied to Luiz Felipe Heemann's topic in VCL
@Luiz Felipe Heemann As @Dany Marmur said, create a custom message and handler: const CM_OPEN_FORM2 = WM_APP + 1337; TForm1 = class(TForm) . private procedure CM_OPEN_FORM2_HANDLER(var Message: TMessage); message CM_OPEN_FORM2; .. procedure TForm1.CM_OPEN_FORM2_HANDLER(var Message: TMessage); begin TForm2.Create(Self).ShowModal; end; procedure TForm1.Panel1DblClick(Sender: TObject); begin Postmessage(Self.Handle, CM_OPEN_FORM2, 0,0); end; -
I prefer caFree action in onClose so I don't have to deal with references at all and doesn't really care if it's shown modal or not. Of course this means the forms are always (re)-created.
-
Analyze your executable. It could have more debug info, more rtti, more resources, more anything.. different linking options, compiler directives, who knows, we can't see those apps.