я получаю эти две ошибки, пытаясь просмотреть 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
.
Второе происходит в строке ниже, чем вы ожидаете. ПоказатьСообщение ожидает 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;
спасибо Уве. InternetOpenUrl работал, теперь это showmessage(buffer), все еще дает мне ошибки
лемме обновить код.
изменение на строку возвращает нарушение прав доступа. Позвольте мне показать вам, как выглядит мой код на этот раз
См. мое редактирование этого ответа для примера преобразования байтов в строку.
он возвращает это как ошибку, сэр [dcc32 Error] Unit1.pas(45): E2250 Нет перегруженной версии GetString, которую можно было бы вызвать с этими аргументами
Вот почему я попросил версию Delphi, которую вы используете. Если ничего не указано, я всегда предполагаю самое последнее.
Delphi XE8 — это версия Delphi.
Я добавил пример для XE8
В C/C++ вы обычно используете строку с завершением NUL и выделяете память для хранения этой строки самостоятельно. Это то, что вы сделали в своем коде с массивом BYTE.
В Delphi string
— это нативный тип, а не просто указатель на символьные данные с нулевым завершением.
Из предоставленного вами сообщения об ошибке ошибка возникает при вызове 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, я думаю, что такой взгляд на операцию помогает понять различия между двумя языками.
Пожалуйста, добавьте версию Delphi, которую вы используете.