Рисование JPG в MFC - PullRequest
       1

Рисование JPG в MFC

3 голосов
/ 28 июля 2010

Я пытался показать изображение JPG в MFC, но я не могу его нарисовать. Я полный новичок в 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 для вызова. Что я делаю неправильно? Любая помощь будет оценена.

Ответы [ 4 ]

3 голосов
/ 31 января 2012

Вот простой способ нарисовать изображение в диалоговом окне 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);

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

1 голос
/ 28 июля 2010

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

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

РЕДАКТИРОВАТЬ: Поскольку я не могу комментировать, надеюсь, будет достаточно редактирования. Я думаю, что ваш коллега ошибается, так как я недавно внедрил элемент управления CStatic с использованием SS_OWNERDRAW. Я предполагаю, что добавление WS_CHILD | WS_VISIBLE при вызове Create - это ключ.

1 голос
/ 29 июля 2010

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

Спасибо всем за помощь.

0 голосов
/ 28 июля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...