Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.218.184.214] |
|
Сообщ.
#1
,
|
|
|
Начал изучать. Надо рисовать схемы с прокруткой и масштабированием.
Для основы взял: 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 Скрытый текст 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); }; Скрытый текст 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 Скрытый текст 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); }; Скрытый текст 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, не исключаю, что двойные вызовы из-за этого, так как при втором вызове, отличается размер по высоте (с учетом текущего набора фреймов), но хотелось бы и этого избежать. Скрытый текст 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 Скрытый текст 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); } |