不能想象这个简单的程序会出什么问题 [英] Cant imagine whats the problem with this simple program
问题描述
嗨.我是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 callInvalidateRect
[^] in yourOnLButtonDown
function after setting all the squares. Windows only get redrawn in response to aWM_PAINT
message, so whenever you change something in your application that affects the display you need to force aWM_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屋!