Jump to content

aehimself

Members
  • Content Count

    1096
  • Joined

  • Last visited

  • Days Won

    24

Everything posted by aehimself

  1. aehimself

    Send a message to App users??

    Sorry for my previous post being so blunt - I just had different matters to attend to and wanted to leave my comments. With the reappearance the issue is that if the user leaves his PC for half an hour, 30 dialogs will be shown as not even a modal window "blocks" processing further WM_TIMER messages. In these cases I'm usually wrapping the whole OnTimer event in a Timer.Enabled := False; Try [...] Finally Timer.Enabled := True; End; to make sure I'm not rendering my app in an unwanted state. As for the error handling even if this functionality is being used once in a lifetime it worths to add those extra 2-3 lines. Anything is more beautiful than the standard application error dialog πŸ™‚ Just my 2 cents.
  2. aehimself

    Send a message to App users??

    This code is completely missing error handling and does not consider access sharing and will read only the first line of the message. As an extra if the file is not deleted it will pop back up every 60 seconds. If {$I-}, use ERRORLEVEL to determine if the Reset was successful, if {$I+} swallow (or just politely indicate) the error. Wrap the Reset...ReadLn...Close to a Try-Finally bloc to ensure the file will be closed no matter what. As for access sharing you might want to use TFileStream instead with fmShareDenyNone.
  3. aehimself

    TPopupMenu with group headers

    @David Duffy I have no XE experience (went to 10.0-10.1 from 7) but you can fall back to the idea of @Lars Fosdal safely: TStyleManager is only used here to extract colors of the currently active style so the header will always "fit in" nicely.
  4. aehimself

    Delphi 11: Text size too small!

    Seriously, wtf...
  5. aehimself

    TPopupMenu with group headers

    Does anyone know what is the name of Delphi's menueditor? I only could find it in FMX but I guess I should be looking at the VCL version. It would be nice to extend it so it is capable of adding header items.
  6. Hello, We had a large legacy component suite which I managed to split into Runtime and Design time packages in preparation to be able to build our application in 64 bit. I don't have much experience, so what I did was, basically: - Created a new package, set it as runtime only, moved all contains and requires section from the old suite - Created a new package, set it as design time only - Attempt to compile the runtime package - Move units to the design time package which blocks compilation (has references to designide, etc) - Repeat until both packages compiled error free - Added "implicitly imported" units to design time package All works fine, except one strange issue. Delphi chooses a seemingly random unit and throws an Internal Error when I want to install the package (compiling works fine both in 32 bit Debug / Release). Here's the twist: if I close Delphi, modify the unit with VS code and add a line break to the end of the unit (or remove one - basically change something completely insignificant) and save, reopen and install - all works just fine. I'm wondering if I missed something when creating the packages? Did anyone face this before? Does anyone has any tips I can check? Thank you!
  7. It seems so far that I solved the issue, the Internal Errors are gone - at least I can not reproduce them no matter how hard I abuse switching branches (where the component suite is the old) or building-installing. What I ended up doing was to have a runtime package, a design time package for component installation in the IDE and one more design time package for the property editors. This didn't work until I realized I set the required package of the property editors to the runtime package. In the moment I changed this so the property editors "only" require the first design time package, all started to work. During the trial process I also trashed several old units which function is now covered by Delphi itself and corrected some programming issues too but the error itself went away by changing the required package. I don't know what caused the issue at the first place (and more importantly why it went away...?) but this can be a possible solution too.
  8. aehimself

    TPopupMenu with group headers

    I ended up combining the code of @chkaufmann and @Lars Fosdal plus added the always-disabled property. The end result fully supports VCL styles and looks awesome! The full code became: Unit uHeaderMenuItem; Interface Uses Vcl.Menus, Vcl.Graphics, WinApi.Windows, System.Classes; Type THeaderMenuItem = Class(TMenuItem) strict private Procedure SetEnabled(Const inEnabled: Boolean); Function GetEnabled: Boolean; protected Procedure AdvancedDrawItem(ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState; TopLevel: Boolean); Override; Procedure DoAdvancedDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState); Procedure Loaded; Override; Public Constructor Create(AOwner: TComponent); Override; published Property Enabled: Boolean Read GetEnabled Write SetEnabled; End; Implementation Uses Vcl.Themes, System.SysUtils; Procedure THeaderMenuItem.AdvancedDrawItem(ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState; TopLevel: Boolean); Begin Self.DoAdvancedDrawItem(Self, ACanvas, ARect, State); End; Constructor THeaderMenuItem.Create(AOwner: TComponent); Begin inherited; Self.Enabled := False; OnAdvancedDrawItem := DoAdvancedDrawItem; End; Procedure THeaderMenuItem.DoAdvancedDrawItem(Sender: TObject; ACanvas: TCanvas; ARect: TRect; State: TOwnerDrawState); Begin ACanvas.Brush.Color := TStyleManager.ActiveStyle.GetStyleColor(scPanelDisabled); ACanvas.FillRect(ARect); ACanvas.Font.Color := TStyleManager.ActiveStyle.GetStyleFontColor(sfWindowTextNormal); ACanvas.Font.Style := [fsBold]; ACanvas.TextRect(ARect, ARect.Left + 3, ARect.Top + 3, StripHotkey(Caption)); End; Function THeaderMenuItem.GetEnabled: Boolean; Begin Result := inherited Enabled; End; Procedure THeaderMenuItem.Loaded; Begin inherited; Self.Enabled := False; End; Procedure THeaderMenuItem.SetEnabled(Const inEnabled: Boolean); Begin inherited Enabled := False; End; End.
  9. My theory doesn't seem to work. I created a second design-time package and moved the property editors there as some property editors were using components which are to be installed in the very same package... no luck. Now the component package installs just fine, the package containing the property editors are throwing the errors. I read that the code in property editors have to be extra clean (no WITH statements, no "confusing" parts for the compiler) so I made a cleanup there too.
  10. aehimself

    RAD Studio 10.4.2 crashes upon exit

    We had this issue at work, the root cause was a poorly written in-house IDE plugin. As others already mentioned - start uninstalling / disabling plugins and then component suites. You'll quickly find the culprit.
  11. aehimself

    TPopupMenu with group headers

    @chkaufmann This looks awesome! Btw add Vcl.Themes to your uses list and use TStyleManager.ActiveStyle.GetStyleColor and GetStyleFontColor to add VCL style support to your code. Questions, though: - If you hover your mouse on the header does it get highlighted? I guess not because state is ignored in general but worth to ask... - This is my bigger issue: clicking on a header will close the menu, right? Maybe this can be fixed by overriding protected methods of the TMenuItem / TPopupMenu
  12. 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...
  13. 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 πŸ™‚
  14. aehimself

    Locate

    cds.Filter := 'MyField LIKE ''%contains%'''; cds.Filtered := True; ?
  15. 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.
  16. You mean a font is not meant to be installed runtime or not to be drawn with GDI+?
  17. 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.
  18. 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!
  19. 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?
  20. 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;
  21. 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.
  22. 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.
  23. 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.
  24. I added auto-close as an option now πŸ™‚
  25. 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...?
Γ—