-
Content Count
1090 -
Joined
-
Last visited
-
Days Won
23
Posts posted by aehimself
-
-
5 hours ago, Lars Fosdal said:There are numerous Unicode white space chars of varying width, so adjusting the distance "by character" is possible.
In my opinion, just because there's a possibility to do something doesn't mean you should use it 🙂
2 hours ago, Rollo62 said:Don't mess with youself too much,
if Microsoft shows not any attempt to make these controls practically more usable since the last 20+ years, why should we do ?2 hours ago, Sherlock said:And in the end, what is the effort worth? Just to say: "In my product 1+1 is still 2 but it looks better than the others".
I do understand and agree with you on this. But it's not for the others, it's because of my own self.
I just don't want to produce code I don't like or as "time-resistant" as I can think of. Whilst it's a good thing it's a curse as well... I can easily waste hours on a single "Hello World" application this way.
-
1
-
-
No insult taken. My attention may have slipped - I did not see the static part and for that I apologize.
For the record, my intention was not to argue: I just had to refactor too many lines of code (written 10-15 years ago) which broke or misbehaved on specific modern systems. The days-weeks wasted there taught me to proudly waste hours when I write fresh code which will still work the same way everywhere in the foreseeable future.
Do I still have "hacks" like this in production? Hell yes, I do. Do I hate myself for it when I see it? That's a question for a different topic 🙂
-
2
-
-
@rcaspers I had no idea you can "override" default TField types. Would have made my life a lot easier a couple of years ago!
@Max Terentiev You can easily do the conversion by TEncoding.Convert, GetBytes and GetString. However, the easiest solution would be to upgrade the component you are using to one, which actually supports Unicode. If they are all TDataSet descendants, you should face no issues.
If upgrading is not an option, I'd create a TFieldHelper with an .AsUnicodeString property.
Getter would read the fields value as a byte array, and return it as a String with TEnoding.Unicode.GetString(fieldbytearray);
Setter would accept a string, convert it to a byte array with TEncoding.Unicode.GetBytes and strore this instead of the string.
-
6 minutes ago, Attila Kovacs said:btw. how did you separate the words back in the high school?
I might not phrased myself correctly - forgive me; English is not my native language. The point is, you know exactly what I meant by "distancing". Let's play adults and not starting to argue on choice of words.
-
1
-
-
2 minutes ago, Attila Kovacs said:what is your problem?
Nothing, really. As smart people say "if it works it ain't stupid". It's a perfect quick-and-dirty solution which will achieve what you want in this, very specific project and configuration.
Lately I like to think in general solutions, that's all. And that is custom drawing.
-
On 7/8/2020 at 5:09 PM, Attila Kovacs said:Caption = ' Unga'#13#10' Bunga'
WordWrap = True
Holy Frank, this smells. I already learned not to use whitespaces for distancing back in high school.
And while it might work - can you please check if the above functions correctly if "Width = 30" for example?
-
10 hours ago, Remy Lebeau said:GetMem() operates on bytes, but s.Length is expressed in characters, not bytes, and SizeOf(Char) is 2 bytes in D2009+, so you need to double the allocation, otherwise you will have a buffer overflow on StrPCopy(), corrupting surrounding memory, which can lead to all kinds of problems, including leaks of other things that were allocated dynamically, if you corrupt the pointers to them:
That was exactly my purpose 🙂 Don't worry, this is only for testing and satisfying my curiosity.
10 hours ago, Remy Lebeau said:It is likely that one of the pointers you are corrupting may be the one used by 'pc' or 's' itself!
I guess this will be the cause of the "leak". Today, I attempted to check the addresses of pc and s, and I can not seem to trigger a memory leak, nor access violation even with StrPCopy(pc, s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s + s);
maybe today I have more free continuous unused memory than the last time...
It makes sense, though. If by accident I managed to corrupt the pointer itself, the release will not happen at the right place (or maybe not happen at all?). I just cannot seem to find what the 3rd leaked allocation might be.
Anyway, memory corruption is no job for an allocation detection tool. I just found it strange that sometimes even these were triggered.
-
We are getting close to the next release so time is not that much to spare, but I managed to run my test. DeLeaker shows about the same results with 1, 2 and 5 copies of "s".
I am no expert with memory leak detection in Delphi, but can someone explain this to me?
On 6/25/2020 at 10:18 PM, aehimself said:Var pc: PChar; s: String; begin s := 'Hello, world!'; GetMem(pc, s.Length + 1); Try StrPCopy(pc, s); Finally FreeMem(pc); End; end;
No leaks, however (on a Unicode Delphi) this used up twice as much space as it was reserved. Fine, it's not a leak (as it is properly released), it's corruption. But why StrPCopy(pc, s + s); already pops up as leak in this case?
-
18 minutes ago, Skullcode said:current i use this function is it fine or more correction needed ?
Function Checkstr(const astr: string):Boolean; var Regexs : TRegEx; i : integer; svalue : string; Allowed : string; begin svalue := Trim(astr); for i := 1 to Length(svalue) do begin if Regexs.IsMatch(svalue[i], '^[ء-يA-Za-z0-9$&+=?@#~<>.^*()%!\s]+$') then begin Allowed := 'YES'; end else begin Allowed := 'NO'; Break; end; end; if Allowed = 'YES' then begin Result := True; end else begin Result := False; end; end;
Ummm.... Why make a string?
Why not getting rid of Allowed and setting Result directly? Why going through character by character if Regex can validate the whole string at once?
If I'm not mistaken you'll achieve the same with this one line:
Result := Regexs.IsMatch(svalue.Trim, '^[ء-يA-Za-z0-9$&+=?@#~<>.^*()%!\s]+$');
-
1
-
-
4 hours ago, MDagg said:Besides, I am not seeing a RJ45 for Ethernet connection, or RS232 serial which would definitely exclude it from PLC modbus use as a master sub module and that is key in embedded designs for controls and general SCADA.
According to the initial specs it has an USB - which can host both. But this immediately adds a USB hub / USB NIC / serial to USB to the price in a real-world application.
I don't know how well USB handles dusty, hot and or moist environments though to call this reliable.
-
1 hour ago, David Schwartz said:I started my professional career working with embedded systems for nearly a decade, so I guess that's why hardware like this catches my eye. This isn't particularly useful for ordinary office tasks or testing or anything like that. But it would be great for a standalone kiosk, or some kind of dedicated application.
A kiosk is - usually - a larger hardware, allowing the manufacturer to stuff in standard PC / laptop parts. In case something goes bad, they can swap it without changing the whole thing. This allows less downtime, cheaper and quicker repairs - probably happier customers.
1 hour ago, David Schwartz said:Today you can get a Raspberry Pi for under $50, sure, but you can't build stuff that runs on it with all versions of Delphi.
There is always a way, we have way too many (not that ethical) ethical hackers and hardware nerds (and I say that in the most positive meaning); it's only a matter of time when one of them decides to do it. Win10 IoT Core seems to be installable on an Rpi:
https://www.techrepublic.com/article/windows-10-on-the-raspberry-pi-what-you-need-to-know/
I never used an Rpi (I'm more of an Arduino person), so it's possible that it's outdated or not working anymore. Take it with a grain of salt, this was just the first Google hit.
1 hour ago, David Schwartz said:This little box includes Win 10, and for the price, the hardware is practically free
Now I don't want to start anything in this topic, but even I received officially purchased hardware, coming with the software on an unlabeled CD-R with a readme file stating "Execute the ... application in the \Crack folder". I have absolutely no experience with Chuwi per se, so I might be damn wrong and in that case I immediately apologize for assuming. All I'm saying, they are located where most of the AliExpress sellers are 🙂
1 hour ago, David Schwartz said:I've always had this vision of little functional building blocks, like "smart" Lego blocks, that perform specific functions and can be plugged into a network and used to solve specific problems.
It's called IoT. It exists. The difference is, they have dedicated hardware for one specific task. This makes production cheaper, devices sucking less power. For comparison: Arduino is running a standard ATMega chip. An Arduino can be connected to the TCP/IP network. With a bit of soldering, you can "build" your own Arduino and upload your projects on a single chip (on 8 Mhz, for 16 Mhz you need a crystal and two capacitors, too). If you do power management right, those beasts are using picowatts, allowing them to be able to run on batteries.
Specialized hardware will beat general hardware in price, space and parts required and power consumption.
I'm not going to quote the whole "car" thing, I'll just say "bluetooth". Most cars already have it, or can have it with a really cheap adapter. And why on Earth I would want to be able to read my E-mails in my car?! I should keep my eyes on the road and I already spend too much time "connected" - if you know what I mean.
Reading this post back I admit that it sounds offensive, but believe me - there's none. I'm just saying these overminimized PCs are usually good for one thing: thin clients. Cheap, no clutter on your desk, the unbeatable processing power comes from a server room from 3 racks.
I'll never buy something like this, but I'd be glad to play around with it if I'd get one for free. I'm a tech geek after all 🙂
-
I am fond of mini PCs. Love them. But - as always - it always comes down to the basics.
- What do I want to do with them? Use as a server? NAS? Replace my noisy and hot running PC?
- What kind of processing power it has and is it enough for my needs described in point 1? Two years later if the room gets too tight, what are my options? Complete replacement, or simple expansion?
- Power consumption, especially at 24/7 devices
- Pricetag? I'm not going to spend a month worth of salary for something that is just "good to have".
I own a HP ProLiant MicroServer G6 running ESXi, hosting my test environment. I have (severely underpowered) VMs running major Windows releases since 2000 and I am testing my apps on these. 24/7 availability is needed, as sometimes I code at 3 AM, sometimes at 8 PM depending on my mood and I don't want to wait for the system to start up.
This machine is with me for about 6-7 years, and was only turned off when I expanded the memory, cleaned out the interior or swapped the power supply out with a PicoPSU. Price is ridiculously low (especially now, when Gen10 is the latest and greatest), processing power is acceptable, with the power consumption of 50 watts peak; averaging around 30 with 1 SSD and 2 HDDs.
If I'd have to buy something like this again, I'd look in this area; not something what a startup company is attempting to crowdfund.
16 hours ago, David Schwartz said:I was thinking of it mainly for use with embedded or dedicated Delphi apps.
It's usually the other way around for me. I write an app which fulfills a job I want it to, and then install it on the machine where the job is done. I'm not writing something because I have a dedicated platform and I want to make use of it 🙂
-
1
-
-
I guess no.
LibMariaDB is a valid replacement; the question is, though, until how long they will stay compatible.
-
1 minute ago, Kas Ob. said:Multi-Threading
Damn, forgot about multithreading, too. +1 for that sharp eye!
14 minutes ago, Kas Ob. said:overflow it and have fun finding the culprit
I never actually thought about this. Running this on a Unicode Delphi shows no memory leaks (with ReportMemoryLeaksOnShutdown := True):
Var pc: PChar; s: String; begin s := 'Hello, world!'; GetMem(pc, s.Length + 1); Try StrPCopy(pc, s); Finally FreeMem(pc); End; end;
...but make it StrPCopy(pc, s + s); and you have 2 unknown objects leaked. Make it 5 times s and you have 3 unknown objects leaked. I could not find 4 unknown objects without an actual access violation.
I guess it's only the limitations of the shipped FastMM...? Since our company bought it, I'll run this code with DeLeaker tomorrow out of curiosity to see what it will say about it.
At the end of the day, however, we all can agree that memory corruption is a bit more serious issue, and - personally - I would not even consider it as a memory leak 🙂
Still, an interesting aspect!
-
21 hours ago, Remy Lebeau said:Which means the TBetFairApi object that is holding that UnicodeString is not freeing that UnicodeString properly.
Without manually modifying the pointer as you suggested and properly released owner... how exactly you can cause a memory leak with Strings?
I always thought records, arrays behave like interfaces and are automatically discarded when their lifetime is over.
-
In my personal experience, leaks pointing to some kind of a Sting routine are never the leaks you have to pay attention to. They are never the cause, they are the side effect - especially if the allocation is initiated in a in a component (let's hope 🙂 ). As @Kas Ob. said, most probably you forgot to release an instance which is keeping the reference count high. Unless if you are playing with reference counts yourself, that is.
And again supporting the statement above mine - I never had a leak which could be fixed in the same method. Because of messed up design, sometimes releasing the object had to go to a different unit!
Always handle allocation call stacks as a pointer only. You have to know what was allocated and why - and when that specific instance can be released.
-
48 minutes ago, David Schwartz said:I'm clicking and dragging from browser window A to the app, and I guess the http component looks like an unrelated browser window B.
That is exactly how it looks like from the webapp's perspective. A is logged on, B is not.
49 minutes ago, David Schwartz said:I guess Right-Click --> Save As ... runs in the security context of browser window A, but a drag&drop runs in the context of browser window B.
Well, not security context but it has a valid session open. But effectively yes.
49 minutes ago, David Schwartz said:I don't really want to force the user into a second login. That said, I could add Name + Pwd fields to this little app and save them, but that's getting into a very muddy area here....
I wonder if I can set up a proxy of some kind? They really should be the same context.
Having your username / password is always going to be way more easy. Normally session identifiers can distinguish between browser instances running on the same PC with the same user. Which means, even if you can "catch" that session ID somehow, it's not going to work from your Delphi app.
I'd just drop a TWebBrowser / TEdgeBrowser on a form, make the users use this program to use the ticketing system. From within the program you can easily get the page source, discover and download attachments automatically within the exact same session. Even without drag & drop.
-
You can try:
http(s)://ticketing.system.local/images/imagetobedownloaded.jpg?username={URL_Encoded_Username}&password={URL_Encoded_Password}
or, add a header to the request: Authorization=Basic {Base64_Encoded username:password}
or, if you are lucky, there will be a (now unhandled) onAuth event in the component. When it fires, you can set the username / password to access the resource.
These all require though that the system allows these kind of authentications. If you are unlucky, you still can "log on" first and then download the picture with the component. Just make sure you re-attach the session cookie in the second request.
-
1 minute ago, Kyle Miller said:I'll try using a connection per thread and possibly test out TZMethodThread.
One connection per thread is like an unwritten rule. I experimented with one connection for 7 workers, but gave the idea up quickly. One thing I found strange is that if I called dataset.Open in a background thread, I had to call .FetchAll too, otherwise it still froze the VCL thread upon accessing .RecordCount.
But the jumping between records error still makes me believe that the connection is going to be the issue - if FireDAC works similar to the components I use.
-
1
-
-
2 hours ago, Dany Marmur said:I'll have a good thorough read of the code above, and the link.
You don't need much time - it's about 200 lines 🙂 As I said I tried to keep it as simple as possible. If someone needs more, the code is easy enough to be extended with someone's own needs.
2 hours ago, Dany Marmur said:But i think that your/similar solutions somewhat needs to advertised and available to the community.
Completely agreed. That's one reason I chose to hand over the code to the Zeos team. I wrote a custom DB management app and I needed to keep the GUI responsive even if the user entered a hour-long query. That's when I came up with the idea of pushing it to a background thread. It does nothing though if you can not gracefully end it so aborting running operations was born.
I needed it to satisfy my colleagues needs using my tool and it felt good to finally give something back to the component I was using for long years now.
Effectively a win-win situation.
-
@Dany Marmur I used to have one but I decided to discontinue my own website as it started to be a burden to maintain. The idea is to be as simple as possible:
Type TProcedureOfObject = Procedure Of Object; TErrorEvent = Procedure(Sender: TObject; Error: Exception) Of Object; TZMethodThread = Class(TThread) private _runmethod: TProcedureOfObject; _onerror: TErrorEvent; protected Procedure Execute; Override; public Constructor Create(inMethod: TProcedureOfObject; inErrorEvent: TErrorEvent; inFinishEvent: TNotifyEvent); ReIntroduce; End; Constructor TZMethodThread.Create(inMethod: TProcedureOfObject; inErrorEvent: TErrorEvent; inFinishEvent: TNotifyEvent); Begin inherited Create(False); _runmethod := inMethod; _onerror := inErrorEvent; Self.OnTerminate := inFinishEvent; End; Procedure TZMethodThread.Execute; Begin Try If Assigned(_runmethod) Then _runmethod; Except On E:Exception Do If Assigned(_onerror) Then _onerror(Self, E); End; End;
And then there is a "wrapper" around this, where you just pass a dataset and it is creating a TZMethodThread with Dataset.Open for example. I hope I can say this and it's not considered an advertisement; the latest version of the unit is included in Zeos 7.3 (look for ZMethodInThread.pas) which is although "specialized" can easily be ported back to use a standard dataset.Or throw the wrapper out and just use the thread with any procedure of object - with the necessary caution to VCL synchronization, of course.
-
5 hours ago, Lars Fosdal said:Treat console apps like you treat VCL or FMX apps. Keep the actual code in units and have just the skeleton init and run code in the .dpr.
This is exactly what I started to do lately. All my applications business logics are basically a TObject-descendant, and service initializations or console launchers only create an instance of them.
I find this structure really easy to test, to port, to maintain or extend. This might be my own personal preference, though.
-
2
-
-
7 hours ago, Lachlan Gemmell said:hopelessly broken error insight we've been putting up with for the past 15 years
1 hour ago, mmb said:It definitely is better than 10.3 (which was just plain broken) but also <10.3.
This is something I can not c
ompare. The first thing I always did on a fresh Delphi installation is to disable error insight altogether as it made the IDE unbearable slow with 1500+ units and 20-30 custom components. Therefore I don't know how bad it was before - I had hopes with 10.4 and LSP - it did not come up to my expectations, unfortunately. I personally like Delphi's IDE a lot more than Visual Studio, but VS's error insight works a lot better (even with large projects), unfortunately.
It hogs up the system more too, though.
1 hour ago, mmb said:I am now at the point that error insight and code insight work reliably most of the time and wait times till red wiggles disappear is down to seconds.
When refactoring, I'm following these guidelines too. As least visibility to properties as absolutely needed, cutting out excess things from the Uses list, etc. As I said - unfortunately - my experience is far from yours. With a low number of units and 3rd party components wiggly lines are likely there to stay until execution / IDE restart 😞
Hopefully this week I'll start to check how Delphi 10.4 handles a big project at work... with poorly written code, interfaces here and there, 10+ depth in dependencies... that will be the true test, though. It will decide if we move or stay on 10.3.
-
I don't use FireDAC, but a 3rd party library to connect to databases, Unfortunately though, they work in async mode only, so a huge query with lots of blob fields could take up to a couple of hours (!!!) to load through the Internet.
God bless those SELECT * FROM ... JOIN ... JOIN ... JOIN ... type queries.
My solution was to unhook all datasets from any datasources, and call the dataset's .Open method in a separate thread, Once the thread finishes it executes a callback routine to hook the datasets back to the datasources. This resulted a completely unblocked VCL thread, and I even could implement a button to execute the "Abort" command through the same connection if the user does not want to wait until the end of the query.
You can create a custom TThread descendant with a parameter of a dataset, but I chose to take an incoming Procedure Of Object parameter instead. This way, I can execute the same thread with a Dataset.open, Dataset.Post or Connection.Commit when I please, leaving the application as responsive as ever.
Centered message?
in VCL
Posted · Edited by aehimself
For not that important applications I'm using MessageDlg, but for more advanced ones I always use my own "message dialog". Fully customizable, with a short (and if needed) an extended version of the message which is visible if the user clicks the down arrow. It uses the system's icons, but follows themeing correctly. I included a class function "Confirm" which returns a boolean and displays the dialog in "confirm" mode (question icon, yes and no buttons visible) and a .Error class procedure, which takes an exception and dumps as much information as possible in the extended text. I'm also planning to add a "Report" button to errors, which would send me an e-mail with the information collected; I was just too lazy to to do so until now (and I did not look for a component. Worst case, I'll implement my own lightweight SMTP client, idk yet).
Based on this logic I also created a multi-input form, where my application can request multiple inputs validated (number only, can be null, predefined values from a combobox, multi-line text, etc.
The problem is, this input form became so versatile and useful, most of my applications are heavily depending on it now.
So yeah, I completely support @haentschman in this. Just write your own, and you will have a truly cross-platform solution satisfying all your needs.