MFC: Bild anzeigen lassen (jpg)

biba

Grünschnabel
Hi

ich will in meinem dialog ein jpg bild anzeigen lassen... das file sollte man über einen öffnen dialog selber wählen... dies klappt auch schon, nur das mit der picturebox wollte nicht klappen...

weiss jemand rat?

thx
biba

ps: das bild muss nur angezeigt werden... also nix bearbeiten oder so....
 
sorry das es etwas länger gedauert hat...hab deinen beitrag aber immer noch im hinterkopf gehabt :)

http://www.mpdvc.de/html.htm#Q78

7.16 Wie kann ich andere Bitmap-Formate als .bmp anzeigen?
Wenn Bitmapformate außer .bmp benötigt werden, hilft ::LoadBitmap bzw. ::LoadImage nicht weiter. Allerdings stellt Windows mit der API-Funktion ::OleLoadPicture eine Möglichkeit zur Verfügung, diverse Formate (JPEG, GIF, WMF, ICO etc.) zu laden. Die Funktion liefert ein IPicture-Interface, welches genutzt werden kann, das geladene Grafikformat auf den übergebenen DC zu zeichnen (IPicture::Render).

Für MFC-Anwender gibt es unter Code Project eine erweiterte Bitmapklasse (CEnBitmap), die ::OleLoadPicture/IPicture kapselt (CEnBitmap::LoadImage), die sich aber ansonsten wie CBitmap verhält.

Das folgende Beispiel zeigt das Laden eines Bildes mit LoadPicture und die Ausgabe mit DrawPicture:

Code:
LPPICTURE pPicture;
long lWidth, lHeight;
int iWidth, iHeight;

BOOL LoadPicture(LPCTSTR pszFileName)
{
  //datei öffnen
  HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

  if(INVALID_HANDLE_VALUE == hFile)
   return FALSE;

  //datei größe ermitteln
  DWORD dwFileSize = GetFileSize(hFile, NULL);

  //speicher in größe der datei allokieren
  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
  LPVOID  pvData  = GlobalLock(hGlobal);

  //datei lesen u. im speicher behalten
  DWORD dwBytesRead = 0;
  BOOL  bRead       = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);

  if(!bRead)
   return FALSE;

  GlobalUnlock(hGlobal);
  CloseHandle(hFile);

  //IStream* aus dem speicher erzeugen
  LPSTREAM pstm = NULL;
  HRESULT  hr   = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

  //IPicture vom bild erzeugen
  if(pPicture)
      pPicture->Release();

  hr = OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&pPicture);
  pstm->Release();

  //breite u. höhe vom bild holen
  pPicture->get_Width(&lWidth);
  pPicture->get_Height(&lHeight);

  HDC hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);

  //in Pixel konvertieren
  iWidth = (lWidth  * GetDeviceCaps(hdc, LOGPIXELSX)) / 2540;
  iHeight = (lHeight * GetDeviceCaps(hdc, LOGPIXELSY)) / 2540;

  return TRUE;
}

BOOL DrawPicture(HWND hwnd, HDC hdc)
{
  if(pPicture) //wenn bild geladen
  {
   RECT rc;
   GetClientRect(hwnd, &rc);

   //Bild anzeigen mittels Render
   pPicture->Render(hdc, 0, 0, iWidth, iHeight, 0, lHeight, lWidth, -lHeight, &rc);

   return TRUE;
  }

  return FALSE;
}

mehr verweise zu dem thema:
http://www.codeproject.com/useritems/ExtendedBitmap.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/ofn_ol2z_0k4l.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/ctin_p_482t.asp
http://msdn.microsoft.com/msdnmag/issues/01/10/c/default.aspx
 
Hi Joki,

stehe vor einem ähnlichen Problem, d.h. ich würde gerne in meiner Dialoganwendung ein beliebiges JPG anzeigen.

Den Code deiner Funktion LoadPicture habe ich verstanden und erfolgreich eingefügt. Ich schaffe es ein Bild zu laden (Pixel werden z.B. korrekt in den Variablen angezeigt).

Allerdings hab ich ein ungelöstest Problem. Wie zeige ich nun das geladene JPG in meiner Dialoganwendung an? Mache erst erste Schritte mit der MFC und stehe wohl deshalb auf dem Schlauch.

