Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Cambiar entre imágenes en TImage (https://www.clubdelphi.com/foros/showthread.php?t=92558)

aguml 27-11-2017 16:02:00

Cambiar entre imágenes en TImage
 
Quiero hacer que al elegir una de las opciones de un combobox cambie la imagen de un TImage pero no quiero que se vean los archivos de imagen. He probado a meterlos en un TImageList pero me dice que exceden el tamaño del TImageList o algo así y al mostrarlas en el TImage me salen imágenes de píxeles enormes y no se ve la imagen. ¿Cómo puedo hacerlo? Otro modo se que es meter las imágenes en los recursos y luego leerlas pero ni idea de como hacer eso.
¿Me podrían ayudar?

roman 27-11-2017 16:28:31

Puedes guardarlas en otros TImage que estén ocultos.

LineComment Saludos

escafandra 27-11-2017 16:43:08

Cambia el ancho y el alto del TImageList

Saludos.

aguml 27-11-2017 17:59:58

Lo estoy intentando pero ahora al añadir las imágenes al TImageList y dar a guardar o ejecutar c++builder 6 se queda congelado y tengo que acabar cerrándolo a la fuerza. He probado incluso con una sola imagen y sigue pasando. El tamaño es de height: 179 width: 320.

ecfisa 27-11-2017 21:54:02

Hola.

Estuve reproduciendo tu caso y obtengo el mismo resultado.

Según este enlace, A problem with ImageList in C++ Builder 6 Professional, se trataría de un bug que se presenta cuando el ancho de la imágen es grande, no pude encontrar otra referencia al problema.

Saludos :)

escafandra 27-11-2017 22:45:25

El máximo que admite es 256 x 256, a Berlín le pasa lo mismo, solo que te avisa

Sin embargo con la API no hay problema. Lo siguiente funciona en BCB5 tranquilamente:
Código PHP:

HIMAGELIST IL ImageList_Create(16001600ILC_COLOR2411); 


Saludos.

movorack 27-11-2017 23:00:59

Y si las cargas de un archivo de recursos?

Código Delphi [-]
procedure LoadImages;
var
  RS: TResourceStream;
  JPGImage: TJPEGImage;
begin
  //Cargar un BMP
  Image1.Picture.Bitmap.LoadFromResourceName(HInstance, 'SampleBMP');  

  //Cargar un JPG
  JPGImage := TJPEGImage.Create;
  RS := TResourceStream.Create(HInstance, 'SampleJPG', RT_RCDATA);
  try
    JPGImage.LoadFromStream(RS);
    Image1.Picture.Graphic := JPGImage;
  finally
    RS.Free;
    JPGImage.Free;
  end;
end;

Puedes usar este editor de recursos

Que pena... es C++, Aunque acá en la documentación muestran como se maneja

aguml 27-11-2017 23:22:02

Cita:

Empezado por escafandra (Mensaje 522934)
El máximo que admite es 256 x 256, a Berlín le pasa lo mismo, solo que te avisa

Sin embargo con la API no hay problema. Lo siguiente funciona en BCB5 tranquilamente:
Código PHP:

HIMAGELIST IL ImageList_Create(16001600ILC_COLOR2411); 

Saludos.

No entiendo como harías con ese código para añadir las imágenes al TImageList.

escafandra 28-11-2017 00:23:04

El código solo demuestra que la API puede crear ImageList de tamaño grande sin problemas. Ese componente no se lo inventó Borland, existe en Windows con el mismo nombre y para usos similares a los de la VCL. Ahora bien, a veces es complejo unir VCL on API. De un HIMAGELIST puedes obtener las imágenes en forma de HBITMAP que puedes asignar a un TImage. Para cargar las Imágenes puedes hacerlo como recursos o de un stream. Te dejo la información: About Image Lists

Saludos.

aguml 28-11-2017 00:36:06

Lo estoy intentando hacer con recursos y algo estoy haciendo mal porque me dice que no encuentra dicho recurso.
Lo que hago es que voy en la consola a esta ruta: "C:\Archivos de programa\Borland\CBuilder6\Bin"

Ejecuto esta línea:
Código:

brcc32 -r "C:\Documents and Settings\BlueDeep\Escritorio\Prueba PS3\Imagenes.rc"
Dentro del archivo .rc hay esto:
Código:

MAPA1 UPCBMP24 "img1.BMP"
MAPA2 UPCBMP24 "img2.BMP"

Se crea un archivo .RES el cual añado al proyecto con:
Código PHP:

#pragma resource "Imagenes.RES" 

