Forum > Beginners

Microexamples

(1/4) > >>

Spoonhorse:
FPC's great and all but it's very hard to find out how to do stuff in it. A lot of the time when I Google some feature the top hits aren't the documentation (because what even is that? ) but people on message boards bickering about some abstruse detail of the feature and whether certain wicked people are betraying an unholy love of C dialects.

Then when I do find something it's often howlingly bad, even I can see that. Things done with people's handful of known hacks, without insight. I was trying to find out how to turn off Paste in TEdit and TMemo. Suggestions included "make any key event erase the contents of the clipboard", "use the key events to erase the Shift state when the user presses Ctrl" and this absolute monstrosity. I believe that it works, I believe that the author was proud of it.

And then there's the obstacle presented by the "good" code I find on the Internet.

I put "good" in quotation marks because the one good coding practice it never seems to follow is proper commenting. If you're going to show something to other people, please please explain how it works, otherwise you're just saying "and here we chant the mystic runes" and I and everyone else who reads it are left with something we can neither understand nor modify.

(This is, I think, how some of the bad code happens. Features of the good code are retained when it's modified even though the modification makes them unnecessary. Rinse, repeat.)

In other ways the good code is often obnoxiously good in that the actual point I'm trying to get to is hidden under excellent software engineering. The author will kick off by defining the public constants that the user should use when setting the property of the component that's going to control the behavior ... and then goes on through the exception handling ... and so on down to the end where the author says where to register the component.

Meanwhile what I want for my own purposes are the handful of lines that actually do the clever thing. Instead I'm being presented with a complete solution to something different from what I want to do and I have to start digging for these lines, which will not be marked as the particularly useful bit, or explained in any way.

What one needs is the exact opposite, a minimal example which is thoroughly explained. Like this.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// The OS sends messages to the visual components which we can intercept by// overriding the WinProc method of the class. // (For historical reasons everything related to this feature including the names// of the constants is Windows-related but the feature is not in fact OS specific.) // This example is implemented as an interposer class, see// https://forum.lazarus.freepascal.org/index.php?topic=54971.msg408998#msg408998// for more details. unit NoPaste; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, StdCtrls, Windows; type  TEdit = class(StdCtrls.TEdit)  protected      procedure WndProc(var M: TMessage); override;  end; implementation   procedure TEdit.WndProc(Var M: TMessage);  begin  if M.msg = WM_PASTE then M.msg:=WM_NULL;   // We turn off the message ...  inherited;   // .. and then go ahead and do what the method would usually do.  end;end. // You can use it to turn off any of the other Windows messages to any// components (a list of the messages can be found here:// https://wiki.winehq.org/List_Of_Windows_Messages ) and indeed// to do things other than just shutting them off, though that alone// could be done with nicer syntactic sugar using the "message" keyword.
This tiny bit of code which can easily be understood and repurposed is way more useful to someone who stumbles across it than a good bit of code that can't. I shall be putting some more stuff here, I've found out some gritty technical things about messing with TEdit and TMemo and TRichMemo, of which the bits other people need to know could be distilled down to five or six snippets of code which are much more readable than my source.

I wish more people could do the same. Perhaps they all have already and it's all sitting in a repository I don't know about.

Spoonhorse:
One more example-of-an-example tonight to show what I'm talking about. Let's learn how to mess with the input field of a TEdit, changing the user's input like an autocorrect or autocomplete. Similar techniques will work for a TMemo or TRichMemo. (More about that later.) As in the previous example, this is implemented as an interposer class, because no-one would want it as-is.

So there are two parts to knowing how to do this. The first is knowing where to do it. Trying to do it using the event handlers simply doesn't work so well, try it if you don't believe me. This Is The Way. (I'll explain why if anyone's interested.) Second, when you reset the Text field of a TEdit the OS "helpfully" puts the cursor at the start of the TEdit. We need to put it where it should be. We can do this by assuming that the change took place just behind the cursor. Then after the change has been made we need to put the cursor back where it was and then increase its position by the difference between the new length of the string and the old length. High school algebra should show you that this is what the expressions in the code do.

I'll talk about why we're using the UFT16 length later. If you don't do that, see what happens if you use some of the higher-range Unicode characters, such as Chinese.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit SmartEdit; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, StdCtrls, StrUtils, LazUTF16, Windows; type  TEdit = class (StdCtrls.TEdit)  protected    procedure TextChanged; override;end; implementation procedure TEdit.TextChanged;var offset: integer;beginoffset:=SelStart-utf16length(Text);Text:=replacestr(Text,'x','yy');SelStart:=offset+utf16length(Text);end; end.
The code given will slickly and seamlessly turn 'x' into 'yy'. Anyone who wants to do anything else with it can take it from there much more easily than if I'd posted code that does something useful.

dbannon:
Hmm, looking at your first example, I wonder how cross platform it is ?   8)

https://wiki.freepascal.org/Portal:HowTo_Demos might be usefull.  But honestly, to expect a nicely packaged snipit for every specific problem is probably a bit optimistic.

But don't let that put you off !

Davo

Spoonhorse:
dbannon, I haven't tested that because all I have is this one laptop BUT as I say in the comments, the fact that the thing uses Windows terminology is just a historical relic presumably left over from Delphi days, according to the documentation stuff I found on the Internet Lazarus is set up so the same messages are passed by every OS.

And no, there's not going to be a snippet for every problem but if people are going to solve problems and then tell people about the solutions on the Internet they could consider doing it in the most snippety way possible.

Kays:

--- Quote from: Spoonhorse on June 15, 2021, 12:08:11 pm ---[…] I was trying to find out how to turn off Paste in TEdit and TMemo. […]
--- End quote ---

--- Quote from: Spoonhorse on June 15, 2021, 01:00:07 pm ---[…] the input field of a TEdit, changing the user's input like an autocorrect or autocomplete. […]
--- End quote ---
I think you’re looking for recipes, a “cookbook”, not what you call “micro-examples”. The documentation and textbooks do contain “micro-examples”, source code (fragments) explaining individual details, but alone they aren’t that helpful if you’re trying to solve problems like you want, because you have to arrange multiple steps in the correct order, you know. That’s a “recipe” to me, and I’m afraid there is simply no Delphi-specific cookbook available (via the internet, for free).

Navigation

[0] Message Index

[#] Next page

Go to full version