Delphi FastReport 4和VCL样式错误

Delphi FastReport 4和VCL样式错误,delphi,delphi-xe5,fastreport,vcl-styles,Delphi,Delphi Xe5,Fastreport,Vcl Styles,一些背景资料。我在一家非常小的公司工作,他最近将Delphi从版本6(!!!)升级到Rad Studio XE5,在10多年的时间里,情况确实发生了很大的变化。IDE和框架中的大多数东西似乎都得到了改进,但新的VCL样式特性存在很大的问题。它是非常马车,不符合我们从Borland回来的质量。我们已经做了很多调整和变通,以使事情顺利进行,但有一个问题目前确实困扰着我,它与FastReport4中的预览表单有关 工具栏周围有一个白色边框 打印对话框中的控件和其他控件未对齐或位置错误 我们真的想用VC

一些背景资料。我在一家非常小的公司工作,他最近将Delphi从版本6(!!!)升级到Rad Studio XE5,在10多年的时间里,情况确实发生了很大的变化。IDE和框架中的大多数东西似乎都得到了改进,但新的VCL样式特性存在很大的问题。它是非常马车,不符合我们从Borland回来的质量。我们已经做了很多调整和变通,以使事情顺利进行,但有一个问题目前确实困扰着我,它与FastReport4中的预览表单有关

  • 工具栏周围有一个白色边框
  • 打印对话框中的控件和其他控件未对齐或位置错误
  • 我们真的想用VCL风格给我们的软件一个新的面貌,所以我们希望有一个解决这些问题的办法

    重现问题的步骤:

  • 创建新的VCL表单应用程序
  • 在项目>选项>应用程序>外观中检查VCL样式,例如Sapphire Kamri
  • 将TfrxReport报表组件添加到表单中
  • 双击组件frxReport1并添加一个页面标题栏,以获得一些内容
  • 添加一个TButton,并在OnClick事件中调用frxReport1.ShowReport()
  • 运行程序并单击按钮。在预览表单中,您现在可以看到工具栏被白色边框包围,看起来很奇怪
  • 单击最左侧的“打印”按钮以打开“打印”对话框,您可以看到“组框”和“取消”按钮是如何放置在客户端区域之外的
  • 你有什么解决问题的办法或建议吗

    编辑:RRUZ给出了一个很好的答案,但是他解决问题1的方法有一些副作用,所以我决定简化代码,只是手动在工具栏周围绘制边框。像这样:

    procedure TToolBarStyleHookEx.PaintNC(Canvas: TCanvas);
    begin
      if TToolBar(Control).BorderWidth>0 then
      begin
        Canvas.Pen.Width := 4;
        Canvas.Pen.Color := StyleServices.GetStyleColor(scWindow);
        Canvas.Brush.Style := bsClear;
        Canvas.Rectangle(2,2,Control.Width-2,Control.Height-1);
      end;
      inherited;
    end;
    

    实际上,这两个问题似乎都是VCL风格的缺陷

    1) 问:工具栏周围有一个白色边框

    答:
    TToolBarStyleHook
    StyleHook不处理BorderWidth属性。因此,您必须创建一个新的样式挂钩,并覆盖
    PaintNC
    ,以克服此问题

    type
      TToolBarStyleHookEx = class(TToolBarStyleHook)
      protected
        procedure PaintNC(Canvas: TCanvas); override;
      end;
    
    { TToolBarStyleHookEx }
    procedure TToolBarStyleHookEx.PaintNC(Canvas: TCanvas);
    var
      Details: TThemedElementDetails;
      LStyle: TCustomStyleServices;
      R: TRect;
    begin
      if TToolBar(Control).BorderWidth>0 then
      begin
        LStyle := StyleServices;
        R := Rect(0, 0, Control.Width, Control.Height);
        Details.Element := teToolBar;
        Details.Part := 0;
        Details.State := 0;
        if LStyle.HasTransparentParts(Details) then
          LStyle.DrawParentBackground(Handle, Canvas.Handle, Details, False);
        LStyle.DrawElement(Canvas.Handle, Details, R);
      end;
      inherited;
    end;
    
    这样登记

    initialization
      TCustomStyleEngine.RegisterStyleHook(TToolBar, TToolBarStyleHookEx);
    
    2) 问:打印对话框中的控件和其他控件未对齐或位置错误

    答:这似乎是一个与
    t FORMSTYLEHOOK
    有关的问题,您有3种选择

    1) 您可以编辑frxPrintDialog单元并增加表单的宽度

    2) 您可以修补窗体样式挂钩

    3) 您可以在运行时更改打印对话框的宽度

    检查此代码,使用
    HCBT\u ACTIVATE
    hook在运行时更改对话框的宽度

    var
    
     hhk: HHOOK;
    
    function CBT_FUNC(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    const
      ClassNameBufferSize = 1024;
    var
     hWindow: HWND;
     RetVal : Integer;
     ClassNameBuffer: Array[0..ClassNameBufferSize-1] of Char;
     i : integer;
    begin
       Result := CallNextHookEx(hhk, nCode, wParam, lParam);
       if nCode<0 then exit;
       case nCode of
         HCBT_ACTIVATE:
         begin
           hWindow := HWND(wParam);
           if (hWindow>0) then
           begin
              RetVal := GetClassName(wParam, ClassNameBuffer, SizeOf(ClassNameBuffer));
              if (RetVal>0) and SameText(ClassNameBuffer, 'TfrxPrintDialog') then
              for i:= 0 to Screen.FormCount-1 do
              if (SameText(Screen.Forms[i].ClassName, 'TfrxPrintDialog')) and (Screen.Forms[i].Width<=563) then
                Screen.Forms[i].Width:=Screen.Forms[i].Width+8;
           end;
         end;
       end;
    
    end;
    
    Procedure InitHook();
    var
      dwThreadID : DWORD;
    begin
      dwThreadID := GetCurrentThreadId;
      hhk := SetWindowsHookEx(WH_CBT, @CBT_FUNC, hInstance, dwThreadID);
      if hhk=0 then RaiseLastOSError;
    end;
    
    Procedure KillHook();
    begin
      if (hhk <> 0) then
        UnhookWindowsHookEx(hhk);
    end;
    
    initialization
      InitHook();
    
    finalization
      KillHook();
    
    var
    hhk:HHOOK;
    函数CBT_FUNC(nCode:Integer;wParam:wParam;lParam:lParam):LRESULT;stdcall;
    常数
    ClassNameBufferSize=1024;
    变量
    hWindow:HWND;
    RetVal:整数;
    ClassNameBuffer:字符的数组[0..ClassNameBufferSize-1];
    i:整数;
    开始
    结果:=CallNextHookEx(hhk、nCode、wParam、lParam);
    如果nCode0)那么
    开始
    RetVal:=GetClassName(wParam、ClassNameBuffer、SizeOf(ClassNameBuffer));
    如果(RetVal>0)和SameText(ClassNameBuffer,'TfrxPrintDialog'),则
    对于i:=0到Screen.FormCount-1 do
    
    if(SameText(Screen.Forms[i].ClassName,'TfrxPrintDialog'))和(Screen.Forms[i].WidthPlease每个问题只有一个问题。FR有一个工具可以重新编译和更改语言。请查看StartMenu…好的,我已上载到。可以只删除问题3吗,因为1和2密切相关?我已用我的评论回答了FR的问题,因此您可以删除该问题;o)谢谢,我将研究重新编译的问题。我见过它,但不知道它到底做了什么。只是“重新编译”一词吓得我不敢进一步调查,但我现在就开始行动。非常感谢!我真的没想到会有答案!您的解决方案对问题2和问题1都非常有效,但当我将鼠标移到工具栏上时,它会闪烁,有时“缩放”组合框和页码编辑框会消失。你也有这种症状吗?我一定是瞎了。现在我可以在您的屏幕截图中看到组合框和编辑不可见:)关于工具栏样式挂钩的副作用,我决定简化事情,只是手动绘制工具栏周围的边框。我已经用这个解决方案编辑了我的文章。这个问题似乎与工具栏上的控件(TEdit,TSpin)有关。如果没有这些控件,则答案上的样式挂钩可以正常工作。我现在没有太多时间来深入研究这个问题,但我知道你找到了另一种解决方法。作为建议,请尝试使用borderwith属性而不是使用固定值。是的,它在没有特殊控件的情况下可以工作,但仍会闪烁。如果stylehook未激活,工具栏不会闪烁,至少在我的计算机上是这样。但你的回答让我找到了一个足够好的解决方案,所以谢谢你:)我一开始使用了borderwidth,但实际上它是2而不是4,所以如果我使用它,会留下一些白色区域。另外,我只是在我们的应用程序中处理这个特定的工具栏,所以在这种情况下使用固定值是可以的。