2010-07-28 2 views
3

Я пытался показать jpg-образ в MFC, но я не могу его нарисовать. Я полный новичок MFC, и все, что я встал до сих пор, в основном адаптировано из вещей, которые я нашел в сети. В настоящее время у меня есть это:Рисование jpg в 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); 
} 

Конструктор вызов:

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? –

+0

Идея такова: в другом процессе есть камера и фотографирует вещи.Он сохраняет эти изображения как jpg. Когда возникает определенное условие, он уведомляет мой процесс и предоставляет путь к изображению, которое соответствует этому условию. Мне нужно показать диалоговое окно для пользователя, содержащего изображение, теперь пользователь должен выбрать способ продолжения. – Tekar

ответ

0

Я никогда не использовал MFC, но быстрый прочтение CStatic::DrawItem documentation говорит о том, что он должен быть создан с помощью стиля SS_OWNERDRAW для DrawItem для вызова. Вы не указали линию Create для своего PictureView, так что, возможно, это так?

+0

Это действительно не так, и теперь я изменил код. Однако это не изменило проблему. Код, который я добавил, выглядит так: PictureView * image = new PictureView (путь); image-> Create ("", SS_OWNERDRAW, CRect (horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), это, childId); Есть ли способ опубликовать это в более читаемом формате здесь? – Tekar

+0

@Tom: Вы можете добавить эту информацию, просто отредактировав исходный вопрос. – Troubadour

1

Я не уверен, что GetDC в вызове m_picture-> draw обязательно будет ссылаться на тот же DC, который указан в CREATESTRUCT. Что я сделал:

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

EDIT: Поскольку я не могу комментировать, надеюсь, редактирования будет достаточно. Я думаю, что ваш коллега ошибается, так как я только недавно внедрил CStatic-контроль, используя SS_OWNERDRAW. Я предполагаю, что добавление WS_CHILD | WS_VISIBLE на вызове Create - это ключ.

+0

Возможно, но я не могу заставить функцию DrawItem вызываться, поэтому я еще не могу это проверить. – Tekar

+0

Мой плохой - по-видимому, я могу прокомментировать мой собственный ответ. Ливинь и учись. – rlduffy

+0

Вы правы, когда WS_CHILD и WS_VISIBLE добавлены, он работает как CStatic. – Tekar

1

с помощью моего коллеги я нашел ответ. Он сказал мне, что невозможно иметь владельца CStatic. Поэтому, когда я теперь наследую PictureView от CButton и делаю это 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; 
}; 

Thank за всю помощь.

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

Надеется, что это работает!

Смежные вопросы