写MFC程序中碰到的一些小问题

1        VC++中窗口的最大化问题   

看到很多MFC初学者都有这样的问题:MFC单文档程序默认运行时窗口不是最大化,怎么才能使其一开始就最大化显示,其实对于这个问题,很多网友都解释的不清楚,或是不全面!

  其实这是在修改MFC的窗口界面的外观,修改MFC窗口的外观或是风格是要用到类风格(CS_XXXX)和窗口风格(WS_XXXX),学过MFC的学者都知道在WinMain函数中,最开始都定义了WNDCLASS窗口类,该类可以改变窗口的图标,背景,光标等;

  若要改变窗口的大小,一般在CMainFrame::PreCreateWindow(CREATESTRUCT& cs)中修改构造类cs的值,可以修改cs的cx,cy来改变大小;如果要最大化,就要修改cs.style|=WS_MAXIMIZE 使主框架类(CMainFrame)最大化,自然视图类(CView)创建时也会跟随主框架类(CMainFrame)而变化,但是此时显示时,仍然是没有变化,因为MFC主框架类(CMainFrame)的最后显示要通过SW_XXXX参数来决定,一些朋友就建议在CXXApp::InitInstance()中的m_pMainWnd->ShowWindow(SW_SHOW);前加入m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);或直接改掉,其实最终效果可以实现,但运行开始时会出现先是正常的小窗口,然后马上变成最大化,给人的视觉效果明显不好!

  那为什么会产生这种效果,是因为在m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);调用之前会先调用CMainFrame::ActivateFrame(int nCmdShow);此时便会根据nCmdShow(默认为SW_SHOWNORMAL)调用显示窗口一次,SW_SHOWNORMAL会根据cs中的cx,cy,x,y来显示窗口,所以cs.style便失去作用(视图类(CView)已经创建,所以它已经是最大化了),所以再次调用m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);会形成视觉暂留!

最终解决方法是

1.重载CMainFrame::ActivateFrame(intnCmdShow)

2.令nCmdShow=SW_SHOWMAXIMIZED即可

3.在CXXApp::InitInstance()中的m_pMainWnd->ShowWindow(SW_SHOW);会根据之前的设置而显示窗口

2        GetClientRect获取view类的大小为0

OnCreate是一个消息响应函数,是响应WM_CREATE消息的一个函数,而WM_CREATE消息是由Create函数调用的。

  在view类中,Create 是虚函数由框架调用,是用来生成一个窗口的子窗口OnCreate 函数是用来表示一个窗口正在生成

  一个窗口创建(Create)之后,会向操作系统发送WM_CREATE消息,OnCreate()函数主要是用来响应此消息的。因为在MFC里面用一种消息映射的机制来响应消息,也就是可以用函数来响应相应的消息。就拿CMainFrame类来说,当窗口创建后会产生WM_CREATE消息,我们可以在OnCreate函数里实现我们要在窗口里面增加的东西,例如按扭,状态栏,工具栏等。这些子窗口一般是定义成类中的一个成员变量,因为要保证生命周期。一般以m_开头来表示成员(member)

3        MFC调试

 在调试MFC程序时,我们经常需要查看特定位置变量的输出值。或者在某特定条件执行时,给出一个输出标识。

一般来说,有3种方法:

1) 调用TRACE(LPCTSTR lpszFormat, ...)函数

   在MFC中使用TRACE函数来打印输出结果却是非常方便,和在控制台程序中使用printf函数的使用方法和效果类似。不过有几点  

   需要注意:一,TRACE函数的输出是在Output窗口的Debug选项下; 二,只有在DEBUG版本调试时才会有输出,如果是在

   Release版本调试或者运行程序时,将不会看到输出。

2)使用AfxMessageBox( )函数来输出信息

    这个函数在调试时也比较常用,使用方法简单,此处就不做介绍。

