-
Content Count
2563 -
Joined
-
Last visited
-
Days Won
134
Everything posted by Anders Melander
-
Why on earth are you using RegEx at all? Just use one of the many existing functions or bake your own: function ValidateChars(const Value, ValidChars: string): boolean; begin for var v in Value do begin var Valid: boolean := False; for var c in ValidChars do if (c = v) then begin Valid := True; break; end; if (not Valid) then Exit(False); end; Result := True; end; Also consider using character classes. See TCharHelper in the System.Character unit.
-
F11 does not show the Object Inspector in the Form Designer
Anders Melander replied to PeterPanettone's topic in Delphi IDE and APIs
Hardly. Just press Enter instead or press F11 one more time. -
Can you blame them?
-
Translations of the exception notification dialog text
Anders Melander replied to dummzeuch's topic in Delphi IDE and APIs
For Delphi 10.4 The dialog is TEXCEPTIONNOTIFICATIONDLG in dbkdebugide270.* (bpl, de, fr, ja). The string is resourcestring 65448 in the same file. I don't know the name of the resourcestring since I don't have the .drc file. I can send you a translation project with all four languages if you like - Or I can just explain how to get them yourself. English: "Project %s raised exception class %s with message '%s'." German: "Im Projekt %s ist eine Exception der Klasse %s mit der Meldung '%s' aufgetreten." French: "Le projet %s a déclenché la classe d'exception %s avec le message '%s'." Japanese: "プロジェクト %s は例外クラス %s (メッセージ '%s')を送出しました。" I was briefly tempted to replace the Japanese with something amusing 😈 -
I mostly agree; Tag is often the mark of poor workmanship. When used at design-time you have to assign magic numbers with "hidden meaning" and it can very easily become a nightmare to maintain. The same goes for the GroupIndex property. For run-time though I'm not that concerned with it as long as the use is very limited. Sometimes you just want to get on with the the task at hand and using a dictionary to associate a handful of controls to some context can seem like overkill. That said, use of Tag definitely goes against my primary rule of development: Don't be lazy
-
Versatility comes at a cost. You can use an external TDictionary<TButtonItem, WhatEver> if you need to associate additional data.
-
Use the TButtonItem.Data property instead - or TButtonItem.Action.Tag?
-
Search for Usages not usable
Anders Melander replied to PeterPanettone's topic in Delphi IDE and APIs
Sometimes it works, sometimes it doesn't. https://www.merriam-webster.com/dictionary/-ish But I agree that it's mostly broken. Sure. I don't know why we need both Search for Usages and Find References though. It seems to me that Find References is better integrated - and it isn't as broken 🙂 -
Search for Usages not usable
Anders Melander replied to PeterPanettone's topic in Delphi IDE and APIs
Like I said: It work-ish -
Search for Usages not usable
Anders Melander replied to PeterPanettone's topic in Delphi IDE and APIs
Completely useless? It's not a new feature and it used to work-ish so it's probably just broken in 10.4. Maybe you can use "Find References" (Ctrl+Shift+Enter) instead. It also works sporadically in 10.3. I don't know about 10.4 though. Personally I always just do a Find In Files. Much more reliable. I guess once they have ironed out the worst LSP bugs Search for Usages and Find Reference can replace that. -
There are plenty of them here. It would be interesting to hear a Yea or Nay from some. My understanding is that the only reason commercial component vendors ship run-time packages is to cater for users that build their applications with them - i.e. run-time linking. That is a separate problem with a very simple solution: It may not be typical but that is exactly the way to do it. By having the component source in the project path instead of the global path and by linking against the project's local copy of the dcu you avoid duplicate dcu and version conflicts. The project I'm working on right now has something like 20-30 different branches under active development. I change my active branch maybe twice that amount during the day. If I were to work by your model every time I changed the active branch I would need to recompile the close to 100 different design- and run-time packages related to this project, including 3rd party packages. What I do now is just change the branch and keep on trucking. And that's just on my local machine; I would need to do the same on all the build servers since apparently they have also been compiling and linking the wrong way all these years.
-
Possible custom Format types?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
Hmm. Looking at that RegEx I just realized that I forgot to handle the asterisk parameter specifier in my own code. To fix replace all three occurrences of: while (Result[n].IsDigit) do Delete(Result, n, 1); with: if (Result[n] = '*') then Delete(Result, n, 1) else while (Result[n].IsDigit) do Delete(Result, n, 1); -
Possible custom Format types?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
Wise decision. They are fun to write but a nightmare to maintain. -
I'm contesting the requirement to use run-time packages on the basis that I've written hundreds of components and I don't think I've ever had to use run time packages. There might have been cases where code was shared between different design-time packages, but that has apparently been so rare that I'm not sure if I remember it correctly. I can't find any documentation that backs your claim (if I've understood you correctly) that the component must go into a run-time package regardless if you use run-time packages or not. I agree that design-time editors (and component registration) go into design-time packages but unless you make the (often bad) choice to build your application with run-time packages there is no need to put the component into a run-time package. Who/what will use that package? The IDE will only use it because you've forced it to do so by creating a dependency from the design-time package to the run-time package. Yes, I expect the project to either have the pas or the dcu in the search path and I expect the compiler to static link to the dcu. The design-time package isn't bypassed. It's used by the IDE and only by the IDE - at design-time.
-
Possible custom Format types?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
It depends on what I use the string for afterwards. For example if I need to compare with another string I just trim consecutive spaces down to a single. If I need to parse out the individual words I leave the spaces there since the parser will skip over them anyway. The function is for use in a translation tool. AFAIR it can also remove shortcut accelerators, () [] {} <> pairs and punctuation .:;? etc. -
Possible custom Format types?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
'%%' -
Possible custom Format types?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
You can find a function to strip out format specifiers (among other things), including the index, width and precision stuff, here: https://bitbucket.org/anders_melander/better-translation-manager/src/a9e47ac90e7f80b67176cdb61b72aa34f4a8f165/Source/amLocalization.Normalization.pas#lines-306 The code as-is replaces %... with space to make the result readable. This is the relevant code: Result := Value; // Find first format specifier n := PosEx('%', Result, 1); while (n > 0) and (n < Length(Result)) do begin Inc(n); if (Result[n] = '%') then begin // Escaped % - ignore Delete(Result, n, 1); end else if (IsAnsi(Result[n])) and (AnsiChar(Result[n]) in ['0'..'9', '-', '.', 'd', 'u', 'e', 'f', 'g', 'n', 'm', 'p', 's', 'x']) then begin Result[n-1] := ' '; // Replace %... with space // Remove chars until end of format specifier while (Result[n].IsDigit) do Delete(Result, n, 1); if (Result[n] = ':') then Delete(Result, n, 1); if (Result[n] = '-') then Delete(Result, n, 1); while (Result[n].IsDigit) do Delete(Result, n, 1); if (Result[n] = '.') then Delete(Result, n, 1); while (Result[n].IsDigit) do Delete(Result, n, 1); if (IsAnsi(Result[n])) and (AnsiChar(Result[n]) in ['d', 'u', 'e', 'f', 'g', 'n', 'm', 'p', 's', 'x']) then Delete(Result, n, 1) else begin // Not a format string - undo Result := Value; break; end; end else begin // Not a format string - undo Result := Value; break; end; // Find next format specifier n := PosEx('%', Result, n); end; -
No one has mentioned run-time packages except you, so where does that requirement come from? Again I'm puzzled why you keep explaining these things. I'm pretty sure you must be aware that I know all this already. Besides that your explanation is wrong. The form will load just fine since the component unit has been linked directly into the application because it's not in a run-time package.
-
That's pretty easy: RecreateWnd is part of the documented public API. CM_RECREATEWND is undocumented. The VCL core is the implementation of the API so there's no surprise there. No I am not. I said "it seems" so I'm talking about appearances. I have no idea about why you do what you do so I can only guess. Calm down. I'm free to state what I think he means since it seems you misunderstood what he said. There is no conspiracy here and we're not all out to get you. We just disagree with you.
-
I think the point is that you are violating the API contract; You are supposed to call the API but instead you are circumventing the API and calling the implementation directly - for no good reason. Sometimes there are good reasons to do so but this isn't one of them so it seems you are doing so just because you can, because you don't know better or because you are stubborn. There are multiple definitions of perverse. In this case I think David meant obstinate in opposing what is right, reasonable, or accepted (from Merriam-Webster).
-
The OP asked for design time functionality. I replied with a design time solution and stated that there's no need for a run time package, so I don't understand what you are arguing about; You are the only one mentioning run-time executables. Here's a complete solution in a single design-time package: The component unit: unit amAwesome; interface uses Classes; type TMyAwesomeComponent = class(TComponent) // You awesome code here end; implementation end. The design time unit: unit amAwesomeDesign; interface procedure Register; implementation uses Classes, VCL.Dialogs, DesignIntf, DesignEditors, amAwesome; type TMyAwesomeComponentEditor = class(TComponentEditor) public function GetVerb(Index: Integer): string; override; function GetVerbCount: Integer; override; procedure ExecuteVerb(Index: Integer); override; end; procedure Register; begin RegisterComponents('Awesome', [TMyAwesomeComponent]); RegisterComponentEditor(TMyAwesomeComponent, TMyAwesomeComponentEditor); end; procedure TMyAwesomeComponentEditor.ExecuteVerb(Index: Integer); begin var LocalIndex := Index - inherited GetVerbCount; case (LocalIndex) of 0: ShowMessage('TMyAwesomeComponent 1.0'); else inherited ExecuteVerb(Index); end; end; function TMyAwesomeComponentEditor.GetVerb(Index: Integer): string; begin var LocalIndex := Index - inherited GetVerbCount; case (LocalIndex) of 0: Result := 'About...'; else Result := inherited GetVerb(Index); end; end; function TMyAwesomeComponentEditor.GetVerbCount: Integer; begin Result := inherited GetVerbCount + 1; end; end. The design time package source: package AwesomeSuite; {$R *.res} {yada yada yada lots of options here...} {$DESIGNONLY} requires rtl, designide; contains amAwesome in 'amAwesome.pas', amAwesomeDesign in 'amAwesomeDesign.pas'; end.
-
There's no requirement for both run- and design-time packages. A design time package alone is enough. Assuming you mean component editor the purpose is to separate run- and design-time functionality. The end-user doesn't need to know that the application uses TAwesomeComponent version x.y.z and there's no need to include the about form in the compiled application.
-
Yes of course and it does but ShowHint controls if the control supplies hint text when the mouse hovers over the control. If it doesn't then it will try to get the hint from the parent control, etc. The help is pretty clear on how it works.
-
Okay. What you need is a component editor. With this you can specify what happens when the user double clicks your component (at design time) and you can add menu items to the context menu. For example a "About My Awesome Component..." menu item. The help is a bit sparse on how to implement a component editor for VCL (there's a good example for FireMonkey though) but there's plenty of examples available on the net: https://www.google.com/search?q=delphi+component+editor There might also be an example installed with Delphi.
-
Don't do that. You're trying to eliminate the symptoms of a problem somewhere else in your application. Hint/ShowHint works just fine. If you manage to "hide" the problem by setting ShowHint=False then you will just have removed the only lead you currently have to the underlying problem. By the way, ShowHint does more than controlling if the control displays hints. It also controls if the child controls display hints - if Child.ParentShowHint=True. You usually set ShowHint=True on the form and then ParentShowHint=True on all child controls. Setting ParentShowHint=True just means that the parent ShowHint value propagates down to the child control. Anyway, what I would do is install MadExcept and configure it to "Instantly crash on buffer overrun". I'm guessing you have a stale pointer or a memory overwrite somewhere.