Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 10/07/24 in all areas

  1. Although, I just had to check because I thought it was a little old... are you sure the listing is right? 10.14 Mojave is an Intel OS released 2 years before the M1 machines. I'd expect it to be macOS 11 Big Sur at a minimum.
  2. Yeah, lots of hidden gems have been added over the years. I don't always read everything in the "What's New" section and also occasionally discover features that have been there for a while! It wouldn't be the underlying database structure but how they're accessed. I often get this type of warning when upgrading old applications (Delphi 5/7/2007) to newer versions where string fields were assigned like this: procedure UpdateValues(const NewValue: string); begin MyTable.StrField.Value := NewValue; ... The .Value property is AnsiString; simply changing it to use the explicit type eliminates the warning: procedure UpdateValues(const NewValue: string); begin MyTable.StrField.AsString := NewValue; ...
  3. Kazantsev Alexey

    Items of custom managed records

    program Project1; {$APPTYPE CONSOLE} uses System.Rtti; type TvatIndividual = record DocumentNumber: string; TurnoverDate: TDate; PaymentDate: TDate; DocumentType: string; Year: integer; TurnoverDescription: string; TurnoverAmount: Currency; end; begin for var f in TRttiContext.Create.GetType(TypeInfo(TvatIndividual)).GetFields do WriteLn(f.ToString); ReadLn; end.
  4. Brandon Staggs

    Old Window border style on Delphi MDI child form

    That looks like a straw man to me. It may be true that MDI is not technically deprecated, but it seems to exist in a state of de-facto deprecation. MDI is a strange middle place between Mac's windowing model and the Windows windowing model. Other than supporting legacy applications, I can't see why anyone would use it. A decent docking system should easily replace any perceived benefits of an MDI paradigm.
  5. Uwe Raabe

    Old Window border style on Delphi MDI child form

    Well, no official announcement from MS, if you are looking for something like this. The source is the shear lack of proper support in Windows itself. One can talk and write a lot or not - in the end it is facts that count.
  6. Remy Lebeau

    Old Window border style on Delphi MDI child form

    It is a underlying Windows issue. Microsoft simply doesn't render MDI windows using modern styles or high DPI support (ie, MDI does not operate under DWM). That is why Embarcadero finally decided to revamp their MDI system in the VCL in Delphi 12: https://docwiki.embarcadero.com/RADStudio/Athens/en/What's_New#MDI_Reworked_for_HighDPI_and_Styles Not on-hand, but I've seen MS employees verify the issue. I also found this tidbit, take it with a grain of salt: https://www.akadia.com/services/dotnet_software_design.html#The MDI (Multiple Document Interface) Approach Nobody ever claimed that .NET would replace COM. GDI+ augments GDI, but does not replace GDI. It is a well-known fact that after XP, MDI has been left behind in visual handling. MS simply never bothered to update MDI for modern systems. Feels like deprecation to me.
  7. In order to use a loop correctly in the OnExecute event, you must call ProcessRequests() with WaitForMessage=false. Using WaitForMessage=true, ProcessRequests() will not return until the service is stopped, and the stop will set Terminated=true, thus making such a loop useless. If you want to prevent the service from being stopped at all while the TProcess is busy, then you can do one of the following: when starting the TProcess, set the service's AllowStop property to false and call the ReportStatus() to update the SCM, and then once the TProcess has finished you can set AllowStop back to true and call ReportStatus() again. leave AllowStop set to true, and have the OnStop event return Stopped=false (and set the service's Win32ErrCode or ErrCode property accordingly) if the TProcess is currently busy. On the other hand, if you want the service to stop normally but wait for the TProcess to finish, then you can handle that in the OnStop event. The service's Status is already csStopPending when the OnStop event is entered. Simply run a loop inside of the OnStop event to call ReportStatus() at regular intervals (not exceeding the WaitHint property) while the TProcess is busy so the SCM knows the service is not frozen. Once the TProcess has finished, then OnStop can return Stopped=true, which will update the SCM with a status of csStopped. As I explained earlier, the OnExecute code you have shown is basically useless and should be eliminated completely. I would not use that approach. The init code should be in the OnStart event. The termination code should be in OnStop event. The OnExecute event should be eliminated whenever possible. Yes, and yes. Yes. For example: void __fastcall TService1::ServiceStart(TObject *Sender, bool &Started) { TProcess->Enabled = true; log1.Log(L"Service started"); Started = true; } void __fastcall TService1::ServiceStop(TObject *Sender, bool &Stopped) { while (TProcess->Enabled) { Sleep(WaitHint-100); ReportStatus(); } log1.Log(L"Service STOPPED"); Stopped = true; } void __fastcall TService1::TProcessTimer(TObject *Sender) { ... if (some condition) { TProcess->Enabled = false; if (Status != csStopPending) ServiceController(SERVICE_CONTROL_STOP); } ... } One thing to keep in mind - you keep saying the TProcess is a "timer method". If you mean a TTimer, then such a loop in the OnStop event would block the timer from firing any further OnTimer events, unless you manually pump the service thread's message queue to dispatch WM_TIMER messages. You would have had to do that anyway in the OnExecute event, if you start the timer in the context of the service thread. Personally, I never do any work in the service thread directly. I always have the OnStart event create a worker thread, and then have the OnStop event terminate the worker thread and wait on it. If I need to do things at regular intervals, I have the worker thread use a Waitable Timer Object or Waitable Event Object in a loop.
  8. Your record structure would have a lot of string fields, one for each possible type of data you want to save; it'd also have a DateTime field so you could record when the snapshot of your system was taken. The key is to be consistent in how you store the data; for example, the network adapter information should always be stored in the same field(s) requiring some way of identifying them (or lumping all network adapters in one big memo field, perhaps). I'd probably create a detail table for some fields, like the storage section in your screen-shot above. You could have a field for GUID to identify each disk and then the main table would have a summary of how many disks and the total GB. You could use something like Mitec System Information components to scan your computer every time it booted up and if something changed, add an entry to your database with a new date/time stamp. Later, you could go through and see various changes over time as you scan the records. You could also filter on certain fields to see when something changed. It's really important that you evaluate what and how often your data will change and what you want to do with it later. If this is a product you're building for others, definitely store it in a database; if it's just a one-time information gathering tool for your self over the next six months as your play around with different hardware configurations, just manually enter stuff into a spreadsheet. It really depends on your usage requirements and how much time you have.
  9. Sorted CSV is an easy way to handle comparison you need. And if more advanced comparison is required, you may load the CSV in a SQL database (maybe SQLite) or even use a spreadsheet like Excel if you are comfortable with VBA. Excel can directly load CSV files. Of course you can write your analysis in pure Delphi. You'll easily find a library to load a CSV file in an array in memory. What you shall use depends on your preferences and skills.
×