不能想象这个简单的程序会出什么问题 [英] Cant imagine whats the problem with this simple program

查看:186
本文介绍了不能想象这个简单的程序会出什么问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗨.我是MFC编程的新手.我只是在写一些简单的井字游戏程序.我的代码如下所示.它仅在出现"l button down"消息的正方形中绘制X.但神秘地,它无法在所有正方形中绘制X.如果单击所有正方形,它只会绘制3或4次的X.之后,即使我单击一个正方形,它也会停止工作.没有错误.没有提示音消息提示音.它只是停止.但是我不明白错误在哪里.

这是我在头文件中的代码.

< blockquote  class  = " >< div  class  = " >引用:</div>

 class  MainWindow: public  CFrameWnd
{
公共:
MainWindow()
{
Create(NULL,L " );

}




受保护的:
afx_msg  void  OnPaint();

afx_msg  void  OnLButtonDown(UINT,CPoint);

私有:
 void  DrawGrid(CDC *);

 void  DrawO(CDC *, int ); // 忽略此

 void  DrawX(CDC *, int );


DECLARE_MESSAGE_MAP()
};



 class 应用程序: public  CWinApp
{
公共:
BOOL InitInstance()
{
m_pMainWnd =  MainWindow;
m_pMainWnd-> ShowWindow(m_nCmdShow);
m_pMainWnd-> UpdateWindow();

CRect rec( 0  0  300  300 );
m_pMainWnd-> CalcWindowRect(rec);
m_pMainWnd-> SetWindowPos(NULL, 0  0 ,rec.Width(),rec.Height( ),SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);

返回 TRUE;
}
};</blockquote> 



这是cpp文件.

 #include   "  stdafx.h"
 #include   " 

#define O 1
 #define X 2


CRect sqs [ 9 ] =
{
{ 0  0  100  100 },
{ 100  0  200  100 },
{ 200  0  300  100 },

{ 0  100  100  200 },
{ 100  100  200  200 },
{ 200  100  300  200 },

{ 0  200  100  300 },
{ 100  200  200  300 },
{ 200  200  300  300 }
};

 int  vals [ 9 ] { 0  0  0  0  0  0  0  0  0 };

无效 MainWindow :: OnPaint()
{
CClientDC dc();
DrawGrid(& dc);

 for ( int  i {}; i<  9 ; i ++)
如果(值[i] == X)
DrawX(& dc,i);
}

无效 MainWindow :: OnLButtonDown(UINT标志,CPoint cp)
{
 for ( int  i {}; i<  9 ; i ++)
{
如果(PtInRect(sqs [i],cp))
vals [i] = X;
}
}

无效 MainWindow :: DrawGrid(CDC * pDC)
{
CPen * pen = 新的 CPen(PS_SOLID, 5 ,RGB( 0  0  0 )));
pDC-> SelectObject(pen);

pDC-> MoveTo( 0  100 );
pDC-> LineTo( 300  100 );
pDC-> MoveTo( 0  200 );
pDC-> LineTo( 300  200 );

pDC-> MoveTo( 100  0 );
pDC-> LineTo( 100  300 );
pDC-> MoveTo( 200  0 );
pDC-> LineTo( 200  300 );
}


无效 MainWindow :: DrawO(CDC * pDC, int  pos)// 忽略此
{
CPen * pen = 新的 CPen(PS_SOLID, 3 ,RGB( 255  0  0 )));

pDC-> SelectObject(pen);

pDC-> Ellipse(sqs [pos]);
}

无效 MainWindow :: DrawX(CDC * pDC, int  pos)
{
CPen * pen = 新的 CPen(PS_SOLID, 3 ,RGB( 0  0  255 )));
pDC-> SelectObject(pen);

pDC-> MoveTo(sqs [pos] .left,sqs [pos] .top);
pDC-> LineTo(sqs [pos] .right,sqs [pos] .bottom);
pDC-> MoveTo(sqs [pos] .right,sqs [pos] .top);
pDC-> LineTo(sqs [pos] .left,sqs [pos] .bottom);
}

应用程序myApp;

