Delphi 11.3 和 Delphi 12.1 中的 Visual Basic 6.0 OCX 问题

问题描述 投票:0回答:1

我在 Delphi 中使用 Visual Basic 6.0 OCX 时遇到宽度和高度问题。

当我将一些 OCX 控件拖放到 Delphi 12.1 中的窗体上时,OCX 的宽度和高度属性设置为 0(零),即使在对象检查器中也无法更改这些值。这些 OCX 控件在 Delphi 7 中完美工作。我还禁用了所有视觉清单,因此它在经典 Windows 模式下运行。

我试图理解为什么这些问题出现在较新版本的 Delphi 中。

这些 OCX 是由我以前工作的公司开发的,它们在 Delphi 7 中运行没有任何问题。

delphi delphi-7 ocx
1个回答
0
投票

以下是 Olaf Monien 发布的问题报告内容 https://embt.atlassian.net/servicedesk/customer/portal/3/RSB-209

某些 ActiveX/OleControls 以零大小呈现。 IE。宽度/高度 无论您在设计或运行时做什么,都会回落到 (0,0) 这 似乎与以下事实有关:其中一些控件不 响应

SetExtent()
,返回“E_Fail”。这不是“随机 error2,但根据 MS 文档,它是为组件设计的 要么没有 UI,要么在内部独立设置尺寸 他们的遏制控制。

VCL.OleCtrls.pas
中的相关代码过去几次没有改变 版本,所以它在伊卡利亚并不是什么新鲜事。还是值得入手的 已修复,因为 ActiveX 仍在旧项目中使用,已迁移到 12。

该行为的原因显然是某些 ActiveX 控件 不会响应

SetExtent()
所调用的
SetBounds()
VCL.OleCtrls.pas
。这不是一个“随机”错误,但可能是 设计 - 根据 MS 文档:

如果一个对象的大小是固定的,也就是说,如果它不能由它的对象来设置 容器,IOleObject::SetExtent 应该返回 E_FAIL。这总是 具有链接对象的情况,其大小由其链接设置 来源,而不是容器。

在这些情况下,Delphi 只是将 ActiveX 的边界重置为零 - 这至少不方便。

VCL.OleCtrls.pas
中的代码也有一些奇怪的HighDPI 计算,但这些似乎并不影响这个bug。
AWidth = 100
将导致 2645(对于 96dpi 屏幕),这至少看起来是 有疑问。我在 MS 文档中找不到有关这些单位的任何内容 不过,用在
SetExtent()
中。

                        MulDiv(AHeight, 2540, Screen.PixelsPerInch)); ```

Here is a proposal for a fixed `TOleControl.SetBounds(ALeft, ATop,
AWidth, AHeight: Integer);`

```delphi procedure TOleControl.SetBounds(ALeft, ATop, AWidth,
AHeight: Integer); var   LRect: TRect;   Temp: TPoint;   LResult:
HResult;   LIsVisible: boolean; begin   if ((AWidth <> Width) and
(Width >= 0)) or ((AHeight <> Height) and (Height >= 0)) then   begin
    LResult := S_OK;
    LIsVisible := (FMiscStatus and OLEMISC_INVISIBLEATRUNTIME) = 0;
    //Only call SetExtent if control has visible UI at runtime
    if LIsVisible then
    begin
      Temp := Point(MulDiv(AWidth, 2540, Screen.PixelsPerInch),
                    MulDiv(AHeight, 2540, Screen.PixelsPerInch)); {$IFDEF WIN64}
      LResult := FOleObject.SetExtent(DVASPECT_CONTENT, @Temp); {$ELSE}
      LResult := FOleObject.SetExtent(DVASPECT_CONTENT, Temp); {$ENDIF}
    end;
    // UI won't respond to SetExtend, use default dimensions for design time
    if ((LResult <> S_OK) or (not LIsVisible)) then
    begin
      if (Height > 0) and (Width > 0) then
      begin
        AWidth := Height;
        AHeight := Width;
      end
      else
      begin
        AWidth := 25;
        AHeight := 25;
      end;
    end;
    if FOleInplaceObject <> nil then
    begin
      LRect := Rect(Left, Top, Left+AWidth, Top+AHeight);
      FOleInplaceObject.SetObjectRects(LRect, LRect);
    end;   end;   inherited SetBounds(ALeft, ATop, AWidth, AHeight); end; ```

**Steps to reproduce**

Install and Import an ActiveX control, such as SysTray_OCX.zip from
here: [Sample Code : ActiveX Controls][2]

Note: this control (like many others) depends on the VB5 Runtime.

Note 2: MS does no longer offer an official link - due to it's age
http://www.tools4vb.de/download/vb5run.exe

Create a new VCL app, and drop a "cSysTray" component onto the main
form.

**Result:** component is on form, with dimension set to "zero". You can only find the component using the structure pane.

**Expected:** Component should show up as 25x25 px component - like any non-visual component (TFDQuery etc…)
© www.soinside.com 2019 - 2024. All rights reserved.