WriteConsoleOutput使用动态数组

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

我已经编写了这个小程序来演示WriteConsoleOutput。只要我使用静态数组,Everythings就可以正常工作。

但如果我改变CI的声明

CI: array of array of CHAR_INFO;

CI: array [0 .. 80, 0 .. 25] of CHAR_INFO;

当然初始化它:

  SetLength(Ci, 80, 25);

然后我只会在屏幕上看到垃圾。

uses
  Winapi.Windows,
  System.Console,
  System.Diagnostics,
  System.SysUtils;

var
  CH: THandle;
//  CI: array of array of CHAR_INFO;
  CI: array [0 .. 80, 0 .. 25] of CHAR_INFO;
  Character, Attribute: Integer;
  X, Y: COORD;
  z: SMALL_RECT;
  i, j: Integer;
  StopWatch: TStopwatch;

begin
  CH := CreateFile('CONOUT$', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);

  X.X := high(CI) - low(CI);
  X.Y := high(CI[high(CI)]) - low(CI[high(CI)]);
  Y.X := 0;
  Y.Y := 0;
  z.Left := low(CI);
  z.Top := low(CI[low(CI)]);
  z.Right := high(CI);
  z.Bottom := high(CI[low(CI)]);

  StopWatch := TStopwatch.StartNew;

  for Character := 65 to 65 + 26 - 1 do
    for Attribute := 0 to 15 - 1 do
    begin
      for i := low(CI) to high(CI) do
        for j := low(CI[i]) to high(CI[i]) do
        begin
          CI[i, j].UnicodeChar := Char(Character);
          CI[i, j].Attributes := Attribute;
          CI[i, j].AsciiChar := AnsiChar(Character);
        end;

      WriteConsoleOutput(CH, @CI, X, Y, z);
    end;

  StopWatch.Stop;
  Console.Title := StopWatch.ElapsedMilliseconds.ToString;
  Console.ReadLine;
end.

PS。该示例使用DelphiConsole

UPDATE

根据MBo给出的答案,我将代码更改为以下内容:

uses
  Winapi.Windows,
  System.Console,
  System.Diagnostics,
  System.SysUtils;
var
  CH: THandle;
  CI: array of CHAR_INFO;
  Character, Attribute: Integer;
  X, Y: COORD;
  Z: SMALL_RECT;
  i, j: Integer;
  StopWatch: TStopwatch;
begin
  CH := CreateFile('CONOUT$', GENERIC_READ or GENERIC_WRITE, FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  X.X := 80;
  X.Y := 25;
  Y.X := 0;
  Y.Y := 0;
  Z.Left := Y.X;
  Z.Top := Y.Y;
  Z.Right := X.X;
  Z.Bottom := X.Y;
  SetLength(CI, X.X * X, Y);

  StopWatch := TStopwatch.StartNew;

  for Character := 65 to 65 + 26 - 1 do
    for Attribute := 0 to 15 - 1 do
    begin
      for i := 0 to X.X * X.Y do
      begin
        CI[i].UnicodeChar := Char(Character);
        CI[i].Attributes := Attribute;
        CI[i].AsciiChar := AnsiChar(Character);
      end;

      WriteConsoleOutput(CH, CI, X, Y, Z);
    end;

  StopWatch.Stop;
  Console.Title := StopWatch.ElapsedMilliseconds.ToString;
  Console.ReadLine;
end.
delphi console
1个回答
3
投票

静态数组占用连续的内存区域,@CI参数是数组内容的地址。

但是动态数组已经是指针,所以@CI是指向数据的指针的地址,而不是数据的地址。对于在类似情况下使用1D动态数组,可以使用@A[0]技巧。

而且 - 2D动态数组不会占用连续的内存区域,所以你没有机会在这里使用它。

但是你可以在长度为80*25的一维动态数组中重新打包2D数据并使用提到的语法。第y行和第x列的屏幕元素的表达式为CI[y * screenwidth + x]

© www.soinside.com 2019 - 2024. All rights reserved.