¿Cómo leer un archivo de mapa de bits externo y mostrarlo en un control de imagen MFC?
1. Agregue un botón y un control de imagen al cuadro de diálogo.
2. Agrega una clase, no puedo cargarla aquí, solo puedo copiar .h y .cpp, luego puedes copiarla en txt y cambiar la extensión.
Esta es Imagen.h
#if! definido(AFX_PICTURE_H__COPYFREE_BY_YOVAV_GAD__SOURCES_AT_SUPERMAIN_DOT_COM__INCLUDED_)
#define AFX_PICTURE_H__COPYFREE_BY_YOVAV_GAD__SOURCES_AT_SUPERMAIN_DOT_COM__INCLUDED_
#if _MSC_VER > p >#pragma once
# endif // _MSC_VER > 1000
clase CPicture
{
público:
void FreePictureData();
BOOL Load(CString) sFilePathName );
BOOL Load(UINT ResourceName, LPCSTR ResourceType);
BOOL LoadPictureData(BYTE* pBuffer, int nSize
BOOL SaveAsBitmap( CString sFilePathName);
BOOL Show(CDC* pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY
BOOL Show(CDC* pDC, CRect DrawRect
BOOL ShowBitmapResource(CDC* pDC, const int BMPResource, CPoint LeftTop);
BOOL UpdateSizeOnDC(CDC* pDC);
CPicture();
virtual ~CPicture();
IPicture* m_IPicture; // Igual que LPPICTURE (typedef IPicture __RPC_FAR *LPPICTURE)
LONG m_IPicture; // Alto (Entrada); Altura (Entrada); // Altura (Entrada); // Altura (Entrada). Altura; // Altura (en píxeles, ignora el contexto actual del dispositivo)
LONG m_Weight; Objeto en bytes (archivo o recurso)
LONG m_Width; // Ancho (en píxeles, ignora lo que utiliza el contexto actual del dispositivo)
};
#endif
Esto es Picture.cpp
#include "stdafx.h"
#include "Picture.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef ESTE_FILE
carácter estático ESTE_FILE[] =
__FILE__;
#endif
#define HIMETRIC_INCH 2540
#define ERROR_TITLE "CPicture Error" // Título del error (relacionado con esta clase)...
//------------------------------------------ --- ----------------------------------
/ Hace: Constructor - Crear un nuevo objeto CPicture para contener datos de imagen
// ~~~~
//
/------------ ------------------------------------------------- - ------------ -
CPicture::CPicture()
//=============== = =================================================== = ============
{
m _IPicture = NULL;
m_Height = 0;
m_Peso = 0;
m_Ancho = 0;
}
//----------------- - ---------------------------- --------------------- ------- ---------
// Hace: Destructor: libera datos e información del objeto CPicture
//~~~~
//
//-------------------------------- ------------- ------------------------------------- ---
Imagen CP:: ~Imagen CP()
//=============== ========= ============= ====================================== ===
{ p>
if(m_IPicture != NULL) FreePictureData() // Importante: evitar fugas...
}
//-------- ------------------------------------- ------------- ------------------
// Función: Liberar la memoria asignada que contiene datos de la interfaz IPicture
// ~~ ~~ y borre la información de la imagen
//
// Nota: Si solo necesita mostrar la imagen una vez, p>
// ~~~~~ o si copia la imagen al contexto del dispositivo para que aún
// permanezca en la pantalla, pero ya no necesite los datos de IPicture
// permanece en la pantalla, pero ya no requiere datos de IPicture
//
/---------------- ---------------- ---------------------------------- -------------
void CPicture::.FreePictureData()
//============
==================================================== ================
{
if(m_ IPicture ! = NULL)
{
m_IPicture->Release();
m_IPicture = NULL;
m_Height = 0;
m_Weight = 0;
m_Width = 0;
}
}
//-------------------- -------------------------------------------------- -------
// Hace: abrir un recurso y cargarlo en IPicture (interfaz)
// ~~~~ (.BMP .DIB .EMF . GIF .ICO .JPG .WMF)
/ return(bResultado);
}
//------------ -------------------------------------------------- ---------------
// Hace: abrir el archivo y cargarlo en IPicture (interfaz)
// ~~~~ (.BMP .DIB .EMF)BMP .DIB .EMF .GIF .ICO .JPG .WMF)
//
/ Entrada: sFilePathName: ruta guardada y destino del nombre de archivo p>
// ~~~~~
//
/ Salida: VERDADERO Si tiene éxito...
//~~ ~~ ~~
//--------------------------------- --- ----------------------------------------
BOOL CPicture: :Load( CString sFilePathName)
//================================= ==== ===========================================
{
BOOL bResult = FALSE;
CFile PictureFile;
CFileException e;
int nSize = 0; p>
if(m_IPicture!
if(m_IPicture ! = NULL) FreePictureData(); // Importante: evitar fugas...
if(PictureFile.Open(sFilePathName, CFile::modeRead | CFile:: typeBinary, &e))
{
nSize = PictureFile.GetLength();
BYTE* pBuffer = new BYTE[nSize];
if (PictureFile.Read(pBuffer, nSize) > 0 )//Leer pBuffer del archivo
{ if(LoadPictu
reData(pBuffer, nSize)) bResult = TRUE }// Asumir la llamada a la función para leer pBuffer
PictureFile.Close();
eliminar [] pBuffer;
}
else // Error al abrir...
{
TCHAR szCause[255];
e. GetErrorMessage (szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_ hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP , LANG_ENGLISH);
bResult = FALSE;
}
m_Weight = nSize; // Actualiza la información del tamaño de la imagen.
..
if(m_IPicture ! = NULL) // No intentes leer datos de una memoria que no existe...
{
m_IPicture- > get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Calcula su tamaño en el contexto del dispositivo "estándar" (96 DPI)
m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, 96, HIMETRIC_INCH);
}
else // Datos de imagen No es un tipo de imagen conocido
{
m_Height = 0;
m_Width = 0;
bResult = FALSE;
}
> return(bResultado);
}
//--------------- ------------------------------------------------- - -----------
// Hace: Leer datos de imagen de una fuente (archivo/recurso)
// ~~~~ y es cargado en el objeto IPicture utilizado actualmente
//
// InPut: el búfer de la fuente de datos (archivo/recurso) y su tamaño
/ / ~~~~~
//
// Salida: proporciona datos de imagen al objeto IPicture
// ~~~~~~ (Usa dibujo La función se muestra en el contexto del dispositivo)
// TRUE si se realiza correctamente...
// ------------------ ------------------------------------------------- - --------
BOOL CPicture::LoadPictureData(BYTE * pBuffer, int nSize)
//============ = =================================================== = ==============
{
BOOL bResult = FALSE;
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize ) ;
if(hGlobal == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "No se puede asignar suficiente memoria\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}
void* pData = GlobalLock(hGlobal);
memcpy(pData, pBuffer, nSize);
GlobalUnlock(hGlobal);
IStream
* pStream = NULL;
if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
{
HRESULT hr;
if((hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&m_IPicture)) == E_NOINTERFACE)
{
HWND hWnd = AfxGetApp()-> ;GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "La interfaz IPicture no es compatible\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}
else // S_OK
{
pStream->Release();
pStream = NULL;
bResult = TRUE;
}
}
FreeResource(hGlobal); // Requerido para Windows de 16 bits ( 32 bits - liberación automática)
return(bResult);
}
//------ ------- -------------------------------------------------- -- ------------
// Si: dibuja la imagen cargada directamente en el DC del cliente
// ~~~~
//
// Nota: El tamaño es mayor o menor que el tamaño de la imagen original
// ~~~~ La imagen se dibujará de acuerdo con la nueva tamaño dado.
..
//
// InPut: pDC - el DC dado que se dibujará
// ~~~~~ DrawRect - el tamaño de la imagen dibujada (como un rectángulo)
//
// Salida: TRUE Si tiene éxito...
// ~~~~~~
//------------------------------------------ ------ ----------------------------------
BOOL CImagen: :Mostrar(CDC * pDC, CRect DrawRect)
//================================ ======= ========================================== p>
{
if (pDC == NULL || m_IPicture == NULL) devuelve FALSO;
largo Ancho = 0;
largo Alto = 0;
m_IPicture->get_Width(&Width);
m_ IPicture->get_Height(&Height);
HRESULT hrP = NULL;
hrP = m_IPicture- >Render(pDC->m_hDC,
DrawRect.left, // Izquierda
DrawRect.top, // Arriba
DrawRect.right - DrawRect.left , // Derecha
DrawRect.bottom - DrawRect.top, // Abajo
0,
Altura,
Ancho,
-Alto,
&DrawRect);
if (SUCCEEDED(hrP)) return(TRUE);
HWND hWnd = AfxGetApp()-> GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "No se puede asignar suficiente memoria\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
retorno(FALSO );
}
//------------------------ ---------- ---------------------------------------- ----------
// Hace: dibujar la imagen cargada directamente en el DC del cliente
// ~~~~
//
// Nota: Un tamaño mayor o menor que el tamaño de la imagen original
// ~~ ~~ La imagen se dibujará en las nuevas dimensiones dadas. ..
//
/ InPut: pDC - el DC dado para dibujar
/ ~~~~~ LeftTop - el que comenzar a dibujar Punto de apertura (izquierda, arriba)
// AnchoAlto: el tamaño de la imagen sobre la que dibujar.
Dimensiones de la imagen a dibujar (ancho, alto)
// MagnifyX - Ampliar el ancho de píxel, 0 = predeterminado (sin ampliación)
// MagnifyY - Ampliar el alto de píxel, 0 = Valor predeterminado (sin amplificación)
//
// Salida: TRUE Si tiene éxito...
// ~~~~~~ p >
//---------------------------------------------------- ---- ----------------------------------
BOOL CImagen::Mostrar (CDC *pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY)
/========================== ======= =============================== ============ ===== p>
{
if (pDC == NULL || m_IPicture == NULL) devuelve FALSO;
largo Ancho = 0; p>
altura larga = 0;
m_IPicture->get_Width(&Width);
m_IPicture->get_Height(&Height);
if(MagnifyX == NULL) MagnifyX = 0 ;
if( MagnifyY == NULL) MagnifyY = 0;
MagnifyX = int(MulDiv(Width, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH ) * MagnifyX)* MagnifyX) ;
MagnifyY = int(MulDiv(Height,pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH)* MagnifyY);
CRect DrawRect(LeftTop.x , LeftTop.y, MagnifyX, MagnifyY);
HRESULT hrP = NULL;
hrP = m_IPicture->Render(pDC->m_hDC,
LeftTop. x, // Izquierda p>
LeftTop.y, /
&DrawRect);
if(SUCCEEDED(hrP)) return(TRUE);
HWND hWnd = AfxGetApp ()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "No se puede asignar suficiente memoria\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH); p>
retorno( FALSO);
}
/ /----------------------- ------- ------------------------------------------- ----
// Hace: Guarda la imagen almacenada en el objeto IPicture como
Mapa de bits
// ~~~~ (convierte de cualquier tipo de imagen conocida a un archivo de mapa de bits/icono)
//
// InPut: sFilePathName - Ruta Y nombre de archivo destino a guardar
// ~~~~~
//
/ Salida: VERDADERO Si tiene éxito...
// ~~~~~~
//-------------------------------- ---------------------------------------- p>
BOOL CImagen: .SaveAsBitmap(CString sFilePathName)
//============================== ====== =============================================
{
BOOL bResult = FALSE;
ILockBytes *Buffer = 0;
IStorage *pStorage = 0;
IStream *FileStream = 0;
BYTE *BufferBytes;<
STATSTG BytesStatistics;
DWORD OutData;
OutStream largo ;
CFile BitmapFile; CFileException e;
doble SkipFloat = 0;
DWORD ByteSkip = 0;
_ULARGE_INTEGER RealData;
p>CreateILockBytesOnHGlobal(NULL, TRUE, &Buffer); // Crear búfer ILockBytes
HRESULT hr = ::StgCreateDocfileOnILockBytes(Buffer,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, & amp;pStorage );
hr = pStorage->CreateStream(L "PICTURE",
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, 0, & FileStream);
m_IPicture->SaveAsFile(FileStream, TRUE y OutStream); // Copiar flujo de datos
FileStream->Release();
pStorage->Release();
Buffer->Flush();
// Obtener estadísticas para el tamaño final de la matriz de bytes
Buffer->Stat(& BytesStatistics, STATFLAG_NONAME);
/ / Elimina los datos innecesarios de SaveAsFile() (dejando solo datos de imagen "puros")
SkipFloa
t = ( double(OutStream) / 512); // Deben ser 512 bloques. ..
if(SkipFloat > DWORD(SkipFloat)) ByteSkip = (DWORD)SkipFloat + 1;
else ByteSkip = (DWORD)SkipFloat;
ByteSkip = ByteSkip * 512; // Debe estar en 512 bloques...512; // Debe estar en 512 bloques...
// Encuentra la diferencia entre dos valores
p>ByteSkip = (DWORD)(BytesStatistics.cbSize.QuadPart - ByteSkip);
// Solo asigna datos de imagen "puros"
RealData.LowPart = 0;
RealData.HighPart = 0;
RealData.QuadPart = ByteSkip* 512 // Debe estar dentro de 512 bloques.
QuadPart = ByteSkip;
BufferBytes = ( BYTE*)malloc(OutStream);
if(BufferBytes == NULL)
{
Buffer->Release();
HWND hWnd = AfxGetApp()->GetMainWnd ()->m_hWnd;
MessageBoxEx(hWnd, "No se puede asignar suficiente memoria\t" , ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
}
Buffer->ReadAt(RealData, BufferBytes, OutStream, &OutData);
if(BitmapFile. modeCreate | CFile::modeWrite, &e))
{
BitmapFile.Write(BufferBytes, OutData);
BitmapFile.Close();
bResult = TRUE;
}
else // Error al escribir el archivo...
{
TCHAR szCause[ 255];
e.GetErrorMessage(szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_ hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
bResult = FALSE;
}
Buffer->.Release();
gratis(BufferBytes);
return(bResult);
}
//--------- ----------------------------------------- --- - ------------------
// Función: Dibujar recursos de mapa de bits al DC del cliente (usando Bitblt())
// ~~~~ Utilizará el tamaño original (ancho y alto) del recurso de mapa de bits
// (.BMP .DIB)
// ~~~~ Se utilizará el tamaño original (ancho y alto) del recurso de mapa de bits
//(.BMP .DIB)
//
// NOTA: Esta función es solo otra forma sencilla de mostrar recursos de mapa de bits.
// ~~~~ No tiene nada que ver con la interfaz IPicture y se puede usar sola (directamente) en cualquier contexto de dispositivo.
/ /
// InPut: BMPResource - el nombre del recurso definido en el recurso
// ~~~~~ pDC - especifica el DC en el que recurrir
// LeftTop - punto de partida para comenzar a dibujar (izquierda, arriba)
//
// Salida: TRUE si tiene éxito...
// ~~~~~~
//--------------------------------- - ----
-------------------------------
BOOL CPicture:.ShowBitmapResource ( CDC *pDC, const int BMPResource, CPoint LeftTop)
//=============================== = =============================== ==================< / p>
{
if (pDC == NULL) return(FALSE);
CBitmap BMP;
if(BMP.LoadBitmap(BMPResource ) )
{
// Obtener detalles del mapa de bits
BITMAP BMPInfo;
BMP.GetBitmap(&BMPInfo);
// Crea un DC de memoria compatible con el DC de visualización que queremos dibujar
CDC DCMemory;
DCMemory. POldBitmap = DCMemory.SelectObject(&BMP);
//Copia bits del DC en la memoria al DC en la pantalla
pDC->BitBlt(LeftTop.x,LeftTop.y, BMPInfo. bmWidth, BMPInfo.bmHeight, &DCMemory, 0, 0, SRCCOPY);
DCMemory.SelectObject(pOldBitmap); // (Como se muestra en el ejemplo de MSDN...)
}
else
{
TRACE0("ERROR: No se puede encontrar el recurso de mapa de bits\n");
return( FALSE) ;
}
return(VERDADERO);
}
//------ -- ------------------------------------------------ -- -------------------
// Sí: obtiene el tamaño en píxeles de la imagen original (ignorando la corriente utilizada por DC)
// ~~~~ El puntero que apunta al contexto del dispositivo es necesario para calcular los píxeles,
//
// También actualiza las propiedades de alto y ancho de la clase. ,
// (Dado que hasta ahora no tenemos un contexto de dispositivo con el que trabajar. Se supone .96DPI).
.96 DPI asumidos)
//
// Entrada: Cliente DC (necesita verificar el tamaño de píxel)
// ~~~~~ p>
//
//////////////////////////////// Salida: VERDADERO si exitoso ..
// ~~~~~~
//--------------------- -. -------------------------------------------------- --
BOOL CPicture:.UpdateSizeOnDC(CDC *pDC)
//======================= ==================================================== ======
{
if(pDC == NULL || m_IPicture == NULL) { m_Height = 0; m_Width = 0;
m_IPicture->get_Height(&m_Height);
m_IPicture-&>get_Width(&m_Height);
m_IPicture-& gt;get_Width(&m_Width); p> p>
// Obtener DPI actuales - Puntos por pulgada
int CurrentDPI_X = pDC->GetDeviceCaps(LOGPIXELSX);
int CurrentDPI_Y = pDC->GetDeviceCaps( LOGPIXELSY) ;
// Utilice la impresión "estándar" (al imprimir)
if(pDC->IsPrinting())
{
CurrentDPI_X = 96;
CurrentDPI_Y = 96;
}
m_Height = MulDiv(m_Height, CurrentDPI_Y, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, CurrentDPI_X, HIMETRIC_INCH);
return(TRUE);
}
Defina en el archivo de encabezado del diálogo:
Primero, incluya el archivo de encabezado #include "Picture.h"
Luego defina
CPicture m_Pic;
4. Escriba en la función del botón : (Tenga en cuenta que este IDC_SHOWPIC) es el número de identificación de su control de pantalla.
CRect rect;
GetDlgItem(IDC_SHOWPIC)->GetWindowRect(&rect);
ScreenToClient(&rect);
CFile f;
CString FilePathName;
CFileException e;
CFileDialog dlg(TRUE,NULL,NULL,0,_T("Todos los archivos (*. *)|* .*)|*.*|BMP(*.bmp)|*.bmp|DIB(*.dib)|*.dib|EMF(*.emf)|*.emf|GIF(*.gif)|*. gif|ICO(*.ico)|*.ico|JPG(*.JPG (*.jpg)|*.jpg|WMF (*.wmf)|*.wmf||"),NULL);
if(dlg.DoModal()==IDOK)
{
FilePathName=dlg.GetPathName()