Jump to content

Renate Schaaf

Members
  • Content Count

    126
  • Joined

  • Last visited

  • Days Won

    4

Posts posted by Renate Schaaf


  1. Just a note: Flickering when using styles can almost completely be eliminated by removing seBorder from the form's style elements. But if you prefer to see the buggy styled caption bar, you're out of luck:)


  2. Ok, here is the installable component. The dimming is not tied to visible anymore, but to a property Active, which can only be set at runtime. The control to be dimmed isn't tied to the parent at design time, instead there is a published property DimmedControl, which the parent will be set to at runtime (unless it's nil, then no dimming is possible). At design time the component can be dropped anywhere to design the child controls. DimmedControl can be changed at runtime.

    The attachment contains packages for runtime and design and a crude demo. I haven't changed aehimself's unit- and class names, which I should have done, but I'm too tired now.

    I'm using Delphi 10.3.3, it should work for 10.4.*, too.

     

    Instructions:

    Load BuildandDemo.groupproj

    Build DimPanel.bpl (runtime) for both Win32 and Win64

    Build DimPanelD.bpl (design)

    Install DimPanelD.bpl

    Open and run DemoDim

     

    The component is on the "Additional" tab. If TDimPanel is grayed under Win64, try to close and reopen the IDE.

    Hope it roughly works 🙂

    Edit: Bug in previous attachment

    The size was not set right initially, has been fixed by an override to Loaded

    DimPanel.zip

     

     

    • Like 2

  3. 31 minutes ago, aehimself said:

    The constructor can be the standard, just throw an AV if the specified owner is not a TWinControl.

    If you drop a component, the owner is always the form. That's one of the things. You could of course always drop it on the control you want to dim, then you've got the parent right. But some things need to be disabled at design time, the VisibleChanging for once. I'm working on something that doesn't blow up in your face, lets you design the child controls, and also allows you to specify a dimmed control other than what you can drop it on at design time ... say, a listbox or a pagecontrol. Much of this works really nicely with your runtime-only version.

    I want to get this done without having to write a designer. Maybe it's not worth the trouble and placing the controls at runtime is easy enough 🙂

    • Like 1

  4. 8 hours ago, aehimself said:

    I might also want to disable controls on the parent in VisibleChanging to ensure nothing can be focused by pressing tab as @Attila Kovacs suggested earlier.

    Good idea, also it's possible to parent the panel to the pagecontrol (I hadn't thought that it would work, but...). Then you also have the pagecontrol tabs disabled.

    https://imgur.com/48gzWCX  (how do you get images in here?)

    But for this some small changes must be made:

    Constructor TDimPanel.Create(inOwner: TWinControl);
    Begin
     ..........
     //******Width/Height instead of ClientWidth/ClientHeight
     Self.Width := Self.Parent.Width;
     Self.Height := Self.Parent.Height;
     Self.Anchors := [akLeft, akTop, akRight, akBottom];
     Self.BevelOuter := bvNone;
    End;
    Procedure TDimPanel.VisibleChanging;
    Begin
     inherited;
    
     If Not Self.Visible Then
     Begin
       Self.Resize;
       Self.UpdateBitmap; // UpdateBitmap is not called if Self.Visible is false...
       //********
       Self.BringToFront;  //BringToFront isn't called either, necessary for parent is TPageControl
     End
     Else
       _bitmap.SetSize(0, 0); // clear bitmap to free up memory
    End;

    Now it would be really nice if one could use it as a component so one can design the controls on it...


  5. 29 minutes ago, Remy Lebeau said:

    Basically, the shadow TForm uses its AlphaBlend/Value properties to provide the dimming effect, and its TransparentColor/Value properties to mask out holes in the shadow where individual controls want to peek through.

    Dang! That's like the sample I posted and then deleted. There's nothing one can think of without you guys having thought of it before... :classic_smile:


  6. 1 hour ago, aehimself said:

    ..unless you have VCL Styles active. Then it flickers like madness 🙂

    For very simple forms I use a Fake-Style, which improves drawing immensely.

    One could call RemoveStyle(self) in OnCreate and FakeStyle(self) in OnCreate or whenever the style changes:

     

    uses ... VCL.Controls, VCL.ComCtrls, VCL.Forms, VCL.Themes;
    //and what I forgot
    
    type
    
      TCrackControl = class(Vcl.Controls.TControl);
    
    procedure RemoveStyle(aControl: TControl);
    var
      i: integer;
    begin
      if (csDesigning in aControl.ComponentState) then
        exit;
      // I like to keep the style of the buttons and TabControls
      if not((aControl is TButton) or (aControl is TCustomTabControl)) then
        aControl.StyleElements := [];
      //keep the scrollbars of scrollboxes but get rid of the form's styled caption bar
      if (aControl is TScrollingWinControl) and (not(aControl is TForm)) then
      aControl.StyleElements:=[seBorder];
    
      if aControl is TWinControl then
        with TWinControl(aControl) do
          for i := 0 to ControlCount - 1 do
            RemoveStyle(Controls[i]);
    end;
    
    procedure FakeStyle(aControl: TControl);
    var
      BGColor, FontColor {
        , SelectedColor,
        SelectedFontColor
      } : TColor;
      i: integer;
    begin
      if (csDesigning in aControl.ComponentState) then
        exit;
      BGColor := StyleServices.GetStyleColor(scWindow);
      FontColor := StyleServices.GetStyleFontColor(sfWindowTextNormal);
      TCrackControl(aControl).Font.Color := FontColor;
      TCrackControl(aControl).Color := BGColor;
      if aControl is TWinControl then
        with TWinControl(aControl) do
          for i := 0 to ControlCount - 1 do
            FakeStyle(Controls[i]);
    end;

     


  7. 4 hours ago, aehimself said:

    Self.Canvas.Draw(0, 0, _bitmap, 128); draws only the top half of the panel.

    Maybe the bottom half gets alphablended away?  I noticed that black vanishes, which I don't understand. Everything is fine, when drawing a colored background first.

     

    Quote

    One more thing, this is not really going to work when resizing, as the parent of my dimmed control is the tabsheet (which I need the image of). When I take an image of the tabsheet while the dimmed panel is visible, it's image will be seen on the picture, slowly fading out everything in the process.

    On resize:

    You can send the panel to back, redraw its parent, capture the parent's bitmap, send the panel back to front. Surprisingly, there's hardly any flicker when doing this.

    ------------------------------- unless you use styles :classic_wacko:


  8. 3 hours ago, aehimself said:

    While the bitmap screenshot idea will work, it feels really hacky.

     

    Here's a different kind of hack:

    Design another form with a completely transparent background (transparentColor = true) and borderless.

    Place the controls you would have on the semitransparent panel on this form instead.

    When you want to dim your tabsheet, place a blank semitransparent panel as before.

    Then place the second form on top of the tabsheet and show it.

    If so desired, you can have the transparent form size and move (WM_Move) with the main form.

       (In the handler for WM_Move check that the transparent form is assigned, as it is called very early for the main form)

    Event handlers for the controls on the 2nd form can be assigned in the code of the main form to avoid circular reference.

    It works so far for me, you can certainly figure out how to deal with the rest of the nooks and crannies.

     

    This is fun! :classic_biggrin:

     

    Edit: I forgot the styles: you need to remove seClient and seBorder from the style elements of the transparent form

     


  9. 2 hours ago, aehimself said:

    ...one small question, though. Is it possible to make the panel transparent, but not the components on it?

    As you see, the code I referred to isn't mine, I just found it useful. But let me try 🙂

     

    Edit:

    The short answer seems to be that it isn't supported. When one tries to remove the layered style from the child controls of the panel they either get invisible or one gets a Win-Error. For the long answer I guess you have to go back to your bitmap-idea.

    This: https://www.codeguru.com/csharp/csharp/cs_controls/tutorials/article.php/c12323/Creating-NonTransparent-Controls-on-a-SemiTransparent-Window.htm is old, but looks good.


  10. This is my video-project on GitHub:

    https://github.com/rmesch/Bitmaps2Video

     

    I am presenting it here, because it is useful as it is, but could use some ideas for improvement.

     

    Features:

    • A Delphi-class to support encoding of a series of bitmaps and video clips to a video file
    • Requires the ffmpeg-library and is intended as an easy to use interface to this library
    • Versions for Win32/Win64 and a cross-platform version currently supporting Win32/Win64/Android32/Android64
    • Most popular file formats and codecs supported, more codecs contained in FFMpeg can be registered
    • Rudimentary support for adding an audio-stream
    • Demos for both versions, set up to compile and run "out of the box", as library files and support for their deployment to Android are included

     

    There are some problem areas though, the most important one in my opinion being threading issues with TBitmap under Android. For more see the readme and the demos.

     

    Critique, ideas, bug reports most welcome, maybe someone would even like to contribute, that would be delightful. There have been valuable contributions so far, but there are some areas which could use the input of an expert.

     

    Thanks for reading,

    Renate

    • Like 4
    • Thanks 1

  11. Please excuse my lack of knowledge here, I'm just starting to work with this Android stuff.

    Quote

    Does it mean the files contained in the folder returned by TPath.GetDocumentsPath

    I guess so.

    Quote

    If so, is there some reason why you cannot iterate the files in that folder, and just present them in a list box?

    Well, I think I know how to do this, but that wouldn't help the user to pick to right video file, I need the thumbnails.

    By browers I mean that every app that processes the file type gets displayed at the top of the window that opens. For example Google fotos, Samsung gallery, ...

    I just want to open the documents folder ("Eigene Dateien" in my German tablet).


  12. All I want is a substitute for an OpenFileDialog on Android, I mean, that can't be so hard, I thought.

    In particular I want the user to pick a video file and read its file name. I found this

    https://delphi-developers-archive.blogspot.com/2017/05/delphi-android-get-file-path-of-image.html

    and modified it a bit, so it either returns a valid file name or else fails:

     

    procedure TForm1.BrowseForVideoFile;
    var
      Data: Jnet_Uri;
      Intent: JIntent;
    begin
      // fMessageSubscriptionID: integer is a field of TForm1
      FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage
        (TMessageResultNotification, HandleActivityMessage);
      Intent := TJIntent.Create;
      Intent.setType(StringToJString('video/*'));
      Intent.setAction(TJIntent.JavaClass.ACTION_GET_CONTENT);
      MainActivity.startActivityForResult(Intent, 0);
    end;
    
    // when message is received
    procedure TForm1.HandleActivityMessage(const Sender: TObject;
      const M: TMessage);
    begin
      if M is TMessageResultNotification then
        if HandleIntentAction(TMessageReceivedNotification(M).Value) then
        begin
          // A valid filename has been returned
          // Do The Videofile processing
        end;
        Edit2.text := fVideoFilename;
    end;
    
    // This retrieves the file name the user picked, but reliably only if done per
    // opening MyDocuments
    function TForm1.HandleIntentAction(const Data: JIntent): Boolean;
    var
      P: TJavaObjectArray<Jstring>;
      // in case you want only specific fields... not used here. I have passed nil to get all the columns.
      C: JCursor;
      I: integer;
    begin
      P := nil;
      // The following makes no difference
      // P:=TJavaObjectArray<Jstring>.create(1);
      // P.Items[0]:=StringToJstring('_data');
    
      // this is suppose to give the information back to C ( : JCursor)
      C := MainActivity.getContentResolver.query(Data.getData, nil,
        // when projection is nil... it returns all columns. Ideally, you should only ask for the columns you need
        StringToJString(''),
        // java accepts nil... but you cannot give nil here, you need to give an empty JString
        nil, StringToJString(''));
      // java accepts nil... but you cannot give nil here, you need to give an empty JString
    
      C.moveToFirst;
      Result := false;
      for I := 0 to C.getColumnCount - 1 do
      begin
        if JStringToString(C.getColumnName(I)) = '_data' then
        // '_data' column contains the path... you can use this to create the filestream to upload or do whatever....
        begin
          // fVideoFilename is a field of the form
          fVideoFilename := JStringToString(C.getString(I));
          Result := true;
          Break;
        end;
      end;
      if not Result then
        fVideoFilename := '';
      // P.Free;
    end;

    My problem is, that this offers way too many browsers for the user to choose from, when all that really works is browsing MyDocuments.

    What is the right approach to limit the browsers to MyDocuments?

    Or is there an easier way to begin with?

     

    Thanks for reading,

    Renate


  13. 33 minutes ago, David Schwartz said:

    There are TONS of places throughout the VCL where the original developers could be accused of not thinking through the various use-cases enough

    That's my limited impression after a break of 12 years from Delphi. I paid for all versions up to 2006, now I'm using the community edition, and I am grateful for having the chance this way to come up to par with the new stuff, so I'm a bit reluctant to bash them. I answered here because of general interest in component design, not because I'm particularly interested in this component.

     

    1 hour ago, Kas Ob. said:

    2) Have a look at https://github.com/MahdiSafsafi/DDetours it can do magic, but does need special experience level, so the level you must have to use this library range from novice to guru, based on your mission, check it anyway you might need it in the furute.

    This looks good, I have it tagged.


  14. 38 minutes ago, Kas Ob. said:

    Simply put, sloppy work done by developers who don't understand the Delphi soul.

    I didn't dare to say that, but that's what I thought:)

     

    Now I wonder whether there is a way to make this safe short of changing the source code or writing a wrapper component with a TNetHTTPClient as a subcomponent and exposing its things as needed, which seems to be a lot of work.
     


  15. 8 hours ago, Magno said:

    OnReceiveData := ReceiveData;

    I'm a bit puzzled here, because usually it is a big no-no to assign code to a published event in a descendant component. Because the event is still published and anybody using your component can assign something else to this event and your added functionality is gone.

    Usually you should override the method which calls the event, add the functionality and call inherited.

    Only: Looking at the source code I see that this method (DoReceiveData) is both private and not virtual, so there's no chance to do it this way.

     

    I wonder whether there's a reason the Delphi developers did it that way, or why have they abandoned the usual component design patterns?

     

    Anyway, I would at least unpublish these events, along the lines in

    https://stackoverflow.com/questions/53677049/hide-properties-and-events-in-new-component

    • Like 4
×