На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
  
> Direct2D , Порядок вызова в MFC
    Начал изучать. Надо рисовать схемы с прокруткой и масштабированием.
    Для основы взял:
    https://docs.microsoft.com/ru-ru/cpp/mfc/wa...ct?view=vs-2019
    Используются костыли в коде для его корректной работе в двух разных примерах
    Гугл на Direct2D дает только разные примеры (ну и топиики с проблемами), как рисовать и т.д. в виде полноценной документации у меня не находится.

    VS 2019
    I Первая проблема
    Создал проект MFC с одним документов без Document/View

    При изменении размера окна, по факту, сперва вызывается OnDraw2D, а потом OnSize.
    Хотя, если смотреть пример из документации, то по логике, должно быть на оборот, так как в OnSize меняются настройки Градиента от размера окна (в коде перенесено в OnDraw2D).

    CScrollGraph
    Скрытый текст
    ExpandedWrap disabled
      class CScrollGraph : public CScrollView
      {
          DECLARE_DYNCREATE(CScrollGraph)
       
          CD2DTextFormat          *m_pTextFormat = nullptr;
          CD2DSolidColorBrush     *m_pBlackBrush = nullptr;
          CD2DLinearGradientBrush *m_pLinearGradientBrush = nullptr;
       
      public:
          CScrollGraph();           // защищенный конструктор, используемый при динамическом создании
          virtual ~CScrollGraph();
       
      public:
      #ifdef _DEBUG
          virtual void AssertValid() const;
      #ifndef _WIN32_WCE
          virtual void Dump(CDumpContext& dc) const;
      #endif
      #endif
       
      protected:
          virtual void OnDraw(CDC* pDC);      // для отрисовки этого представления
          virtual void OnInitialUpdate();     // впервые после создания
       
          DECLARE_MESSAGE_MAP()
      public:
          afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
          virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
      protected:
          afx_msg LRESULT OnDraw2D(WPARAM wParam, LPARAM lParam);
          void InitObj1();
      public:
          afx_msg void OnSize(UINT nType, int cx, int cy);
      };

    Скрытый текст
    ExpandedWrap disabled
      IMPLEMENT_DYNCREATE(CScrollGraph, CScrollView)
       
      CScrollGraph::CScrollGraph()
      {
       
      }
       
      CScrollGraph::~CScrollGraph()
      {
      }
       
       
      BEGIN_MESSAGE_MAP(CScrollGraph, CScrollView)
          ON_WM_CREATE()
          ON_REGISTERED_MESSAGE(AFX_WM_DRAW2D, &CScrollGraph::OnDraw2D)
          ON_WM_SIZE()
      END_MESSAGE_MAP()
       
       
      // Рисование CScrollGraph
       
      void CScrollGraph::OnInitialUpdate()
      {
          CScrollView::OnInitialUpdate();
       
          CSize sizeTotal;
          // TODO: рассчитайте полный размер этого представления
          sizeTotal.cx = sizeTotal.cy = 1000;
          SetScrollSizes(MM_TEXT, sizeTotal);
      }
       
      void CScrollGraph::OnDraw(CDC* pDC)
      {
          CDocument* pDoc = GetDocument();
          // TODO: добавьте код отрисовки
      }
       
      // Диагностика CScrollGraph
       
      #ifdef _DEBUG
      void CScrollGraph::AssertValid() const
      {
          CScrollView::AssertValid();
      }
       
      #ifndef _WIN32_WCE
      void CScrollGraph::Dump(CDumpContext& dc) const
      {
          CScrollView::Dump(dc);
      }
      #endif
      #endif //_DEBUG
       
      // Обработчики сообщений CScrollGraph
       
      int CScrollGraph::OnCreate(LPCREATESTRUCT lpCreateStruct)
      {
          if (CScrollView::OnCreate(lpCreateStruct) == -1)
              return -1;
       
          // TODO:  Добавьте специализированный код создания
       
          // Enable D2D support for this window:
          EnableD2DSupport();
       
          InitObj1();
       
          return 0;
      }
       
      void CScrollGraph::OnUpdate(CView *pSender, LPARAM lHint, CObject *pHint)
      {
          // TODO: добавьте специализированный код или вызов базового класса
          CScrollView::OnUpdate(pSender, lHint, pHint);
      }
       
      afx_msg LRESULT CScrollGraph::OnDraw2D(WPARAM wParam, LPARAM lParam)
      {
          CHwndRenderTarget* pRenderTarget = (CHwndRenderTarget*) lParam;
          ASSERT_VALID(pRenderTarget);
          if (pRenderTarget->IsValid())
          {
              if (1)
              {
       
                  //GetClientRect(rect);
                  //m_pLinearGradientBrush->SetEndPoint(CPoint(rect.right, rect.bottom));
       
                  int nMapMode;
                  SIZE sizeTotal;
                  SIZE sizePage;
                  SIZE sizeLine;
                  GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);
                  //CPoint pos1 = GetScrollPosition();
                  //CPoint pos2 = GetDeviceScrollPosition();
                  //CSize sss = GetTotalSize();
       
                  // apply translation transform according to view's scroll position
                  CPoint point = GetScrollPosition();
                  D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation((float) -point.x, (float) -point.y);
                  pRenderTarget->SetTransform(matrix);
       
                  CRect rect(0, 0, sizeTotal.cy, sizeTotal.cx);
                  m_pLinearGradientBrush->SetEndPoint(CPoint(sizeTotal.cx, sizeTotal.cy));
                  pRenderTarget->FillRectangle(rect, m_pLinearGradientBrush);
       
                  pRenderTarget->DrawText(
                      _T("Hello, World!"),
                      rect,
                      m_pBlackBrush,
                      m_pTextFormat);
              }
          }
       
          return TRUE;
      }
       
      void CScrollGraph::InitObj1()
      {
          // Initialize D2D resources:
          m_pBlackBrush = new CD2DSolidColorBrush(
              GetRenderTarget(),
              D2D1::ColorF(D2D1::ColorF::Black));
       
          m_pTextFormat = new CD2DTextFormat(
              GetRenderTarget(),
              _T("Verdana"),
              50);
       
          m_pTextFormat->Get()->SetTextAlignment(
              DWRITE_TEXT_ALIGNMENT_CENTER);
       
          m_pTextFormat->Get()->SetParagraphAlignment(
              DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
       
          D2D1_GRADIENT_STOP gradientStops[2];
       
          gradientStops[0].color =
              D2D1::ColorF(D2D1::ColorF::White);
       
          gradientStops[0].position = 0.f;
          gradientStops[1].color =
              D2D1::ColorF(D2D1::ColorF::Indigo);
       
          gradientStops[1].position = 1.f;
       
          m_pLinearGradientBrush = new CD2DLinearGradientBrush(
              GetRenderTarget(),
              gradientStops,
              ARRAYSIZE(gradientStops),
              D2D1::LinearGradientBrushProperties(
                  D2D1::Point2F(0, 0),
                  D2D1::Point2F(0, 0)));
      }
       
      void CScrollGraph::OnSize(UINT nType, int cx, int cy)
      {
          CScrollView::OnSize(nType, cx, cy);
       
          // TODO: добавьте свой код обработчика сообщений
      }

    CChildView
    Скрытый текст
    ExpandedWrap disabled
      class CChildView : public CWnd
      {
          CScrollGraph    *m_Graph = nullptr;
      // Создание
      public:
          CChildView();
       
      // Атрибуты
      public:
       
      // Операции
      public:
       
      // Переопределение
          protected:
          virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
       
      // Реализация
      public:
          virtual ~CChildView();
       
          // Созданные функции схемы сообщений
      protected:
      //  afx_msg void OnPaint();
          DECLARE_MESSAGE_MAP()
      public:
          afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
          afx_msg void OnSize(UINT nType, int cx, int cy);
      };

    Скрытый текст
    ExpandedWrap disabled
      CChildView::CChildView()
      {
      }
       
      CChildView::~CChildView()
      {
      }
       
       
      BEGIN_MESSAGE_MAP(CChildView, CWnd)
      //  ON_WM_PAINT()
          ON_WM_CREATE()
          ON_WM_SIZE()
      END_MESSAGE_MAP()
       
       
       
      // Обработчики сообщений CChildView
       
      BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
      {
          if (!CWnd::PreCreateWindow(cs))
              return FALSE;
       
          cs.dwExStyle |= WS_EX_CLIENTEDGE;
          cs.style &= ~WS_BORDER;
          cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
              ::LoadCursor(nullptr, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), nullptr);
       
          return TRUE;
      }
       
      //void CChildView::OnPaint()
      //{
      //  CPaintDC dc(this); // контекст устройства для рисования
      //  
      //  // TODO: Добавьте код обработки сообщений
      //  
      //  // Не вызывайте CWnd::OnPaint() для сообщений рисования
      //}
       
       
       
      int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
      {
          if (CWnd::OnCreate(lpCreateStruct) == -1)
              return -1;
       
          m_Graph = new CScrollGraph();
          m_Graph->Create(nullptr, nullptr, AFX_WS_DEFAULT_VIEW, { 100, 100 }, this, 1, nullptr);
       
          return 0;
      }
       
       
      void CChildView::OnSize(UINT nType, int cx, int cy)
      {
          CWnd::OnSize(nType, cx, cy);
          if (m_Graph->GetSafeHwnd()) m_Graph->MoveWindow(0, 0, cx, cy);
          // TODO: добавьте свой код обработчика сообщений
      }


    II Вторая проблема
    Тот же проект, только с включенным режимом Document/View
    Для View (при создании проекта) выбираем базовым классом CScrollView.

    OnDraw2D вызывается перед OnInitialUpdate/OnUpdate (дважды) (в коде добавлен костыль для проверки инициализации)
    В OnUpdate команда SetScrollSizes инициирует вызов OnDraw2D, т.е. OnDraw2D вложен в OnUpdate , в первом примере этого не происходит.
    При изменении размера, так же как в первом примере, OnDraw2D перед OnSize, но OnDraw2D+OnSize вызывается дважды при однократном изменении размера.
    ЗЫ: при создании приложения были добавлены дополнительные фреймы в стиле Outlook, не исключаю, что двойные вызовы из-за этого, так как при втором вызове, отличается размер по высоте (с учетом текущего набора фреймов), но хотелось бы и этого избежать.

    Скрытый текст
    ExpandedWrap disabled
      class CGraph1View : public CScrollView
      {
          CD2DTextFormat          *m_pTextFormat = nullptr;
          CD2DSolidColorBrush     *m_pBlackBrush = nullptr;
          CD2DLinearGradientBrush *m_pLinearGradientBrush = nullptr;
       
          CD2DBitmap              *m_pBitmap = nullptr;
          //CHwndRenderTarget     *m_renderTarget = nullptr;
       
          bool                    m_Init = false;
       
      protected: // создать только из сериализации
          CGraph1View() noexcept;
          DECLARE_DYNCREATE(CGraph1View)
       
      // Атрибуты
      public:
          CGraph1Doc* GetDocument() const;
       
      // Операции
      public:
       
      // Переопределение
      public:
          virtual void OnDraw(CDC* pDC);  // переопределено для отрисовки этого представления
          virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
      protected:
          virtual void OnInitialUpdate(); // вызывается в первый раз после конструктора
          virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
          virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
          virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
       
      // Реализация
      public:
          virtual ~CGraph1View();
      #ifdef _DEBUG
          virtual void AssertValid() const;
          virtual void Dump(CDumpContext& dc) const;
      #endif
       
      protected:
          void InitObj1();
       
       
      // Созданные функции схемы сообщений
      protected:
          afx_msg void OnFilePrintPreview();
          afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
          afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
          DECLARE_MESSAGE_MAP()
      public:
          afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
      protected:
          afx_msg LRESULT OnDraw2D(WPARAM wParam, LPARAM lParam);
          virtual void OnUpdate(CView* /*pSender*/, LPARAM /*lHint*/, CObject* /*pHint*/);
      public:
          afx_msg void OnSize(UINT nType, int cx, int cy);
      };
       
      #ifndef _DEBUG  // версия отладки в Graph1View.cpp
      inline CGraph1Doc* CGraph1View::GetDocument() const
         { return reinterpret_cast<CGraph1Doc*>(m_pDocument); }
      #endif

    Скрытый текст
    ExpandedWrap disabled
      IMPLEMENT_DYNCREATE(CGraph1View, CScrollView)
       
      BEGIN_MESSAGE_MAP(CGraph1View, CScrollView)
          // Стандартные команды печати
          ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)
          ON_COMMAND(ID_FILE_PRINT_DIRECT, &CScrollView::OnFilePrint)
          ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CGraph1View::OnFilePrintPreview)
          ON_WM_CONTEXTMENU()
          ON_WM_RBUTTONUP()
          ON_WM_CREATE()
          ON_REGISTERED_MESSAGE(AFX_WM_DRAW2D, &CGraph1View::OnDraw2D)
          ON_WM_SIZE()
      END_MESSAGE_MAP()
       
      // Создание или уничтожение CGraph1View
       
      CGraph1View::CGraph1View() noexcept
      {
          // TODO: добавьте код создания
       
      }
       
      CGraph1View::~CGraph1View()
      {
      }
       
      BOOL CGraph1View::PreCreateWindow(CREATESTRUCT& cs)
      {
          // TODO: изменить класс Window или стили посредством изменения
          //  CREATESTRUCT cs
       
          return CScrollView::PreCreateWindow(cs);
      }
       
      // Рисование CGraph1View
       
      void CGraph1View::OnDraw(CDC* /*pDC*/)
      {
          //CGraph1Doc* pDoc = GetDocument();
          //ASSERT_VALID(pDoc);
          //if (!pDoc)
          //  return;
       
          // TODO: добавьте здесь код отрисовки для собственных данных
      }
       
      void CGraph1View::OnInitialUpdate()
      {
          CScrollView::OnInitialUpdate();
      }
       
       
      // Печать CGraph1View
       
       
      void CGraph1View::OnFilePrintPreview()
      {
      #ifndef SHARED_HANDLERS
          AFXPrintPreview(this);
      #endif
      }
       
      BOOL CGraph1View::OnPreparePrinting(CPrintInfo* pInfo)
      {
          // подготовка по умолчанию
          return DoPreparePrinting(pInfo);
      }
       
      void CGraph1View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
      {
          // TODO: добавьте дополнительную инициализацию перед печатью
      }
       
      void CGraph1View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
      {
          // TODO: добавьте очистку после печати
      }
       
      void CGraph1View::OnRButtonUp(UINT /* nFlags */, CPoint point)
      {
          ClientToScreen(&point);
          OnContextMenu(this, point);
      }
       
      void CGraph1View::OnContextMenu(CWnd* /* pWnd */, CPoint point)
      {
      #ifndef SHARED_HANDLERS
          theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
      #endif
      }
       
       
      // Диагностика CGraph1View
       
      #ifdef _DEBUG
      void CGraph1View::AssertValid() const
      {
          CScrollView::AssertValid();
      }
       
      void CGraph1View::Dump(CDumpContext& dc) const
      {
          CScrollView::Dump(dc);
      }
       
      void CGraph1View::InitObj1()
      {
          // Initialize D2D resources:
          m_pBlackBrush = new CD2DSolidColorBrush(
              GetRenderTarget(),
              D2D1::ColorF(D2D1::ColorF::Black));
       
          m_pTextFormat = new CD2DTextFormat(
              GetRenderTarget(),
              _T("Verdana"),
              50);
       
          m_pTextFormat->Get()->SetTextAlignment(
              DWRITE_TEXT_ALIGNMENT_CENTER);
       
          m_pTextFormat->Get()->SetParagraphAlignment(
              DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
       
          D2D1_GRADIENT_STOP gradientStops[2];
       
          gradientStops[0].color =
              D2D1::ColorF(D2D1::ColorF::White);
       
          gradientStops[0].position = 0.f;
          gradientStops[1].color =
              D2D1::ColorF(D2D1::ColorF::Indigo);
       
          gradientStops[1].position = 1.f;
       
          m_pLinearGradientBrush = new CD2DLinearGradientBrush(
              GetRenderTarget(),
              gradientStops,
              ARRAYSIZE(gradientStops),
              D2D1::LinearGradientBrushProperties(
                  D2D1::Point2F(0, 0),
                  D2D1::Point2F(0, 0)));
      }
       
      CGraph1Doc* CGraph1View::GetDocument() const // встроена неотлаженная версия
      {
          ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraph1Doc)));
          return (CGraph1Doc*)m_pDocument;
      }
      #endif //_DEBUG
       
       
      // Обработчики сообщений CGraph1View
       
      int CGraph1View::OnCreate(LPCREATESTRUCT lpCreateStruct)
      {
          if (CScrollView::OnCreate(lpCreateStruct) == -1)
              return -1;
       
          // Enable D2D support for this window:
          EnableD2DSupport();
       
          InitObj1();
       
          return 0;
      }
       
      void CGraph1View::OnUpdate(CView *pSender, LPARAM lHint, CObject *pHint)
      {
          
          //CScrollView::OnUpdate(pSender, lHint, pHint);
          CHwndRenderTarget* pRenderTarget = this->GetRenderTarget();
          ASSERT_VALID(pRenderTarget);
          if (pRenderTarget->IsValid())
          {
              if (1)
              {
                  CSize size;
                  // TODO: рассчитайте полный размер этого представления
                  size.cx = size.cy = 1000;
                  SetScrollSizes(MM_TEXT, size);
                  ScrollToPosition(CPoint(0, 0));
              }
              if (0)
              {
                  CSize sizeImage(100, 100);
                  delete m_pBitmap;
                  m_pBitmap = nullptr;
       
                  const CString strFile = L"D:\\Photos\\73030609.jpg";
                  if (!strFile.IsEmpty())
                  {
       
                      m_pBitmap = new CD2DBitmap(pRenderTarget, strFile);
                      HRESULT hr = m_pBitmap->Create(pRenderTarget);
                      if (m_pBitmap->IsValid())
                      {
                          CD2DSizeF size = m_pBitmap->GetSize();
                          sizeImage.SetSize(static_cast<int>(size.width), static_cast<int>(size.height));
                      }
                  }
                  SetScrollSizes(MM_TEXT, sizeImage);
                  ScrollToPosition(CPoint(0, 0));
              }
              m_Init = true;
          }
      }
       
      afx_msg LRESULT CGraph1View::OnDraw2D(WPARAM wParam, LPARAM lParam)
      {
          CHwndRenderTarget* pRenderTarget = (CHwndRenderTarget*) lParam;
          ASSERT_VALID(pRenderTarget);
          if (m_Init && pRenderTarget->IsValid())
          {
              if (1)
              {
       
                  //GetClientRect(rect);
                  //m_pLinearGradientBrush->SetEndPoint(CPoint(rect.right, rect.bottom));
       
                  int nMapMode;
                  SIZE sizeTotal;
                  SIZE sizePage;
                  SIZE sizeLine;
                  GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine);
                  //CPoint pos1 = GetScrollPosition();
                  //CPoint pos2 = GetDeviceScrollPosition();
                  //CSize sss = GetTotalSize();
       
                  // apply translation transform according to view's scroll position
                  CPoint point = GetScrollPosition();
                  D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation((float) -point.x, (float) -point.y);
                  pRenderTarget->SetTransform(matrix);
       
                  CRect rect(0, 0, sizeTotal.cy, sizeTotal.cx);
                  m_pLinearGradientBrush->SetEndPoint(CPoint(sizeTotal.cx, sizeTotal.cy));
                  pRenderTarget->FillRectangle(rect, m_pLinearGradientBrush);
       
                  pRenderTarget->DrawText(
                      _T("Hello, World!"),
                      rect,
                      m_pBlackBrush,
                      m_pTextFormat);
              }
              if (0)
              {
                  D2D1_COLOR_F color = { 1.f, 1.f, 1.f, 1.f }; // r, g, b, a
                  pRenderTarget->Clear(color);
                  if ((nullptr != m_pBitmap) && m_pBitmap->IsValid())
                  {
                      // apply translation transform according to view's scroll position
                      CPoint point = GetScrollPosition();
                      D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation((float) -point.x, (float) -point.y);
                      pRenderTarget->SetTransform(matrix);
                      // draw the bitmap
                      CD2DSizeF size = m_pBitmap->GetSize();
                      pRenderTarget->DrawBitmap(m_pBitmap, CD2DRectF(0, 0, size.width, size.height));
                  }
              }
          }
       
          return TRUE;
      }
       
      void CGraph1View::OnSize(UINT nType, int cx, int cy)
      {
          CScrollView::OnSize(nType, cx, cy);
      }
    Сообщение отредактировано: Black_Dragon -
    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
    0 пользователей:


    Рейтинг@Mail.ru
    [ Script execution time: 0,0303 ]   [ 16 queries used ]   [ Generated: 16.04.24, 19:30 GMT ]