Jump to content

PeterBelow

Members
  • Content Count

    565
  • Joined

  • Last visited

  • Days Won

    13

Posts posted by PeterBelow


  1. 4 minutes ago, Willicious said:

     

     

    The above suggestions will run the code if i is equal to any number between 1 and 7. So, it's more like this:

    
    if (i = 1) or (i = 2) or (i = 3) or (i = 4) etc...

     

    What I need is for the code to run only when all numbers are satisfied, like this (note "and" instead of "or"😞

    
    if (i - 1) and (i = 2) and (i = 3) and (i = 4) etc...

     

    I realise that, of course, it's not possible for i to equal more than one value at once, that's why I need help with this. Essentially, it's a collision detection check in which the character has to turn around if they reach a vertical wall of at least 7 pixels in height, but  - all 7 pixels have to be filled. The following code works, but I want to try and simplify it if possible:

    
    if HasPixelAt(X, Y) and HasPixelAt(X, Y -1)
      and HasPixelAt(X, Y -2) and HasPixelAt(X, Y -3)
      and HasPixelAt(X, Y -4) and HasPixelAt(X, Y -5)
      and HasPixelAt(X, Y -6) and HasPixelAt(X, Y -7) then
    begin
    ...
    end;

     

    Thanks in advance, I hope this explains the question a little better.

    I see no other way to do this for vertical walls, since the memory locations of the pixels in question are not contiguous if the storage used has the typical bitmap layout.

     

    But you may be approaching the whole problem the wrong way. Instead of working directly with the bitmap image of the rendered scene you should build the scene as a list of objects, each of which represents an element of the scene. In this case the vertical wall would be one such object, storing its location and dimensions internally. You then walk over the list of objects and test whether the point (X,Y) falls inside such an object. This search can be sped up considerably by storing the objects in a tree or list sorted on coordinates. I have never worked in this area myself, but it is a common problem in game design, there should be plenty of literature around on the subject.

    • Like 1

  2. 5 hours ago, Willicious said:

    But, what if you only want to run the code when "i" matches every value between 0 and 7 at the same time?

    That makes no sense, a variable can only have one value at a time. Of course it may be a complex "value", like an array or set, but that does not seem to be what you want.


  3. 14 hours ago, Willicious said:

    I have a form with a treeview, which can be browsed using the arrow keys. Once an item in the treeview is selected, hitting an "OK" button on the form (which has the modal result mrOK) will close the form, and load the currently selected item into the app.

     

    What I want to do is assign VK_RETURN (which I believe is the [Enter] key...?) to the OK button, so that when browsing the treeview using keys, the user can just hit Enter/Return to load the currently selected item.

     

     

    Just set the buttons Default property to true, it will then automatically "click" when the user presses Enter/Return and the active control does not handle the key itself. No code needed...

    • Like 2

  4. 19 hours ago, softtouch said:

    Thanks for that. But the user edit the key in the valuelisteditor grid, Ido not add the key with insertrow or such. There are existing entries, the user select the entry to edit and change it, and when the user leaves the cell (with mouse or keyword/arrow keys for example), the exception is triggered.

    Try to handle the OnSetEditText or OnValidate events.


  5. 2 hours ago, Robert Gilland said:

    I am trying to create a function that creates a class at runtime lie this:

     

    function CreateDescentantClass( pcAncestorClass : TClass; const psDescendentClassName : String 😞 Class;

    begin

      Result := psDescendentClassName of  pcAncestorClass;

    end;

     

    Is this possible? I am using Delphi Alexandria

    Basically you have to enumerate all classes defined in the application and check their classname and ancestry to find one that matches the criteria you pass to the function. So it is misnamed: it does not creaste a class, it searches for one and returns it. The enumeration can be done using the advanced run-time type information support provided by the System.Rtti unit. You start with a variable of type TRttiContext, which has a GetTypes method to enumerate all types that have advanced RTTI info available. You check with the individual types IsInstance property whether it describes a class type, use the AsInstance property to obtain a TRttiInstanceType and use its methods and properties to examine the class to see whether it matches your criteria.

     

    There are two drawbacks to be aware of: RTTI generation can be disabled for individual units or even the whole application through compiler switches ($RTTI), so may not be available for 3rd-party classes you use, and RTTI can be used to examine the compiled executable and thus be considered a security risk.

     

    If you need this funktionality only for a limited set of classes it may be better to just create your own class registry and register all relevant classes in it in the initialization sections of the relevant units.


  6. 12 minutes ago, Philip Vivier said:

    When I click

    Tools->Options->Language->Delphi->Library -> [...] button, the whole system hangs. Does not matter on which [...] button I click.

    I need to stop Delphi every time with task manager.

     

    I am using windows 11 and Delphi 1.2.

    You can select and copy the path from the edit field and paste it into Notepad to check it for invalid characters or nonexistent pathes, perhaps that reveals a problem.


  7. 13 hours ago, msd said:

    Hello, 

     

    I would like to develop a KBMMW-based Windows Service Application.

    So I need a little assistance with this idea, with code for starting and monitoring KBMMW components.

    KBMMW is some kind of middleware framework that connects to databases and provides server connections to clients.

    So, I need to develop a classic Windows service application, which has a part where I need to register services and start the KBMMW Server listener to true.

    Do I need to execute the main thread of the service app because the KBMMW server is a listener on the port by itself, and is it ok to put this part of the code (registration services) in the service start event handler?

     

    Thanks in advance...

    You can only put code in the OnStart event handler that executes fast and does not block the thread, otherwise it will prevent the service from starting because the service manager runs into a timeout waiting for the event handler to return. Better just create a secondary thread in OnStart and do all other work in/from its Execute method.

    • Like 1

  8. 7 hours ago, Ian Branch said:

    Hi Team,

    One last aspect.

    I don't need to att, but if the Customer asks, where/how would I incorporate a printersetup dialog so they could select the printer and parameters?

     

    Regards & TIA,

    Ian

    Launch the dialog before you do anything with the Printer object (i.e. construct your print job). The VCL TPrintDialog and TPrinterSetupDialog components modify the Printer properties according to the user's selection in these dialogs.


  9. 4 hours ago, Ian Branch said:

    Hi Team,

    I have jpegs saved into TTable Blob fields.  1 per record.

    How do I extract and print that jpeg to the PCs Printer please?

    I have made several 'attempts' without success.

     

    Regards & TIA,

    Ian

    I found some really ancient code for this in my old snippets file, perhaps you can get it to work. It loads a JPEG from file but you can load it from a TBlobstream attached to your field as well.

     

    Printing a JPEG image:
    
    uses jpeg, printers;
    
    
    // This procedure has been adapted from the one found near the end of
    // the Delphi 1 MANUALS.TXT file.
    procedure PrintBitmap(Bitmap: TBitmap; printrect: TRect);
    var
      Info: PBitmapInfo;
      InfoSize: Cardinal;
      Image: Pointer;
      ImageSize: Cardinal;
    begin
      with Bitmap do
      begin
        GetDIBSizes(Handle, InfoSize, ImageSize);
        Info := AllocMem(InfoSize);
        try
          Image := AllocMem(ImageSize);
          try
            GetDIB(Handle, Palette, Info^, Image^);
            with Info^.bmiHeader, printrect do
              StretchDIBits(Printer.Canvas.Handle, Left, Top, Right-Left,
                Bottom-Top, 0, 0, biWidth, biHeight, Image, Info^,
                DIB_RGB_COLORS, SRCCOPY);
          finally
            FreeMem(Image, ImageSize);
          end;
        finally
          FreeMem(Info, InfoSize);
        end;
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      bmp: TBitmap;
      jpegimage: TJPegImage;
      outputrect: TRect;
      i: Integer;
    begin
      jpegimage:= TJPegImage.Create;
      try
        jpegimage.Loadfromfile('d:\daten\pix\fraktal_1.jpg');
        bmp := tbitmap.Create;
        try
          bmp.assign( jpegimage );
          i:= 1;
          While ((i+1)*bmp.Width < printer.pagewidth) and
                ((i+1)*bmp.Height < printer.pageheight)
          Do
            Inc(i);
          outputrect := Rect( 0, 0, i*bmp.width, i*bmp.height );
          try
            printer.Orientation := poLandscape;
            printer.begindoc;
            PrintBitmap( bmp, outputrect );
          except
            printer.abort;
            raise;
          end;
          printer.enddoc;
        finally
          bmp.Free;
        end;
    
      finally
        jpegimage.free
      end;
    
    end;

     

    • Like 1

  10. 10 hours ago, Willicious said:

    Tag added, apologies for the oversight.

     

    If I remove everything to do with the colour shifting, the text does display. The colour-shifting code is actually mostly copied over and then adapted from another part of the project (where it does work). The only thing I couldn't copy was a line which started "Result := ", so it's very likely that this line is what actually draws the hue-shifted bitmap.

     

    Adding "Result :=" here generates an undeclared identifier error, so I just left it out and hoped for the best. Clearly, though, I need something to explicitly say "draw the hue-shifted bitmap."

    Result is only available in a Function, while your current code is in a Procedure.

     

    Have you ever taken the time to read the Delphi Language Guide? It is part of the IDE main help file. It's a bit disturbing to see that such a basic thing has tripped you up...


  11. 42 minutes ago, Dave Craggs said:

    Hi I have a VCL application. Some of the forms stay visible when switching between windows desktops. The main form doesn't. 

     

    Couldn't see an obvious property causing ths.

     

    Any ideas?

    Is Application.MainformOnTaskbar set to true or false in the DPR file? Or are you using an ancient Delphi version that does not support this property? Do any of the misbehaving forms override the CreateParams method?


  12. You usually get that on lines that have been removed by the smart linker since it has concluded that this code is never executed.

     

    If you are sure that the code can be reached your source file may contain invalid line breaks (just CR or just LF instead of the CR LF pair). The IDE editor still breaks the line on such characters but it throws off the calculation of source code locations from the compiled binary. You can get such bad line breaks if you paste code copied from a web page or get source from an improperly configured version control system. As a test, place the editor's caret at the end of the line before the one with the missing dot and press the DEL key until the break is removed, then hit the RETURN key to insert a proper line break. Rebuild the project and see if the dot is now there.


  13. 23 hours ago, scienceguy said:

    Another question:

    I try to hide the scrollbars. My html document is only a few sentences such that no scrolling is needed, however the bar is still there. Even after

    adding the following code AFTER loading my html page

    Sorry, I cannot help you with that; my knowledge of TWebBrowser is pretty basic.


  14. How do you display the result? You can control the number of decimals displayed when converting a floating-point value from its internal binary (not decimal!) representation, but the exact syntax depends on the function you use (Write, WriteLn, Format, FormatFloat, FloatToStr, FloatToStrF etc. The run-time library has accumulated quite a number of such conversion functions over time. Oh, and the result of your multiplication is actually not exactly  99,49995 since the computer stores numbers as binary and not as decimal, and since it only has a limited number of bits available many decimal numbers cannot be stored without a small loss of precision. These errors accumulate over calculation steps...


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


  16. 19 hours ago, Jim Sawyer said:

    I use Delphi 10.2 and MySQL.  By default, the code exists in the 

     

       ...\Project\

     

    directory.   When the project is compiled, the Executable program is in the 

     

       ...\Project\Win64\Debug\

     

    directory.  I want to put my code in a

     

       ...\Project\AmeriVet\Current\

     

    directory, but still have the compiled executable program in the

     

       ...\Project\Win64\Debug\

     

    directory.  What do I need to do to make that happen?

     

    Thanks,

    Jim Sawyer

     

    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.


  17. 11 hours ago, Willicious said:

    I get undeclared identifiers almost every time I try to implement something in the project I'm working on. Here's an example:

     

    I'm trying to check the state of a condition called GameSpeed, which is defined in the unit GameWindow. In the unit LemGame, if I try to add "GameWindow" under "uses" at the top of the unit, I get a circular reference error. It's previously been explained to me that when this happens, I should list the unit under "implementation > uses" instead.

     

    Here's what I currently have (edited to fit it here😞

     

    
    unit LemGame
    
    implementation
    
    uses
      GameWindow;
    
    procedure TGame.Start(aReplay: Boolean = False);
    begin
      if GameSpeed = gspRewind then
      begin
        GameSpeed := gspNormal;
      end;
    end;

     

    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.


  18. On 3/27/2023 at 7:51 PM, PenelopeSkye said:

    I created a test database and pointed the connection string to it, and I found 1 other place where the database name is mentioned after searching in all files.

     

    Unfortunately although some of the code works to insert into the database, not everything does, and I am thinking that there are other places indicating the database that I am not finding by using the search function.

     

    Does anyone know how to find other places where code is pointed to a database or do I need to search through every object?

     

    Thanks!

    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.


  19. 1 hour ago, RTollison said:

    Ok here is overall process/issue. i have a microfocus cobol program that uses a runtime (exe) to open an cobol compiled object file. in that program it has logic for printing bitmaps. However, it requires that the bitmap be a saved file. I had created the dll to load base64 encoded data and converted to bitmap and saved to disk. Then the cobol program would read the file and print then delete the bitmap file. But the bitmap is for a customers signature that quality control says 'No you will not save it to disk and delete due to security reasons.' So now i need to change the process so that the dll can copy the bitmap to the cobol programs bitmap handle. i figure that i will have to change the cobol to open a blank/empty bitmap and then send that handle to the dll to get the signature bitmap loaded into the cobol program. Cobol side is limited in what it can do, so the dll was needed to read/convert/save the bitmap.

     

    Since this is not a full delphi process i just posted a general question and then would work out the details on my own.

    If the Cobol programm passes a HBITMAP to the DLL procedure the following may work:

     

    In the DLL procedure,

    1. create a TBItmap object
    2. assign the passed HBITMAP to that objects Handle property
    3. adjust with and height of the bitmap object to the signature bitmap's dimensions, if necessary
    4. draw the signature bitmap on the bitmap object's canvas (using Assign instead may recreate the bitmap Handle)
    5. set the bitmap Handle to 0 to disconnect the passed HBITMAP from the TBitmap object
    6. 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.


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

    • Like 2

  21. 4 hours ago, Pat Foley said:

    I tried the codegear dslusr and it would not allow dropping the control on a form in 64 mode. Controls could be placed on form in 32 mode though. I removed and made a fresh package that allows the controls to be placed on form. 🙂 

    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.

    • Thanks 1

  22. On 3/18/2023 at 4:36 PM, dummzeuch said:

    Has anybody ever implemented something like this in a Delphi program? Or did we all just sit there and tell everybody that this is not possible because the VCL is not thread safe?

    Sometimes it would be really nice to be able to create additional (VCL) controls in a background thread and then somehow pass these on to the main thread to add to a form. I never came around spending any time on this though.

    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.

×