PeterBelow
Members-
Content Count
490 -
Joined
-
Last visited
-
Days Won
13
Everything posted by PeterBelow
-
Passing back a string from an external program
PeterBelow replied to dummzeuch's topic in Windows API
A fairly simple method is to pass a window handle to program2 on the command line an then have that program sent its result back in a WM_COPYDATA message to that window. Only caveat: program1 must not wait on program2 to finish in a manner that blocks message processing of the main thread. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
It all depends on what type of application you write. Singletons are, in my opinion, a good and easy to implement solution for apps that require some global state and are fairly small and focused on specific tasks, i. e. a typical one-user desktop application. They would certainly not be a good solution for a large distributed application with many modules and build by a whole team of developers. There are no panaceas in software development, be pragmatic, not dogmatic 😉. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Singletons are no problem for unit tests, you just need to make them implement an additional interface that resets all the singleton fields to the startup state for the test build. That is the called from the Setup method of the test case. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I have a code template for creating a singleton that uses a thread-safe factory method, and making the interface methods thread-safe is also no big deal, since all the code is hidden in the implementation section of the unit. I don't do that by default, though, only when the singleton is actually used by several threads. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
In a way, yes. The class itself exists only once, so all its class vars also exist only once in the application memory. The beauty is that it is impossible to create a second "instance" of the data, even if you were to create an object of that class it would still only access the class variables. The singleton pattern is classically implemented using a class of which only one instance can be created, which will typically live as long as the application is running. Using a "normal" class for that has its problems, since such classses are designed to allow the creation of any number of instances (objects) of that class. It is also hard to prevent code using the singleton object from destroying it. Using class variables eliminates all these problems, and using the interface to a hidden object method does this as well, although malicious code can in fact prematurely destroy the singleton object by calling _Release on the interface, at least if lifetime management by reference counting is used (hidden class derived from TInterfacedObject). But that is easy enough to prevent as well, just by using a class with a implementation of the IInterface methods that does not use reference counting for lifetime control. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
No, you just use TDatastore.Data1 whereever you need the value stored in that field. Basically the class vars of the TDatastore class are your global variables, they are just neatly packaged and hidden in the class. -
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
A record is about equivalent to using class variables. The main difference is the syntax you use to access the data. // a record as global storage var gDataStore: record Data1: string; .... end; // accessed as // someLocalVar := dDataStore.Data1; // class as global storage type TDataStore = class private class var FData1: string; ... public class property Data1: string read FData1 write FData1; ... end; // uses as // someLocalVar := TDataStore.Data1; As you can see there is no global variable, and using the Delphi syntax rules it is clear that you accessing a class here. You can also better control access to the data and use setter and getter methods if necessary. -
The RAD Server stuff is only available in the higher RAD Studio SKUs (Architect, Enterprise).
-
Should I keep class alive (global) or not?
PeterBelow replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
While it is generally a good idea to avoid global variables there are cases where they can be useful, and your case is one of them. Do you know what a singleton object is? A singleton is a good solution for a scenario where you need to store some data internally in your application that you have to access from several different places in your code (different units, for instance). You place the class into a unit of its own. The unit is then used by all other units that need access to the singleton. There are different ways to implement a singleton object. The simplest one is to actually never create an instance of the class at all. Instead you use class variables and class properties to hold the data. That works well if all data you need available are simple or compiler-managed types (ordinal types, numeric types, strings). It works less well if you need more complex types, e.g. other objects. This can be handled now that Delphi has class constructors and class destructors, however. My preferred way to implement singletons is to only expose an interface type that has the necessary properties and methods to store and retrieve the data, and a factory method that returns an instance of the interface. The class implementing the interface is private to the unit (declared and implemented in its implementation section). The factory method creates an instance of the class on the first call to it and stores the interface obtained from it in a variable only visible in the unit implementation section. The unit gets a finallization section that sets the interface to nil to finally destroy the singleton. -
Keep in mind that the IDE uses a different desktop while in debug mode. Move the IDE back to the other monitor and then save the desktop and make it the default debug desktop, that should fix the problem.
-
I have no idea what this TEMSProvider is, sorry, so just gave you the stock answer for installing a component. OK, I see this component in the dclemsclient260.bpl (for Rio), which appears as "Rad Server client components" in the installed package list. Do you see this package in the Components-> Install package dialog? I see the component in the palette under the RAD Server item. Keep in mind that the palette is context-sensitive, you need to have a form, data module or such open in the designer to see most items.
-
You have to add it to a designtime package and install that. The Components->Install component menu calls up a dialog that steps you through the process.
-
See for example https://www.geeksforgeeks.org/enumeration-enum-c/ If i understand that correctly the ordinals should be type VmbPixelLayout = ( VmbPixelLayoutMono, {0} VmbPixelLayoutMonoPacked, {1} VmbPixelLayoutRaw, {2} VmbPixelLayoutRawPacked, {3} VmbPixelLayoutRGB, {4} VmbPixelLayoutBGR, {5} VmbPixelLayoutRGBA, {6} VmbPixelLayoutBGRA, {7} VmbPixelLayoutYUV411, {8} VmbPixelLayoutYUV422, {9} VmbPixelLayoutYUV444, {10} VmbPixelLayoutMonoP, {11} VmbPixelLayoutMonoPl, {12} VmbPixelLayoutRawP, {13} VmbPixelLayoutRawPl, {14} VmbPixelLayoutYYCbYYCr411, {15} VmbPixelLayoutCbYYCrYY411 = VmbPixelLayoutYUV411, {8} VmbPixelLayoutYCbYCr422, {9} VmbPixelLayoutCbYCrY422 = VmbPixelLayoutYUV422, {9} VmbPixelLayoutYCbCr444, {10} VmbPixelLayoutCbYCr444 = VmbPixelLayoutYUV444, {10} VmbPixelLayoutLAST {11} ); which shows that the person that extended the enum after the RawP1 element did not understand the rules, since VmbPixelLayoutLAST is now definitely not the highest value in the enumeration.
-
Delphi actually supports C-style enums, although they are supposed to be used only in code that needs to interface with C Dlls. The compiler creates no RTTI for them, so they cannot be used in published properties, for instance. But this compiles without problem: type VmbPixelLayout = ( VmbPixelLayoutMono, VmbPixelLayoutMonoPacked, VmbPixelLayoutRaw, VmbPixelLayoutRawPacked, VmbPixelLayoutRGB, VmbPixelLayoutBGR, VmbPixelLayoutRGBA, VmbPixelLayoutBGRA, VmbPixelLayoutYUV411, VmbPixelLayoutYUV422, VmbPixelLayoutYUV444, VmbPixelLayoutMonoP, VmbPixelLayoutMonoPl, VmbPixelLayoutRawP, VmbPixelLayoutRawPl, VmbPixelLayoutYYCbYYCr411, VmbPixelLayoutCbYYCrYY411 = VmbPixelLayoutYUV411, VmbPixelLayoutYCbYCr422, VmbPixelLayoutCbYCrY422 = VmbPixelLayoutYUV422, VmbPixelLayoutYCbCr444, VmbPixelLayoutCbYCr444 = VmbPixelLayoutYUV444, VmbPixelLayoutLAST );
-
TThread.Synchronize in a Parallel.For Loop?
PeterBelow replied to Steve Maughan's topic in Algorithms, Data Structures and Class Design
I have not checked the source in this case but the symptoms reported by the OP seem to indicate that it just blocks until all tasks launched by the for loop have completed. -
Go to the project options dialog, Application -> Manifest node. Do you have the "enable run-time themes" checkbox checked? (Caption may be different, i'm extrapolating from a german IDE here). If you use a custom manifest for the application it needs to contain the equivalent entry for that.
-
TThread.Synchronize in a Parallel.For Loop?
PeterBelow replied to Steve Maughan's topic in Algorithms, Data Structures and Class Design
If you execute the TParallel.For loop in the main thread then it would probably block the Synchronize call, since that tries to execute code in the main thread. The code can only be executed when the main thread reaches a "safe" state, which, in a typical VCL application, is the message loop. Your code does not get there until the complete loop has been finished. What you need here is a thread-safe stack class, or you have to use a standard TStack<T> in a thread-safe manner, i. e. use a TCriticalSection object, which you enter before each pop or push call on the stack and leave when the call has returned (using try finally!). The loop will still block your main thread until it is done, though. -
I'm just guessing here, since I don't know this component. You may have to use GDI functions like SetViewportExtEx to modify the device context "size" before drawing on it.
-
A metafile canvas can be created with a reference device context handle. If you do not specify one it uses the screen dc as reference. Specify a printer canvas handle as reference, that should work better.
-
Saving a large project takes soooo Loooonnnnggg..
PeterBelow replied to Ian Branch's topic in General Help
Oh, it makes perfect sense. This feature makes it possible to work on a project with only the component packages loaded that this project requires. That reduces the IDE memory print, especially if you have a lot of 3rd-party packages installed (these things tend to breed if you don't look 😉), of which the current project only uses a small subset. That was certainly more important in the early times of Delphi (D1, Win16!) but can still make a difference today. You can drastically reduce the IDE start time, for example, by using a default package set that is the absolute minimum, basically only what is needed for every project you work on. Other packages are then only enabled for the project that needs them. -
Is it possible to know when a TObject is instanciated/freed?
PeterBelow replied to santiago's topic in General Help
Looks like a reference counting problem. Do you have classes where an object referenced by another also has to keep a backreference to the object that references it? That is the most common cause of such problems if the backreference is not declared as weak, but you probably know that already. Another problem scenario is passing interface references across a module boundary where it may be necessary to call _addref and _release manually, that's easy to screw up. -
Saving a large project takes soooo Loooonnnnggg..
PeterBelow replied to Ian Branch's topic in General Help
The package list is specific for the active project. To change the default you have to edit the package list with no project or project group open, and that will still only apply to new projects you create after that. -
Is it possible to know when a TObject is instanciated/freed?
PeterBelow replied to santiago's topic in General Help
You can do this for any class hierarchy you wrote yourself, but doing it for any class starting with TObject would be difficult without patching routines of the run-time library. The full version of FastMM4 has more options for tracing memory leaks that the one used in the Delphi RTL, I think, but I have never had to investigate this myself. Even if you manage to do it somehow you will drown in data; any even moderately complex program will create and delete tens of thousands of objects during a program run, and most of the collected data will be totally useless for figuring out where in your code the problem point is located. Are you trying to track a particular problem? If so, give us more detail, perhaps there is a more focused way to handle that. -
Do you design each form for separate case, or use common forms for similar design?
PeterBelow replied to Mike Torrettinni's topic in VCL
If I build an application using the same framework I would definitely use the same approach again. In fact I could reuse much of the old code 1:1 in this case since the dialog and its frames are completely independent of the actual data classes to search. -
Do you design each form for separate case, or use common forms for similar design?
PeterBelow replied to Mike Torrettinni's topic in VCL
It all depends on how your application is constructed. In the largest one I ever wrote I used data classes with an ORM on the back to interact with the database. The application had a number of views to shows list of different kinds of those data objects (which represented the entities in the data model), and each of these views had a search function. They all used a common search dialog, which was configured at run-time using a configuration interface, which had implementations for each of the searchable data classes. The dialog contained frames for the user to specify the search critertia, each of which had a dropdown list with the available searchable properties, applicable operators, and input controls (dynamically adjusted according to property type) to specify the criteria. The dialog build the WHERE clause to use from the input, which the user could modify to change the default AND combination used if necessary. Worked quite well, the work required to build the configuration interface was not that large since the dialog could use the data classes' metadata to construct the property list, figure out the applicable operators and input controls needed. The interface just told it which data class to configure itself for, which properties to exclude from the dropdown, and which values to offer for selection for properties with a restricted list of possible values.