Jump to content

PeterBelow

Members
  • Content Count

    447
  • Joined

  • Last visited

  • Days Won

    12

Everything posted by PeterBelow

  1. PeterBelow

    Delphi WebBrowser Display Problem

    Well, the image source file is specified using a relative path. But what is it relative to? If you open a HTML file in a web browser the path is relative to the folder the HTML file resides in, if you serve the HTML from a web server it is relative to the folder defined as root for the web page. If you load the HTML directly into a TWebbrowser it may be relative to the current directory as seen by the running program. As a test set the current directory in the program to the folder that contains the img subfolder, using the System.IOUtils.TDirectory.SetCurrentDirectory method, before loading the HTML string. Oh, and forget the old file functions, TFile from System.IOUtils has ReadAllText method that does the job in one line...
  2. PeterBelow

    Project Directory

    To change the folder for the project source file open the project in the IDE and use the "Save project as..." menu entry of the File menu to save the DPR and DPROJ files in the new location you want. Then open each file (form, frame, datamodule) in the IDE and use the "Save as..." menu to save it to the new folder. Finally use "Project -> view source" to open the DPR file in the editor and check the entries in the Uses clause and any $R statements for pathes that still refer to the old folder. This is certainly laborious but the safest way to make sure the entries in the DPROJ and DPR file are changed properly to the new location. You will retain the files in the old location this way and can zip them up or delete them at leisure. If the project is large (many files to move) it may be easier to just move the files to the new folder (with the IDE not running!) using Windows explorer, delete the DPROJ and any files with "local" in the extension, open the DPR file in a text editor (not the IDE), correct any pathes that need it there, and then open the project DPR file from the new location in the IDE. That will create a new DPROJ file, you then just need to check the project options to modify the output folder to your requirements.
  3. You are not understanding the concept of identifier scope correctly. Gamespeed is a property of the class TGameWindow, which is defined in unit GameWindow. To access it in your TGame class this class has to derive from TGameWindow (in which case is can access all members of TGameWindow that are not declared private) or you need an instance of TGameWindow accessible from TGame, in which case you have to change the code to qualify Gamespeed with that instances name, e.g. FWindow.Gamespeed, if FWindow is the variable/field containing the TGameWindow instance. If you want all instances of the TGameWindow class to share the same Gamespeed value you can change the property into a class property and the corresponding field and accessor methods to class field and class methods. In this case you can use the syntax TGameWindow.Gamespeed in TGame.Start to access the property.
  4. PeterBelow

    Find all mentions of the database

    Are you working on an older project written by someone else? Which database framework does it use, FireDAC, IBObjects, ADO (dbGo), BDE, some 3rd-party framework? In a properly designed DB app there should be only one place that uses the actual database name: the object handling the database connection/session . All other objects accessing the database should use this connection instance. A possible exception are apps that need to work with the same database from more than one thread, since DB sessions are usually bound to the thread that creates them.
  5. PeterBelow

    Copy bitmap from one app to another app bitmap

    If the Cobol programm passes a HBITMAP to the DLL procedure the following may work: In the DLL procedure, create a TBItmap object assign the passed HBITMAP to that objects Handle property adjust with and height of the bitmap object to the signature bitmap's dimensions, if necessary draw the signature bitmap on the bitmap object's canvas (using Assign instead may recreate the bitmap Handle) set the bitmap Handle to 0 to disconnect the passed HBITMAP from the TBitmap object destroy the temporary TBitmap object. If the Cobol program can get you a HDC from its bitmap you can pass that to the DLL instead of a HBITMAP and use BitBlt directly to copy the signature to it. That requires the Cobol program to properly size the bitmap first, though.
  6. PeterBelow

    Drawing text with GDI

    What you see is due to rounding errors when scaling individual character widths, these accumulate over the text width. If you want true WYSIWYG display you have to basically place each character individually at positions calculated from the font information. The API offers a large group of functions for this purpose, see Font and Text Functions
  7. 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.
  8. 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.
  9. 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.
  10. 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.
  11. 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.
  12. 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' ;
  13. 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...
  14. 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.
  15. 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).
  16. 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)^;
  17. PeterBelow

    Refresh dbedit after insert

    Very sensible policy, it saves you from serious headaches.
  18. DEF files are a C/C++ thing, no? Delphi definitely does not need them.
  19. 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).
  20. 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.
  21. 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;
  22. 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.
  23. 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.
  24. 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 .
  25. 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.
×