O yendo a "Project->Add to Project..." y añadiendo ese archivo ahí.

Para cargar una imagen de esas en el TImage hago esto:
Código PHP:

Image1->Picture->Bitmap->LoadFromResourceName((unsigned int)HInstance,"MAPA1"); 

¿En que estoy fallando? El archivo ocupa el espacio esperado pero se ve que hago algo mal porque no lee ningun recurso.

ecfisa 28-11-2017 22:40:32

Hola.

Te pongo este ejemplo por si te sirve de ayuda.

img.rc
Código:

1 RCDATA "img1.bmp"
2 RCDATA "img2.bmp"
3 RCDATA "img3.bmp"


Código PHP:

...

#pragma resource "IMG.RES"

void resToimg(TImage *img, const int inx)
{
 
TResourceStream *RS = new TResourceStream((int)HInstanceinxRT_RCDATA);

 try {
   
img->Picture->Bitmap->LoadFromStream(RS);
 }
 
__finally {
   
delete RS;
 }

}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  
resToimg(Image11);
  
resToimg(Image22);
  
resToimg(Image33);


Muestra:


Saludos :)

escafandra 29-11-2017 00:36:07

No hace mucho publiqué un truco para cargar imágenes de un recurso que admitía varios formatos usando GDI+. El mensaje original en delphi y C++ se encuentra aquí:
Cargar una Imagen de un Resource RT_RCDATA con API pura y GDI+ Flat

El código es el siguiente:

El archivo de recursos RC:
Código PHP:

Imagen1 RCDATA "Imagen1.png" 
Imagen2 RCDATA "Imagen2.jpg" 

La función de carga: CreateHBITMAPFromRCDATAResurce (sobran declaraciones de APIs GDI+ pero ahí quedan por si las queréis para otros usos)
Código PHP:

#include <windows.h>

#pragma link "Gdiplus.lib"
#pragma resource "MiArchivo.res"

extern "C" {
DWORD WINAPI GdiplusStartup(ULONG_PTR *hTokenvoid *inputvoid *Output);
void  WINAPI GdiplusShutdown(ULONG_PTR token);
DWORD WINAPI GdipCreateBitmapFromHBITMAP(HBITMAP hBmpHPALETTE hPalHANDLEGBitmap);
DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE BmpHBITMAPhBmpDWORD BKColor);
DWORD WINAPI GdipCreateFromHDC(HDC hDCHANDLEhGraphics);
DWORD WINAPI GdipDisposeImage(HANDLE hImage);
DWORD WINAPI GdipTranslateWorldTransform(HANDLE hGraphicsfloat sxfloat syDWORD Order);
DWORD WINAPI GdipRotateWorldTransform(HANDLE hGraphicsfloat AngleDWORD Order);
DWORD WINAPI GdipDrawImage(HANDLE hGraphicsHANDLE hImagefloat sxfloat sy);
DWORD WINAPI GdipDeleteGraphics(HANDLE hGraphics);
DWORD WINAPI GdipCreateBitmapFromFile(WCHARfilenameHANDLEbitmap);
DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE bitmapHBITMAPhBitmapDWORD BKColor);
//DWORD WINAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, WCHAR* lpBitmapName, HANDLE* GBitmap);
DWORD WINAPI GdipCreateBitmapFromStream(IStreamstreamHANDLEGBitmap);


DWORD WINAPI GdipImageRotateFlip(HANDLE hImageDWORD rfType);
}

TForm1 *Form1;

