2010-07-28 65 views
3

我一直试图在MFC中显示一个jpg图像,但是我无法绘制它。我是一个完整的MFC新手,一直到现在为止我所做的一切大部分都是从我在网上找到的东西改编而来的。目前,我有这样的:在MFC中绘制JPG

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); 
} 

构造函数调用:

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; 
} 

的问题是,我不能让DRAWITEM函数被调用。我究竟做错了什么? 任何帮助将不胜感激。

+0

你需要一个按钮或菜单项来保存图像,并调用PictureView :: DrawItem? – 2010-07-28 14:01:11

+0

想法是这样的:另一个过程有一个摄像头并拍摄事物的照片。它将这些图片存储为JPG格式。当某种情况发生时,它会通知我的过程并提供与该条件相对应的图像的路径。我需要向包含图像的用户显示一个对话框,用户现在必须选择如何继续。 – Tekar 2010-07-28 14:54:38

回答

0

我从来没有使用MFC,但快速细读CStatic::DrawItem documentation说,它必须创建与SS_OWNERDRAW样式为DrawItem被调用。您没有为您的PictureView显示Create行,因此可能是这样吗?

+0

事实并非如此,我现在已经更改了代码。但是这并没有改变这个问题。我添加的代码如下所示: PictureView * image = new PictureView(path);我们可以通过下面的例子来说明如何使用这种方法来创建一个新的图像: - 创建(“”,SS_OWNERDRAW,CRect(horizo​​ntalPos,verticalPos,width + horizo​​ntalPos,height + verticalPos),this,childId); 有没有什么办法可以在这里以更具可读性的格式发布? – Tekar 2010-07-28 14:49:46

+0

@Tom:您可以通过编辑原始问题来添加此信息。 – Troubadour 2010-07-28 15:38:51

1

我不确定GetDC在调用m_picture-> draw时必然会引用CREATESTRUCT中给出的相同DC。我所做的是:

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

编辑:由于我不能评论,希望编辑就足够了。我认为你的同事是错误的,因为我刚刚使用SS_OWNERDRAW实现了一个CStatic控件。我猜测添加了WS_CHILD |创建呼叫上的WS_VISIBLE是关键。

+0

可能,但我不能得到DrawItem函数被调用,所以我不能测试这个呢。 – Tekar 2010-07-29 06:35:11

+0

我的坏 - 显然我可以评论我自己的答案。 Livin'学习'。 – rlduffy 2010-07-29 22:02:52

+0

你是正确的,当WS_CHILD和WS_VISIBLE被添加它作为一个CStatic。 – Tekar 2010-08-03 10:10:07

1

在我的一位同事的帮助下,我找到了答案。他告诉我,不可能拥有一个自己的CStatic。所以当我现在从CButton继承PictureView并使其BS_OWNERDRAW呈现我的图像时。

就我个人而言,我认为这是一个丑陋的解决方案,但我现在很厌倦这个问题,所以我并不在乎那么多。这些都是我做,使其工作的变化:

构造函数调用:

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; 
}; 

感谢各位的所有帮助。

2

下面是一个MFC对话框绘制图像的简单方法:

链路与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); 

希望工程!