Ich würde mich über ein paar hilfreich Angaben freuen. Vielen Dank schon mal im vorraus.

Gruß Michael
 
C++:
#include <iostream>
#include <math.h>
//#include <sstream>
#include <tchar.h> //für _tcslen() länge char *
using namespace std;
#include <olectl.h>
#include <windows.h>
#include "res\\Resource.h"
// geht:
// JPEG/GIF/ICO/WMF/BMP
const WCHAR *charToWCHAR(const char *s)
{
  WCHAR data[_tcslen(s)];
  for (unsigned int n=0; n<= _tcslen(s); n++)
  {
  data[n] = s[n];
  }
  data[_tcslen(s)] = * L"\0";
  return data;
}
class COlePicture
{
public:
  COlePicture() : pPicture(NULL)
  {
  }
  ~COlePicture()
  {
  if(pPicture != NULL)
  {
  pPicture->Release();
  }
  }
  BOOL Load(LPCTSTR szFile)
  {
// open file
  HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  if(hFile == INVALID_HANDLE_VALUE)
  {
  return FALSE;
  }
// get file size
  DWORD dwFileSize = GetFileSize(hFile, NULL);
  if(dwFileSize == -1)
  {
  return FALSE;
  }
  LPVOID pvData = NULL;
// alloc memory based on file size
  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
  if(hGlobal == NULL)
  {
  return FALSE;
  }
  pvData = GlobalLock(hGlobal);
  if(pvData == NULL)
  {
  return FALSE;
  }
  DWORD dwBytesRead = 0;
// read file and store in global memory
  BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
  if(bRead == FALSE)
  {
  return FALSE;
  }
  GlobalUnlock(hGlobal);
  CloseHandle(hFile);
  LPSTREAM pstm = NULL;
// create IStream* from global memory
  HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
  if(FAILED(hr) || pstm == NULL)
  {
  return FALSE;
  }
// Create IPicture from image file
  if(pPicture)
  {
  pPicture->Release();
  }
  hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&pPicture);
// ::OleSavePictureFile((LPDISPATCH)pPicture,L"XXX.wmf");//OK
// Oder
// char szFile2[MAX_PATH];
// strcpy( szFile2, "X-" );
// strcat( szFile2, szFile );
// const WCHAR *bs = charToWCHAR(szFile2);
// ::OleSavePictureFile( (LPDISPATCH)tPicture, (BSTR)bs );//OK
  if(FAILED(hr) || pPicture == NULL)
  {
  return FALSE;
  }
  pstm->Release();
  return TRUE;
  }
  VOID Show(HWND hWindowHandle, LONG nX, LONG nY)
  {
  if(pPicture)
  {
  HDC hDC = GetDC(hWindowHandle);
// get width and height of picture
  LONG hmWidth;
  LONG hmHeight;
  pPicture->get_Width(&hmWidth);
  pPicture->get_Height(&hmHeight);
// convert himetric to pixels
  INT nWidth = MulDiv(hmWidth, GetDeviceCaps(hDC, LOGPIXELSX), 2540);
  INT nHeight = MulDiv(hmHeight, GetDeviceCaps(hDC, LOGPIXELSY), 2540);
  RECT rc;
  GetClientRect(hWindowHandle, &rc);
// display picture using IPicture::Render
// pPicture->Render(hDC, nX, nY, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
  pPicture->Render(hDC, nX, nY, rc.right, rc.bottom, 0, hmHeight, hmWidth, -hmHeight, &rc);
  DeleteDC(hDC);
  }
  }
private:
  LPPICTURE pPicture;
};
/////////////////////////////////////////////////////
// Prototypes
/////////////////////////////////////////////////////
LRESULT CALLBACK MainWindowProcedure(HWND hWindowHandle,
  UINT uMessage,
  WPARAM wParam,
  LPARAM lParam);
LRESULT CALLBACK PictureBoxProcedure(HWND hWindowHandle,
  UINT uMessage,
  WPARAM wParam,
  LPARAM lParam);
