230 likes | 360 Views
Our Application with Clicks. What do we need to display the locations of our clicks An application to act as main and instantiate the window Derive and instantiate a class from CWinApp Some mechanism of associating a mouse click message (or event) to a method (message or event handler)
E N D
Our Application with Clicks What do we need to display the locations of our clicks • An application to act as main and instantiate the window • Derive and instantiate a class from CWinApp • Some mechanism of associating a mouse click message (or event) to a method (message or event handler) • We’ll need another Message Map to do this • A way to display the contents of our window • Some way to represent get the coordinates of our click • Clean way to convert these numerical points to a character array
Capturing Mouse Clicks • System has built-in routines to capture mouse clicks • OnLButtonDown, OnLButtonUp • OnRButtonDown, OnRButtonUp • All four routines take two parameters • UINT flags, a 32-bit unsigned integer • CPoint point, a class for points, x and y coordinates are available (can retrieve), as well as other operations
#include <afxwin.h> #include <string> using namespace std; class CMouseWin : publicCFrameWnd{ public:CMouseWin();afx_msg void OnLButtonDown(UINT, CPoint);afx_msg void OnRButtonDown(UINT, CPoint);afx_msg void OnLButtonUp(UINT, CPoint);afx_msg void OnRButtonUp(UINT, CPoint); private:void showUp(CPoint);void showDown(CPoint);DECLARE_MESSAGE_MAP( ) }; Our class will provide new methods for processing the various mouse click events Utilizes two private methods to process these mouse clicks (showUp and showDown) Program captures mouse clicks
#include <strstrea.h> #include "example.h" CMouseWin::CMouseWin() { Create(NULL, "Mouse Click Example", WS_OVERLAPPEDWINDOW, CRect(100,100,500,500)); } afx_msg void CMouseWin::OnLButtonDown(UINT uFlags, CPoint point){ showDown(point); } afx_msg void CMouseWin::OnLButtonUp(UINT uFlags, CPoint point) { showUp(point); } afx_msg void CMouseWin::OnRButtonDown(UINT uFlags, CPoint point) { showDown(point); } afx_msg void CMouseWin::OnRButtonUp(UINT uFlags, CPoint point) { showUp(point); } One new header file (will use it shortly) Constructor creates a standard window Four methods defined to capture each of the four mouse actions Two methods call the showDown method (press mouse button) Two methods call the showUp method (release mouse button) Program Body (part one)
void CMouseWin::showDown(CPoint point) { CClientDC dc(this); ostrstream s; s << "(" << point.x << ",“ << point.y << ")"; dc.TextOut(50,50,s.str(), s.pcount()); } void CMouseWin::showUp(CPoint point) { CClientDC dc(this); char carText[32]; ostrstream s(carText, sizeof(carText)); s << "(" << point.x << ",“ << point.y << ")"; dc.TextOut(200,200,carText, s.pcount()); } New concept here (writing to a string) Already seen writing to files and stdout Can also write to an array of chars Process Declare array Declare output stream Write to it (s.pcount has count of chars written) Take this array (with the output that was written to it) and display it in the window Program Body (part two)
BEGIN_MESSAGE_MAP ( CMouseWin,CFrameWnd) ON_WM_LBUTTONDOWN( ) ON_WM_RBUTTONDOWN( ) ON_WM_LBUTTONUP( ) ON_WM_RBUTTONUP( ) END_MESSAGE_MAP( ) class CMouseApp : publicCWinApp{ public: BOOL InitInstance( ) { m_pMainWnd= new CMouseWin; m_pMainWnd->ShowWindow (m_nCmdShow); m_pMainWnd->UpdateWindow(); return TRUE; } } mouseApp; Message map section defines four events that this program is watching out for (all related to mouse buttons). All four are built into the system, you don’t need to define further Standard clause at the end of the program to get things started (register mouseApp with WinMain and have it invoked when the program starts) Program Body (part three)
Class Exercises • Modify the code from the previous “catching mouse clicks example” so that: • The right mouse button down and up locations are printed at the top of the window (in the left and right corners) • The left mouse button down and up locations are printed at the bottom of the window (in the left and right corners) • Files • MouseWin.h • MouseWin.cpp
Drawing on the window • Similar to writing text on the window CClientDC dc(this); // get window context dc.TextOut( … ) // write out some text • Routines exist to do almost anything • We will focus on routines to: • Move to a given location • Draw a line from where you are to another location • Create a filled rectangle of some color
Sample drawing program • Want to be able to write text on the screen • Already seen this (Menu example) • New capabilities • Want to be able to draw lines on the screen • Want to be able to draw shapes on the screen • Example • Extremely “simplistic” version of tic-tac-toe • Menu with two options (“new” and “quit”) • Draw a simple board, click to indicate moves Use red and blue blocks instead of X’s and O’s
#include <afxwin.h> class CTTTWin : public CFrameWnd { public:CTTTWin();~CTTTWin();afx_msg void OnExit();afx_msg void OnNew();afx_msg void OnLButtonDown (UINT uFlags, CPoint point); private:void DrawBoard();int m_iToggle;DECLARE_MESSAGE_MAP( ) }; Standard class header Handle two “menu events” (new and quit) Handle the left mouse down event (processing occurs as soon as you press the mouse button) Private routine DrawBoard is used to draw an image on the window Header file for program
#include “TTTWin.h" #include "menus.h“ CTTTWin::CTTTWin() { Create(NULL, "TicTacToe", WS_OVERLAPPEDWINDOW, CRect(100,100,410,450), NULL, "MyMenus"); m_iToggle = 0; } CTTTWin::~CTTTWin() { } afx_msg void CTTTWin::OnNew() { m_iToggle = 0; DrawBoard(); } afx_msg void CTTTWin::OnExit() { SendMessage(WM_CLOSE); } Constructor builds basic window Our board is 300x300 Need a little extra height as window header stuff counts in overall size Destructor does nothing When “new” menu item is selected, draw a new board Quit program when “quit” option is selected Program body (part one)
void CTTTWin::DrawBoard() { CClientDC dc(this); CBrush *pBrush = new CBrush(); pBrush->CreateSolidBrush(RGB(255,255,255)); dc.FillRect(CRect(0,0,300,300), pBrush); CPen *pPen = new CPen; pPen->CreatePen(PS_SOLID, 1, RGB(0,0,0) ); dc.MoveTo(0,100); dc.LineTo(300,100); dc.MoveTo(0,200); dc.LineTo(300,200); dc.MoveTo(100,0); dc.LineTo(100,300); dc.MoveTo(200,0); dc. LineTo(200,300); } Use CBrush and FillRect to paint full device (window) white Use Cpen, MoveTo, and LineTo to draw lines for TicTacToe Board Program body (part two)
afx_msg void CTTTWin::OnLButtonDown (UINT uFlags, CPoint point) { CClientDC dc(this); CBrush *pBrush = new CBrush(); if (m_iToggle) { pBrush->CreateSolidBrush(RGB(255,0,0)); dc.FillRect(CRect(point.x-20,point.y-20, point.x+20,point.y+20), pBrush); m_iToggle = 0; } else { pBrush->CreateSolidBrush(RGB(0,0,255)); dc.FillRect(CRect(point.x-20, point.y-20, point.x+20,point.y+20), pBrush); m_iToggle = 1; } } To process a mouse click, we draw a rectangle (using FillRect) around where you clicked and then change colors (assuming the next move is from the other player) No checking of location of click is done Program body (part three)
BEGIN_MESSAGE_MAP (CTTTWin, CFrameWnd)ON_COMMAND(IDM_NEW, OnNew)ON_COMMAND(IDM_EXIT, OnExit)ON_WM_LBUTTONDOWN( ) END_MESSAGE_MAP( ) class CTTTApp : public CWinApp { public: BOOL InitInstance() {m_pMainWnd = new CTTTWin;m_pMainWnd->ShowWindow (m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE; } } tttApp; Standard message map, we want to handle two unique menu items, don’t need to worry about mouse clicks (built into system) Standard clause to invoke/control execution of program (via WinApp) Program body (part four)
menus.rc #include <afxres.h> #include "menus.h" MyMenus MENU{ POPUP "Tic-Tac-Toe" { MENUITEM "New", IDM_NEW MENUITEM "Quit", IDM_EXIT } } menus.h #define IDM_EXIT 5000 #define IDM_NEW 5001 Extra “menu” files needed
Events (messages) • Each message has a unique id associated with it • Windows-defined • ID’s 0 – 1023 • You-defined • Can name between 1024 –65535 • Naming Convention: • ID’s • WM_MESSAGE: Windows Message • IDM_MESSAGE: Menu Id • Handlers (methods) • OnMessage
Event/Message Handlers • Each unique message ID needs to be associated with message handler (method) • MFC-defined • Has already been associated • Use pre-defined macro ON_WM_MESSAGE()in message to signify it is to be handled in the class specified in the BEGIN_MESSAGE_MAP params • You-defined • You must make the association • Use macro ON_COMMAND(ID, OnMessage)
Macros / Message Map • The macros we use have already been defined. Before compilation time, there is a text replacement where we use the macro identifier. • We have been using the Message Map macros(where we associate a message ID to its handler) BEGIN_MESSAGE_MAP(owner-class name, base-class name) //mappings ON_WM_MESSAGE() // for pre-defined ON_COMMAND(ID, OnMessage) //for you-defined END_MESSAGE_MAP() • For more than you want to know about message maps • http://msdn.microsoft.com/library/default.asp?URL=/library/devprods/vs6/visualc/vcmfc/_mfcnotes_tn006.htm
Message Boxes • Often want to pop up a little window to let the user know something • Information • Question • Notification • MessageBox class simplifies this process • MessageBox has a title • MessageBox displays information • MessageBox might have • Icons and/or selections for the user to pick
Four basic types of message boxes exist Our example will generate one of four message boxes depending on which mouse button you click and where you clicked it Will see a more complete description of message boxes shortly #include <afxwin.h> class CMessageWin : publicCFrameWnd { public: CMessageWin(); ~CMessageWin(); afx_msg void OnLButtonDown (UINT uFlags, CPoint point); afx_msg void OnRButtonDown (UINT uFlags, CPoint point); private: DECLARE_MESSAGE_MAP( ) }; MessageBox example
#include <afxwin.h> #include “MessageWin.h" CMessageWin::CMessageWin() { Create(NULL, "MessageBox Example",WS_OVERLAPPEDWINDOW,CRect(100,100,500,500)); } CMessageWin::~CMessageWin() { } Standard include files Constructor Destructor Body of the program (1)
Body of the program (2) afx_msg void CMessageWin::OnLButtonDown(UINT uFlags, CPoint point) { // handle left button click if (point.x < 200)MessageBox("x coordinate is small", "Stop Message Box", MB_ICONSTOP); elseMessageBox("x coordinate is large", "Question Message Box", MB_ICONQUESTION); } afx_msg void CMessageWin::OnRButtonDown(UINT uFlags, CPoint point) { // handle right button click if (point.y < 200) MessageBox("y coordinate is small", "Exclamation Message Box", MB_ICONEXCLAMATION); elseMessageBox("y coordinate is large", "Info Message Box", MB_ICONINFORMATION); }
BEGIN_MESSAGE_MAP(CMesssageWin, CFrameWnd) ON_WM_LBUTTONDOWN( ) ON_WM_RBUTTONDOWN( ) END_MESSAGE_MAP( ) class CMessageApp : public CWinApp { public: BOOL InitInstance() {m_pMainWnd = new CMessageWin;m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE; } } MessageApp; Our message map section indicates we are interested in capturing two types of events Left button down Right button down Standard main portion Body of the program (3)