UniSoft

Forum Replies Created

Viewing 20 posts - 1 through 20 (of 40 total)
  • Author
    Posts
  • in reply to: TsGauge animation is freeze #70769
    UniSoft
    Participant

    Just tried to run on a virtual machine VMWare with the Windows 7 x64, same issue.

    in reply to: TsGauge animation is freeze #70766
    UniSoft
    Participant

    No, I didn’t touch or recompile.
    Windows 7

    in reply to: FormDialogs skinned label issues #70736
    UniSoft
    Participant

    If you have source code
    open file: acSBUtils.pas

    find function:
    function TacStaticWnd.PaintText(DoCalc: boolean): TRect;

    fix:
    Flags := DT_EDITCONTROL or DT_WORDBREAK or DT_NOCLIP or {DT_TABSTOP or} DT_VCENTER; // or MAKEWORD(0, 10);


    @Support

    For what here MAKEWORD(0, 10)?
    it turns to be DT_NOPREFIX or DT_EXTERNALLEADING

    PS: This bug presence since v16.18

    • This reply was modified 2 years, 9 months ago by UniSoft.
    UniSoft
    Participant

    that is a fixed code, with comments what was wrong

    UniSoft
    Participant

    See update, there is a bug in x64

      PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
      TAbsoluteIndirectJmp = packed record
        OpCode: Word; // $FF25(Jmp, FF /4)
        Addr: Int32; //PPointer <-- here should be signed Int32 (4 bytes) not a pointer (8 bytes in x64!)
      end;
    
    function acGetActualAddr(Proc: Pointer): Pointer;
    var
      J: PAbsoluteIndirectJmp;
    begin
      J := PAbsoluteIndirectJmp(Proc);
      if J.OpCode = $25FF then
    {$IFDEF WIN64}
        Result := PPointer(PByte(Proc) + J.Addr + 6 {Instruction Size})^ // Int32(Proc) - Here You cuts 64-bit pointer to 32-bit in x64
    {$ELSE}
        Result := PPointer(J.Addr)^
    {$ENDIF}
      else
        Result := Proc;
    end;
    in reply to: I would really like to see the TsPaintBox… #70204
    UniSoft
    Participant

    In my humble opinion, I think it could be a good idea to have a TsPaintBox optimized to combine the application’s drawing with AlphaSkins’ painting in a non flickering maner.

    Container (example TPanel) draws its background and then draws child controls (TPaintBox)
    region of all windowed child controls excluded, and therefore there is no flicker,
    but not TPaintBox! if exclude it’s region as well then you will have to draw background yourself,
    but TPaintBox doesn’t have any drawing and therefore it is just transparent (if you don’t draw anything)
    cause parent already take care of draw background.
    That is the reason of flickering (it is a pause between draw parent background and draw PaintBox content).
    You can’t easy avoid it.
    So it is not the problem of AlphaControls.
    With AlphaControls (active and skinned) there will not be any flicker, cause all drawing done
    in shadow buffer (FCommonData.FCacheBmp).
    So if to inherit it from TGraphicControl then there are nothing to change…
    If inherit it from TWinControl then you will get almost the same what I did
    (I just add some common function, like the draw caption and Marquee rect)

    • This reply was modified 3 years, 4 months ago by UniSoft.
    in reply to: I would really like to see the TsPaintBox… #70201
    UniSoft
    Participant

    Maybe we can just inherit TsPaintBox from the TsPanel?

    Initially I inherit it from TCustomControl.
    But when I write the code to draw the background
    I found that the code will be too version dependent (latest uses styles etc..)
    (while you keep compatibility with old versions of delphi).
    Why I don’t inherit it from TsPanel?
    Actually TsPanel is a container and therefore contains a lot of code to support/draw/update/repaint child controls,
    what will slow down. Need to remove all code related to child controls.
    I would also like to add frame highlighting (Glow?) on mouse hover, like on TsEdit.

    Your control seems to be way more complicated than a TPaintBox.

    So that is the main Idea!
    If need a simple there is standard TPaintBox,
    if need advanced functionality use TsPaintBox (or what ever else, the name can be changed TsAdvPaintBox, TsDrawBox, …).

    And since your demo is based on a TsPanel, I don’t understand what benefit a TsPaintBox could bring you.

    TsPanel is a container…
    just advanced PaintBox, which can be used as a base to draw whatever you want, if you can’t find ready component.
    Example, see screenshot…
    I didn’t found ready controls as I want, so I draw it myself on TPaintBox,
    cause I have few TPaintBox and all of them have the same features,
    I subclass the class… (or how is it calling right?) (Sorry, I can be incorrect in terminology)
    BTW: That is why it is not good if it will be TsPanel,
    no need that added functionality affects all TsPanel(s) on the form.

    type
      TPaintBox = class(Vcl.ExtCtrls.TPaintBox)
        // ...
      end;
    
      TMainForm = class(TForm)
        ...
        pboxOutVoltage: TPaintBox;
        pboxOutCurrent: TPaintBox;
        pboxOutCurrent: TPaintBox;
        ...
      end;

    Now why TPaintBox is shit…
    1. It does’t have a window,
    2. extra flickering if place it on Panel/GroupBox/TabSheet/etc (when skinning disabled, even if AC not used at all), and to redraw need to call direct Paint(), but it cause some another crazy problems
    (for example it can randomly disappear suddenly, just empty space…
    Only DoubleBuffered=False helps to solve it, but it starts super extra flickering)
    3. Cause I have some animation, repeat, delay I need a 4 timers, so what to do? create 4 TTimers?
    Instead of 4 TTimer(s) I use FWindowHandle := AllocateHWnd(TimerWndProc);
    And can use SetTimer/KillTimer
    4. It doesn’t get mouse wheel messages, key press, etc…
    5. Not fill background according to the selected skin
    6. etc

    Attachments:
    You must be logged in to view attached files.
    in reply to: I would really like to see the TsPaintBox… #70193
    UniSoft
    Participant

    yes, TsPanel can be used…
    but better if it will be another class.
    I already made component myself (demo exe included),
    take a look, maybe you can add it?

    Attachments:
    You must be logged in to view attached files.
    UniSoft
    Participant

    Can I offer you a nice very compact hook engine MinHook.
    https://github.com/TsudaKageyu/minhook
    It is written in pure C…

    I wrote a delphi unit, see attach
    (in file sSkinManager.txt you can see all changes for sSkinManager.pas)
    all what need is to add unit uMinHook to the project, and add to uses
    also copy the folder with obj files
    (alternatively you can compile sources yourself,
    there is a source code of library and the C++Builder project)

    The advantages:
    + supports x86 and x64
    + thread safe
    + small footprint
    + easy to use
    + correctly applies hooks (pause all threads)
    + supports the hotpatch (if available)
    + creates trampolines

    Attachments:
    You must be logged in to view attached files.
    UniSoft
    Participant

    By the way, here is one more BUG
    in WIN64 – Addr should be signed INT32 (or just Integer)

      PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
      TAbsoluteIndirectJmp = packed record
        OpCode: Word;   // $FF25(Jmp, FF /4)
        Addr: Cardinal;//PPointer;
      end;
    UniSoft
    Participant

    I fix problems

    1. Grip lose the background, after move the window
    (if a window loses a focus or resize then it redraws normally)

    When window get Activated…

    procedure TacDialogWnd.Ac_WMNCActivate(var Message: TMessage);
    ...
        SkinData.BGChanged := True; /// <<<<<<< NOTE This
        InvalidateRect(CtrlHandle, nil, False);
        RedrawWindow(CtrlHandle, nil, 0, RDW_ALLCHILDREN or RDW_FRAME or RDW_INVALIDATE); // Repaint of child controls
    ...
    end;

    End here is the problem…

    procedure InitBGInfo(const SkinData: TsCommonData; const PBGInfo: PacBGInfo; ...
    begin
      with SkinData do
        if PBGInfo^.PleaseDraw then begin
          if BGChanged and (FOwnerControl <> nil) then // here FOwnerControl is nil
            FOwnerControl.Perform(SM_ALPHACMD, AC_PREPARECACHE_HI, 0);
    
          if not BGChanged then // <strong><<<<<<< The problem is HERE, I just commented this line</strong>
            with PBGInfo^ do
              BitBlt(DrawDC, R.Left, R.Top, WidthOf(R), HeightOf(R), FCacheBmp.Canvas.Handle, Offset.X, Offset.Y, SRCCOPY);
    ...
    end;

    2. Each time (for example when dialog gets the focus), popups tooltip,
    even if the mouse cursor is in a different location
    (on the screenshot you can see the second tooltip under cursor).

    This is again the problem of AnVir 🙁
    when AnVir active, then the ‘toolbarwindow32’ gets the message WM_SETFOCUS,
    and when ‘toolbarwindow32’ gets that message it makes hot button with index 1 (that is why popup tooltip)
    (also found that behavior from winxp source code).
    If you want make it work with AnVir, you can just suppress that message,

    procedure TacToolBarWnd.acWndProc(var Message: TMessage);
    var
      R: TRect;
      P: TPoint;
    begin
      case Message.Msg of
      WM_SETFOCUS:
        begin
          GetWindowRect(CtrlHandle, R);
          GetCursorPos(P);
          if not PtInRect(R, P) then
          begin
            Message.Result := 1;
            Exit;
          end;
        end;
      end;
      ...
    end;
    • This reply was modified 3 years, 4 months ago by UniSoft.
    • This reply was modified 3 years, 4 months ago by UniSoft.
    UniSoft
    Participant

    No need add 2, otherwise EDIT overlay the button
    very good can see on AutumnSky skin

    function TacComboBoxWnd.ButtonRect: TRect;
    ...
    begin
      Style := GetWindowLong(CtrlHandle, GWL_STYLE);
      if not DlgMode or (Style and CBS_DROPDOWNLIST = CBS_DROPDOWNLIST) then
        w := GetComboBtnSize(Skindata.SkinManager, SkinData.CommonSkinData.PPI) // + 2 //UniSoft
      else
    Attachments:
    You must be logged in to view attached files.
    UniSoft
    Participant

    Still have a few problems…
    1. Grip lose the background, after move the window
    (if a window loses a focus or resize then it redraws normally)
    2. Each time (for example when dialog gets the focus), popups tooltip,
    even if the mouse cursor is in a different location
    (on the screenshot you can see the second tooltip under cursor).

    Attachments:
    You must be logged in to view attached files.
    UniSoft
    Participant

    Hello!
    I Checked v16.12
    still have the same crash… 🙁

    I can clearly see in the debugger what exactly is going on…
    Look

    1. AC sets the new Window Pointer

       InitializeACWnd
          OldProc := Pointer(GetWindowLong(CtrlHandle, GWL_WNDPROC));
          NewWndProcInstance := {$IFDEF DELPHI6UP}Classes.{$ENDIF}MakeObjectInstance(acWndProc);
          SetWindowLong(CtrlHandle, GWL_WNDPROC, LONG_PTR(NewWndProcInstance));

    2. Now AnVir do the same (and saves OldProc which is actually already = NewWndProcInstance)
    3. Closing Dialog
    4. Get message WM_DESTROY (Notice! it doesn’t get WM_CLOSE, at least I don’t see it in WinSpy)
    Now the AnVir first pass processing to the old wndProc (what is actually = NewWndProcInstance!)
    on process of WM_DESTROY – AC restores original OldProc, after that AC deletes NewWndProcInstance
    FreeObjectInstance(ListSW.NewWndProcInstance);

       procedure UninitializeACWnd(...
            if Assigned(ListSW.OldProc) then begin
              SetWindowLong(Handle, GWL_WNDPROC, LONG_PTR(ListSW.OldProc));
              ListSW.OldProc := nil;
              if Assigned(ListSW.NewWndProcInstance) then begin
                {$IFDEF DELPHI6UP}Classes.{$ENDIF}FreeObjectInstance(ListSW.NewWndProcInstance);
                ListSW.NewWndProcInstance := nil;
              end;
            end

    5. process returns back to the AnVir, where this shit also thinking that restores old WndProc
    SetWindowLong(Handle, GWLP_WNDPROC, PrevWndFunc);
    BUT! it is a pointer to already deleted NewWndProcInstance
    And follow send the messages

            SendMessageA(Handle, TB_DELETEBUTTON, btncount + 1, 0);
             SendMessageA(Handle, TB_DELETEBUTTON, btncount    , 0);

    That is the actually reason!


    BUG with StatusBar still not fixed as well 🙁
    to see it:
    1. Launch ASkinDemo.exe
    2. Select skin: Standard theme
    3. Move cursor over StatusBar
    Fixed code is few posts up…

    UniSoft
    Participant

    Up to you
    If you need I can check it before release…

    UniSoft
    Participant

    just some explain, what doing AnVir, now you can see why it cause crash

      case Msg of
      WM_DESTROY, WM_CLOSE: 
        begin
          // here is the problem!!! 
          // this call should be after clean up, not before
          CallWindowProc(PrevWndFunc, ...); // !!!
    
         // After called Destructor all bottom crap can cause an error
    	  
          // this called on init time, then add custom buttons
          //  so btncount cotaint number of buttons in toolbat before add new buttons
          //btncount := SendMessageA(Handle, TB_BUTTONCOUNT, 0, 0); //
    	  
          // restore previous WndProc
          SetWindowLong(Handle, GWLP_WNDPROC, PrevWndFunc);
    	  
          // delete custom buttons
          SendMessageA(Handle, TB_DELETEBUTTON, btncount + 1, 0);
          SendMessageA(Handle, TB_DELETEBUTTON, btncount    , 0);
        end;
      end;
    UniSoft
    Participant

    This helps to solve that crash
    comment WM_DESTROY
    What for need to process both WM_DESTROY and WM_NCDESTROY?
    WM_NCDESTROY is the last one, so should be enough.

    procedure TacDialogWnd.acWndProc(var Message: TMessage);
    var
      PS: TPaintStruct;
      X, Y, i: integer;
      cR, rClient: TRect;
    begin
      case Message.Msg of
        {WM_DESTROY,} WM_NCDESTROY: begin
          if SkinData.FCacheBmp <> nil then
            SkinData.FCacheBmp.Assign(nil);
      ...
        end;
    UniSoft
    Participant

    I found problem…
    “AnVir Task Manager” adds an icon to the tool bar of open/save dialog and it is the reason why it crash.
    But anyway strange, if to disable skinning, then there is no crash.
    BTW, message 1046 – probably TB_DELETEBUTTON
    shit.. and I had this problem before, just forgot :(.

    UniSoft
    Participant

    I tried to make demo, but it is crashed only under debugger
    First I commented try..except
    then compile release version…
    if I run it from rad studio in debugger, then it crash…
    If I open exe in any debugger (OllyDbg, x64dbg, …) they catch Access Violation…

    function TacMainWnd.CallPrevWndProc(const Handle: hwnd; const Msg: longint; const WParam: WPARAM; var LParam: LPARAM): LRESULT;
    var
      M: TMessage;
    begin
      if Assigned(OldWndProc) then begin
        M.Msg := Msg;
        M.WParam := WParam;
        M.LParam := LParam;
        M.Result := 0;
        OldWndProc(M);
        Result := M.Result;
        LParam := M.LParam;
      end
      else
        if Assigned(OldProc) then
          //try
            Result := CallWindowProc(OldProc, Handle, Msg, WParam, LParam)
          //except
          //  Result := 0;
          //end
        else
          Result := 0;
    end;

    Alternate link to demo (with compiled exe)
    __https__://mega.nz/file/xO5BiQpJ#MRE7uX5rWFFbe1gKJ8snE1Fruj8XJiXfuKUqxXNcP_g

    Attachments:
    You must be logged in to view attached files.
    UniSoft
    Participant

    Windows 7
    RAD 10.4 with last 2 updates

    By the way, bug with GripPos is not fixed

    function TsStatusBar.GripPos: TPoint;
    begin
      if FCommonData.SkinManager <> nil then
        with FCommonData.SkinManager, SkinData.CommonSkinData do
          if IsValidImgIndex(GripRightBottom) then begin
            Result := Point(Width - ma[GripRightBottom].Width - BorderWidth, Height - ma[GripRightBottom].Height - BorderWidth);
            Exit;
          end;
    
      Result := Point(Width - GetSystemMetrics(SM_CXSIZEFRAME), Height - GetSystemMetrics(SM_CYSIZEFRAME));
    end;
Viewing 20 posts - 1 through 20 (of 40 total)