Mfc. Координаты Scroll окна и Потоки.

  • Автор темы OberonTSM
  • Дата начала
Статус
Закрыто для дальнейших ответов.
O

OberonTSM

Гость
#1
Проблема такая:
Есть Приложение, вычисляющее точку оптимума функции по методу симплекса. объект вида - скроллинговый, причём размер больше размера экрана, то есть скролл нужен всегда. В главном окне в OnDraw рисуются координатные оси для трёх графиков. Также есть отдальный поток, рисующий сам процесс поиска методом симплекса (рисует наглядно, то есть шаг за шагом, по типу анимации). Собственно суть проблемы в том, что при любом скролле вниз координатная система для потока меняется и точка (0,0) совпадает с левым верхним углом ОТОБРАЖАЕМОЙ В ДАННЫЙ МОМЕНТ части объекта вида. А координатные оси остаются на своих местах. Соответственно
следующий после прокрутки вниз шаг графика рисуется ниже чем надо. Как сделать так чтобы координаты для потока были постоянными и не зависили от скроллинга и отображаемой части объекта вида? Возможно ошибка в контексте устройства... Пожалуйста, подскажите что и где надо поменять\дописать...

Также интересно, как сделать чтобы прис выходе за границу области где должен быть рисунок (когда сильно прокручиваешь вниз), графическая информация потока не стиралась а оставалась нарисованной.
вот код потока и метода OnDraw:
Код:
///////////////////////////////////////////////////////////////////////////////////////////////////

Объявление класса
class CSimplexView : public CScrollView
{
protected: // create from serialization only
CSimplexView();
DECLARE_DYNCREATE(CSimplexView)

// Attributes
public:
CSimplexDoc* GetDocument();

// Operations
public:
CClientDC *m_pDC;		// óêàçàòåëü íà êîíòåêñò êëèåíòñêîé ÷àñòè îêíà
CRITICAL_SECTION m_ClientDCLock;	// êðèòè÷åñêàÿ ñåêöèÿ
//	int m_nThreadCounter;		// ñ÷åò÷èê ÷èñëà çàïóùåííûõ ïîòîêîâ 
bool m_bWorking;	
int ViewCheck;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSimplexView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void OnInitialUpdate(); // called first time after construct
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CSimplexView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif


// SimplexView.cpp : implementation of the CSimplexView class
//

#include "stdafx.h"
#include "Simplex.h"

#include "SimplexDoc.h"
#include "SimplexView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSimplexView

IMPLEMENT_DYNCREATE(CSimplexView, CScrollView)

BEGIN_MESSAGE_MAP(CSimplexView, CScrollView)
//{{AFX_MSG_MAP(CSimplexView)
ON_COMMAND(ID_VIEW_GRAPH, OnViewGraph)
ON_COMMAND(ID_VIEW_TABLE, OnViewTable)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_VIEW_SEARCHPROCESS, OnUpdateViewSearchprocess)
ON_COMMAND(ID_VIEW_SEARCHPROCESS, OnViewSearchprocess)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSimplexView construction/destruction

CSimplexView::CSimplexView()
{
// TODO: add construction code here
ViewCheck=0;
m_pDC = 0;
m_bWorking = false;
// m_nThreadCounter = 0;
InitializeCriticalSection(&m_ClientDCLock);

}

CSimplexView::~CSimplexView()
{
DeleteCriticalSection(&m_ClientDCLock);
}

BOOL CSimplexView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs

return CScrollView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CSimplexView drawing

UINT SearchThread(LPVOID pParam)
{
CSimplexView* pView = (CSimplexView*)pParam; // ïðåîáðàçîâàíèå àðãóìåíòà ê óêàçàòåëþ íà îáúåêò âèäà
CSimplexDoc* pDoc = pView->GetDocument();
//	ASSERT_VALID(pDoc);
pView->m_bWorking = true;
int xmin=30, xmax=1030, ymin=30, ymax=1030;
int morphX=(xmax-xmin)/5;
int morphY=-morphX;
CPen penlight(PS_SOLID, 1, RGB(230,230,230));
CPen pendark(PS_SOLID, 2, RGB(25,25,25));
CPen pengreen(PS_SOLID, 5, RGB(0,255,0));
CPen penbluefat(PS_SOLID, 5, RGB(0,0,255));
CPen penbluethin(PS_SOLID, 1, RGB(0,0,255));
for (int i=0;i<pDoc->Iter;i++)
if (pView->ViewCheck==1)
{
EnterCriticalSection(&pView->m_ClientDCLock);
pView->m_pDC->SelectObject(pengreen);
pView->m_pDC->MoveTo(pDoc->X[i][0][0]*morphX+(xmax+xmin)/2, pDoc->X[i][0][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->LineTo(pDoc->X[i][0][0]*morphX+(xmax+xmin)/2, pDoc->X[i][0][1]*morphY+(ymax+ymin)/2);

pView->m_pDC->SelectObject(penlight);
pView->m_pDC->LineTo(pDoc->X[i][1][0]*morphX+(xmax+xmin)/2, pDoc->X[i][1][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->LineTo(pDoc->X[i][2][0]*morphX+(xmax+xmin)/2, pDoc->X[i][2][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->LineTo(pDoc->X[i][0][0]*morphX+(xmax+xmin)/2, pDoc->X[i][0][1]*morphY+(ymax+ymin)/2);

pView->m_pDC->SelectObject(penbluefat);
pView->m_pDC->MoveTo(pDoc->X[i][pDoc->MaxF[i]][0]*morphX+(xmax+xmin)/2, pDoc->X[i][pDoc->MaxF[i]][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->LineTo(pDoc->X[i][pDoc->MaxF[i]][0]*morphX+(xmax+xmin)/2, pDoc->X[i][pDoc->MaxF[i]][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->SelectObject(penbluethin);
pView->m_pDC->LineTo(pDoc->X[i+1][0][0]*morphX+(xmax+xmin)/2, pDoc->X[i+1][0][1]*morphY+(ymax+ymin)/2);		
pView->m_pDC->SelectObject(penbluefat);
pView->m_pDC->LineTo(pDoc->X[i+1][0][0]*morphX+(xmax+xmin)/2, pDoc->X[i+1][0][1]*morphY+(ymax+ymin)/2);
GdiFlush();
LeaveCriticalSection(&pView->m_ClientDCLock);

Sleep(1000);
}
pView->m_pDC->SelectObject(pendark);
for (i=0;i<pDoc->Iter-1;i++)
if (pView->ViewCheck==1)
{
pView->m_pDC->MoveTo(pDoc->X[i][pDoc->MinF[i]][0]*morphX+(xmax+xmin)/2, pDoc->X[i][pDoc->MinF[i]][1]*morphY+(ymax+ymin)/2);
pView->m_pDC->LineTo(pDoc->X[i+1][pDoc->MinF[i+1]][0]*morphX+(xmax+xmin)/2, pDoc->X[i+1][pDoc->MinF[i+1]][1]*morphY+(ymax+ymin)/2);
}
pView->m_bWorking = false;
return 0;
}

void CSimplexView::OnDraw(CDC* pDC)
{
CSimplexDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
TEXTMETRIC Metric;
pDC->GetTextMetrics(&Metric);
CString str;
CSize size;
if (ViewCheck==1)
{
CPen pen(PS_SOLID, 1, RGB(0,0,0));
pDC->SelectObject(pen);
CSize NameSize;
CString strName;
CFont font;
CFont* pOldFont = NULL;	// óêàçàòåëü íà ðàíåå èñïîëüçóåìûé øðèôò
//	int xmin[3]={30,30,560}, xmax[3]={530,530,1060}, ymin[3]={30,560,30}, ymax[3]={530,1060,530};
int xmin[3]={30,30,30}, xmax[3]={1030,1030,1030}, ymin[3]={2090,1060,30}, ymax[3]={3090,2060,1030};
int morphX=(xmax[1]-xmin[1])/5;
int morphY=-morphX;
if(font.CreateFontIndirect(&pDoc->m_logFont)) pOldFont=pDC->SelectObject(&font);

//Ñèñòåìà êîîðäèíàò
//îêíà		
for (int i=0;i<3;i++)
{
pDC->MoveTo(xmin[i]-5,ymin[i]-5);
pDC->LineTo(xmax[i]+5,ymin[i]-5);
pDC->LineTo(xmax[i]+5,ymax[i]+5);
pDC->LineTo(xmin[i]-5,ymax[i]+5);
pDC->LineTo(xmin[i]-5,ymin[i]-5);
pDC->MoveTo(xmin[i]-10,ymin[i]-10);
pDC->LineTo(xmax[i]+10,ymin[i]-10);
pDC->LineTo(xmax[i]+10,ymax[i]+10);
pDC->LineTo(xmin[i]-10,ymax[i]+10);
pDC->LineTo(xmin[i]-10,ymin[i]-10);
}

//îñè äëÿ òðàåêòîðèè
i=2;
pDC->MoveTo((xmax[i]+xmin[i])/2,ymin[i]);
pDC->LineTo((xmax[i]+xmin[i])/2+3,ymin[i]+10);
pDC->MoveTo((xmax[i]+xmin[i])/2,ymin[i]);
pDC->LineTo((xmax[i]+xmin[i])/2-3,ymin[i]+10);
pDC->MoveTo((xmax[i]+xmin[i])/2,ymin[i]);
pDC->LineTo((xmax[i]+xmin[i])/2,ymax[i]);
pDC->MoveTo(xmin[i],(ymax[i]+ymin[i])/2);
pDC->LineTo(xmax[i],(ymax[i]+ymin[i])/2);
pDC->LineTo(xmax[i]-10,(ymax[i]+ymin[i])/2+3);
pDC->MoveTo(xmax[i],(ymax[i]+ymin[i])/2);
pDC->LineTo(xmax[i]-10,(ymax[i]+ymin[i])/2-3);				
//ðàçìåòêà äëÿ òðàåêòîðèè
for (int j=-4;j<5;j++)
{
pDC->MoveTo((xmax[i]+xmin[i])/2+(morphX/2)*j,(ymax[i]+ymin[i])/2-2);
pDC->LineTo((xmax[i]+xmin[i])/2+(morphX/2)*j,(ymax[i]+ymin[i])/2+3);
str.Format("%.1f",j*0.5);
pDC->TextOut((xmax[i]+xmin[i])/2+(morphX/2)*j-5,(ymax[i]+ymin[i])/2+10,str);
}
for (j=-4;j<5;j++)
{
pDC->MoveTo((xmax[i]+xmin[i])/2-2, (ymax[i]+ymin[i])/2+(morphY/2)*j);
pDC->LineTo((xmax[i]+xmin[i])/2+3, (ymax[i]+ymin[i])/2+(morphY/2)*j);
str.Format("%.1f",-j*0.5);
pDC->TextOut((xmax[i]+xmin[i])/2+10,(ymax[i]+ymin[i])/2+(morphY/2)*j-5, str);
}
for (i=1;i>=0;i--)
{
//îñè äëÿ îñòàëüíûõ ãðàôèêîâ
pDC->MoveTo(xmin[i],ymin[i]);
pDC->LineTo(xmin[i]+3,ymin[i]+10);
pDC->MoveTo(xmin[i],ymin[i]);
pDC->LineTo(xmin[i]-3,ymin[i]+10);
pDC->MoveTo(xmin[i],ymin[i]);
pDC->LineTo(xmin[i],ymax[i]);
pDC->LineTo(xmax[i],ymax[i]);
pDC->LineTo(xmax[i]-10,ymax[i]+3);
pDC->MoveTo(xmax[i],ymax[i]);
pDC->LineTo(xmax[i]-10,ymax[i]-3);				
//ðàçìåòêà äëÿ îñòàëüíûõ ãðàôèêîâ
for (int j=0;j<10;j++)
{
pDC->MoveTo(xmin[i]+(morphX/2)*j,ymax[i]-2);
pDC->LineTo(xmin[i]+(morphX/2)*j,ymax[i]+3);
str.Format("%.1f",j*0.5);
pDC->TextOut(xmin[i]+(morphX/2)*j-5,ymax[i]-20,str);
}
for (j=0;j<10;j++)
{
pDC->MoveTo(xmin[i]-2,ymax[i]+(morphY/2)*j);
pDC->LineTo(xmin[i]+3,ymax[i]+(morphY/2)*j);
str.Format("%.1f",-j*0.5);
pDC->TextOut(xmin[i]+10,ymax[i]+(morphY/2)*j-5, str);
}
}
//íàçâàíèÿ
if (pOldFont != NULL) pDC->SelectObject(pOldFont);

i=2;
strName="Òðàåêòîðèÿ ïîèñêà";
NameSize=pDC->GetTextExtent(strName);
pDC->TextOut((xmax[i]+xmin[i]-NameSize.cx)/2,ymin[i]+30,strName);
pDC->TextOut((xmax[i]+xmin[i])/2+10,ymin[i],"X2");
pDC->TextOut(xmax[i]-15,(ymax[i]+ymin[i])/2-25, "X1");

for (i=1; i>=0; i--)
{
if (i==0)
strName="Ãðàôèê çíà÷åíèÿ ôóíêöèè ïî øàãàì";
if (i==1)
strName="Ãðàôèê ðàññòîÿíèÿ îò òåêóùåé òî÷êè äî òî÷êè îïòèìóìà";			
NameSize=pDC->GetTextExtent(strName);
pDC->TextOut((xmax[i]+xmin[i]-NameSize.cx)/2,ymin[i]+30,strName);
pDC->TextOut(xmin[i]+10,ymin[i],"X2");
pDC->TextOut(xmax[i]-15,ymax[i]-25, "X1");		
}
//////////////////////////////
// ñîáñòâåííî ãðàôèêè
CPen pengreen(PS_SOLID, 5, RGB(0,255,0));
CPen penred(PS_SOLID, 5, RGB(255,0,0));

pDC->SelectObject(penred);
pDC->MoveTo(morphX+(xmax[2]+xmin[2])/2, morphY+(ymax[2]+ymin[2])/2);
pDC->LineTo(morphX+(xmax[2]+xmin[2])/2, morphY+(ymax[2]+ymin[2])/2);

pDC->SelectObject(pengreen);
pDC->MoveTo(pDoc->XInst[0]*morphX+(xmax[2]+xmin[2])/2, pDoc->XInst[1]*morphY+(ymax[2]+ymin[2])/2);
pDC->LineTo(pDoc->XInst[0]*morphX+(xmax[2]+xmin[2])/2, pDoc->XInst[1]*morphY+(ymax[2]+ymin[2])/2);

size.cx= xmax[0]+30;
size.cy= ymax[0]+10;
}
else
{
pDC->TextOut(0, 0, "Ôóíêöèÿ (x2 - x1^2 )^2 + (1 - x1 )^2");
str="Íà÷àëüíàÿ òî÷êà ("+pDoc->Coord+')';
pDC->TextOut(0, Metric.tmHeight, str);
pDC->TextOut(0, 2*Metric.tmHeight, "Òåîðåòè÷åñêàÿ òî÷êà îïòèìóìà (1;1)");

CString tmp;
for (int k=0; k<pDoc->Iter; k++)
{
str.Format("%d",k+1);
str="Ñèìïëåêñ "+str;
pDC->TextOut(0,(4+6*k)*Metric.tmHeight, str);
for (int i=0;i<3;i++)
{
tmp.Format("%d",i);
str=" òî÷êå "+tmp+" (";
for (int j=0;j<2;j++)
{
tmp.Format("%.3f",pDoc->X[k][i][j]);
str+=tmp+';';
}
tmp.Format("%.3f",pDoc->Fx[k][i]);
str=str.Left(str.GetLength()-1);
str+=") ôóíêöèÿ ðàâíà "+tmp;
pDC->TextOut(0,(5+i+6*k)*Metric.tmHeight, str);
}
tmp.Format("%d",pDoc->MaxF[k]);
str="Ìàêñèìàëüíîå çíà÷åíèå ôóíêöèè íàáëþäàëîñü â òî÷êå "+tmp;
pDC->TextOut(0,(8+6*k)*Metric.tmHeight, str);
}
size.cx= 500;
size.cy= (4+6*pDoc->Iter)*Metric.tmHeight;
}
SetScrollSizes(MM_TEXT,size);
}

void CSimplexView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();

CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
}

/////////////////////////////////////////////////////////////////////////////
// CSimplexView printing

BOOL CSimplexView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}

void CSimplexView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}

void CSimplexView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CSimplexView diagnostics

#ifdef _DEBUG
void CSimplexView::AssertValid() const
{
CScrollView::AssertValid();
}

void CSimplexView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}

CSimplexDoc* CSimplexView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSimplexDoc)));
return (CSimplexDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CSimplexView message handlers

void CSimplexView::OnViewGraph() 
{
// TODO: Add your command handler code here
if (ViewCheck==0)
{
Invalidate ();
ViewCheck=1;
}
}

void CSimplexView::OnViewTable() 
{
// TODO: Add your command handler code here
if (ViewCheck==1)
{
Invalidate ();
ViewCheck=0;
}
}

int CSimplexView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
m_pDC = new CClientDC(this);	// ïîëó÷åíèå óêàçàòåëÿ íà êîíòåêñò îêíà	
return 0;
}

void CSimplexView::OnDestroy() 
{

// TODO: Add your message handler code here
m_bWorking=false;
//	Sleep(m_nThreadCounter*20);	// çàñíóòü íà 20 ìèëëèñåêóíä äëÿ êàæäîãî ïîòîêà
//	m_nThreadCounter=0;
delete m_pDC;
m_pDC = 0;
CView::OnDestroy();

}

void CSimplexView::OnUpdateViewSearchprocess(CCmdUI* pCmdUI) 
{
// TODO: Add your command update UI handler code here
if (ViewCheck==0 || m_bWorking==true)
pCmdUI->Enable(false);
else
pCmdUI->Enable(true);

}

void CSimplexView::OnViewSearchprocess() 
{
// TODO: Add your command handler code here
Invalidate ();
AfxBeginThread(SearchThread, this, THREAD_PRIORITY_IDLE);
//	m_nThreadCounter++;
}
PS. Visual C++ 6.0
 
G

gamecreator

Гость
#2
абсолютная координата = относительная координата + сдвиг по оси
сдвиг по оси изменяешь при прокрутке.
относительная координата - координата точки на экране
 
O

OberonTSM

Гость
#3
Спасибо... только как получить значение сдвига при прокрутке? если это знать думаю получится)
Но всё таки хотелось бы понять как эту проблему решить с контекстом устройства... наверняка же от этого зависит... хотя... я не особо разбираюсь, может ерунду говорю.
 
O

OberonTSM

Гость
#4
Получилось!!! спасибо огромное!
только
абсолютная координата = относительная координата + сдвиг по оси это неправильно
относительная координата = абсолютная координата + сдвиг по оси

Теперь интересует как сделать так, чтобы рисунок не обнулялся
 
A

Azrael

Гость
#5
Для: OberonTSM

рекомендую рисовать всё в back-буффер, который может быть и больше экрана, а на onShow вешать обработку копирования нужной области из back-буффера, заодно и от мерцания избавитесь.
 
O

OberonTSM

Гость
#6
Спасибо! надо будет как нибудь попробовать!
 
Статус
Закрыто для дальнейших ответов.