Jump to content

PeterBelow

Members
  • Content Count

    508
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by PeterBelow

  1. PeterBelow

    No TEMSProvider on my component pallet

    The RAD Server stuff is only available in the higher RAD Studio SKUs (Architect, Enterprise).
  2. 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.
  3. PeterBelow

    Multi-screen misbehavior

    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.
  4. PeterBelow

    No TEMSProvider on my component pallet

    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.
  5. PeterBelow

    No TEMSProvider on my component pallet

    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.
  6. PeterBelow

    converting a C enum to Delphi

    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.
  7. PeterBelow

    converting a C enum to Delphi

    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 );
  8. 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.
  9. PeterBelow

    Windows 10 OS Themes and VCL Styles

    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.
  10. 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.
  11. PeterBelow

    PlayEnhMetaFile on non visible area

    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.
  12. PeterBelow

    PlayEnhMetaFile on non visible area

    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.
  13. PeterBelow

    Saving a large project takes soooo Loooonnnnggg..

    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.
  14. 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.
  15. PeterBelow

    Saving a large project takes soooo Loooonnnnggg..

    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.
  16. 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.
  17. 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.
  18. 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.
  19. PeterBelow

    change the path to an existing windows explorer

    Just an idea: The IShellBrowser interface has a method GetControlWindow which you can use to get the window handle of a control inside the browser. You should be able to use the GetAncestor API function with the GA_ROOT flag with this handle to find the Explorer window itself, and then you can use the SetForegroundwindow API function on that to bring it to front.
  20. What I would do in your case is to load only the document title (and the primary key plus perhaps a submission date, but only the minimum of data you need for display and to later fetch the full record) for all records at first, perhaps ordering the result by submission date descending or alphabetically. The resulting data would be stored client-side in a suitable data structure, and the tree would show it from that structure. Only when the user indicates that he wants to examine a document in more detail would you fetch the actual document content from the server and display it. This way your first query should still be fast enough to not cause a too noticable delay; even if it returns 30,000 rows each of the rows would be fairly short, so the total amount of data transferred is not that large. I'm not familiar with this VirtualTreeview control, but with such virtual controls the time saver is not having to load all the data into the control in one operation. But you still need to know, up front, how many "records" your control has to display, so you can create the necessary number of virtual nodes, and you need to have the data available somewhere, to be able to provide it when the control asks for it. If the ultimate source of the data is a database you need not only the number of records the query you use returns, you also need some piece of data for each of the records that allows you to tie each of the virtual nodes to a record in the database unambiguously, usually a primary key. Only then can you fetch the full data for a node when you need it for display. A database is usually not like a sequential file or list, there is no convenient way to partition a query result set into "pages". Even though some SQL databases support the ANSI SELECT syntax with OFFSET and FIRST ROWS in some manner these are very inefficient queries, since the server still has to compose the full result set on each query, it just returns only part of the resulting rows. Also keep in mind that such list-type controls have a vertical scrollbar. The user can frustrate your attempts at reading the data in chunks sequentially by grabbing the scrollbar thumb and dragging it down, ending up somewhere way below the current page you have laboriously fetched before. You can only react fast to that if you have the data needed to display already stored in some data structure on the client side. In summary: using this kind of display does not work well with the classical RAD "drop a query and tied that to a databound control" way of design. You are much better served by using a list of objects for the client-side data storage. You fill that with objects holding only the minimum of data at first (primary key and a display string, e.g. your document title) and tie the objects to the virtual nodes of your UI. You fetch the rest of the data only when it is needed for display. If you grow ambitious after having that working you can then use a secondary thread with a second conncection to the database to fill the objects corresponding to the next visual page of the control in background, while the user is still staring at the display of the current page.
  21. Whenever I see such a statement I have to wonder: has the poster ever actually tried to work with a list that large? It is completely useless as an UI element in my opinion, nobody in his right mind wants to scroll around in such a list to find something he is looking for. Give your user a decent search function and show only the database records matching the search criteria. At least, if that is possible, devide the "data space" into chunks of manageable size, e.g all records where a person name starts with the same letter, then allow the user to select the letter to look for.
  22. PeterBelow

    function stripcslashes()

    The PHP function converts escaped characters like \n to their actual character (chr(13) in this case), no? Delphi has nothing like that since there is no need to escape characters in Delphi strings, they are all UTF-16 by default. So you have to write your own, I think.
  23. PeterBelow

    Get UserID from LogIn form at startup.

    Modifying the DPR file's body can be done safely, if you know what you are doing and where the IDE may step on your modifications 😉. In my experience is best to just not add reams of code to the main block directly but only the absolute minimum you get away with, usually a single call to a function that then does the brunt of the work. This has never caused a problem for me if said line was added directly after the Application.Initialize line. What the IDE modifies are the uses clause and the lines to create the autocreated objects (after the first Application.CreateForm line). Additions you make there may get wiped out, so don't touch these sections of the dpr file. Adding procedures, functions, types, constants, even classes to the dpr file works without problems otherwise, although it is a bad idea in my opinion.
  24. PeterBelow

    screen shot - reliable method

    One way that is fairly reliable is to fake a press of the print screen key. The main problem is that you have to get the image from the clipboard, and that of course overwrites any previous content. procedure TForm1.Button1Click(Sender: TObject); begin Clipboard.Clear; PostKeyEx32(VK_SNAPSHOT, [], false); Application.ProcessMessages; // 'ware timers! if Clipboard.HasFormat(CF_BITMAP) then image1.Picture.Bitmap.Assign(Clipboard) else label1.Caption := 'No image!'; end; {! <summary> PostKeyEx32 uses keybd_event to manufacture a series of key events matching the passed parameters.</summary> <param name="key"> is the virtual keycode of the key to send. For printable keys this is simply the ANSI code (Ord(character)). </param> <param name="shift"> encodes the state of the modifier keys. This is a set, so you can set several of these keys (shift, control, alt, mouse buttons) in tandem. The TShiftState type is declared in the Classes unit.</param> <param name="specialkey"> normally this should be False. Set it to True to pecify a key on the numeric keypad, for example.</param> <remarks> The events go to the control with focus, even if it is part of another process. Note that for characters key is always the upper-case version of the character. Sending without any modifier keys will result in a lower-case character, sending it with [ssShift] will result in an upper-case character! </remarks> } procedure PostKeyEx32(key: Word; const shift: TShiftState; specialkey: Boolean); type TShiftKeyInfo = record shift: Byte; vkey: Byte; end; byteset = set of 0..7; const shiftkeys: array[1..3] of TShiftKeyInfo = ((shift: Ord(ssCtrl); vkey: VK_CONTROL), (shift: Ord(ssShift); vkey: VK_SHIFT), (shift: Ord(ssAlt); vkey: VK_MENU)); var flag: DWORD; bShift: ByteSet absolute shift; i: Integer; begin for i := 1 to 3 do begin if shiftkeys[i].shift in bShift then keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), 0, 0); end; { For } if specialkey then flag := KEYEVENTF_EXTENDEDKEY else flag := 0; keybd_event(key, MapvirtualKey(key, 0), flag, 0); flag := flag or KEYEVENTF_KEYUP; keybd_event(key, MapvirtualKey(key, 0), flag, 0); for i := 3 downto 1 do begin if shiftkeys[i].shift in bShift then keybd_event(shiftkeys[i].vkey, MapVirtualKey(shiftkeys[i].vkey, 0), KEYEVENTF_KEYUP, 0); end; { For } end; { PostKeyEx32 }
  25. PeterBelow

    DPI-change, crashes tDrawgrid.

    You can send a WM_SETREDRAW message to the control to block painting, but that may not affect the updating of the scrollbar range.
×