【问题标题】:Project Project1.exe raised exception class ERangeError with message 'Range check error'Project Project1.exe 引发异常类 ERangeError,并带有消息“范围检查错误”
【发布时间】:2023-03-18 00:40:02
【问题描述】:

我正在阅读一本关于 Windows API 的旧 Delphi 书籍。这是一个例子。

unit Unit1;

interface

uses
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
    System.Classes, Vcl.Graphics,
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
    TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
    private
        { Private declarations }
    public
        { Public declarations }
    end;

var
    Form1: TForm1;

implementation

{$R *.dfm}

{ Register the Window Class }
function RegisterClass: Boolean;
var
    WindowClass: TWndClass;
begin
    { setup our new window class }
    WindowClass.Style := CS_HREDRAW or CS_VREDRAW; { set the class styles }
    WindowClass.lpfnWndProc := @DefWindowProc;     { point to the default window procedure }
    WindowClass.cbClsExtra := 0;                   { no extra class memory }
    WindowClass.cbWndExtra := 0;                   { no extra window memory }
    WindowClass.hInstance := hInstance;            { the application instance }
    WindowClass.hIcon := 0;                        { no icon specified }
    WindowClass.hCursor := 0;                      { no cursor specified }
    WindowClass.hbrBackground := COLOR_WINDOW;     { use a predefined color }
    WindowClass.lpszMenuName := nil;               { no menu }
    WindowClass.lpszClassName := 'TestClass';      { the registered class name }

    { now that we have our class set up, register it with the system }
    Result := Winapi.Windows.RegisterClass(WindowClass) <> 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    hWindow: HWND;
begin
    { Step 1: Register our new window class }
    if not RegisterClass then
    begin
        ShowMessage('RegisterClass failed');
        Exit;
    end;

    { Step 2: Create a window based on our new class }
    hWindow := CreateWindowEx(0, { no extended styles }
        'TestClass',             { the registered class name }
        'New Window',            { the title bar text }
        WS_OVERLAPPEDWINDOW,     { a normal window style }
        CW_USEDEFAULT,           { default horizontal position }
        CW_USEDEFAULT,           { default vertical position }
        CW_USEDEFAULT,           { default width }
        CW_USEDEFAULT,           { default height }
        0,                       { no owner window }
        0,                       { no menu }
        hInstance,               { the application instance }
        nil                      { no additional information }
        );

    { Step 3: If our window was created successfully, display it }
    if hWindow <> 0 then
    begin
        ShowWindow(hWindow, SW_SHOWNORMAL);
        UpdateWindow(hWindow);
    end
    else
    begin
        ShowMessage('CreateWindow failed');
        Exit;
    end;
end;

end.

用户界面非常简单。我只需拖动一个按钮并将其放在表单上。但是,当我使用Embarcadero® Delphi 11.0 Version 28.0.42600.6491 运行程序并单击表单上的按钮时,我得到Project Project1.exe 引发异常类ERangeError 并带有消息“范围检查错误”。。之后,我得到了这个错误。

谁能帮忙看看问题出在哪里?

顺便说一句,我刚刚尝试了 Delphi 7,该程序运行正常。当我单击按钮时,会弹出一个空窗口。

【问题讨论】:

  • 根据错误消息,Delphi IDE (bds.exe) 正在尝试自动恢复 System.SysUtils.pas。您是否可能有未保存的更改(如果您尝试保存它,IDE 应该会抱怨)然后您的 IDE 崩溃了?在这种情况下,我可能会尝试重新安装 Delphi。
  • 我在安装时尝试了代码(Delphi 10.4 版本 27.0.40680.4203),它工作正常。

标签: delphi winapi vcl createwindowex


【解决方案1】:

CW_USEDEFAULT 常量的值与 CreateWindowEx 函数的声明不一致。 将以下代码添加到 Button1Click 顶部的 var 部分附近:

const
  CW_USEDEFAULT = -MaxInt - 1;

【讨论】:

  • 你不能简单地将Winapi.Windows.CW_USEDEFAULT 转换为Integer 吗? CreateWindowEx(..., Integer(CW_USEDEFAULT), ...); 否则,只需使用 {$R-} 关闭围绕 CreateWindowEx() 调用的范围检查@
  • 在 Delphi 10.4 版本 27.0.40680.4203 中,它被声明为 const CW_USEDEFAULT = DWORD($80000000);(如果在调用 CreateWindowEx 时使用,则只生成 W1012)。 Integer 和 DWORD 都是 32 位的,所以即使 Delphi 的 CreateWindowEx 接口使用整数代替 DWORD,它仍然与导出的 DLL 函数二进制兼容。
  • 谢谢,它有效。 @RemyLebeau 的建议也有效。
  • @fritten "它被声明为const CW_USEDEFAULT = DWORD($80000000);" - 是的,因此,将DWORD 传递给Integer 参数时会发生范围检查错误并启用范围检查,因为该值高于MaxInt
  • @RemyLebeau:是的,你完全正确。但是,我看不出它与这个问题有什么关系。
猜你喜欢
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 2013-03-20
  • 2010-11-01
  • 2011-07-16
  • 1970-01-01
相关资源
最近更新 更多