BEGIN_MESSAGE_MAP(MainWindow,CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()



我的代码有什么问题?为什么要在单击4次后停止绘图?
在此先谢谢您.

解决方案

谢谢大家的帮助.我解决了问题.是笔.

  void  MainWindow :: DrawX(CDC * pDC, int  pos)
{
/*   CPen * pen = new CPen(PS_SOLID,3,RGB(0,0,255));
pDC-> SelectObject(pen); */

pDC-> SelectObject(pn);

pDC-> MoveTo(sqs [pos] .left,sqs [pos] .top);
pDC-> LineTo(sqs [pos] .right,sqs [pos] .bottom);
pDC-> MoveTo(sqs [pos] .right,sqs [pos] .top);
pDC-> LineTo(sqs [pos] .left,sqs [pos] .bottom);
} 



在这种情况下,您必须在功能外部创建笔并在功能内部选择它. (因为我已经评论了前两行)
不知道为什么在函数内部创建笔会产生这样的问题.我认为这一定是占用了内存.


您应该致电 InvalidateRect [^ 设置所有正方形后,在OnLButtonDown函数中单击]. Windows仅在响应WM_PAINT消息时才重绘,因此,每当您在应用程序中更改某些会影响显示的内容时,都需要强制发送WM_PAINT,这是执行此操作的简单方法.

我已经注意到您每次在堆上创建新的GDI时都会创建对象,而不会像这样将其释放:

  void  MainWindow :: DrawX(CDC * pDC, int  pos)
{
    CPen * pen = 新的 CPen(PS_SOLID, 3 ,RGB( 0  0  255 ))); 



那是错的!尝试使用堆栈上的对象:

  void  MainWindow :: DrawX(CDC * pDC, int  pos)
{
    CP笔(PS_SOLID, 3 ,RGB( 0  0  255 )); 



很好地看一下这篇文章:附加和分离对象 [ ^ ]


Hi. Im a novice to MFC programming. And I was just writing some simple tic tac toe program. My codes are shown below. It only draws X in a square where "l button down" messages occur. But mysteriously it fails to draw Xs in all the squares. If I click in all the squares, it only draws Xs for like 3 or 4 times. After that it stops working even though I click on a square. No errors. No beep message beep sounds. It just stops. But I cant understand where the error is.

Heres my code in header file.

<blockquote class="quote"><div class="op">Quote:</div>

class MainWindow : public CFrameWnd
{
public:
	MainWindow()
	{
		Create(NULL, L"WINDOW");
		
	}




protected:
	afx_msg void OnPaint();

	afx_msg void OnLButtonDown(UINT, CPoint);

private:
	void DrawGrid(CDC*);

	void DrawO(CDC*, int);  //Ignore this

	void DrawX(CDC*, int);


	DECLARE_MESSAGE_MAP()
};



class App : public CWinApp
{
public:
	BOOL InitInstance()
	{
		m_pMainWnd = new MainWindow;
		m_pMainWnd->ShowWindow(m_nCmdShow);
		m_pMainWnd->UpdateWindow();

		CRect rec(0, 0, 300, 300);
		m_pMainWnd->CalcWindowRect(rec);
		m_pMainWnd->SetWindowPos(NULL, 0, 0, rec.Width(), rec.Height(), SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
		
		return TRUE;
	}
};</blockquote>



And here is the cpp file.

#include "stdafx.h"
#include "MFCApplication15.h"

#define O 1
#define X 2


CRect sqs[9] =
{
	{ 0, 0, 100, 100 },
	{ 100, 0, 200, 100 },
	{ 200, 0, 300, 100 },

	{ 0, 100, 100, 200 },
	{ 100, 100, 200, 200 },
	{ 200, 100, 300, 200 },

	{ 0, 200, 100, 300 },
	{ 100, 200, 200, 300 },
	{ 200, 200, 300, 300 }
};

int vals[9]{0, 0, 0, 0, 0, 0, 0, 0, 0};

void MainWindow::OnPaint()
{
	CClientDC dc(this);
	DrawGrid(&dc);

	for (int i{}; i < 9; i++)
		if (vals[i] == X)
			DrawX(&dc, i);
}

void MainWindow::OnLButtonDown(UINT flags, CPoint cp)
{
	for (int i{}; i < 9; i++)
	{
		if (PtInRect(sqs[i], cp))
			vals[i] = X;
	}
}

void MainWindow::DrawGrid(CDC* pDC)
{
	CPen *pen = new CPen(PS_SOLID, 5, RGB(0, 0, 0));
	pDC->SelectObject(pen);

	pDC->MoveTo(0, 100);
	pDC->LineTo(300, 100);
	pDC->MoveTo(0, 200);
	pDC->LineTo(300, 200);

	pDC->MoveTo(100, 0);
	pDC->LineTo(100, 300);
	pDC->MoveTo(200, 0);
	pDC->LineTo(200, 300);
}


void MainWindow::DrawO(CDC* pDC, int pos)  //Ignore this
{
	CPen* pen = new CPen(PS_SOLID, 3, RGB(255, 0, 0));

	pDC->SelectObject(pen);

	pDC->Ellipse(sqs[pos]);
}

void MainWindow::DrawX(CDC* pDC, int pos)
{
	CPen* pen = new CPen(PS_SOLID, 3, RGB(0, 0, 255));
	pDC->SelectObject(pen);

	pDC->MoveTo(sqs[pos].left, sqs[pos].top);
	pDC->LineTo(sqs[pos].right, sqs[pos].bottom);
	pDC->MoveTo(sqs[pos].right, sqs[pos].top);
	pDC->LineTo(sqs[pos].left, sqs[pos].bottom);
}

App myApp;

BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd)
	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()



What''s the wrong with my code ? Why it stops the drawing after like 4 clicks ?
Thanks in advance.

解决方案

Thank you all for helps. I solved the problem. It was the pen.

void MainWindow::DrawX(CDC* pDC, int pos)
{
	/*CPen* pen = new CPen(PS_SOLID, 3, RGB(0, 0, 255));
	pDC->SelectObject(pen);*/

	pDC->SelectObject(pn);

	pDC->MoveTo(sqs[pos].left, sqs[pos].top);
	pDC->LineTo(sqs[pos].right, sqs[pos].bottom);
	pDC->MoveTo(sqs[pos].right, sqs[pos].top);
	pDC->LineTo(sqs[pos].left, sqs[pos].bottom);
}



In this, you have to create the pen outside the function and select it inside the function. (as i have commented the the first two lines)
No idea why creating a pen inside a function creates such problems though. I reckon it must be something with memory consumption.


You should call InvalidateRect[^] in your OnLButtonDown function after setting all the squares. Windows only get redrawn in response to a WM_PAINT message, so whenever you change something in your application that affects the display you need to force a WM_PAINT to be sent, and this is the simple way to do it.


I''ve noticed that you create each time a new GDI objeects on the heap without to get it free like this:

void MainWindow::DrawX(CDC* pDC, int pos)
{
    CPen* pen = new CPen(PS_SOLID, 3, RGB(0, 0, 255));



That is wrong! Try instead to work with objects on the stack:

void MainWindow::DrawX(CDC* pDC, int pos)
{
    CPen pen(PS_SOLID, 3, RGB(0, 0, 255));



Take a look at this article aa well: Attaching and Detaching Objects[^]


这篇关于不能想象这个简单的程序会出什么问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