Jump to content

A.M. Hoornweg

Members
  • Content Count

    446
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by A.M. Hoornweg


  1. Hello all,

     

    I have a tImagecollection with square transparent PNG images at 256x256 size which I want to downscale smoothly. The collection's interpolation mode is set to icIMModeHighQualityCubic.

     

    I notice that tVirtualImage gives much smoother image quality at 32x32 than tImage if I manually downscale the image using tImageCollection.GetBitmap().   

     

    I would very much like to get to the bottom of this.

    This is the code I use to manually extract and downscale an image from tImagecollection.

    Parameter "Targetimage" is just a TImage on some TPanel on a TForm. Am I doing something wrong?

     

     

    procedure LoadImageFromCollection(TargetImage: tImage; ImageName: string; Collection: TImageCollection;
      DesiredHeight: Integer);
    var
      tb: tbitmap;
      h,idx: Integer;
    begin
      idx := Collection.GetIndexByName(ImageName);
      if idx > -1 then
      begin
        h:=desiredHeight;
        if TargetImage.AlignWithMargins then
          h := h - TargetImage.Margins.Top - TargetImage.Margins.Bottom;
        TargetImage.Height := h;
        TargetImage.width := h;
        TargetImage.Transparent := True;
        tb := Collection.getbitmap(idx, h, h);
        try
          tb.AlphaFormat := afDefined;
          TargetImage.Picture.Bitmap.Assign(tb);
        finally
          tb.free;
        end;
      end;
    end;

     

     


  2. 3 hours ago, David Heffernan said:

    Not if the comctl v6 manifest hasn't been activated in your thread. You'll have comctl v5.8.

     

    You need to activate the comctl v6 manifest whenever your DLL is called and deactivate whenever it returns. Every function should activate on entry, deactivate on exit. 

     

    I do this in my Excel com add in. 

     

    Oww, that sounds like a pain.   But I think it should be possible to just pack a manifest alongside an existing application, without embedding it and damaging the digital signature?


  3. 9 minutes ago, Lajos Juhász said:

    You mean this reference at https://docwiki.embarcadero.com/Libraries/Sydney/en/Vcl.Controls.TImageList:

    Note: Image lists depend on Comctl32.dll. If the system does not have the latest version installed, there may be problems getting images to appear.

    The problem isn't tImageList related - the DLL used tImageList in the past without problems or manifest requirements until I replaced it with tImageCollection & tVirtualImageList.

     

    Also, the operating system is Windows 10, so comctl32 on the system is most certainly the current version.  By the way, with a properly manifested application, the new icons display correctly even on Windows XP which is vintage so I don't think it's a matter of an outdated comctl32.

     

    ( edit: I compiled the test application under Delphi 11 fixpack 1 with {$SETPEOSVERSION 5.1} {$SETPESUBSYSVERSION 5.1} to make it work on XP).


  4. Hello all,

     

    I am using tImageCollection and tVirtualImageList inside a COM DLL to display some images on buttons etc.  This COM DLL is an update to an existing version - the calling processes are existing programs, many of which were compiled with older Delphi versions.

     

    I'm observing a very strange phenomenon: the images on the buttons in the DLL are not displayed if the calling executable does not have a manifest.  They are only displayed if the calling executable has a manifest. I find no reference in the Delphi documentation that tImageCollection has manifest requirements.

     

    Can anyone shed some light on this?

     

    My reason for asking: I cannot update the existing legacy applications with a new manifest - they are digitally signed and inserting a new manifest would break the signature.. 


  5. 4 minutes ago, emileverh said:

    I agree. DPI awareness in Delphi 11 is a mess!!  People who are telling; you have to develop in 96dpi mode do not own a high-end PC with a high resolution screen. The forms are incredible small in that way, it's impossible to design a form. And frames are the worst part....

    One simple workaround is to run Delphi inside a VMWare VM and to configure that VM so, that its resolution is 1920x1080 and "stretched".  That way Delphi will run at a resolution of 2K even though the monitor really has a much higher resolution.

     

     

    As for DPI awareness in compiled Delphi applications themselves, I have a whole bunch of workarounds to make things work better. The key for me was to inherit every TForm from a common ancestor and to override some virtual methods in that ancestor  (DoBeforeMonitorDPIChanged, DoAfterMonitorDPIChanged, Loaded, Docreate and some more ...)  to fix the most egregious bugs.  That way any form derived from that common ancestor behaves much better.

     

     

     

     

     

     

     

     

     


  6. 1 hour ago, Sherlock said:

    Well cancel Windows 11 then. No need for it anyway. Only for testing. Some folks still use WinXP, being stuck on Win10 till MS comes to their senses seems not that long.

    Some things (like Per-Monitor DPI-awareness V2) are really awkward to test through Remote Debugging.  Delphi 11 still has tons of issues regarding DPI Awareness, for which I had to devise workarounds until Embarcadero hopefully gets it right. I expect some improvements to this feature in Windows 11 and it would be really nice to be able to debug it natively rather than remotely.

     

     


  7. 14 minutes ago, Attila Kovacs said:

    With your logic not only the VM but an encrypted HDD would not be recoverable anymore.

    A virtual HDD encrypted by VMWare would not be recoverable anymore indeed.

     

    [edit]

    I make weekly backups of my VM's on an external HDD. If they were cryptographically tied to my notebook's hardware, they would become worthless if my notebook broke.


  8. Hello all,

     

    this question isn't strictly Delphi related but rather Windows 11 / VMWare Workstation related.

     

    I develop under Windows 10 X64 in a VMWare virtual machine. I'd like to migrate this VM to Windows 11 but there are a few things that currently make this unfeasible IMHO:

     

    - before adding a virtual TPM module, VMWare insists on encrypting all virtual hard drives (*.vmdk files) of the VM.

    - The encryption key contains information of the host machine. The drives will only decrypt on the same host machine.

    - So if my notebook dies, I'm basically scr##ed because the VM won't run anywhere else.

     

     

    That's totally unacceptible to me. The whole purpose of virtualization is having virtual hardware so the VM's are independent of the host hardware and its life span. A backup of a VM shouldn't be worthless if my hardware breaks!  I currently have VM's that were created on at least 3 different machines and they still run fine, thanks to a vmx entry uuid.action= "keep" that tells VMWare to maintain the machine identity even if the VM is moved to a different machine.

     

     

    So... What gives? Is there a viable workaround for this problem? 

     

    I know about the undocumented managedvm.autoAddVTPM="software" vmx entry but let me warn you, that has dire side effects: instead of encrypting the vmdk files as a whole it will just encrypt the header area of the vmdk files. That is even worse because you can't undo it - the decryption password isn't revealed. And it's not documented if this header encryption is machine dependent or not.

     

     

     

     

     

     

    • Like 1

  9. Hello all,

     

    I have a question regarding dynamic methods in Delphi that handle Windows messages. The documentation is not clear about this.  Suppose I declare a Windows message handler in my form like 

     

     procedure WMNCCreate (var Message: TWMNCCreate); message WM_NCCREATE;

     

    with a trivial implementation like

    procedure WMNCCreate(var Message: TWMNCCreate); 
    begin
      inherited;
    end;

     

    how is the inherited() call resolved by Delphi? Is it resolved by method name or by message number?

    In other words, does inherited() call an ancestor's method having the name WMNCCreate,  or does it call any method that handles message number WM_NCCreate regardless of the method's name ?

     

     

     

     


  10. 5 hours ago, baoquan.zuo said:
    
    type
      {$I jedi.inc}
      {$IFDEF DELPHI28_UP}
        {$DEFINE HasPixelsPerInch}
      {$ENDIF}
    
      TBaseDataModule = class(TDataModule)
      {$IFNDEF HasPixelsPerInch}
      protected
        // Ignore PixelsPerInch property in TFrame introduced since Delphi 11
        procedure DefineProperties(Filer: TFiler); override;
        procedure IgnorePixelsPerInch(Reader: TReader);
      {$ENDIF}
      end;
    
    {$IFNDEF HasPixelsPerInch}
    procedure TBaseDataModule.DefineProperties(Filer: TFiler);
    begin
      inherited DefineProperties(Filer);
      Filer.DefineProperty('PixelsPerInch', IgnorePixelsPerInch, nil, False);
    end;
    
    procedure TBaseDataModule.IgnorePixelsPerInch(Reader: TReader);
    begin
      Reader.ReadInteger;
    end;
    {$ENDIF}

    I created a base module to solve this kind of issue 

    I like the idea, but it would require changing existing projects. Existing datamodules, services and frames would need to inherit from new classes.  Maybe it would be more elegant to write a patching unit for older Delphi versions that hooks into the dfm reader and ignores PixelsPerInch. 


  11. 16 hours ago, Uwe Raabe said:

    They are visual in the designer and the designer has to know the resolution the datamodule has been designed last.

     

    I know this is annoying and even error prone. That's why I made a suggestion to store all dfm with an implicite PixelsPerInch value of 96 and scale only for designing: Option to design in Screen PPI but save in 96 PPI

    That may cause the non-visual components on the datamodule moving out of sight in the designer when the datamodule is opened about 2-3 times.

    AFAIK there is no property "scaled" in tService and tDatamodule, so why would the designer need to know PixelsPerInch if it's not supposed to do any scaling? There's "Width" and "Height" so it can still create the window big enough to display the placed components.

     

     

    As a workaround, I've written a command line application that detects if a DFM is tdatamodule or a tservice and if so, removes the "pixelsperinch" property. Maybe I should do the same for tFrame because I intend to always use 96 dpi in design mode. The tool is now integrated in my Finalbuilder build scripts and so far it looks promising.  If it is error-free, I may use it inside a pre-commit hook in SVN as well.

     

     

     

     


  12. Hello all,

     

    I'm having some trouble debugging DLL's in Delphi 11, trouble which I did not have before in Delphi 10.4.   
    My DLL is compiled in debug mode and has remote debugging symbols.

     

     

    If I specify the host executable (Run-> Parameters -> Debugger -> Host application) and execute the process, breakpoints will not fire in my DLL.

    But....  if I start the application manually and tell the debugger to attach to the process, breakpoints will fire in the DLL without any problems.

     

     

    This workaround works, but it is super uncomfortable and slows me down.  Any idea how I can get the debugging situation back to normal?

     

     

     

     

     

×