如何在 Pascal 中获取 IP 地址
How to get IP address in Pascal
我在尝试查看 IP 地址并在消息框中显示时遇到这两个错误
错误看起来像这样
[dcc32 Error] Unit1.pas(38): E2010 Incompatible types: 'PAnsiChar' and
'PWideChar' => Error1
和
[dcc32 Error] Unit1.pas(40): E2010 Incompatible types: 'string' and
'array[1..1024] of Byte' => Error2
我可以在 C/C++ 中做到这一点,但我想在 Delphi
中尝试一些新的东西
我的源代码是这样的
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: array[1..1024] of byte;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrlA(hInet, PChar(url), nil, 0, 0, 0); //Error 1
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead); // Error 2
showmessage(buffer);
end;
end.
请问我做错了什么?
编辑
好的,InternetOpenUrl
成功了,但是,它仍然在 showmessage(buffer)
上给我错误
代码现在看起来像这样
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: array[1..1024] of byte;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
showmessage(buffer);
end;
end.
编辑2
我的代码现在看起来像这样
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: String;
bytesRead: DWORD;
url : String;
szMessage : String;
i : integer;
begin
//url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar('https://icanhazip.com'), nil, 0, 0, 0);
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
//showmessage(buffer);
Label1.Caption := buffer;
end;
end.
第一个错误发生是因为您调用了函数的 AnsiChar 版本。
使用 InternetOpenUrl
代替 InternetOpenUrlA
。
第二个发生在您预期的下面一行。 ShowMessage 需要 string
而不是 array of byte
。
编辑:
要从要传递给 ShowMessage 的字节数组中获取字符串,您需要知道发送字节的编码。假设是 UTF-8,转换可以简单地完成:
ShowMessage(TEncoding.UTF8.GetString(Slice(buffer, bytesRead)))
编辑 2:
好的,对于 XE8,您需要做更多的工作。
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: TBytes;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
SetLength(buffer, 1024);
InternetReadFile(hFile,@buffer[0],Length(buffer),bytesRead);
showmessage(TEncoding.UTF8.GetString(buffer, 0, bytesRead));
end;
在 C/C++ 中,您通常使用以 NUL 结尾的字符串 - 并自己分配存储空间来保存该字符串。这就是您在代码中使用 BYTE 数组所做的。
在 Delphi 中,string
是原生类型,而不仅仅是指向 NUL 终止字符数据的指针。
根据您提供的错误消息,错误发生在调用 ShowMessage 时,而不是调用 InternetReadFile 时。
您需要将字符串变量传递给 ShowMessage。
你可以试试这个:
var
szMessage: String;
i: Integer;
SetLength(szMessage, bytesread);
for i =1 to bytesread do
szMessage[i]:=buffer[i-1];
ShowMessage(szMessage);
有一些方法可以更紧凑地完成此操作,但作为最近从 C++ 转向主要使用 Delphi 的人,我认为以这种方式查看操作有助于理解两种语言之间的差异.
我在尝试查看 IP 地址并在消息框中显示时遇到这两个错误
错误看起来像这样
[dcc32 Error] Unit1.pas(38): E2010 Incompatible types: 'PAnsiChar' and 'PWideChar' => Error1
和
[dcc32 Error] Unit1.pas(40): E2010 Incompatible types: 'string' and 'array[1..1024] of Byte' => Error2
我可以在 C/C++ 中做到这一点,但我想在 Delphi
中尝试一些新的东西我的源代码是这样的
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: array[1..1024] of byte;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrlA(hInet, PChar(url), nil, 0, 0, 0); //Error 1
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead); // Error 2
showmessage(buffer);
end;
end.
请问我做错了什么?
编辑
好的,InternetOpenUrl
成功了,但是,它仍然在 showmessage(buffer)
代码现在看起来像这样
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: array[1..1024] of byte;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
showmessage(buffer);
end;
end.
编辑2
我的代码现在看起来像这样
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: String;
bytesRead: DWORD;
url : String;
szMessage : String;
i : integer;
begin
//url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar('https://icanhazip.com'), nil, 0, 0, 0);
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
//showmessage(buffer);
Label1.Caption := buffer;
end;
end.
第一个错误发生是因为您调用了函数的 AnsiChar 版本。
使用 InternetOpenUrl
代替 InternetOpenUrlA
。
第二个发生在您预期的下面一行。 ShowMessage 需要 string
而不是 array of byte
。
编辑: 要从要传递给 ShowMessage 的字节数组中获取字符串,您需要知道发送字节的编码。假设是 UTF-8,转换可以简单地完成:
ShowMessage(TEncoding.UTF8.GetString(Slice(buffer, bytesRead)))
编辑 2: 好的,对于 XE8,您需要做更多的工作。
procedure TForm1.Button1Click(Sender: TObject);
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: TBytes;
bytesRead: DWORD;
url : String;
begin
url := 'https://icanhazip.com';
hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
SetLength(buffer, 1024);
InternetReadFile(hFile,@buffer[0],Length(buffer),bytesRead);
showmessage(TEncoding.UTF8.GetString(buffer, 0, bytesRead));
end;
在 C/C++ 中,您通常使用以 NUL 结尾的字符串 - 并自己分配存储空间来保存该字符串。这就是您在代码中使用 BYTE 数组所做的。
在 Delphi 中,string
是原生类型,而不仅仅是指向 NUL 终止字符数据的指针。
根据您提供的错误消息,错误发生在调用 ShowMessage 时,而不是调用 InternetReadFile 时。
您需要将字符串变量传递给 ShowMessage。
你可以试试这个:
var
szMessage: String;
i: Integer;
SetLength(szMessage, bytesread);
for i =1 to bytesread do
szMessage[i]:=buffer[i-1];
ShowMessage(szMessage);
有一些方法可以更紧凑地完成此操作,但作为最近从 C++ 转向主要使用 Delphi 的人,我认为以这种方式查看操作有助于理解两种语言之间的差异.