3)将标准输出定向到自己创建的控制台

     #include "io.h"
      #include "fcntl.h"

       void InitConsole()
      {
            int nRet= 0;
           FILE* fp;
           AllocConsole();
           nRet=_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
           fp = _fdopen(nRet,"w");
          *stdout = *fp;
          setvbuf(stdout, NULL,_IONBF, 0);
    }

  将此函数在MFC程序初始化的地方调用,即可使用控制台查看printf函数的打印信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是基于MFC的简单贪吃蛇程序: 1. 创建一个MFC应用程序,并命名为SnakeGame。 2. 在资源视图,添加一个位图资源,命名为IDB_SNAKE,用于绘制贪吃蛇和食物。 3. 在stdafx.h文件添加以下头文件: ``` #include <vector> using namespace std; ``` 4. 在SnakeGameDlg.h文件添加以下代码: ``` #pragma once #include <vector> using namespace std; #define ROWS 30 #define COLS 30 #define BLOCK_SIZE 20 class CSnakeGameDlg : public CDialogEx { public: CSnakeGameDlg(CWnd* pParent = nullptr); #ifdef AFX_DESIGN_TIME enum { IDD = IDD_SNAKEGAME_DIALOG }; #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support DECLARE_MESSAGE_MAP() public: afx_msg void OnPaint(); virtual BOOL OnInitDialog(); afx_msg void OnTimer(UINT_PTR nIDEvent); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); private: vector<CPoint> m_snake; // 贪吃蛇身体 CPoint m_food; // 食物 int m_direction; // 移动方向 CBitmap m_bmpSnake; // 贪吃蛇位图 CBitmap m_bmpFood; // 食物位图 void InitGame(); // 初始化游戏 void DrawBlock(CDC* pDC, int x, int y, COLORREF color); // 绘制方块 void MoveSnake(); // 移动贪吃蛇 bool IsGameOver(); // 判断游戏是否结束 }; ``` 5. 在SnakeGameDlg.cpp文件添加以下代码: ``` #include "pch.h" #include "framework.h" #include "SnakeGame.h" #include "SnakeGameDlg.h" #include "afxdialogex.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #define TIMER_ID 1 CSnakeGameDlg::CSnakeGameDlg(CWnd* pParent /*=nullptr*/) : CDialogEx(IDD_SNAKEGAME_DIALOG, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_direction = VK_RIGHT; } void CSnakeGameDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CSnakeGameDlg, CDialogEx) ON_WM_PAINT() ON_WM_TIMER() ON_WM_KEYDOWN() END_MESSAGE_MAP() BOOL CSnakeGameDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 初始化游戏 InitGame(); // 设置定时器 SetTimer(TIMER_ID, 100, NULL); return TRUE; } void CSnakeGameDlg::OnPaint() { CPaintDC dc(this); // device context for painting // 绘制游戏区域 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { DrawBlock(&dc, j * BLOCK_SIZE, i * BLOCK_SIZE, RGB(255, 255, 255)); } } // 绘制贪吃蛇 for (auto& pt : m_snake) { DrawBlock(&dc, pt.x * BLOCK_SIZE, pt.y * BLOCK_SIZE, RGB(0, 255, 0)); } // 绘制食物 DrawBlock(&dc, m_food.x * BLOCK_SIZE, m_food.y * BLOCK_SIZE, RGB(255, 0, 0)); } void CSnakeGameDlg::OnTimer(UINT_PTR nIDEvent) { // 移动贪吃蛇 MoveSnake(); // 更新界面 Invalidate(FALSE); CDialogEx::OnTimer(nIDEvent); } void CSnakeGameDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch (nChar) { case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: m_direction = nChar; break; default: break; } CDialogEx::OnKeyDown(nChar, nRepCnt, nFlags); } void CSnakeGameDlg::InitGame() { // 初始化贪吃蛇 m_snake.push_back(CPoint(5, 5)); m_snake.push_back(CPoint(4, 5)); m_snake.push_back(CPoint(3, 5)); // 随机生成食物 srand((unsigned int)time(NULL)); m_food.x = rand() % COLS; m_food.y = rand() % ROWS; // 加载位图资源 m_bmpSnake.LoadBitmap(IDB_SNAKE); m_bmpFood.LoadBitmap(IDB_SNAKE + 1); } void CSnakeGameDlg::DrawBlock(CDC* pDC, int x, int y, COLORREF color) { CBrush brush(color); CBrush* pOldBrush = pDC->SelectObject(&brush); pDC->Rectangle(x, y, x + BLOCK_SIZE, y + BLOCK_SIZE); pDC->SelectObject(pOldBrush); } void CSnakeGameDlg::MoveSnake() { // 计算贪吃蛇头部位置 CPoint head = m_snake.front(); switch (m_direction) { case VK_LEFT: head.x--; break; case VK_RIGHT: head.x++; break; case VK_UP: head.y--; break; case VK_DOWN: head.y++; break; default: break; } // 判断是否吃到食物 if (head == m_food) { m_snake.insert(m_snake.begin(), head); // 随机生成新的食物 m_food.x = rand() % COLS; m_food.y = rand() % ROWS; return; } // 移动贪吃蛇身体 for (int i = m_snake.size() - 1; i > 0; i--) { m_snake[i] = m_snake[i - 1]; } m_snake[0] = head; // 判断游戏是否结束 if (IsGameOver()) { KillTimer(TIMER_ID); MessageBox(_T("游戏结束!"), _T("提示"), MB_OK | MB_ICONINFORMATION); PostQuitMessage(0); } } bool CSnakeGameDlg::IsGameOver() { // 判断是否碰到边界 CPoint head = m_snake.front(); if (head.x < 0 || head.x >= COLS || head.y < 0 || head.y >= ROWS) { return true; } // 判断是否碰到贪吃蛇身体 for (int i = 1; i < m_snake.size(); i++) { if (head == m_snake[i]) { return true; } } return false; } ``` 6. 运行程序,即可开始游戏。使用方向键控制贪吃蛇的移动方向,吃到食物后贪吃蛇会变长。当贪吃蛇碰到边界或自己的身体时,游戏结束。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值