typedef struct {
  
UINT32 GdiplusVersion;
  
PVOID  DebugEventCallback;  //DebugEventProc
  
BOOL   SuppressBackgroundThread;
  
BOOL   SuppressExternalCodecs;
GdiplusStartupInput;

HBITMAP CreateHBITMAPFromRCDATAResurce(PWCHAR FileName)
{
  
PWCHAR RT_RCDATAW MAKEINTRESOURCEW(10);
  
HBITMAP hBitmap 0;
  
HANDLE GBitmap 0;
  
IStreamStream;
  
ULONG_PTR  gdiplusToken;
  
GdiplusStartupInput gdiplusStartupInput = {0};
  
gdiplusStartupInput.GdiplusVersion 1;
  if(
GdiplusStartup(&gdiplusToken, &gdiplusStartupInputNULL)) return 0;

  
HRSRC Res FindResourceW(0FileNameRT_RCDATAW);//MAKEINTRESOURCEW(10));
  
if(Res){
    
DWORD Size SizeofResource(0Res);
    
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLESize);
    
LPVOID pImage = ::GlobalLock(hMem);
    
CopyMemory(pImageLockResource(LoadResource(0Res)), Size);
    ::
GlobalUnlock(hMem);
    ::
CreateStreamOnHGlobal(hMemtrue, &Stream);
    
GdipCreateBitmapFromStream(Stream, &GBitmap);
    
GdipCreateHBITMAPFromBitmap(GBitmap, &hBitmap0);
    
GdipDisposeImage(GBitmap);
    
//GlobalFree(hMem);
    
Stream->Release();
  }

  
//shutdown GDI+
  
GdiplusShutdown(gdiplusToken);

  return 
hBitmap;


Un ejemplo de uso:
Código PHP:

Image1->Picture->Bitmap->Handle CreateHBITMAPFromRCDATAResurce(L"Imagen1"); 


Saludos.

aguml 29-11-2017 11:12:53

Genial a todos, al final lo consegui gracias a vuestra ayuda. Ahora estoy con lo mismo pero con archivos mp3 y lo he conseguido asi:
Código PHP:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Songs.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
bool retval;
char my_song[]="my_song.mp3";
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
    : 
TForm(Owner)
{
}
//---------------------------------------------------------------------------

bool ResToFile(char *nombre_salida,int ID)
{
    
retval=true;
    try{
        
TResourceStream *RS= new TResourceStream((unsigned int)HInstance,SONG1,RT_RCDATA);
        try{
            
RS->SaveToFile(my_song);
        }catch(...){
            
retval=false;
        }
        
delete RS;
    }catch(...){
        
retval=false;
    }
    return 
retval;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
    if(
ResToFile(my_song,SONG1)==true){
        
MediaPlayer1->FileName=my_song;
        
MediaPlayer1->Open();
        
MediaPlayer1->Play();
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *SenderTCloseAction &Action)
{
    if(
retval==true){
        
MediaPlayer1->Stop();
        
MediaPlayer1->Close();
        if(
FileExists(my_song))
            
DeleteFile(my_song);
    }
}
//--------------------------------------------------------------------------- 

Solo tengo una duda y es que para reproducirla con el TMediaPlayer ¿tengo que extraerla si o si como archivo? ¿no se puede reproducir sin extraerla en un archivo?
PD: escafandra tu metodo me lo guardo para otro momento que seguro me vendrá bien pero para este son todos BMP con lo que con lo que tengo me sobra y me basta, gracias amigos.
PD2: en Song.h lo que tengo es la declaracion del ID para el recurso que es:
Código PHP:

#define SONG1 100 


aguml 29-11-2017 16:10:30

Cita:

Empezado por escafandra (Mensaje 522963)
No hace mucho publiqué un truco para cargar imágenes de un recurso que admitía varios formatos usando GDI+. El mensaje original en delphi y C++ se encuentra aquí:
Cargar una Imagen de un Resource RT_RCDATA con API pura y GDI+ Flat

El código es el siguiente:

El archivo de recursos RC:
Código PHP:

Imagen1 RCDATA "Imagen1.png" 
Imagen2 RCDATA "Imagen2.jpg" 

La función de carga: CreateHBITMAPFromRCDATAResurce (sobran declaraciones de APIs GDI+ pero ahí quedan por si las queréis para otros usos)
Código PHP:

#include <windows.h>

#pragma link "Gdiplus.lib"
#pragma resource "MiArchivo.res"

extern "C" {
DWORD WINAPI GdiplusStartup(ULONG_PTR *hTokenvoid *inputvoid *Output);
void  WINAPI GdiplusShutdown(ULONG_PTR token);
DWORD WINAPI GdipCreateBitmapFromHBITMAP(HBITMAP hBmpHPALETTE hPalHANDLEGBitmap);
DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE BmpHBITMAPhBmpDWORD BKColor);
DWORD WINAPI GdipCreateFromHDC(HDC hDCHANDLEhGraphics);
DWORD WINAPI GdipDisposeImage(HANDLE hImage);
DWORD WINAPI GdipTranslateWorldTransform(HANDLE hGraphicsfloat sxfloat syDWORD Order);
DWORD WINAPI GdipRotateWorldTransform(HANDLE hGraphicsfloat AngleDWORD Order);
DWORD WINAPI GdipDrawImage(HANDLE hGraphicsHANDLE hImagefloat sxfloat sy);
DWORD WINAPI GdipDeleteGraphics(HANDLE hGraphics);
DWORD WINAPI GdipCreateBitmapFromFile(WCHARfilenameHANDLEbitmap);
DWORD WINAPI GdipCreateHBITMAPFromBitmap(HANDLE bitmapHBITMAPhBitmapDWORD BKColor);
//DWORD WINAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, WCHAR* lpBitmapName, HANDLE* GBitmap);
DWORD WINAPI GdipCreateBitmapFromStream(IStreamstreamHANDLEGBitmap);


DWORD WINAPI GdipImageRotateFlip(HANDLE hImageDWORD rfType);
}

TForm1 *Form1;

typedef struct {
  
UINT32 GdiplusVersion;
  
PVOID  DebugEventCallback;  //DebugEventProc
  
BOOL   SuppressBackgroundThread;
  
BOOL   SuppressExternalCodecs;
GdiplusStartupInput;

HBITMAP CreateHBITMAPFromRCDATAResurce(PWCHAR FileName)
{
  
PWCHAR RT_RCDATAW MAKEINTRESOURCEW(10);
  
HBITMAP hBitmap 0;
  
HANDLE GBitmap 0;
  
IStreamStream;
  
ULONG_PTR  gdiplusToken;
  
GdiplusStartupInput gdiplusStartupInput = {0};
  
gdiplusStartupInput.GdiplusVersion 1;
  if(
GdiplusStartup(&gdiplusToken, &gdiplusStartupInputNULL)) return 0;

  
HRSRC Res FindResourceW(0FileNameRT_RCDATAW);//MAKEINTRESOURCEW(10));
  
if(Res){
    
DWORD Size SizeofResource(0Res);
    
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLESize);
    
LPVOID pImage = ::GlobalLock(hMem);
    
CopyMemory(pImageLockResource(LoadResource(0Res)), Size);
    ::
GlobalUnlock(hMem);
    ::
CreateStreamOnHGlobal(hMemtrue, &Stream);
    
GdipCreateBitmapFromStream(Stream, &GBitmap);
    
GdipCreateHBITMAPFromBitmap(GBitmap, &hBitmap0);
    
GdipDisposeImage(GBitmap);
    
//GlobalFree(hMem);
    
Stream->Release();
  }

  
//shutdown GDI+
  
GdiplusShutdown(gdiplusToken);

  return 
hBitmap;


Un ejemplo de uso:
Código PHP:

Image1->Picture->Bitmap->Handle CreateHBITMAPFromRCDATAResurce(L"Imagen1"); 

Saludos.

Una cosa amigo, intento reproducir tu codigo y practicamente esta hecho pero me falta la libreria gdiplus.lib ¿de donde la saco? Lo digo porque me lo he bajado el GDI+ desde microsoft y no viene ningun .h ni .lib, solo viene una dll, un .cat, y un .man.

aguml 29-11-2017 17:56:25

He conseguido crear el .lib asi:
implib Gdiplus.lib gdiplus.dll
y ahora me encuentro con que el codigo compila pero no encuentra el recurso con FindResource.
El archivo .rc lo tengo asi:
Código:

#include "Imagenes.h"

IMAGEN1 RCDATA "Imagenes\img1.jpg"
IMAGEN2 RCDATA "Imagenes\img2.gif"
IMAGEN3 RCDATA "Imagenes\img3.bmp"

el archivo .res obtenido ocupa lo mismo que las tres imagenes asi que supongo que lo hice bien.
En el Imagenes.h tengo esto:
Código PHP:

#define IMAGEN1 100
#define IMAGEN2 101
#define IMAGEN3 102 

Y la funcion que llama a la tuya la tengo asi:
Código PHP:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    
Image1->Picture->Bitmap->Handle CreateHBITMAPFromRCDATAResurce(L"IMAGEN3");


Algo hago mal para que no encuentre la imagen en los recursos.

aguml 29-11-2017 18:46:17

Lo he conseguido haciendo un par de pequeños cambios.
El primero es cambiar el parametro de tu funcion por esto:
Código PHP:

HBITMAP CreateHBITMAPFromRCDATAResurce(int FileID

Luego en FinResourceW hago esto:
Código PHP:

HRSRC Res FindResourceW(0MAKEINTRESOURCEW(FileID), RT_RCDATAW); 

Y por ultimo en la llamada hago asi:
Código PHP:

Image1->Picture->Bitmap->Handle CreateHBITMAPFromRCDATAResurce(IMAGEN1); 

Donde IMAGEN1 es el id que le asigno a la primera imagen en el archivo Imagenes.h.
Me gustaria saber porque no me funciona como lo tenia ya que tampoco consegui hacerlo antes con el codigo que pasó ecfisa y tuve que hacer mas o menos lo mismo y usar el id en vez del nombre.


La franja horaria es GMT +2. Ahora son las 22:29:48.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi