O
OberonTSM
Проблема такая:
Есть Приложение, вычисляющее точку оптимума функции по методу симплекса. объект вида - скроллинговый, причём размер больше размера экрана, то есть скролл нужен всегда. В главном окне в OnDraw рисуются координатные оси для трёх графиков. Также есть отдальный поток, рисующий сам процесс поиска методом симплекса (рисует наглядно, то есть шаг за шагом, по типу анимации). Собственно суть проблемы в том, что при любом скролле вниз координатная система для потока меняется и точка (0,0) совпадает с левым верхним углом ОТОБРАЖАЕМОЙ В ДАННЫЙ МОМЕНТ части объекта вида. А координатные оси остаются на своих местах. Соответственно
следующий после прокрутки вниз шаг графика рисуется ниже чем надо. Как сделать так чтобы координаты для потока были постоянными и не зависили от скроллинга и отображаемой части объекта вида? Возможно ошибка в контексте устройства... Пожалуйста, подскажите что и где надо поменять\дописать...
Также интересно, как сделать чтобы прис выходе за границу области где должен быть рисунок (когда сильно прокручиваешь вниз), графическая информация потока не стиралась а оставалась нарисованной.
вот код потока и метода OnDraw:
PS. Visual C++ 6.0
Есть Приложение, вычисляющее точку оптимума функции по методу симплекса. объект вида - скроллинговый, причём размер больше размера экрана, то есть скролл нужен всегда. В главном окне в 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