如何正确声明StreamLn

How to correctly declare StreamLn

我正在尝试编译我的程序,但出现此错误:

Undeclared indentifier 'StreamLn'

我什至尝试下载 PSock.dcu 并将其放入库中,但它没有编译,看起来它可以与 delphi 5,

压缩
unit ResourceInfo;

interface

uses
  Classes, SysUtils, Windows;

type
  TResourceInfo = class;

  TDfmMode = ( dfmData, dfmResource, dfmASCII, dfmBinary);

  TDfm = class
  private
    FOwner: TResourceInfo;
    FName: string;
    FData: TStream;

    procedure SetName(const Value: string);
    procedure SetOwner(const Value: TResourceInfo);

  public
    constructor Create(AOwner: TResourceInfo);
    destructor Destroy; override;

    function SaveToFile(FileName: TFileName; Mode: TDfmMode): Boolean;

    property Data: TStream read FData;
    property Name: string read FName write SetName;
    property Owner: TResourceInfo read FOwner write FOwner;
  end; {TDfm}

  TResourceInfo = class(TComponent)
  private
    FActive: Boolean;
    FDfms: TList;
    FExeFileName: TFileName;
    FModule: THandle;
    FOnActivate: TNotifyEvent;
    FOnDeactivate: TNotifyEvent;

    procedure SetExeFileName(const Value: TFileName);
    procedure SetActive(const Value: Boolean);
    function  GetDfms(Index: Cardinal): TDfm;
    function  GetDfmCount: Cardinal;

  protected
    procedure Clear;

  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;

    function  AddDfm(const Name: string; AData: TMemoryStream): Integer;
    procedure DeleteDfm(const Name: string);
    property  DfmCount: Cardinal read GetDfmCount;
    property  Dfms[Index: Cardinal]: TDfm read GetDfms;
    procedure EnumDfmNames;
    property  Module: THandle read FModule;

  published
    property Active: Boolean read FActive write SetActive;
    property ExeFileName: TFileName read FExeFileName write SetExeFileName;

    property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;
    property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate;
  end; {TResourceInfo}

procedure Register;

implementation

uses
 Winsock;

resourcestring
  rsErrorLoadingExeFile = 'An error ocurred loading file %s, it may not be an executable module';

procedure Register;
begin
  RegisterComponents('+HCU', [TResourceInfo]);
end; {Register}

{ TResourceInfo }

function TResourceInfo.AddDfm(const Name: string; AData: TMemoryStream): Integer;
var
  FDfm: TDfm;
begin
  FDfm := TDfm.Create(Self);
  FDfm.Name := Name;
  FDfm.Data.Size := AData.Size;
  FDfm.Data.Seek(0, 0);
  AData.Seek(0, 0);
  FDfm.Data.CopyFrom(AData, AData.Size);
  Result := FDfms.Add(FDfm);
end; {TResourceInfo.AddDfm}

constructor TResourceInfo.Create(AOwner: TComponent);
begin
  inherited;

  FActive := False;
  FDfms := TList.Create;
  FModule := 0;
end; {TResourceInfo.Create}

destructor TResourceInfo.Destroy;
begin
  Clear;
  FDfms.Free;

  inherited;
end; {TResourceInfo.Destroy}

function CB_EnumDfmNameProc(hModule: THandle; lpszType, lpszName: PChar; lParam: Integer): Boolean; stdcall;
var
  ms: TMemoryStream;
  rs: TResourceStream;
  Buffer: array of Byte;
begin
  with TResourceInfo(lParam) do
    begin
      rs := TResourceStream.Create(TResourceInfo(lParam).Module, lpszname, lpszType);
      try
        ms := TMemoryStream.Create;
        try
          try
            SetLength(Buffer, 4);
            rs.Read(Buffer[0], SizeOf(Buffer));
            if string(Buffer) = 'TPF0' then
              begin
                rs.Seek(0, 0);
                ObjectBinaryToText(rs, ms);
                ms.Seek(0, 0);
                AddDfm(StrPas(lpszName), ms);
              end;
          except
            raise;
          end;
        finally
          ms.Free;
        end;
      finally
        rs.free;
      end;
    end;

  Result := True;
end; {CB_EnumDfmNameProc}

procedure TResourceInfo.EnumDfmNames;
begin
  if FModule > 0 then
    EnumResourceNames(FModule, RT_RCDATA, @CB_EnumDfmNameProc, Integer(Self));
end; {TResourceInfo.EnumDfmNames}

procedure TResourceInfo.DeleteDfm(const Name: string);
var
  i: Cardinal;
begin
  if FDfms.Count > 0 then
    for i := Pred(FDfms.Count) downto 0 do
      if UpperCase(TDfm(FDfms[i]).Name) = UpperCase(Name) then
        begin
          FDfms.Delete(i);
          Break;
        end;
