-
Content Count
2857 -
Joined
-
Last visited
-
Days Won
156
Everything posted by Anders Melander
-
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
Yes, but the property page crashes explorer (endless "invalid window handle" error messages) with an actual .arw file. An empty text file renamed to xxx.arw works fine. I believe this is a problem with the content functionality of the property page, not with the registration and display of the property page (i.e. it's not related to this thread). Sure. I also shouldn't smoke and eat bacon 🙂 I have Windows 11 on my laptop for when I need a reminder of why I still use Windows 7 on my desktop. -
bde_2_fd FireDAC performances
Anders Melander replied to mario.arosio@gmail.com's topic in Databases
Where else would it execute it? Did you expect it to execute the query locally? If you execute the exact same query remotely via FireDAC and remotely via SQL Server Management Studio and they don't perform almost the same, then the problem is most likely the way the data is fetched by the client. I solved a similar performance problem at one time by fiddling with some connection parameters... Here are the screenshots I took to document the difference in performance: Query executed via MSSQL MS: Same query executed via TFDQuery: Try to compare the network bandwith usage of FireDAC vs SQL Server Management Studio when the query execute/fetches, like I did above. Again, they should be almost identical. In the above case, I solved the problem by disabling MARS on the connection. Query executed via TFDQuery on a connection with MARS disabled: -
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
Still works for me: I'm on a 64-bit Windows 7 so it might be the same problem as this: https://stackoverflow.com/questions/34011698/property-sheet-handlers-on-windows-10 -
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
I already did. What do you mean? -
As I wrote: https://www.google.com/search?q=delphi+graphics+transitions As far as I can tell there's a ton of old transition effects code on Torry.net. No guarantee that it works as-is with newer versions of Delphi though.
-
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
My factory overrides GetProgID to return an empty string and TComObjectFactory.UpdateRegistry has this code: if ProgID <> '' then begin CreateRegKey(RegPrefix + ProgID, '', Description, RootKey); CreateRegKey(RegPrefix + ProgID + '\Clsid', '', ClassID, RootKey); CreateRegKey(RegPrefix + 'CLSID\' + ClassID + '\ProgID', '', ProgID, RootKey); end; Yes. -
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
It's registered for a single extension. I'm not using your IShellExtInit implementation at all. I'm using the shell integration classes from the Drag and Drop Component Suite, so here's the full extent of changes I needed to make in order to register the property sheet handler: type TPropertySheetHandlerFactory = class(TDropContextMenuFactory) protected function HandlerRegSubKey: string; override; end; function TPropertySheetHandlerFactory.HandlerRegSubKey: string; begin Result := 'PropertySheetHandlers'; end; const // CLSID for this shell extension. // Modify this for your own shell extensions (press [Ctrl]+[Shift]+G in // the IDE editor to gererate a new CLSID). CLSID_PropertySheetHandler: TGUID = '{1067C264-8B1F-4B22-919F-DB5191C359CB}'; sFileClass = 'FoobarFile'; sFileType = 'File of foo'; sFileExtension = '.foobar'; sClassName = 'DelphiPropSheetShellExt'; resourcestring // Description of our shell extension. sDescription = 'Property Sheet example'; initialization TPropertySheetHandlerFactory.Create(ComServer, TDataModulePropertySheetHandler, CLSID_PropertySheetHandler, sClassName, sDescription, sFileClass, sFileExtension, ciMultiInstance); end. and here's the code to extract the file names (ShellExtInit.Initialize): function TDataModulePropertySheetHandler.ShellExtInit_Initialize(pidlfolder: PItemIDList; lpdobj: IDataObject; Hkeyprogid: HKEY): HResult; begin Result := NOERROR; FFiles.Clear; SetFolder(pidlFolder); // Save a reference to the source data object. FDataObject := lpdobj; try // Extract source file names and store them in a string list. // Note that not all shell objects provide us with a IDataObject (e.g. the // Directory\Background object). if (DataObject <> nil) then with TFileDataFormat.Create(dfdConsumer) do try if GetData(DataObject) then FFiles.Assign(Files); finally Free; end; finally FDataObject := nil; end; end; FWIW, I believe the thing that you were missing was registering the class ID in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved. The 4-space indent and capitalized keywords probably also had a negative influence 🙂 Source attached. PropertySheetHandler.zip -
How to register a shell property sheet for a single file type?
Anders Melander replied to FPiette's topic in Windows API
Works for me: I'll clean up the code and post it later... -
bde_2_fd FireDAC performances
Anders Melander replied to mario.arosio@gmail.com's topic in Databases
Did you do any of this? -
Should be pretty easy to implement with any of the libraries that can render text along a path. Image32, Graphics32, etc. Are there any particular effects you need, or are you looking at what's available for now?
-
Best Practice Question: Bidirectional EXE-to-EXE communication
Anders Melander replied to Alexander Halser's topic in RTL and Delphi Object Pascal
IMO the restrictions you've put on the implementation seem a bit arbitrary and are getting in the way of the solution. I would definitely go with an out-of-process COM server; It's a piece of cake to implement, it's natively supported by Delphi and you'll get IPC and threading thrown in for free. You could even have the service host it - or have it as a separate component that is used simultaneously from three modules. So why is it a problem that the exe needs to run once (to take care of the COM registration) before the client can access it? If you really can't register the COM server before the modules are run, then just have the modules do it themselves when they are run. No "installation" is necessary when you have complete control of all the components of the system. -
Well, at least it told you what happened so you can fix or work around it 🤦♂️
-
It sounds like you already know the answer to that one.
-
New blog post: Leveraging ChatGPT to generate a Delphi class along with CRUD code from a table schema
Anders Melander replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
Yes, that's the formal definition of it. I'm more referring to professionalism as an attitude toward solving problems; Don't be lazy is the first thing I try to teach new developers. The vast majority of the work I do is horribly boring, but I don't get paid to write "interesting" code. I get paid to write high-quality code and if that means I have to write yet another damned factory, observer, or visitor class so be it. The effort spent will benefit everybody, myself included, down the road. I'm not against using a tool like ChatGPT as long as it is used as what it actually is. -
New blog post: Leveraging ChatGPT to generate a Delphi class along with CRUD code from a table schema
Anders Melander replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
How is it disingenuous? I'm stating pretty clearly that I believe it's an amateurish approach. A professional would look at the problem and then think about how best to solve it within the given constraints. The problem with ChatGPT is not the quality of the code. The problem is that you're delegating the most important element of software development, namely design and architecture, to a construct that has no grasp of these concepts. But okay, what do I know. -
(Possibly) interesting stuff to read
Anders Melander replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
AVX-512... Risky (performance-wise) - unless you know exactly what hardware you're running on. -
New blog post: Leveraging ChatGPT to generate a Delphi class along with CRUD code from a table schema
Anders Melander replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
Once again, it's just a party trick; A complete waste of time. What's demonstrated here is not how a professional solves a problem. If you're lucky the generated code is one possible solution, but regardless of how correct the code is there's almost no chance of it being the best solution to a given problem. -
Yes
-
Memory Leak when loading/unloading Delphi DLL
Anders Melander replied to Thomas B's topic in Windows API
I have not been able to reproduce the problem using the supplied DLL and host source. Compiled with Delphi 11.2 targeting both 32- and 64-bit. Virtual memory, private bytes, working set, and handles were stable. No leaks were identified. I suggest you test it on a clean system (or do a secure boot) to ensure that stuff isn't being injected into your process (e.g. via HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs). -
Keep a reference to the thread when you create it. Use TThread.Terminate to terminate it and use TThread.WaitFor to wait for it to actually terminate.
-
I agree that this is the better approach. Just remember to signal the thread to terminate (and wait for it to do so) when the service is stopping. Also, note that in the case of a COM-server-in-a-service there might not be a need for a separate thread since each COM connection will get its own thread anyway, depending on the apartment model used.
-
Just so you know, while all the code in this thread might be fine for "I'm a hobbyist and I don't know what the hell I'm doing"-level programming, it's nowhere near the best or correct way to solve your problem. With that said, the reason you're losing transparency is that you are operating on the rendered visual representation of the image. Therefore the transparency has been replaced with a background color. In order to resize a PNG without losing transparency you will need to use a method that supports alpha transparency. This means: Convert the PNG to a 32-bit RGBA bitmap. Resample (resize) this bitmap to the desired size. Convert the bitmap to PNG. There are various libraries that can do these steps for you. For example Graphics32 and probably also Image32. I'm guessing Image32 will probably be the easiest for you to understand.
-
It's not clear where the code you posted is located but regardless, exceptions inside TServiceThread.ProcessRequests are caught and handled (logged) there so they won't propagate to your handler. If you need to catch unhandled exceptions on the service level you should create a custom TServiceApplication and override the DoHandleException method. By default, it logs exceptions to the event log but you can change it to do whatever you need. This is what it would look like in Delphi: program ServiceProject; uses Vcl.SvcMgr, MyUnit in 'MyUnit.pas' {MyService: TService}; {$R *.RES} type TMyServiceApplication = class(TMyServiceApplication) protected procedure DoHandleException(E: Exception); override; end; procedure TMyServiceApplication.DoHandleException(E: Exception); begin ...whatever... end; begin // Get rid of TServiceApplication... Vcl.SvcMgr.Application.Free; // ...and use our custom service application class instead Vcl.SvcMgr.Application := TMyServiceApplication.Create(nil); // Usual service code follows... if not Application.DelayInitialize or Application.Installing then Application.Initialize; Application.CreateForm(TMyService, MyService); Application.Run; end.
-
How to enter unicode symbols into the Delphi IDE
Anders Melander replied to Dave Novo's topic in Delphi IDE and APIs
That method only applies to MS Office (Word, Excel, etc). AFAIK this is the only keyboard method that works universally: In the registry, under the HKEY_Current_User/Control Panel/Input Method, set the EnableHexNumpad value to "1" (it's a REG_SZ value in case you need to add it). Press and hold the Alt key. Press the + key on the numeric keypad (I hope you got one 🙂 ). Type the hexadecimal unicode value. Release the Alt key. -
Nested TParallel.For: Immediate deadlock
Anders Melander replied to Der schöne Günther's topic in RTL and Delphi Object Pascal
Okay so I've looked into this some more and I've got good news and bad news: The bad news is that this is probably "as designed". The good news, well I lied; There isn't any good news. If we look at other thread pool implementations "properly designed by skilled practitioners", the old Win32 thread pools also had a hard upper limit on the number of threads in a pool and suffered from the exact same problem. The newer Vista thread pools are a bit more clever but it still has an upper limit (I believe the default max is 500 threads) and suffered from the exact same problem. Same with .NET thread pools (which are a rewrite of Win32 thread pools); For CLR 2.0 the max is 25 threads per core and for 2.0SP1 the max is 250 per core. The reason for this tenfold increase in default max is actually to avoid experiencing deadlocks caused by running out of threads quite so often. Thus .NET too suffers from the exact same problem. See Concurrent Programming on Windows, chapter 7 for a discussion on all this. So the problem is that the RTL thread pool imposes a hard upper limit on the number of threads in it and that the limit is way too small. Ideally what we'd like, in this case, is for the growth algorithm to be a bit more intelligent and flexible but I doubt that will happen. The easy solution is probably to just increase the max and hope for the best 😕 . I still believe that the library should detect (and fail on) the simple case when all threads are blocked waiting for a thread to become available. It's relatively unlikely that this will occur in real code (there are many other things, not controlled by the PPL, that a thread can wait on) but it's so simple to implement that I believe it's worth the effort.