]> git.saurik.com Git - wxWidgets.git/blame - samples/mfc/mfctest.cpp
simplify mouse button handling code
[wxWidgets.git] / samples / mfc / mfctest.cpp
CommitLineData
7818a75c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: mfctest.cpp
be5a51fb 3// Purpose: Sample to demonstrate mixing MFC and wxWidgets code
7818a75c
JS
4// Author: Julian Smart
5// Id: $Id$
6// Copyright: (c) Julian Smart
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
bbf1f0e5 9
be5a51fb 10// This sample pops up an initial wxWidgets frame, with a menu item
bbf1f0e5 11// that allows a new MFC window to be created. Note that CDummyWindow
be5a51fb 12// is a class that allows a wxWidgets window to be seen as a CWnd
bbf1f0e5
KB
13// for the purposes of specifying a valid main window to the
14// MFC initialisation.
15//
16// You can easily modify this code so that an MFC window pops up
be5a51fb 17// initially as the main frame, and allows wxWidgets frames to be
22431134 18// created subsequently.
bbf1f0e5 19//
22431134
JS
20// (1) Make MyApp::OnInit not create a main window.
21// (2) Make MFC's InitInstance create a main window, and remove
bbf1f0e5 22// creation of CDummyWindow.
22431134
JS
23//
24// This can be accomplished by setting START_WITH_MFC_WINDOW to 1 below.
25
26#define START_WITH_MFC_WINDOW 0
27
bbf1f0e5 28//
3f8e5072
JS
29// IMPORTANT NOTES:
30//
885ebd2b
VZ
31// (1) You may need to set wxUSE_MFC to 1 in include/wx/msw/setup.h but
32// normally this shouldn't be needed any longer, i.e. it works without
33// it for me (VZ)
3f8e5072 34//
4d3923a7
JS
35// (2) You should link with MFC DLL, not static libraries: or, to use static
36// run-time libraries, use this command for both building wxWidgets and
37// the sample:
38//
39// nmake -f makefile.vc BUILD=debug SHARED=0 DEBUG_RUNTIME_LIBS=0 RUNTIME_LIBS=static all
40//
9f4905ae 41// Unless the run-time library settings match for wxWidgets and MFC, you
ce00f59b 42// will get link errors for symbols such as __mbctype, __argc, and __argv
9f4905ae
VZ
43//
44// (3) If you see bogus memory leaks within the MSVC IDE on exit, in this
45// sample or in your own project, you must be using __WXDEBUG__ +
46// WXUSINGDLL + _AFXDLL
47// Unfortunately this confuses the MSVC/MFC leak detector. To do away with
48// these bogus memory leaks, add this to the list of link objects, make it
49// first: mfc[version][u]d.lib
50// - [version] -> 42 or 70 or 80 etc
51// - u if using Unicode
885ebd2b 52
ed2da291
VZ
53// Disable deprecation warnings from headers included from stdafx.h for VC8+
54#ifndef _CRT_SECURE_NO_WARNINGS
55 #define _CRT_SECURE_NO_WARNINGS
56#endif
57
58// Also define WINVER to avoid warnings about it being undefined from the
59// platform SDK headers (usually this is not necessary because it is done by wx
60// headers but here we include the system ones before them)
61#ifndef WINVER
62 #define WINVER 0x0600
63#endif
64
885ebd2b 65#include "stdafx.h"
bbf1f0e5
KB
66
67// For compilers that support precompilation, includes "wx/wx.h".
68#include "wx/wxprec.h"
69
70#ifdef __BORLANDC__
71#pragma hdrstop
72#endif
73
885ebd2b
VZ
74#ifndef WX_PRECOMP
75 #include "wx/wx.h"
bbf1f0e5
KB
76#endif
77
885ebd2b 78#include "wx/evtloop.h"
bbf1f0e5
KB
79
80#include "resource.h"
81
82#include "mfctest.h"
83
bbf1f0e5
KB
84/////////////////////////////////////////////////////////////////////////////
85
86// theApp:
87// Just creating this application object runs the whole application.
88//
89CTheApp theApp;
90
be5a51fb 91// wxWidgets elements
bbf1f0e5
KB
92
93// Define a new application type
94class MyApp: public wxApp
885ebd2b
VZ
95{
96public:
97 virtual bool OnInit();
98
bb2775b9
VZ
99 // we need to override this as the default behaviour only works when we're
100 // running wxWidgets main loop, not MFC one
101 virtual void ExitMainLoop();
102
885ebd2b 103 wxFrame *CreateFrame();
22431134 104};
bbf1f0e5 105
bbf1f0e5
KB
106class MyCanvas: public wxScrolledWindow
107{
22431134 108public:
bbf1f0e5
KB
109 MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
110 void OnPaint(wxPaintEvent& event);
111 void OnMouseEvent(wxMouseEvent& event);
22431134 112 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
113};
114
115class MyChild: public wxFrame
116{
22431134 117public:
bbf1f0e5 118 MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
885ebd2b
VZ
119 virtual ~MyChild();
120
bbf1f0e5
KB
121 void OnQuit(wxCommandEvent& event);
122 void OnNew(wxCommandEvent& event);
123 void OnActivate(wxActivateEvent& event);
885ebd2b
VZ
124
125 MyCanvas *canvas;
126
22431134 127 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
128};
129
bbf1f0e5
KB
130// ID for the menu quit command
131#define HELLO_QUIT 1
132#define HELLO_NEW 2
133
134DECLARE_APP(MyApp)
bbf1f0e5 135
885ebd2b
VZ
136// notice use of IMPLEMENT_APP_NO_MAIN() instead of the usual IMPLEMENT_APP!
137IMPLEMENT_APP_NO_MAIN(MyApp)
bbf1f0e5 138
0c9786de
VZ
139#ifdef _UNICODE
140// In Unicode build MFC normally requires to manually change the entry point to
141// wWinMainCRTStartup() but to avoid having to modify the project options to do
142// it we provide an adapter for it.
143extern "C" int wWinMainCRTStartup();
144
145int WINAPI WinMain(HINSTANCE, HINSTANCE, char *, int)
146{
147 wWinMainCRTStartup();
148}
149#endif // _UNICODE
150
bbf1f0e5
KB
151CMainWindow::CMainWindow()
152{
9a83f860
VZ
153 LoadAccelTable( wxT("MainAccelTable") );
154 Create( NULL, wxT("Hello Foundation Application"),
155 WS_OVERLAPPEDWINDOW, rectDefault, NULL, wxT("MainMenu") );
bbf1f0e5
KB
156}
157
bbf1f0e5
KB
158void CMainWindow::OnPaint()
159{
9a83f860 160 CString s = wxT("Hello, Windows!");
2f6c54eb
VZ
161 CPaintDC dc( this );
162 CRect rect;
885ebd2b 163
2f6c54eb
VZ
164 GetClientRect( rect );
165 dc.SetTextAlign( TA_BASELINE | TA_CENTER );
166 dc.SetTextColor( ::GetSysColor( COLOR_WINDOWTEXT ) );
167 dc.SetBkMode(TRANSPARENT);
168 dc.TextOut( ( rect.right / 2 ), ( rect.bottom / 2 ),
22431134 169 s, s.GetLength() );
bbf1f0e5
KB
170}
171
bbf1f0e5
KB
172void CMainWindow::OnAbout()
173{
9a83f860 174 CDialog about( wxT("AboutBox"), this );
2f6c54eb 175 about.DoModal();
bbf1f0e5
KB
176}
177
178void CMainWindow::OnTest()
179{
9a83f860 180 wxMessageBox(wxT("This is a wxWidgets message box.\nWe're about to create a new wxWidgets frame."), wxT("wxWidgets"), wxOK);
22431134 181 wxGetApp().CreateFrame();
bbf1f0e5
KB
182}
183
184// CMainWindow message map:
185// Associate messages with member functions.
186//
187// It is implied that the ON_WM_PAINT macro expects a member function
188// "void OnPaint()".
189//
190// It is implied that members connected with the ON_COMMAND macro
191// receive no arguments and are void of return type, e.g., "void OnAbout()".
192//
193BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
22431134
JS
194//{{AFX_MSG_MAP( CMainWindow )
195ON_WM_PAINT()
196ON_COMMAND( IDM_ABOUT, OnAbout )
197ON_COMMAND( IDM_TEST, OnTest )
198//}}AFX_MSG_MAP
bbf1f0e5
KB
199END_MESSAGE_MAP()
200
bbf1f0e5
KB
201BOOL CTheApp::InitInstance()
202{
885ebd2b
VZ
203 if ( !CWinApp::InitInstance() )
204 return FALSE;
205
206 // TODO: cmd line parsing
207 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
208 wxSetInstance(m_hInstance);
209 wxApp::m_nCmdShow = m_nCmdShow;
210 int argc = 0;
ff964839 211 wxChar **argv = NULL;
885ebd2b
VZ
212 wxEntryStart(argc, argv);
213 if ( !wxTheApp || !wxTheApp->CallOnInit() )
214 return FALSE;
215
22431134
JS
216#if START_WITH_MFC_WINDOW
217 // Demonstrate creation of an initial MFC main window.
2f6c54eb
VZ
218 m_pMainWnd = new CMainWindow();
219 m_pMainWnd->ShowWindow( m_nCmdShow );
220 m_pMainWnd->UpdateWindow();
885ebd2b 221#else
be5a51fb
JS
222 // Demonstrate creation of an initial wxWidgets main window.
223 // Wrap wxWidgets window in a dummy MFC window and
22431134 224 // make the main window.
bbf1f0e5
KB
225 if (wxTheApp && wxTheApp->GetTopWindow())
226 {
227 m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
228 }
22431134 229#endif
885ebd2b 230
2f6c54eb 231 return TRUE;
bbf1f0e5
KB
232}
233
234int CTheApp::ExitInstance()
235{
cc3bb83d
VZ
236#if !START_WITH_MFC_WINDOW
237 delete m_pMainWnd;
238#endif
239
885ebd2b
VZ
240 if ( wxTheApp )
241 wxTheApp->OnExit();
242 wxEntryCleanup();
243
22431134 244 return CWinApp::ExitInstance();
bbf1f0e5
KB
245}
246
885ebd2b 247// Override this to provide wxWidgets message loop compatibility
bbf1f0e5
KB
248BOOL CTheApp::PreTranslateMessage(MSG *msg)
249{
9f4905ae 250 wxEventLoop * const
81d3348a 251 evtLoop = static_cast<wxEventLoop *>(wxEventLoop::GetActive());
885ebd2b 252 if ( evtLoop && evtLoop->PreProcessMessage(msg) )
22431134 253 return TRUE;
885ebd2b
VZ
254
255 return CWinApp::PreTranslateMessage(msg);
bbf1f0e5
KB
256}
257
885ebd2b 258BOOL CTheApp::OnIdle(LONG WXUNUSED(lCount))
bbf1f0e5 259{
885ebd2b 260 return wxTheApp && wxTheApp->ProcessIdle();
bbf1f0e5
KB
261}
262
263/*********************************************************************
be5a51fb 264* wxWidgets elements
22431134
JS
265********************************************************************/
266
885ebd2b 267bool MyApp::OnInit()
bbf1f0e5 268{
45e6e6f8
VZ
269 if ( !wxApp::OnInit() )
270 return false;
271
22431134 272#if !START_WITH_MFC_WINDOW
bb2775b9
VZ
273 // as we're not inside wxWidgets main loop, the default logic doesn't work
274 // in our case and we need to do this explicitly
275 SetExitOnFrameDelete(true);
885ebd2b 276
22431134
JS
277 (void) CreateFrame();
278#endif
279
bb2775b9
VZ
280 return true;
281}
282
283void MyApp::ExitMainLoop()
284{
285 // instead of existing wxWidgets main loop, terminate the MFC one
286 ::PostQuitMessage(0);
bbf1f0e5
KB
287}
288
885ebd2b 289wxFrame *MyApp::CreateFrame()
bbf1f0e5 290{
9a83f860 291 MyChild *subframe = new MyChild(NULL, wxT("Canvas Frame"), wxPoint(10, 10), wxSize(300, 300),
22431134 292 wxDEFAULT_FRAME_STYLE);
885ebd2b 293
9a83f860 294 subframe->SetTitle(wxT("wxWidgets canvas frame"));
885ebd2b 295
22431134
JS
296 // Give it a status line
297 subframe->CreateStatusBar();
885ebd2b 298
22431134
JS
299 // Make a menubar
300 wxMenu *file_menu = new wxMenu;
885ebd2b 301
9a83f860
VZ
302 file_menu->Append(HELLO_NEW, wxT("&New MFC Window"));
303 file_menu->Append(HELLO_QUIT, wxT("&Close"));
885ebd2b 304
22431134 305 wxMenuBar *menu_bar = new wxMenuBar;
885ebd2b 306
9a83f860 307 menu_bar->Append(file_menu, wxT("&File"));
885ebd2b 308
22431134
JS
309 // Associate the menu bar with the frame
310 subframe->SetMenuBar(menu_bar);
885ebd2b 311
22431134
JS
312 int width, height;
313 subframe->GetClientSize(&width, &height);
885ebd2b 314
22431134
JS
315 MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
316 canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
885ebd2b 317 subframe->canvas = canvas;
bb2775b9 318 subframe->Show(true);
22431134
JS
319
320 // Return the main frame window
321 return subframe;
bbf1f0e5
KB
322}
323
324BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
325 EVT_PAINT(MyCanvas::OnPaint)
326 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
327END_EVENT_TABLE()
328
329// Define a constructor for my canvas
885ebd2b
VZ
330MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size)
331 : wxScrolledWindow(parent, -1, pos, size)
bbf1f0e5
KB
332{
333}
334
335// Define the repainting behaviour
885ebd2b 336void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
bbf1f0e5
KB
337{
338 wxPaintDC dc(this);
885ebd2b 339
f5e5bd66 340 dc.SetFont(* wxSWISS_FONT);
17b74d79 341 dc.SetPen(* wxGREEN_PEN);
bbf1f0e5
KB
342 dc.DrawLine(0, 0, 200, 200);
343 dc.DrawLine(200, 0, 0, 200);
885ebd2b 344
17b74d79
JS
345 dc.SetBrush(* wxCYAN_BRUSH);
346 dc.SetPen(* wxRED_PEN);
bbf1f0e5
KB
347 dc.DrawRectangle(100, 100, 100, 50);
348 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
885ebd2b 349
bbf1f0e5 350 dc.DrawEllipse(250, 250, 100, 50);
bbf1f0e5 351 dc.DrawLine(50, 230, 200, 230);
9a83f860 352 dc.DrawText(wxT("This is a test string"), 50, 230);
bbf1f0e5
KB
353}
354
355// This implements a tiny doodling program! Drag the mouse using
356// the left button.
357void MyCanvas::OnMouseEvent(wxMouseEvent& event)
358{
885ebd2b
VZ
359 static long s_xpos = -1;
360 static long s_ypos = -1;
361
bbf1f0e5 362 wxClientDC dc(this);
17b74d79 363 dc.SetPen(* wxBLACK_PEN);
3f8e5072 364 wxPoint pos = event.GetPosition();
885ebd2b 365 if (s_xpos > -1 && s_ypos > -1 && event.Dragging())
bbf1f0e5 366 {
885ebd2b 367 dc.DrawLine(s_xpos, s_ypos, pos.x, pos.y);
bbf1f0e5 368 }
885ebd2b
VZ
369
370 s_xpos = pos.x;
371 s_ypos = pos.y;
bbf1f0e5
KB
372}
373
374BEGIN_EVENT_TABLE(MyChild, wxFrame)
375 EVT_MENU(HELLO_QUIT, MyChild::OnQuit)
376 EVT_MENU(HELLO_NEW, MyChild::OnNew)
377 EVT_ACTIVATE(MyChild::OnActivate)
378END_EVENT_TABLE()
379
885ebd2b
VZ
380MyChild::MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style)
381 : wxFrame(frame, -1, title, pos, size, style)
bbf1f0e5 382{
22431134 383 canvas = NULL;
bbf1f0e5
KB
384}
385
885ebd2b 386MyChild::~MyChild()
bbf1f0e5 387{
cc3bb83d
VZ
388 if ( IsLastBeforeExit() )
389 PostQuitMessage(0);
bbf1f0e5
KB
390}
391
885ebd2b 392void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
bbf1f0e5 393{
bb2775b9 394 Close(true);
bbf1f0e5
KB
395}
396
885ebd2b 397void MyChild::OnNew(wxCommandEvent& WXUNUSED(event))
bbf1f0e5
KB
398{
399 CMainWindow *mainWin = new CMainWindow();
400 mainWin->ShowWindow( TRUE );
401 mainWin->UpdateWindow();
402}
22431134 403
bbf1f0e5
KB
404void MyChild::OnActivate(wxActivateEvent& event)
405{
22431134
JS
406 if (event.GetActive() && canvas)
407 canvas->SetFocus();
bbf1f0e5
KB
408}
409
bbf1f0e5 410// Dummy MFC window for specifying a valid main window to MFC, using
be5a51fb 411// a wxWidgets HWND.
cc3bb83d 412CDummyWindow::CDummyWindow(HWND hWnd)
bbf1f0e5 413{
22431134 414 Attach(hWnd);
bbf1f0e5
KB
415}
416
417// Don't let the CWnd destructor delete the HWND
885ebd2b 418CDummyWindow::~CDummyWindow()
bbf1f0e5 419{
22431134 420 Detach();
bbf1f0e5
KB
421}
422