Jump to content
plumothy

Issue With TForm.AlphaBlend and AlphaBlendValue

Recommended Posts

In my Delphi project, the availability of some features depends on the user's licence. So, a Basic licence will not allow access to Advanced features. However, I want Basic licence users to see what they are missing by placing a "No Entry" form over the restricted part of the application. I have a form with a No Entry sign and a couple of TLabels. The No Entry form has an AlphaBlendValue = 100 so that it is translucent - the user can see what's behind it and the two TLabels tell them what they are missing and what to do about it.

 

This is working nicely except for one thing: the AlphaBlendValue is having no effect so the form displays completely opaque (the user cannot see what is underneath).

 

I cannot upload my project because it is confidential and simply way too big. I have tried for many hours to reproduce this issue in various test projects but have been unable to do so - they all work perfectly!!

 

So, I can only conclude that there is some aspect of my project that is causing the No Entry form to display 100% opaque. I have wasted many hours changing things (pure trial and error), but nothing helped.

 

My only hope is that someone here has experienced the same (or similar) issue and managed to discover the cause.

 

Or, perhaps I am going about this the wrong way and there is a better solution?

 

Delphi 12.2 Enterprise
Windows 11 Professional

 

Here is the unit for the No Entry form:

unit NoEntryForm;

interface

uses
  System.SysUtils, Vcl.Controls, Vcl.Forms, SVGIconImage, Vcl.ExtCtrls, System.Classes, Vcl.StdCtrls;

type

  INoEntryForm = interface
    ['{085FB8DC-3E21-4A50-B4CC-006E9872BF62}']
    procedure ShowMe;
  end;


  /// <summary>
  /// A "no entry" panel to be displayed when a user attempts to access a feature to which their application licence does not permit access.
  /// It is intended to encourage the user to upgrade by showing them a glimpse of what they are missing.
  /// </summary>
  TfrmNoEntry = class(TForm, INoEntryForm)
    imgNoEntry: TSVGIconImage;
    pnlTop: TPanel;
    lblNoEntry: TLabel;
    lblPleaseUpgrade: TLabel;
    procedure ShowMe;
  public
    { Public declarations }
  end;

procedure ShowNoEntry(const strMessage: string; const ctlParent: TWinControl; const strCaption: string);

implementation

{$R *.dfm}

/// <summary>
/// Displays a "No Entry" form over the given control (ctlParent)
/// </summary>
/// <param name="strMessage">Message to the user (typically something about having to upgrade to access the inaccessible feature)</param>
/// <param name="ctlParent">The TWinControl descendant on which the No Entry form should be displayed (eg a TPanel for example)</param>
/// <param name="strCaption">The No Entry form's caption (typically "No Entry")</param>
procedure ShowNoEntry(const strMessage: string; const ctlParent: TWinControl; const strCaption: string);
begin
  for var i := 0 to ctlParent.ControlCount - 1 do begin
    if ctlParent.Controls[i] is TfrmNoEntry then
      exit;   // ctlParent already has a TfrmNoEntry so we can stop here
  end;

  var frmNoEntry := TfrmNoEntry.Create(nil);
  var FormInterface: INoEntryForm := frmNoEntry;

  frmNoEntry.Parent := ctlParent;
  frmNoEntry.TransparentColor := false;
  frmNoEntry.AlphaBlend := True;
  frmNoEntry.AlphaBlendValue := 100;
  frmNoEntry.Align := alNone;
  frmNoEntry.BoundsRect := ctlParent.BoundsRect;
  frmNoEntry.Anchors := [akLeft,akTop,akRight,akBottom];
  frmNoEntry.lblNoEntry.Caption := strCaption;
  frmNoEntry.lblPleaseUpgrade.Caption := strMessage;
  frmNoEntry.ShowMe;
end;

procedure TfrmNoEntry.ShowMe;
begin
  Show;
end;

end.

So, in my project if I need to display a No Entry form on top of Panel1 I just call ShowNoEntry;

ShowNoEntry('Text explaining why access is denied', Panel1, 'No Entry!');

 

Share this post


Link to post

The application needs a manifest with a compatibility entry for Windows 10.

Share this post


Link to post

Uwe Raabe - brilliant, thank you!!!

 

If only the Delphi documentation had mentioned that :classic_smile:

Share this post


Link to post
1 hour ago, Uwe Raabe said:

The application needs a manifest with a compatibility entry for Windows 10.

Does it have to be Win10 specifically?  Or is Win8 enough?  The ability to use the WS_EX_LAYERED style on child windows was added in Win8.

Share this post


Link to post

You also can use TDimPanel:

Blocking the access would simply require you to set .Visible to True, plus you can cover only parts of your window as well.

Share this post


Link to post
1 hour ago, Uwe Raabe said:

The application needs a manifest with a compatibility entry for Windows 10.

My joy was short lived.

With a manifest, my application does not maximize MDI windows properly. Large portions remain unpainted and menus are not merging correctly.

Back to the drawing board!

Share this post


Link to post
31 minutes ago, aehimself said:

You also can use TDimPanel:

Blocking the access would simply require you to set .Visible to True, plus you can cover only parts of your window as well.

This looks interesting - I'll give it a go tomorrow.

Share this post


Link to post
2 hours ago, plumothy said:

This looks interesting - I'll give it a go tomorrow.

Just tried it. Does not work (form remains opaque) unless I have a manifest. 

If I have a manifest then maximising MDI forms just produces a mess.

Share this post


Link to post
2 hours ago, plumothy said:

Just tried it. Does not work (form remains opaque) unless I have a manifest. 

If I have a manifest then maximising MDI forms just produces a mess.

Obviously you can't have both.

Share this post


Link to post
11 hours ago, plumothy said:

With a manifest, my application does not maximize MDI windows properly. Large portions remain unpainted and menus are not merging correctly.

You should file a bug report about that. Embarcadero spend a lot of effort revamping the MDI system in 12.0.

Share this post


Link to post

Thank you to everyone who has responded in this listing - you inspired me to look in the right place to solve the issue.

 

As is usually the case, it was my own fault! :classic_sad: 

 

I had a Custom Manifest file specified in the Project Options. The problem with that was the manifest file was missing (which must have happened after I specified it). Delphi does not tell you this when you build (perhaps it should - I'll suggest it to Embarcadero). This explains why my forms were being painted fully opaque.

 

After I corrected the manifest problem, MDI forms were not being painted correctly when maximized (large areas not painted at all). Again, my own fault! My MDI forms descend from a common ancestor (to ensure they all have a consistent appearance and behaviour). I discovered today that the ancestor form had AlphaBlend = True (and AlphaBlendValue = 255). I wouldn't have knowingly done that, so must have had a "senior moment" at some point (no-one else works on this project!). So with AlphaBlend = False, everything works the way I want it to.

 

All that explains why I could not reproduce the issue in a new test project.

 

Once again, thanks for your input guys.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×