codigo de Unit1.cpp
Código:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <System.JSON.hpp>
#include <ShellAPI.hpp>
#pragma hdrstop
#include "Unit1.h"
#include <vector>
#include <IdHTTP.hpp>
#include <System.NetEncoding.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "AdvCustomControl"
#pragma link "AdvWebBrowser"
#pragma resource "*.dfm"
TForm1 *Form1;
struct PreguntaSO
{
int id;
UnicodeString titulo;
};
std::vector<PreguntaSO> preguntas;
void TForm1::AgregarPreguntaALV(int questionId, UnicodeString title, int answerCount)
{
TListItem *item = ListView1->Items->Add();
item->Caption = title;
item->SubItems->Add(IntToStr(answerCount));
item->Data = (void*)(intptr_t)questionId; // Guardamos el QuestionID
}
UnicodeString URLEncode(const UnicodeString &s)
{
UnicodeString outS;
for (int i = 1; i <= s.Length(); i++)
{
wchar_t c = s[i];
if ((c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z') ||
c == '-' || c == '_' || c == '.' || c == '~')
{
outS += c;
}
else if (c == ' ')
{
outS += "%20";
}
else
{
outS += "%" + IntToHex(c, 2);
}
}
return outS;
}
void TForm1::CargarRespuestas(int questionId)
{
if (questionId <= 0) return;
UnicodeString url =
"https://api.stackexchange.com/2.3/questions/" +
IntToStr(questionId) +
"/answers"
"?order=desc"
"&sort=votes"
"&site=stackoverflow"
"&filter=withbody";
try
{
UnicodeString json = IdHTTP1->Get(url);
TJSONValue *val = TJSONObject::ParseJSONValue(json);
TJSONObject *root = dynamic_cast<TJSONObject*>(val);
if (!root) return;
TJSONArray *items =
dynamic_cast<TJSONArray*>(root->GetValue("items"));
if (!items) return;
UnicodeString html = "<html><head>"
"<meta charset='utf-8'>"
"<style>"
"body { font-family: Segoe UI; font-size: 14px; }"
"pre { background:#f4f4f4; padding:8px; border:1px solid #ccc; overflow:auto; }"
"code { color:#c7254e; font-family: Consolas, monospace; }"
"a { color: blue; text-decoration: none; }"
"</style>"
"</head><body>";
for (int i = 0; i < items->Count; i++)
{
TJSONObject *a = dynamic_cast<TJSONObject*>(items->Items[i]);
if (!a) continue;
UnicodeString body = a->GetValue("body")->Value();
html += "<h3>Respuesta " + IntToStr(i + 1) + "</h3>";
html += body;
html += "<hr>";
}
html += "</body></html>";
// Guardamos en archivo temporal
UnicodeString fileName = "respuestas.html";
TStringList *sl = new TStringList();
try
{
sl->Text = html;
sl->SaveToFile(ExtractFilePath(Application->ExeName) + fileName);
}
__finally
{
delete sl;
}
// Cargamos el HTML en TWebBrowser
WebBrowser1->Navigate("file:///" + ExtractFilePath(Application->ExeName) + fileName);
delete root;
}
catch (Exception &e)
{
ShowMessage("ERROR: " + e.Message);
}
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ListView1->Columns->Items[0]->Width = 700; // Título
ListView1->Columns->Items[1]->Width = 100; // Respuestas
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonBuscarClick(TObject *Sender)
{
UnicodeString texto = Edit1->Text.Trim();
if (texto.IsEmpty())
{
ShowMessage("Escribe algo para buscar");
return;
}
ListView1->Items->Clear(); // Limpiamos resultados previos
UnicodeString query = TNetEncoding::URL->Encode(texto);
UnicodeString url =
"https://api.stackexchange.com/2.3/search"
"?order=desc"
"&sort=relevance"
"&intitle=" + query +
"&site=stackoverflow"
"&pagesize=10";
try
{
UnicodeString json = IdHTTP1->Get(url);
TJSONValue *val = TJSONObject::ParseJSONValue(json);
TJSONObject *root = dynamic_cast<TJSONObject*>(val);
if (!root) return;
TJSONArray *items = dynamic_cast<TJSONArray*>(root->GetValue("items"));
if (!items) return;
// ✅ Aquí llenamos el ListView usando nuestra función
for (int i = 0; i < items->Count; i++)
{
TJSONObject *q = dynamic_cast<TJSONObject*>(items->Items[i]);
if (!q) continue;
int questionId = StrToIntDef(
q->GetValue("question_id")->Value(), 0
);
int answerCount = StrToIntDef(
q->GetValue("answer_count")->Value(), 0
);
UnicodeString title = q->GetValue("title")->Value();
AgregarPreguntaALV(questionId, title, answerCount);
}
delete root;
}
catch (Exception &e)
{
ShowMessage("Error al buscar preguntas: " + e.Message);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar &Key)
{
if (Key == VK_RETURN)
ButtonBuscarClick(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Method = sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL1->SSLOptions->Mode = sslmClient;
IdHTTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;
IdHTTP1->Request->UserAgent = "C++Builder StackOverflow Client";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListView1SelectItem(TObject *Sender, TListItem *Item, bool Selected)
{
if (!Selected || !Item) return;
int questionId = (int)(intptr_t)Item->Data; // Recuperamos el QuestionID
CargarRespuestas(questionId); // ✅ Llamada directa
}
//---------------------------------------------------------------------------
codigo fuente Unit1.h
Código:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdHTTP.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerSocket.hpp>
#include <IdIOHandlerStack.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <IdSSL.hpp>
#include <IdSSLOpenSSL.hpp>
#include <Vcl.ComCtrls.hpp>
#include <SHDocVw.hpp>
#include <Vcl.OleCtrls.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.Graphics.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TEdit *Edit1;
TButton *ButtonBuscar;
TIdHTTP *IdHTTP1;
TIdSSLIOHandlerSocketOpenSSL *IdSSLIOHandlerSocketOpenSSL1;
TLabel *Label1;
TLabel *Label2;
TLabel *Label3;
TListView *ListView1;
TWebBrowser *WebBrowser1;
TImage *Image1;
void __fastcall ButtonBuscarClick(TObject *Sender);
void __fastcall Edit1KeyPress(TObject *Sender, System::WideChar &Key);
void __fastcall FormCreate(TObject *Sender);
void __fastcall ListView1SelectItem(TObject *Sender, TListItem *Item, bool Selected);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void CargarRespuestas(int questionId);
void AgregarPreguntaALV(int questionId, UnicodeString title, int answerCount);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif