Delphi FastReport 4和VCL样式错误
一些背景资料。我在一家非常小的公司工作,他最近将Delphi从版本6(!!!)升级到Rad Studio XE5,在10多年的时间里,情况确实发生了很大的变化。IDE和框架中的大多数东西似乎都得到了改进,但新的VCL样式特性存在很大的问题。它是非常马车,不符合我们从Borland回来的质量。我们已经做了很多调整和变通,以使事情顺利进行,但有一个问题目前确实困扰着我,它与FastReport4中的预览表单有关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
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,所以如果我使用它,会留下一些白色区域。另外,我只是在我们的应用程序中处理这个特定的工具栏,所以在这种情况下使用固定值是可以的。