/////////////////////////////////////////////////////
// The application's entry point
/////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstanceHandle,
  HINSTANCE hPreviousInstanceHandle,
  LPSTR lpszCommandLine,
  INT nShowState)
{
/////////////////////////////////////////////////////
// Register main window class
/////////////////////////////////////////////////////
  WNDCLASSEX MainWindowClass = {0};
  MainWindowClass.cbSize = sizeof(WNDCLASSEX);
  MainWindowClass.hInstance = hInstanceHandle;
  MainWindowClass.lpszClassName = "MainWindow";
  MainWindowClass.lpfnWndProc = MainWindowProcedure;
  MainWindowClass.style = CS_HREDRAW | CS_VREDRAW;
  MainWindowClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
  MainWindowClass.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(ID_ICON5));
  MainWindowClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  MainWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  MainWindowClass.lpszMenuName = NULL;
  MainWindowClass.cbClsExtra = 0;
  MainWindowClass.cbWndExtra = 0;
// unsigned int w = MAKEINTRESOURCE(IDB_TEST);
  if(RegisterClassEx(&MainWindowClass) == FALSE)
  {
  MessageBox(NULL, "Can't register MainWindowClass!",
  "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Register PictureBox window class
/////////////////////////////////////////////////////
  WNDCLASSEX PictureBoxWindowClass = {0};
  PictureBoxWindowClass.cbSize = sizeof(WNDCLASSEX);
  PictureBoxWindowClass.hInstance = hInstanceHandle;
  PictureBoxWindowClass.lpszClassName = "PictureBox";
  PictureBoxWindowClass.lpfnWndProc = PictureBoxProcedure;
  PictureBoxWindowClass.style = CS_HREDRAW | CS_VREDRAW;
  PictureBoxWindowClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
  PictureBoxWindowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  PictureBoxWindowClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  PictureBoxWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  PictureBoxWindowClass.lpszMenuName = NULL;
  PictureBoxWindowClass.cbClsExtra = 0;
  PictureBoxWindowClass.cbWndExtra = 0;
  if(RegisterClassEx(&PictureBoxWindowClass) == FALSE)
  {
  MessageBox(NULL, "Can't register PictureBoxWindowClass!",
  "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Create main window
/////////////////////////////////////////////////////
  HWND hMainWindow = CreateWindowEx(
  0, "MainWindow", "Simple PictureBox",
  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  CW_USEDEFAULT, CW_USEDEFAULT,
  CW_USEDEFAULT, CW_USEDEFAULT,
  HWND_DESKTOP, NULL,
  GetModuleHandle(NULL), NULL);
  if(hMainWindow == NULL)
  {
  MessageBox(NULL, "Can't create main window!", "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Create PictureBox 1
/////////////////////////////////////////////////////
  HWND hPictureBox1 = CreateWindowEx(
  0, "PictureBox", "a.BMP",
  WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE,
  40, 20,
  250, 200,
  hMainWindow, (HMENU) 1000,
  GetModuleHandle(NULL), NULL);
  if(hPictureBox1 == NULL)
  {
  MessageBox(NULL, "Can't create PictureBox 1!", "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Create PictureBox 2
/////////////////////////////////////////////////////
  HWND hPictureBox2 = CreateWindowEx(
  0, "PictureBox", "Smaily.ico",
  WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE,
  40, 300,
  350, 300,
  hMainWindow, (HMENU) 1001,
  GetModuleHandle(NULL), NULL);
  if(hPictureBox2 == NULL)
  {
  MessageBox(NULL, "Can't create PictureBox 2!", "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Create PictureBox 3
/////////////////////////////////////////////////////
  HWND hPictureBox3 = CreateWindowEx(
  0, "PictureBox", "a.WMF",
  WS_CHILD | WS_VISIBLE,
  420, 300,
  250, 250,
  hMainWindow, (HMENU) 1002,
  GetModuleHandle(NULL), NULL);
  if(hPictureBox3 == NULL)
  {
  MessageBox(NULL, "Can't create PictureBox 3!", "Information", MB_OK);
  return EXIT_FAILURE;
  }
/////////////////////////////////////////////////////
// Do the message loop
/////////////////////////////////////////////////////
  MSG Message = {0};
  while(GetMessage(&Message, NULL, 0, 0))
  {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
  }
  return Message.wParam;
}
/////////////////////////////////////////////////////
// Callback function for the main window
/////////////////////////////////////////////////////
DWORD *BitmapXGradDrehen( DWORD sourceBm[], int w, int h, float grad )
{
  DWORD *destBm = new DWORD[w*h*3];
  float radians = (grad/180.0 ) * 3.14159265358979;
  float dsin = sin(radians);
  float dcos = cos(radians);
  for (int y = 0; y < h; y++)
  {
  for (int x = 0; x < w; x++)
  {
  int centerx = w / 2, centery = h / 2;
  int m = x - centerx;
  int n = y - centery;
  int j = (int) (m * dcos + n * dsin);
  int k = (int) (n * dcos - m * dsin);
  j += centerx;
  k += centery;
  if (j < 0 || k < 0 || j >= w|| k >= h)
  {
/////Restliche Farben auf weiss
  destBm[(w*y+x)*3+2] = 0x00FFFFFF;
  destBm[(w*y+x)*3+1] = 0x00FFFFFF;
  destBm[(w*y+x)*3+0] = 0x00FFFFFF;
  continue;
  }
  destBm[(w*y+x)*3+0] = sourceBm[(w*k+j)*3+0];
  destBm[(w*y+x)*3+1] = sourceBm[(w*k+j)*3+1];
  destBm[(w*y+x)*3+2] = sourceBm[(w*k+j)*3+2];
// destBm[(w*y+x)*3+2] = 255;
// destBm[(w*y+x)*3+1] = 0;
// destBm[(w*y+x)*3+0] = 0;
  }
  }
  return destBm;
}
void LoadNewPicture(HWND hWindowHandle, LPCTSTR szFile)
{
  COlePicture* pPicture = (COlePicture*) GetWindowLong(hWindowHandle, GWL_USERDATA);
  if(pPicture != NULL)
  {
  pPicture->Load(szFile);
  SetWindowText(hWindowHandle, szFile);
  SetWindowLong(hWindowHandle, GWL_USERDATA, (LONG) pPicture);
  InvalidateRect(hWindowHandle,NULL,TRUE);
// pPicture->Show(hWindowHandle, 0,0);
  }
}
bool test(HWND hWindowHandle, LPCTSTR szFile)
{
// open file
  HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  if(hFile == INVALID_HANDLE_VALUE)
  {
  return FALSE;
  }
// get file size
  DWORD dwFileSize = GetFileSize(hFile, NULL);
  if(dwFileSize == -1)
  {
  return FALSE;
  }
  LPVOID pvData = NULL;
// alloc memory based on file size
  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
  if(hGlobal == NULL)
  {
  return FALSE;
  }
  pvData = GlobalLock(hGlobal);
  if(pvData == NULL)
  {
  return FALSE;
  }
  DWORD dwBytesRead = 0;
// read file and store in global memory
  BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
  if(bRead == FALSE)
  {
  return FALSE;
  }
  GlobalUnlock(hGlobal);
  CloseHandle(hFile);
  LPSTREAM pstm = NULL;
// create IStream* from global memory
  HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
  if(FAILED(hr) || pstm == NULL)
  {
  return FALSE;
  }
// Create IPicture from image file
  LPPICTURE tPicture(NULL);
  hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID*)&tPicture);
  if(FAILED(hr) || tPicture == NULL)
  {
  return FALSE;
  }
  pstm->Release();
  if(tPicture)
  {
  HDC hdc = GetDC(hWindowHandle);
// get width and height of picture
  LONG hmWidth;
  LONG hmHeight;
  tPicture->get_Width(&hmWidth);
  tPicture->get_Height(&hmHeight);
// convert himetric to pixels
  INT nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), 2540);
  INT nHeight = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), 2540);
  RECT rc;
  GetClientRect(hWindowHandle, &rc);
// display picture using IPicture::Render
  tPicture->Render(hdc, 500, 200, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
// pPicture->Render(hdc, nX, nY, rc.right, rc.bottom, 0, hmHeight, hmWidth, -hmHeight, &rc);
  DeleteDC(hdc);
  }
  char szFile2[MAX_PATH];
  strcpy( szFile2, "X-" );
  strcat( szFile2, szFile );
  const WCHAR *bs = charToWCHAR(szFile2);
  ::OleSavePictureFile( (LPDISPATCH)tPicture, (BSTR)bs );//OK
}
LRESULT CALLBACK MainWindowProcedure(HWND hWindowHandle,
  UINT uMessage,
  WPARAM wParam,
  LPARAM lParam)
{
  switch(uMessage)
  {
  case WM_COMMAND:
  switch(LOWORD(wParam))
  {
  case 1000:
  LoadNewPicture((HWND)lParam, "z32.gif");
// cout << w << endl;
//test(hWindowHandle, w );
// test(hWindowHandle, IDB_TEST);
  break;
  case 1001:
  LoadNewPicture( (HWND)lParam, "k3305052.jpg");
  LPCTSTR szFile;
  szFile = "w07.gif";
  test(hWindowHandle, szFile);
  break;
  case 1002:
  LoadNewPicture( (HWND)lParam, "test.jpg");
  test(hWindowHandle, "a.bmp");
  break;
  }
  break;
  case WM_DESTROY:
  PostQuitMessage(0);
  break;
  default:
  return DefWindowProc(hWindowHandle, uMessage, wParam, lParam);
  }
  return 0;
}
/////////////////////////////////////////////////////
// Callback function for the PictureBox
/////////////////////////////////////////////////////
LRESULT CALLBACK PictureBoxProcedure(HWND hWindowHandle,
  UINT uMessage,
  WPARAM wParam,
  LPARAM lParam)
{
  switch(uMessage)
  {
  case WM_CREATE:
  {
  COlePicture* pPicture = new COlePicture;
  CHAR WindowText[MAX_PATH];
  GetWindowText(hWindowHandle, WindowText, MAX_PATH);
  pPicture->Load(WindowText);
  SetWindowLong(hWindowHandle, GWL_USERDATA, (LONG) pPicture);
  }
  break;
  case WM_DESTROY:
  {
  COlePicture* pPicture = (COlePicture*) GetWindowLong(hWindowHandle, GWL_USERDATA);
  if(pPicture != NULL)
  {
  delete pPicture;
  }
  }
  break;
  case WM_LBUTTONDOWN:
  SendMessage(GetParent(hWindowHandle), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hWindowHandle), 0), (LPARAM)hWindowHandle);
  break;
  case WM_PAINT:
  {
  PAINTSTRUCT ps;
  ::BeginPaint(hWindowHandle, &ps);
  COlePicture* pPicture = (COlePicture*) GetWindowLong(hWindowHandle, GWL_USERDATA);
  if(pPicture != NULL)
  {
  pPicture->Show(hWindowHandle, 0, 0);
  }
  ::EndPaint(hWindowHandle, &ps);
  }
  break;
  default:
  return DefWindowProc(hWindowHandle, uMessage, wParam, lParam);
  }
  return 0;
}
 
Zuletzt bearbeitet von einem Moderator:
Hallo klaptnix

Code ist immer gut, aber nicht so wie in diesem Fall. Knapp 500 Zeilen Code, kaum kommentiert und qualitativ nicht überragend. Eigentlich sollte man hier den ganzen Code mal überarbeiten, aber das wird wohl zu viel Zeit in Anspruch nehmen...

Schon alleine die erste Funktion:
C++:
const WCHAR *charToWCHAR(const char *s)
{
  WCHAR data[_tcslen(s)];
 for (unsigned int n=0; n<= _tcslen(s); n++)
 {
  data[n] = s[n];
 }
  data[_tcslen(s)] = * L"\0";
 return data;
}

WCHAR data[_tcslen(s)];
-> nicht standardkonform:
In a declaration T D where D has the form
D1 [ constant-expressionopt ]...
...If the constant-expression (5.19) is present, it shall be an integral
constant expression and its value shall be greater than zero.

Des weiteren: _tcslen verwendest du wenn dann auf TCHAR . Wenn der Typ schon const char* (also multibyte) ist verwende strlen oder bei Verwendung von unicode als default charset wird _tcslen wcslen sein und bei const char* fehlschlagen.
WCHAR data[_tcslen(s)];
data[_tcslen(s)] = * L"\0";

Schreibt über die Grenze von data heraus, und warum die absolut merkwürdige Notation: *L"\0" und nicht einfach L'\0'?

Abschliessend:
Die Funktion macht sogesehen keinen Sinn, wird keine richtige Konvertierung gemacht. Korrekterweise (da schon die Windows-API im Spiel ist): MultiByteToWideChar

Viele Grüsse
Cromon
 
Zurück