2010-07-28 7 views
3

J'ai essayé d'afficher une image jpg dans MFC, mais je n'arrive pas à la dessiner. Je suis un débutant complet MFC et tout ce que j'ai fait jusqu'à maintenant est principalement adapté des choses que j'ai trouvées sur le net. À l'heure actuelle, j'ai ceci:Dessiner un jpg dans MFC

Picture.h:

#pragma once 
#include <afxwin.h> 

class Picture 
{ 
public: 
    Picture(); 

    bool load(LPCTSTR filePath); 

    bool draw(CDC* deviceContext 
      , CRect clientRect 
      , LPCRECT prcMFBounds); 

    CSize getSize(CDC* pDC); 

private: 
    LPPICTURE m_picture; 
}; 

Picture.cpp:

#include "Picture.h" 

Picture::Picture() 
    : m_picture(0) 
{ 
} 

bool Picture::load(LPCTSTR szFile) 
{ 
    HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 
    if (hFile == INVALID_HANDLE_VALUE) 
     return false; 

    DWORD dwFileSize = GetFileSize(hFile, NULL); 
    if (dwFileSize == (DWORD)-1) 
    { 
     CloseHandle(hFile); 
     return false; 
    } 

    LPVOID pvData = NULL; 

    // alloc memory based on file size 
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); 
    if (hGlobal == NULL) 
    { 
     CloseHandle(hFile); 
     return false; 
    } 

    pvData = GlobalLock(hGlobal); 

    if (pvData == NULL) 
    { 
     GlobalUnlock(hGlobal); 
     CloseHandle(hFile); 
     return false; 
    } 

    DWORD dwBytesRead = 0; 

    // read file and store in global memory 
    bool bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL) != 0; 

    GlobalUnlock(hGlobal); 
    CloseHandle(hFile); 

    if (!bRead) 
     return false; 

    LPSTREAM pstm = NULL; 

    // create IStream* from global memory 
    HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm); 
    if (!(SUCCEEDED(hr))) 
    { 
     if (pstm != NULL) 
     pstm->Release(); 
     return false; 
    } 

    else if (pstm == NULL) 
     return false; 

    // Create IPicture from image file 
    if (m_picture) 
     m_picture->Release(); 

    hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&(m_picture)); 
    if (!(SUCCEEDED(hr))) 
    { 
     pstm->Release(); 
     return false; 
    } 

    else if (m_picture == NULL) 
    { 
     pstm->Release(); 
     return false; 
    } 
    pstm->Release(); 

    return true; 
} 

bool Picture::draw(CDC* deviceContext, CRect clientRect, LPCRECT prcMFBounds) 
{ 
    if (clientRect.IsRectNull()) 
    { 
     CSize imageSize = getSize(deviceContext); 
     clientRect.right = imageSize.cx; 
     clientRect.bottom = imageSize.cy; 
    } 

    long pictureWidth = 0; 
    long pictureHeigth = 0; 

    m_picture->get_Width(&pictureWidth); 
    m_picture->get_Height(&pictureHeigth); 

    m_picture->Render(*deviceContext 
        , clientRect.left 
        , clientRect.top 
        , clientRect.Width() 
        , clientRect.Height() 
        , 0 
        , pictureHeigth 
        , pictureWidth 
        , -pictureHeigth 
        , prcMFBounds); 
    return true; 
} 

CSize Picture::getSize(CDC* deviceContext) 
{ 
    if (!m_picture) 
     return CSize(0,0); 

    LONG width, height; // HIMETRIC units 
    m_picture->get_Width(&width); 
    m_picture->get_Height(&height); 
    CSize size(width, height); 
    if (deviceContext==NULL) 
    { 
     CWindowDC dc(NULL); 
     dc.HIMETRICtoDP(&size); // convert to pixels 
    } 
    else 
    { 
     deviceContext->HIMETRICtoDP(&size); 
    } 
    return size; 
} 

PictureView.h:

#pragma once 

#include <afxwin.h> 
#include <string> 

class Picture; 

class PictureView : public CStatic 
{ 
public: 
    PictureView(std::string path); 

protected: 
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 

private: 
    Picture* m_picture; 
}; 

PictureView.cpp:

#include "PictureView.h" 
#include "Picture.h" 

PictureView::PictureView(std::string path) 
{ 
    m_picture = new Picture(); 
    m_picture->load(path.c_str()); 
} 

