Jump to content

PeterBelow

Members
  • Content Count

    567
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by PeterBelow

  1. Design-time packes are only 32 bit, they are only used by the IDE and this is 32 bit programm. Run-time packages (that is what youre compiled programs use) can be 32 or 64 bit. Put the component class into a run-time package and add that to the requires clause of the design-time package. The only thing that package does is registering the component, i. e. it contains the Register procedure the IDE looks for to add the component to the palette. See https://docwiki.embarcadero.com/RADStudio/Alexandria/en/64-bit_Windows_Application_Development#Making_Your_Components_Available_at_Design_Time_and_Run_Time in the online help. It also tells you how you can specify which platforms your component is compatible with (ComponentPlatformsAttribute) if the default is not to yor taste.
  2. PeterBelow

    VCL and VCL styles - bugs and future

    In theory you can create a VCL control (not forms or datamodules since they add themselves to the global Screen object's collection) in a background thread but you cannot do anything with it that causes its window handle to be created, since that would bind it to the background thread. Things like TBitmap or TGraphicControl descendents (the latter only as long as they have no Parent assigned) should work, and I have worked with TBitmap in background threads successfully. To show them you have to pass them to the main thread, though.
  3. PeterBelow

    VCL and VCL styles - bugs and future

    The VCL is not thread-safe and has been documented to not be thread-safe since Delphi 1. If you need to create Windows controls in a secondary thread you have to do it on the naked API level, and the thread probably needs a message loop (API style, not ProcessMessages) as well for the control to work properly.
  4. PeterBelow

    memory paging or segmentation

    You are assuming Sizeof(Char) = 1, which is no longer true since Delphi 2007. Use ballpointer:=GetMemory(3000000*Sizeof(char)); Incrementing a pointer to Char (PChar) will correctly take the size of Char into account, so your statement ballpointer:=ballpointer+1; will increment the address held in ballpointer by 2. Since GetMemory takes the size in bytes your code allocates only half the memory needed for 3,000,000 UTF16 characters, so the loop runs over the end of the buffer when it is halfway through.
  5. PeterBelow

    String literals more then 255 chars

    They are of type String already. The limitation seems to be in the parser which cannot deal with lines longer than 255 characters in the source. But there is an easy workaround, which your third-party tool should use for long string literals: split it into several shorter literals concatenated by '+' plus linebreaks. Much easier to read for you as well if you need to manually correct stuff later.
  6. PeterBelow

    String literals more then 255 chars

    The compiler accepts this without problems: const CTest = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'+ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
  7. PeterBelow

    How to remove metadata from Word document (using OLE)

    Isn't the Last Author set when the file is saved? That would simply undo your change...
  8. There is a case, though: if the code inside the try block calls something in a DLL and that DLL function does not trap any exceptions raised inside the DLL code these would bubble up the exception handler stack into your try except block, be trapped there but not recognized as deriving from the Exception class. This would even be the case if the DLL is written in Delphi, unless DLL and EXE are build with the same Delphi version and with run-time packages enabled for both projects.
  9. PeterBelow

    memory paging or segmentation

    Which OS/CPU are we talking about here? What you show has not been a problem since 16-bit (DOS, Win 2.x, 3.x) programs have gone the way of the dinosaurs. 32 and 64 bit CPUs use a different memory architecture. 32 bit CPUs (Intel) do in fact still have segment registers but their content is constant during normal program runs, and the offset (address) registers are 32 bit wide, so a memory block can be up to 4GB large in theory. Due to OS requirement (Windows) 32 bit application programs can only use 2GByte of this theoretical address space though (3GByte with a special executable flag).
  10. PeterBelow

    memory paging or segmentation

    In Delphi you very rarely need to go as far down to the metal as GetMem. If you need arrays of some element type and don't know the size needed at coding time use a dynamic array type. Once your code has figured out the size needed use SetLength on the array to allocate the needed memory for it, then access members of the array with the classical array syntax ([index]). For array of characters use the String type in the same manner. This way you never have to deal with raw memory allocation or pointer manipulation (where you better know what you are doing if you value your sanity). You can use pointer stuff in Delphi if you really need to, but there is rarely any need. If you need a pointer to pass to some low-level API the @ operator is your friend, you can allocate memory using a dynamic array and then pass @A[0] (the address of the first array element) as the pointer. Just be aware that this only works for one-dimensional arrays. Multidimensional dynamic arrays do not occupy one single memory block. Refer to the Delphi Language Guide to learn about such pesky details, it is part of the main online help. Oh, to get a value a pointer points at you best use a specific pointer type that defines the type of data the pointer points at, e.g you use a PInteger (defined as type PInteger = ^Integer; in the run-time library units, System.Types I think) in preference to the raw Pointer type if you know the pointer points at an integer (or an array of integers). You can then just dereference the pointer to get the pointed-at value into an integer variable: var N: Integer; P: PInteger; begin ...assign an address to P N:= P^; If you only have a raw pointer you can typecast it to the specific pointer type for the assignment. var N: integer; P: Pointer begin ...asign an address to P N:= PInteger(P)^;
  11. PeterBelow

    Refresh dbedit after insert

    Very sensible policy, it saves you from serious headaches.
  12. DEF files are a C/C++ thing, no? Delphi definitely does not need them.
  13. I hope you have the source code of this library. You need to recompile its units to use the Indy version you just installed. And make sure you only have one instance of the Indy dcus on the pathes the compiler searches for files (IDE library path, project search path).
  14. This looks like the Indy folders listed in the IDE library path for 32 bit projects are actually for the 64 bit version of the Indy components. Correct the path entries to point at the 32 bit version of the dcus.
  15. PeterBelow

    Must have multiple var sections

    There are two ways to declare variables inside a method or standalone procedure or function. Sherlock's reply shows the traditional way of declaring all variables in a single var section before the begin keyword that starts the body of the method. That has been part of the Pascal language since the time of its inception by Wirth; variables you declare this way are accessible in every place inside the body of the method. What you showed in your post is a fairly new way to declare variables inline, near the place of first use. In my opinion this should only be used if you need to reduce the scope of a variable to a specific block (e.g. a begin ... end block for an if statement or for loop). In fact in my real opinion it should not be used at all ; for one it is alien to the general structure of the language, and some IDE features do not work correctly (in the current version) when they are used, e.g. refactorings and things depending on the LSP server, like code completion. If you need a lot of variables in a method this is actually a "code smell", it indicates your method is too large and tries to do too many things. Refactor it to call several smaller methods that each do a single task. If that gets complex (i.e. you find you actually need a lot of methods to partition the code correctly) the solution may be to create a new class that does the required work internally and isolates it from the calling code. The array issue you mentioned probably has a different cause. If you declare a variable with a syntax like x: array [1..9] of variant; you are using what is called an anonymous type for the variable. This is allowed for classical variables declared at the top of the method but may not be allowed for inline variables. If in doubt declare a proper type and use that for the variable: procedure.... type T9Variants = array [1..9] of variant; var x: T9Variants;
  16. It's OK, a record or helper is just way to add methods for a type, they always work on the instance of the type you call the added method on.
  17. PeterBelow

    Is there a Delphi equivalent of WriteStr ?

    It used to be possible to kind of redirect the output of Write/WriteLn using something called a "text-file device driver". I found some ancient unit of mine in the newsgroup archives, see https://codenewsfast.com/cnf/article/0/permalink.art-ng1618q5913 . If the link does not work search for "Unit StreamIO". It contains a AssignStream procedure you can use to attach a stream (in this case a TStringstream would be appropriate) to a Textfile variable. Output to this variable would then end up in the stream, from which you can get the content as a string. As I said this is old code, I have no idea how it behaves under Unicode-enabled versions of Delphi.
  18. PeterBelow

    KeyDown and Shift state

    It is expected to act the same since SendInput is just the recommended alternative to the old keybd_event API, which is basically legacy from 16-bit Windows; still supported by current Windows versions but it may be removed sometime in the future, though that seems unlikely based on past experience with other "legacy" APIs. Windows carries a loads of old APIs along, since dropping them will cause old applications still in use at many customers to fail, and the resulting uproar would be bad for business .
  19. PeterBelow

    KeyDown and Shift state

    Why should it? The Shift parameter is not a Var parameter so you just change the local value of it, not the one the caller passed. Even changing that (if you could) would not do what you think it should since it would not change the Windows-internal state of the modifier keys. And the WM_CHAR message for the tab key is already in the message queue anyway. Using keybd_event (in fact thats deprecated, you should use SendInput instead) puts a completely new Shift-Tab combination into the message queue, so you better set Key := 0 to abort processing of the 37 key. You should use virtual key codes instead of numeric values however, those make it clear which key you are processing here. VK_LEFT is much more readable than 37.
  20. PeterBelow

    Skia component and IDE

    Nowhere in fact. Components are installed via design-time packages and those register their components when the package has been loaded, through calls to the Register procedure a unit in the package defines in its interface section (in fact several units can have such a procedure, though that is not recommended). The procedure contains calls to RegisterComponents that tells the IDE how the component class is named and on which page of the palette to display the associated icon. The installed design-time packages are listed in the registry.
  21. PeterBelow

    Using VK_XXX numeric part of keyboard

    Use the OnKeyPress event of the edit control. Like this: procedure TForm2.Edit1KeyPress(Sender: TObject; var Key: Char); begin if (Key = '+') and (GetKeyState(VK_ADD) < 0) then begin Key := #0; label1.Caption := 'VK_ADD'; end else label1.Caption := string.Empty; end; The GetKeyState API function allows you to check which key is currently down. The code above will let the '+' key of the normal keyboard add the character to the edit but block the numpad plus key input.
  22. PeterBelow

    Turn display Off/On

    Have you tried running the code under an admin account? This may be a rights issue, since you are changing a setting that effects all users.
  23. You cannot, since the pixel color in question depends on the background the image is rendered on. Just replace transparent pixels with a default color for the comparison, e.g. black.
  24. The best way is to not have duplicate records in your query result in the first place. If you are using a SQL-supporting database just do not access the table directly (via TDBTable or analog), instead use a query component and give it a SELECT DISTINCT <columnlist> FROM <tablename> statement, optionally with more restrictions on the records to return (WHERE clause) and ordering. This way the result set will not contain duplicates in the first place. If the database you use does not support this kind of statement your best bet is to keep track of what you have already written to the file in an in-memory structure that supports quick lookup. You could concatenate all field values of a record into a string (basically the line you write to the text file) and store them into a TDictionary<string,byte>, using the byte part to keep a count of the duplicates you find. Depending on the number of records you have to process this may use too much memory, though. You could cut down on that by calculating a hash value from the string and storing the hash instead of the string. That is not completely failsafe, though, since different strings can result in the same hash value. You can deal with that by writing any such duplicate detected to separate file, which will end up with only few such records. When done with the task load that file into a stringlist, sort the list, and then do a final run over the record file and compare the lines read with the content of the stringlist, marking each match found there. If you end up with any unmarked items in the stringlist those are false duplicates and need to be added to the record file.
  25. PeterBelow

    tgridpanel resize

    That is an old problem you also have at design-time: using ssPercent each change of a column width recalculates all column widths, including the one you just changed, so you end up with a value different from what you just entered. The algorithm used is faulty, but at design-time it is fairly easy to work around by changing the width in the DFM file directly. If you need to change the width at run-time it is easier to work with absolute column widths and do the calculations yourself, at least it is better for your mental health.
×