]> git.saurik.com Git - wxWidgets.git/blame - samples/mfc/mfctest.cpp
use kind, not id, of a menu item to test whether it's a separator: this allows having...
[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
VZ
41// Unless the run-time library settings match for wxWidgets and MFC, you
42// will get link errors for symbols such as __mbctype, __argc, and __argv
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
VZ
52
53#include "stdafx.h"
bbf1f0e5
KB
54
55// For compilers that support precompilation, includes "wx/wx.h".
56#include "wx/wxprec.h"
57
58#ifdef __BORLANDC__
59#pragma hdrstop
60#endif
61
885ebd2b
VZ
62#ifndef WX_PRECOMP
63 #include "wx/wx.h"
bbf1f0e5
KB
64#endif
65
885ebd2b 66#include "wx/evtloop.h"
bbf1f0e5
KB
67
68#include "resource.h"
69
70#include "mfctest.h"
71
bbf1f0e5
KB
72/////////////////////////////////////////////////////////////////////////////
73
74// theApp:
75// Just creating this application object runs the whole application.
76//
77CTheApp theApp;
78
be5a51fb 79// wxWidgets elements
bbf1f0e5
KB
80
81// Define a new application type
82class MyApp: public wxApp
885ebd2b
VZ
83{
84public:
85 virtual bool OnInit();
86
bb2775b9
VZ
87 // we need to override this as the default behaviour only works when we're
88 // running wxWidgets main loop, not MFC one
89 virtual void ExitMainLoop();
90
885ebd2b 91 wxFrame *CreateFrame();
22431134 92};
bbf1f0e5 93
bbf1f0e5
KB
94class MyCanvas: public wxScrolledWindow
95{
22431134 96public:
bbf1f0e5
KB
97 MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
98 void OnPaint(wxPaintEvent& event);
99 void OnMouseEvent(wxMouseEvent& event);
22431134 100 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
101};
102
103class MyChild: public wxFrame
104{
22431134 105public:
bbf1f0e5 106 MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
885ebd2b
VZ
107 virtual ~MyChild();
108
bbf1f0e5
KB
109 void OnQuit(wxCommandEvent& event);
110 void OnNew(wxCommandEvent& event);
111 void OnActivate(wxActivateEvent& event);
885ebd2b
VZ
112
113 MyCanvas *canvas;
114
22431134 115 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
116};
117
bbf1f0e5
KB
118// ID for the menu quit command
119#define HELLO_QUIT 1
120#define HELLO_NEW 2
121
122DECLARE_APP(MyApp)
bbf1f0e5 123
885ebd2b
VZ
124// notice use of IMPLEMENT_APP_NO_MAIN() instead of the usual IMPLEMENT_APP!
125IMPLEMENT_APP_NO_MAIN(MyApp)
bbf1f0e5 126
bbf1f0e5
KB
127CMainWindow::CMainWindow()
128{
ff964839
JS
129 LoadAccelTable( _T("MainAccelTable") );
130 Create( NULL, _T("Hello Foundation Application"),
131 WS_OVERLAPPEDWINDOW, rectDefault, NULL, _T("MainMenu") );
bbf1f0e5
KB
132}
133
bbf1f0e5
KB
134void CMainWindow::OnPaint()
135{
ff964839 136 CString s = _T("Hello, Windows!");
2f6c54eb
VZ
137 CPaintDC dc( this );
138 CRect rect;
885ebd2b 139
2f6c54eb
VZ
140 GetClientRect( rect );
141 dc.SetTextAlign( TA_BASELINE | TA_CENTER );
142 dc.SetTextColor( ::GetSysColor( COLOR_WINDOWTEXT ) );
143 dc.SetBkMode(TRANSPARENT);
144 dc.TextOut( ( rect.right / 2 ), ( rect.bottom / 2 ),
22431134 145 s, s.GetLength() );
bbf1f0e5
KB
146}
147
bbf1f0e5
KB
148void CMainWindow::OnAbout()
149{
ff964839 150 CDialog about( _T("AboutBox"), this );
2f6c54eb 151 about.DoModal();
bbf1f0e5
KB
152}
153
154void CMainWindow::OnTest()
155{
ff964839 156 wxMessageBox(_T("This is a wxWidgets message box.\nWe're about to create a new wxWidgets frame."), _T("wxWidgets"), wxOK);
22431134 157 wxGetApp().CreateFrame();
bbf1f0e5
KB
158}
159
160// CMainWindow message map:
161// Associate messages with member functions.
162//
163// It is implied that the ON_WM_PAINT macro expects a member function
164// "void OnPaint()".
165//
166// It is implied that members connected with the ON_COMMAND macro
167// receive no arguments and are void of return type, e.g., "void OnAbout()".
168//
169BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
22431134
JS
170//{{AFX_MSG_MAP( CMainWindow )
171ON_WM_PAINT()
172ON_COMMAND( IDM_ABOUT, OnAbout )
173ON_COMMAND( IDM_TEST, OnTest )
174//}}AFX_MSG_MAP
bbf1f0e5
KB
175END_MESSAGE_MAP()
176
bbf1f0e5
KB
177BOOL CTheApp::InitInstance()
178{
885ebd2b
VZ
179 if ( !CWinApp::InitInstance() )
180 return FALSE;
181
182 // TODO: cmd line parsing
183 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
184 wxSetInstance(m_hInstance);
185 wxApp::m_nCmdShow = m_nCmdShow;
186 int argc = 0;
ff964839 187 wxChar **argv = NULL;
885ebd2b
VZ
188 wxEntryStart(argc, argv);
189 if ( !wxTheApp || !wxTheApp->CallOnInit() )
190 return FALSE;
191
22431134
JS
192#if START_WITH_MFC_WINDOW
193 // Demonstrate creation of an initial MFC main window.
2f6c54eb
VZ
194 m_pMainWnd = new CMainWindow();
195 m_pMainWnd->ShowWindow( m_nCmdShow );
196 m_pMainWnd->UpdateWindow();
885ebd2b 197#else
be5a51fb
JS
198 // Demonstrate creation of an initial wxWidgets main window.
199 // Wrap wxWidgets window in a dummy MFC window and
22431134 200 // make the main window.
bbf1f0e5
KB
201 if (wxTheApp && wxTheApp->GetTopWindow())
202 {
203 m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
204 }
22431134 205#endif
885ebd2b 206
2f6c54eb 207 return TRUE;
bbf1f0e5
KB
208}
209
210int CTheApp::ExitInstance()
211{
cc3bb83d
VZ
212#if !START_WITH_MFC_WINDOW
213 delete m_pMainWnd;
214#endif
215
885ebd2b
VZ
216 if ( wxTheApp )
217 wxTheApp->OnExit();
218 wxEntryCleanup();
219
22431134 220 return CWinApp::ExitInstance();
bbf1f0e5
KB
221}
222
885ebd2b 223// Override this to provide wxWidgets message loop compatibility
bbf1f0e5
KB
224BOOL CTheApp::PreTranslateMessage(MSG *msg)
225{
9f4905ae
VZ
226 wxEventLoop * const
227 evtLoop = wx_static_cast(wxEventLoop *, wxEventLoop::GetActive());
885ebd2b 228 if ( evtLoop && evtLoop->PreProcessMessage(msg) )
22431134 229 return TRUE;
885ebd2b
VZ
230
231 return CWinApp::PreTranslateMessage(msg);
bbf1f0e5
KB
232}
233
885ebd2b 234BOOL CTheApp::OnIdle(LONG WXUNUSED(lCount))
bbf1f0e5 235{
885ebd2b 236 return wxTheApp && wxTheApp->ProcessIdle();
bbf1f0e5
KB
237}
238
239/*********************************************************************
be5a51fb 240* wxWidgets elements
22431134
JS
241********************************************************************/
242
885ebd2b 243bool MyApp::OnInit()
bbf1f0e5 244{
45e6e6f8
VZ
245 if ( !wxApp::OnInit() )
246 return false;
247
22431134 248#if !START_WITH_MFC_WINDOW
bb2775b9
VZ
249 // as we're not inside wxWidgets main loop, the default logic doesn't work
250 // in our case and we need to do this explicitly
251 SetExitOnFrameDelete(true);
885ebd2b 252
22431134
JS
253 (void) CreateFrame();
254#endif
255
bb2775b9
VZ
256 return true;
257}
258
259void MyApp::ExitMainLoop()
260{
261 // instead of existing wxWidgets main loop, terminate the MFC one
262 ::PostQuitMessage(0);
bbf1f0e5
KB
263}
264
885ebd2b 265wxFrame *MyApp::CreateFrame()
bbf1f0e5 266{
ff964839 267 MyChild *subframe = new MyChild(NULL, _T("Canvas Frame"), wxPoint(10, 10), wxSize(300, 300),
22431134 268 wxDEFAULT_FRAME_STYLE);
885ebd2b 269
ff964839 270 subframe->SetTitle(_T("wxWidgets canvas frame"));
885ebd2b 271
22431134
JS
272 // Give it a status line
273 subframe->CreateStatusBar();
885ebd2b 274
22431134
JS
275 // Make a menubar
276 wxMenu *file_menu = new wxMenu;
885ebd2b 277
ff964839
JS
278 file_menu->Append(HELLO_NEW, _T("&New MFC Window"));
279 file_menu->Append(HELLO_QUIT, _T("&Close"));
885ebd2b 280
22431134 281 wxMenuBar *menu_bar = new wxMenuBar;
885ebd2b 282
ff964839 283 menu_bar->Append(file_menu, _T("&File"));
885ebd2b 284
22431134
JS
285 // Associate the menu bar with the frame
286 subframe->SetMenuBar(menu_bar);
885ebd2b 287
22431134
JS
288 int width, height;
289 subframe->GetClientSize(&width, &height);
885ebd2b 290
22431134
JS
291 MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
292 canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
885ebd2b 293 subframe->canvas = canvas;
bb2775b9 294 subframe->Show(true);
22431134
JS
295
296 // Return the main frame window
297 return subframe;
bbf1f0e5
KB
298}
299
300BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
301 EVT_PAINT(MyCanvas::OnPaint)
302 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
303END_EVENT_TABLE()
304
305// Define a constructor for my canvas
885ebd2b
VZ
306MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size)
307 : wxScrolledWindow(parent, -1, pos, size)
bbf1f0e5
KB
308{
309}
310
311// Define the repainting behaviour
885ebd2b 312void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
bbf1f0e5
KB
313{
314 wxPaintDC dc(this);
885ebd2b 315
f5e5bd66 316 dc.SetFont(* wxSWISS_FONT);
17b74d79 317 dc.SetPen(* wxGREEN_PEN);
bbf1f0e5
KB
318 dc.DrawLine(0, 0, 200, 200);
319 dc.DrawLine(200, 0, 0, 200);
885ebd2b 320
17b74d79
JS
321 dc.SetBrush(* wxCYAN_BRUSH);
322 dc.SetPen(* wxRED_PEN);
bbf1f0e5
KB
323 dc.DrawRectangle(100, 100, 100, 50);
324 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
885ebd2b 325
bbf1f0e5 326 dc.DrawEllipse(250, 250, 100, 50);
bbf1f0e5 327 dc.DrawLine(50, 230, 200, 230);
ff964839 328 dc.DrawText(_T("This is a test string"), 50, 230);
bbf1f0e5
KB
329}
330
331// This implements a tiny doodling program! Drag the mouse using
332// the left button.
333void MyCanvas::OnMouseEvent(wxMouseEvent& event)
334{
885ebd2b
VZ
335 static long s_xpos = -1;
336 static long s_ypos = -1;
337
bbf1f0e5 338 wxClientDC dc(this);
17b74d79 339 dc.SetPen(* wxBLACK_PEN);
3f8e5072 340 wxPoint pos = event.GetPosition();
885ebd2b 341 if (s_xpos > -1 && s_ypos > -1 && event.Dragging())
bbf1f0e5 342 {
885ebd2b 343 dc.DrawLine(s_xpos, s_ypos, pos.x, pos.y);
bbf1f0e5 344 }
885ebd2b
VZ
345
346 s_xpos = pos.x;
347 s_ypos = pos.y;
bbf1f0e5
KB
348}
349
350BEGIN_EVENT_TABLE(MyChild, wxFrame)
351 EVT_MENU(HELLO_QUIT, MyChild::OnQuit)
352 EVT_MENU(HELLO_NEW, MyChild::OnNew)
353 EVT_ACTIVATE(MyChild::OnActivate)
354END_EVENT_TABLE()
355
885ebd2b
VZ
356MyChild::MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style)
357 : wxFrame(frame, -1, title, pos, size, style)
bbf1f0e5 358{
22431134 359 canvas = NULL;
bbf1f0e5
KB
360}
361
885ebd2b 362MyChild::~MyChild()
bbf1f0e5 363{
cc3bb83d
VZ
364 if ( IsLastBeforeExit() )
365 PostQuitMessage(0);
bbf1f0e5
KB
366}
367
885ebd2b 368void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
bbf1f0e5 369{
bb2775b9 370 Close(true);
bbf1f0e5
KB
371}
372
885ebd2b 373void MyChild::OnNew(wxCommandEvent& WXUNUSED(event))
bbf1f0e5
KB
374{
375 CMainWindow *mainWin = new CMainWindow();
376 mainWin->ShowWindow( TRUE );
377 mainWin->UpdateWindow();
378}
22431134 379
bbf1f0e5
KB
380void MyChild::OnActivate(wxActivateEvent& event)
381{
22431134
JS
382 if (event.GetActive() && canvas)
383 canvas->SetFocus();
bbf1f0e5
KB
384}
385
bbf1f0e5 386// Dummy MFC window for specifying a valid main window to MFC, using
be5a51fb 387// a wxWidgets HWND.
cc3bb83d 388CDummyWindow::CDummyWindow(HWND hWnd)
bbf1f0e5 389{
22431134 390 Attach(hWnd);
bbf1f0e5
KB
391}
392
393// Don't let the CWnd destructor delete the HWND
885ebd2b 394CDummyWindow::~CDummyWindow()
bbf1f0e5 395{
22431134 396 Detach();
bbf1f0e5
KB
397}
398