end; {TResourceInfo.DeleteDfm}

procedure TResourceInfo.SetActive(const Value: Boolean);
begin
  if FActive <> Value then
    begin
      if Value then
        begin
          if FModule > 0 then
            FreeLibrary(FModule);

            (* LOAD_LIBRARY_AS_DATAFILE
               If this value is given, the function does a simple mapping of the file into the
               address space. Nothing is done relative to executing or preparing to execute the
               code in the mapped file. The function loads the module as if it were a data file.
               You can use the module handle that the function returns in this case with the Win32
               functions that operate on resources. Use this flag when you want to load a DLL in
               order to extract messages or resources from it, and have no intention of executing
               its code.If this value is not given, the function maps the file into the address
               space in the manner that is normal for an executable module. The behavior of the
               function is then identical to that of LoadLibrary in this regard. *)

          FModule := LoadLibraryEx(PChar(FExeFileName), 0, LOAD_LIBRARY_AS_DATAFILE);
          if not (FModule >= 32) then
            raise Exception.CreateFmt(rsErrorLoadingExeFile, [FExeFileName]);
          if Assigned(FOnActivate) then
            FOnActivate(Self);
        end
      else
        begin
          Clear;
          if FModule > 0 then
            begin
              FreeLibrary(FModule);
              FModule := 0;
            end;
          if Assigned(FOnDeactivate) then
            FOnDeactivate(Self);
        end;
      FActive := Value;
    end;
end; {TResourceInfo.SetActive}

procedure TResourceInfo.SetExeFileName(const Value: TFileName);
begin
  if FExeFileName <> Value then
    FExeFileName := Value;
end; {TResourceInfo.SetExeFileName}

function TResourceInfo.GetDfms(Index: Cardinal): TDfm;
begin
  Result := TDfm(FDfms[Index]);
end; {TResourceInfo.GetDfms}

function TResourceInfo.GetDfmCount: Cardinal;
begin
  Result := FDfms.Count;
end; {TResourceInfo.GetDfmCount}

procedure TResourceInfo.Clear;
begin
  if FDfms.Count > 0 then
    while FDfms.Count > 0 do
      FDfms.Delete(0);
end; {TResourceInfo.Clear}

{ TDfm }

constructor TDfm.Create(AOwner: TResourceInfo);
begin
  inherited Create;

  FData := TMemoryStream.Create;
  FName := '';
  SetOwner(AOwner);
end; {TDfm.Create}

destructor TDfm.Destroy;
begin
  FData.Free;
  inherited;
end; {TDfm.Destroy}


function TDfm.SaveToFile(FileName: TFileName; Mode: TDfmMode): Boolean;

  function EndOfStream(Stream: TStream): Boolean;
  begin
    with Stream do
      Result := Position = Size;
  end; {EndOfStream}

var
  fs: TFileStream;
  ms: TMemoryStream;
  s: string;
  i, j: Byte;
begin
  fs := TFileStream.Create(FileName, fmCreate or fmShareExclusive);
  try
    FData.Seek(0, 0);

    case Mode of
      dfmASCII:
        begin
          ms := TMemoryStream.Create;
          try
            s := FName + ' RCDATA' + #13#10 + '{';
            StreamLN(fs, s);

            ObjectTextToBinary(FData, ms);
            ms.Seek(0, 0);

            while not EndOfStream(ms) do
              begin
                s := '''';

                for i := 0 to 15 do
                  begin
                    if ms.Read(j, SizeOf(j)) = 0 then
                      Break;
                    s := Concat(s, Format('%2.2x', [j]));
                    if (i = 15) or EndOfStream(ms) then
                      s := Concat(s, '''')
                    else
                      s := Concat(s, ' ');
                  end;

                if EndOfStream(ms) then
                  s := Concat(s, #13#10 + '}');
                StreamLN(fs, s);
              end;

          finally
            ms.Free;
          end;
        end;

      dfmBinary:
        ObjectTextToBinary(FData, fs);
    end;

  finally
    fs.Free;
  end;
end; {TDfm.SaveToFile}

procedure TDfm.SetName(const Value: string);
begin
  if FName <> Value then
    FName := Value;
end; {TDfm.SetName}

procedure TDfm.SetOwner(const Value: TResourceInfo);
begin
  FOwner := Value;
end; {TDfm.SetOwner}

end.

如何才能申报成功?

您需要实现此功能,或将声明此功能的单元添加到您的 uses 部分。

在我看来,WinSock 单元没有 StreamLn 功能(因为 PowerSock 的 PSock.pas 单元使用 Winsock 作为导入单元)。

PSock.pas 中的 StreamLn 函数只是在调用传递的 TStream 参数的 TStream.WriteBuffer 方法之前将 CRLF 序列添加到作为参数传递的字符串。

Here's the google cache snapshot 来自 PSock.pas

的 Powersock 源代码