void PictureView::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) 
{ 
    CRect rect; 
    GetClientRect(&rect); 
    m_picture->draw(GetDC(), rect, rect); 
} 

appel Constructor:

CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId) 
{ 
    PictureView* image = new PictureView(path); 
    image->Create("", SS_OWNERDRAW, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId); 
    return image; 
} 

Le problème est que je ne peux pas la fonction DrawItem à appeler. Qu'est-ce que je fais mal? Toute aide sera appréciée.

+0

Avez-vous besoin d'un bouton ou d'un élément de menu pour enregistrer l'image et avoir cet appel PictureView :: DrawItem? –

+0

L'idée est la suivante: un autre processus a une caméra et prend des photos de choses.Il stocke ces images en jpg. Quand une certaine condition se produit, elle notifie mon processus et fournit le chemin de l'image qui correspond à cette condition. J'ai besoin de montrer une boîte de dialogue à l'utilisateur contenant l'image, l'utilisateur doit maintenant choisir comment procéder. – Tekar

Répondre

0

Je n'ai jamais utilisé MFC mais une lecture rapide du CStatic::DrawItem documentation dit qu'il doit être créé avec le style SS_OWNERDRAW pour DrawItem pour être appelé. Vous n'avez pas montré la ligne Create pour votre PictureView alors peut-être que c'est ça?

+0

Ce n'était pas le cas et j'ai changé le code maintenant. Cependant, cela n'a pas changé le problème. Le code que j'ai ajouté ressemble à ceci: PictureView * image = new PictureView (chemin); image-> Créer ("", SS_OWNERDRAW, CRect (horizontalPos, verticalPos, largeur + horizontalPos, hauteur + verticalPos), this, childId); Y a-t-il un moyen de poster ceci dans un format plus lisible ici? – Tekar

+0

@Tom: Vous pouvez ajouter cette information en modifiant simplement votre question initiale. – Troubadour

1

Je ne suis pas sûr que le GetDC dans l'appel à m_picture-> draw fera nécessairement référence au même DC qui est donné dans le CREATESTRUCT. Ce que j'ai fait est:

 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); 

EDIT: Puisque je ne peux pas commenter, j'espère qu'une édition suffira. Je pense que votre collègue se trompe, car j'ai récemment mis en place un contrôle CStatic en utilisant SS_OWNERDRAW. Je suppose que l'ajout de WS_CHILD | WS_VISIBLE sur l'appel Create est la clé.

+0

Possible mais je n'arrive pas à appeler la fonction DrawItem, donc je ne peux pas encore la tester. – Tekar

+0

Mon mauvais - apparemment, je peux commenter ma propre réponse. Livin 'et learnin'. – rlduffy

+0

Vous avez raison, lorsque WS_CHILD et WS_VISIBLE sont ajoutés, cela fonctionne comme un CStatic. – Tekar

1

avec l'aide d'un de mes collègues, j'ai trouvé la réponse. Il m'a dit qu'il n'est pas possible d'avoir un propriétaire CStatic. Donc, quand j'hérite maintenant PictureView de CButton et le rend BS_OWNERDRAW mon image est rendue.

Personnellement, je pense que c'est une solution moche, mais je suis tellement fatigué de ce problème maintenant que je ne me soucie pas vraiment beaucoup. Ce sont les changements que j'ai fait pour le faire fonctionner:

appel Constructor:

CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId) 
{ 
    PictureView* image = new PictureView(path); 
    image->Create("", BS_OWNERDRAW | WS_CHILD | WS_VISIBLE, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId); 
    return image; 
} 

PictureView.h:

#pragma once 

#include <afxwin.h> 
#include <string> 

class Picture; 

class PictureView : public CButton 
{ 
public: 
    PictureView(std::string path); 

protected: 
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); 

private: 
    Picture* m_picture; 
}; 

Merci de tout le monde de pour toute l'aide.

2

est ici un moyen facile de dessiner une image dans une boîte de dialogue MFC:

lien avec

gdiplus.dll

#include "atlimage.h> 
#include "gdiplus.h> 
using namespace Gdiplus 
. 
. 
. 

CImage ci; 

ci.Load((CString)"D:\\Pictures\\mycat.jpg"); 

CDC *dc = AfxGetMainWnd()->GetDC(); 

HDC hdc = *dc; 

ci.Draw(hdc,10,10); 

Espérons que ça marche!