Jump to content

aehimself

Members
  • Content Count

    1085
  • Joined

  • Last visited

  • Days Won

    23

Everything posted by aehimself

  1. After some time investigating the issue I found out that custom property editors are causing this. We had about 4, removing one from the package caused the Internal Error to simply point to a different one. I have a theory which I will test out during the upcoming week(s). Will post an update once I have any news...
  2. I just went to doublecheck, the runtime package is already included in the Requires section of my designtime package. Seems I added it, I just forgot πŸ™‚
  3. aehimself

    Locate

    cds.Filter := 'MyField LIKE ''%contains%'''; cds.Filtered := True; ?
  4. There is no automatic notification as far as I'm aware, but the app receives the WM_FONTCHANGE message which was broadcasted. In the discussion on GitHub I mentioned that if I put a label on the form, set the font name to the same as in the ListView and paste some characters it shows up correctly without PostMessage / Sleep. This makes me believe that the installation is successful, only GDI+ needs some time before it can access a freshly installed font (or implementation is not correct). Unfortunately I have zero experience with any graphic-related stuff so can not confirm / debug :( This is why it's not even viable as a workaround imo.
  5. You mean a font is not meant to be installed runtime or not to be drawn with GDI+?
  6. Is it just me, or even the demo application does not import the font file properly when started for the first time? If the font is installed on the system (manually or by AddFontResource due to the first run) everything appears correctly. I tried Screen.ResetFonts and ImageList.RecreateBitmaps after the SendMessage, without success. Dumping everything on the disk with .SaveToPngFiles also saves the rectangles only. I'm using the latest snapshot from Git directly.
  7. When I saw the release notes on 10.4.2 and read that TEdgeBrowser now works with the GA Edge, I got excited. I thought it means you have Windows 10 installed with Edge and it works. Well, unfortunately it's not the case, What it means is that you no longer need the Canary edition, you simply can download the runtime from Microsoft's website. In all cases, you need WebView2.dll. It can come from GetIt, or you can download and extract the .NuGet package from Microsoft. You'll find the DLL under build\native folder. Next, download the WebView2 Runtime. Evergreen is the easiest, it downloads and keeps a system wide runtime up-to-date. If you choose this, you are set and ready, everything should work. If you choose the fixed version, things will be a bit different, as you have to tell TEdgeBrowser where to look for the files. Extract the fixed version, and simply add EdgeBrowser1.BrowserExecutableFolder := 'C:\Users\user\Downloads\Microsoft.WebView2.FixedVersionRuntime.89.0.774.54.x86'; before the .Navigate. All set, right? Nah. Embarcadero simply forgot about the TWebBrowser component, which can use Edge mode, but it does not publish this property - so normally it can only be used with Evergreen editions. Fortunately though, this can be fixed with the usual dirty hack: Type THackBrowser = Class(TWebBrowser); procedure TForm2.FormCreate(Sender: TObject); begin // EdgeBrowser1.BrowserExecutableFolder := 'C:\Users\user\Downloads\Microsoft.WebView2.FixedVersionRuntime.89.0.774.54.x86'; THackBrowser(WebBrowser1).GetEdgeInterface.BrowserExecutableFolder := 'C:\Users\user\Downloads\Microsoft.WebView2.FixedVersionRuntime.89.0.774.54.x86'; WebBrowser1.Navigate('https://www.whatismybrowser.com/'); end; Now, you can give your users the freedom. If they decide to download the Edge Runtime, your application will use Edge engine. If not, it still works in IE11 mode. Just don't forget to set FEATURE_BROWSER_EMULATION in the registry πŸ™‚ Hope it helps others!
  8. TEdgeBrowser works, and it works well. The whole reason I posted this topic way before is because it's not straightforward at all... at least not for me πŸ™‚ What issues you ran into? What does not work? What steps did you take already?
  9. My forever favorite stays this: Function GetUserID(APageIndex: Integer): Integer; Begin Case APageIndex Of 0: Result := -1; 1: Result := -1; 2: Result := -1; 3: Result := -1; [...] 50: Result := -1; Else Result := -1; End; Probably it had functionality a long time ago, but this method was still called from a live part of the code when I found it...! There were also some fancy fails (mainly memory leaks), including but not limited to: TMyClass = Class(TObject) private FOwner: TComponent; public Constructor Create(AOwner: TComponent); ReIntroduce; End; Constructor TMyClass.Create(AOwner: TComponent); Begin FOwner := AOwner; End; Or the other, which was probably a typo but took me a while to finally realize the issue: TMyClass = Class(TComponent) public Constructor Create(AOwner: TComponent); Override; End; Constructor TMyClass.Create(AOwner: TComponent); Begin inherited Create(Owner); End;
  10. Long story short: I'd like to get the popular opinion / correct way to handle a situation in a TDataSet descendant - and DelphiPraxis does have the userbase for it. What do you think, does it make sense to be able to change the .SQL property (the SQL query to be executed) of a dataset component while it is open and contains a resultset? Keep in mind that this can be an INSERT, UPDATE, DELETE command too, not necessarily an other SELECT. The full discussion with pros and cons can be read here for those interested.
  11. aehimself

    Something's changed in my IDE??

    Tools \ Options \ User Interface \ Editor \ Language, select Delphi and Block Ident? Not sure, never used the auto formatter.
  12. aehimself

    Synedit Help

    I solved this with the handler of TSynCompletionProposal.OnExecute (TableNamesSelector is a TSynCompletionProposal, SQLEditor is a TSynEdit) : Procedure TSQLConnectionFrame.TableNamesSelectorExecute(Kind: SynCompletionType; Sender: TObject; Var CurrentInput: String; Var x, y: Integer; Var CanExecute: Boolean); Var sa: TArray<String>; Begin If TableNamesSelector.ItemList.Count > 0 Then Exit; sa := SQLEditor.LineText.Substring(0, SQLEditor.CaretX - 1).Split([' ']); If Length(sa) > 0 Then sa := sa[Length(sa) - 1].Split(['.']); If Length(sa) < 2 Then TableNamesSelector.ItemList.Assign(SQLHighlight.TableNames) // No dot, offer table names immediately Else Begin CanExecute := False; If Length(sa) = 2 Then // Start a thread to collect field names of said table... End; End; You have to pass sa[0], sa[1], X and Y to the thread. sa[0] is the table name, sa[1] is the field name fragment which was already typed, x and y is the position where the proposal should pop back up. Once it finishes, you can: TableNamesSelector.ItemList.Assign(worker.FieldNames); TableNamesSelector.Execute(worker.FilterForText {passed to the thread as sa[1] from OnExecute}, worker.X, worker.Y); Also handle the OnClose event of the completionproposal: Procedure TSQLConnectionFrame.TableNamesSelectorClose(Sender: TObject); Begin TableNamesSelector.ItemList.Clear; End; The idea is that if the ItemList is empty the data still has to be collected and execution is disallowed. It will be popped up when the thread finishes.
  13. I added auto-close as an option now πŸ™‚
  14. aehimself

    A screen mirroring utility

    I think Windows 10 has this already via "My Phone", or am I mistaken? Maybe it's a 11 feature...?
  15. aehimself

    multi-threading question

    You also can utilize WaitForMultipleObjects.
  16. aehimself

    Can one include a TDataModule in a console application?

    I started to write my applications as a single class some years ago and never turned back. Want to start from console? TMyApp.Create; From a Windows service? TMyApp.Create; From the Mt. Everest? TMyApp.Create; You'll have to refine logging for sure but this is the easiest way I ever experienced to write self-containing, easy to debug code. I even took this one step further by adding some code to the .dpr of my Delphi services: if you start with the /console parameter, it starts as a console app instead of a service.
  17. aehimself

    Can one include a TDataModule in a console application?

    A TDataModule is basically a descendant of TComponent, there is nothing stopping you adding one to your console application. You'll have to manually create and destroy it though. I just checked and could add a DataModule in my 10.4.2 IDE.
  18. aehimself

    AllocHwnd + TTimer = lag?

    Hello all, I have a progress indicator on a panel which is visible until a thread is running. On here is a timer which is updating the status of the thread every second (elapsed time, some data from inside the thread, etc.). The .OnTerminate event of said thread has a custom message sent to the panel so I can do some final touches plus freeing the thread object up: PostMessage(Self.Handle, UM_WORKERENDED, 0, 0); Procedure TProgressPanel.UMWorkerEnded(Var Msg: TMessage); Begin _worker.WaitFor; FreeAndNil(_worker); End; All was working fine until a recent refactoring, when I changed the panel to a TObject for modularity reasons (now said panel can display different content, so I had to move the progress indicator to it's own). Since a TObject has no handle I created a dummy window with AllocHwnd and sending my message on this dummy handle. Everything works like clockwork, but I realized that the status update timer became laggy. Sometimes it refreshes too quickly (from second 1 to 2 in ~750 msec) and later on delaying more than 1 second (from second 2 to second 3 in 1,25 sec). Elapsed time is measured with a TStopWatch so I doubt the issue is with the measurement. I am aware that the TTimer works via Window Messages - is it possible that adding a dummy window with AllocHwnd (which is picking up ALL window messages, not just the one specified) causes the code to simply be overwhelmed, not processing WM_TIMER in time?
  19. aehimself

    AllocHwnd + TTimer = lag?

    Thank you @Dalija Prasnikar, I learned some new things about window messages! Unfortunately though, none of the above applied to my case. After the comment of @Lars Fosdal I got rid of the TTimer and used the same dummy window to catch the now manually fired SetTimer messages too. I also included a counter which increases each time a window message is received (whether processed or not) to see how swarmed application is. With a timer of 1 second, 70 seconds of runtime I got 72 messages. 1 is UM_WORKERENDED, I count the extra 1 as an acceptable discrepancy due to the timer's accuracy (or something unprocessed). So no, it was not the window messages. The solution is so painfully trivial I'm almost afraid to share... In the TComponent my timer was set to 750 msec to update the elapsed time on the UI. As I'm using TStopWatch, I manually converted the .ElapsedMilliSeconds to some readable format... using dividing and substracting. First time the timer fired at 0,75 seconds, UI was updated with the rounded 0 seconds. Second time the timer fired at 1,5 seconds, UI was updated with the rounded 1 seconds. Third time the timer fired at 2,25 seconds, UI was updated with the rounded 2 seconds. Fourth time the timer fired at 3 seconds, UI was updated with the rounded 3 seconds. Fourth time the timer fired at 3,75 seconds, UI was updated with the rounded 3 seconds. Even if the timer component is spot on it can be seen that every 3 seconds, for 2 seconds the elapsed time does "not update"... thus the feeling of variable speed. After upping the sampling to 1000 msec instead of 750 and some small tweaks to the conversion everything seems to be working fine. Why it was working on the TPanel...? Because originally I forgot to change the default 1000 msec interval to 750... What a nice way to waste a day by debugging something, which is working as it should πŸ™‚
  20. aehimself

    Excel to DBGrid

    If you have Excel installed where the program will run you can use the COM API to interact with Excel files from your Delphi app I think. I personally never used any of these but I know it can send E-mails with Outlook so I suppose you can use Excel too. From there it's easy as a pie. Just do a loop, dataset.Append; dataset.FieldByName.AsString := excelcell; dataset.Post. @FPiette has my preferred answer too. Just export to CSV / TSV (which I personally prefer) and it's really easy to parse those with Delphi.
  21. Hello, On my development PC Delphi 10.4.2 stopped displaying the tooltip with the parameters and their types when a bracket was opened. E.g.: I compared the Code Insight settings with a PC where it is showing up properly and they seem to match. Currently I'm using these: I remember that in the past unchecking something - reopening Delphi - re-checking something - reopening Delphi solved this (my hunch is on Code template completion... unsure though) but I cannot seem to get this tooltip back alive now. Is there something I still can try before dropping my registry entries and start to reconfigure the IDE from ground up?
  22. aehimself

    Which setting enables this feature?

    Thank you @corneliusdavid I didn't know about the shortcut! Strangely enough it triggers with the keyboard but despite the state of the setting it does not. I was afraid of this, this usually means to start again with a clean registry profile 😞
  23. aehimself

    Delphi compatibility with Windows 11?

    It is a VM running on ESXi, with tools installed. Transparency is visible even through RDP. In general, windows do not have rounded corners, just some special ones (like the Start thingie, dialogs in Settings, etc.)
  24. aehimself

    Delphi compatibility with Windows 11?

    Seems it works πŸ™‚ Funny thing is that I'm sure that the N45L CPU is not supported (plus there's no TPM in ESXi VMs) but the insider preview installed without complaints.
  25. Hello all, I've seen discussions about how to properly receive binary packets through the network. I even had my share of mistakes with my first implementation so I decided to create a class to do the heavylifting: receiving data chunks and assembling the packets. Feel free to use, improve and build upon. Keep in mind that 1, Packet is referred to the data sent by the client, not TCP packets! 2, The code is NOT thread safe! 3, Memory allocation is inefficient and can be improved. In my case (really low amount of packets) it's not an issue but the internal data storage easily can be replaced with a stream for example uBinaryPacket.pas
Γ—