简易版本的逃跑按钮的实现,下面是两个实现方法,一个是创建两个一样的按钮,然后通过一个按钮接触鼠标时,隐藏并显示另一个按钮来实现"逃跑"。另一个是通过SetWindowPos函数来随机地让按钮在新位置出现 下面是主要的代码 先是第一个版本 然后是第二个版本
// NewButton.cpp : implementation file // #include "stdafx.h" #include "Test.h" #include "NewButton.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CNewButton CNewButton::CNewButton() { m_pBtn=NULL; } CNewButton::~CNewButton() { } BEGIN_MESSAGE_MAP(CNewButton, CButton) //{{AFX_MSG_MAP(CNewButton) ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CNewButton message handlers void CNewButton::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default ShowWindow(SW_HIDE); m_pBtn->ShowWindow(SW_SHOW); CButton::OnMouseMove(nFlags, point); }
上面是派生于CButton类的一个按键类,用来关联按钮窗口,定义了一个指针变量,用来保存另外一个按钮的地址
BOOL CTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_btn1.m_pBtn=&m_btn2; m_btn2.m_pBtn=&m_btn1; return TRUE; // return TRUE unless you set the focus to a control }
在程序运行时,当对话框及其上面的子控件创建完成,在显示之前会发送一个消息:WM_INITDLALOG,他的响应函数就是上面的OnInitDialog,所以将指针m_pBtn的赋值放在这个函数的后面,当然在return 之前。在运行之前要先把其中一个按钮的属性中的visible选项不选,才不会一开始的时候两个按钮都显示在对话框中。
第二个版本:
// NewButton.cpp : implementation file // #include "stdafx.h" #include "taopao2.h" #include "NewButton.h" #include <time.h> #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CNewButton CNewButton::CNewButton() { i=0; j=0; } CNewButton::~CNewButton() { } BEGIN_MESSAGE_MAP(CNewButton, CButton) //{{AFX_MSG_MAP(CNewButton) ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CNewButton message handlers void CNewButton::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rectLarge; CRect rectbutton; GetParent()->GetWindowRect(&rectLarge); GetWindowRect(&rectLarge); i=point.y+rand()%(rectLarge.Width()*3); j=point.x+rand()%(rectLarge.Height()*3); SetWindowPos(NULL,i,j,0,0,SWP_NOSIZE); CButton::OnMouseMove(nFlags, point); }
新类CNewButton派生于CButton类
这次用到的主要函数有:
void GetWindowRect( LPRECT lpRect ) const; Parameters lpRect Points to a CRect object or a RECT structure that will receive the screen coordinates of the upper-left and lower-right corners
BOOL SetWindowPos( const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags ); Return Value Nonzero if the function is successful; otherwise 0.
下面是关于SetWindowPos的一个介绍 网上找到的
参数pWndInsertAfter 标识了在Z轴次序上位于这个CWnd对象之前的CWnd对象。这个参数可以是指向CWnd对象的指针,也可以是指向下列值的指针: wndBottom 将窗口放在Z轴次序的底部。如果这个CWnd是一个顶层窗口,则窗口将失去它的顶层状态;系统将这个窗口放在其它所有窗口的底部。 wndTop 将窗口放在Z轴次序的顶部。 wndTopMost 将窗口放在所有非顶层窗口的上面。这个窗口将保持它的顶层位置,即使它失去了活动状态。 wndNoTopMost 将窗口重新定位到所有非顶层窗口的顶部(这意味着在所有的顶层窗口之下)。这个标志对那些已经是非顶层窗口的窗口没有作用。有关这个函数以及这些参数的使用规则参见说明部分。 x指定了窗口左边的新位置。 y指定了窗口顶部的新位置。 cx指定了窗口的新宽度。 cy指定了窗口的新高度。 nFlags指定了大小和位置选项。这个参数可以是下列值的组合: SWP_DRAWFRAME 围绕窗口画出边框(在创建窗口的时候定义)。 SWP_FRAMECHANGED 向窗口发送一条WM_NCCALCSIZE消息,即使窗口的大小不会改变。如果没有指定这个标志,则仅当窗口的大小发生变化时才发送WM_NCCALCSIZE消息。 SWP_HIDEWINDOW 隐藏窗口。 SWP_NOACTIVATE 不激活窗口。如果没有设置这个标志,则窗口将被激活并移动到顶层或非顶层窗口组(依赖于pWndInsertAfter参数的设置)的顶部。 SWP_NOCOPYBITS 废弃这个客户区的内容。如果没有指定这个参数,则客户区的有效内容将被保存,并在窗口的大小或位置改变以后被拷贝回客户区。 SWP_NOMOVE 保持当前的位置(忽略x和y参数)。 SWP_NOOWNERZORDER 不改变拥有者窗口在Z轴次序上的位置。 SWP_NOREDRAW 不重画变化。如果设置了这个标志,则不发生任何种类的变化。这适用于客户区、非客户区(包括标题和滚动条)以及被移动窗口覆盖的父窗口的任何部分。当这个标志被设置的时候,应用程序必须明确地无效或重画要重画的窗口和父窗口的任何部分。 SWP_NOREPOSITION 与SWP_NOOWNERZORDER相同。 SWP_NOSENDCHANGING 防止窗口接收WM_WINDOWPOSCHANGING消息。 SWP_NOSIZE 保持当前的大小(忽略cx和cy参数)。 SWP_NOZORDER 保持当前的次序(忽略pWndInsertAfter)。 SWP_SHOWWINDOW 显示窗口。