]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/mfc/mfctest.cpp
Added wxSimplebook class: a wxBookCtrl without controller.
[wxWidgets.git] / samples / mfc / mfctest.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: mfctest.cpp
3// Purpose: Sample to demonstrate mixing MFC and wxWidgets code
4// Author: Julian Smart
5// Id: $Id$
6// Copyright: (c) Julian Smart
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10// This sample pops up an initial wxWidgets frame, with a menu item
11// that allows a new MFC window to be created. Note that CDummyWindow
12// is a class that allows a wxWidgets window to be seen as a CWnd
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
17// initially as the main frame, and allows wxWidgets frames to be
18// created subsequently.
19//
20// (1) Make MyApp::OnInit not create a main window.
21// (2) Make MFC's InitInstance create a main window, and remove
22// creation of CDummyWindow.
23//
24// This can be accomplished by setting START_WITH_MFC_WINDOW to 1 below.
25
26#define START_WITH_MFC_WINDOW 0
27
28//
29// IMPORTANT NOTES:
30//
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)
34//
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//
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
52
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
65#include "stdafx.h"
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
74#ifndef WX_PRECOMP
75 #include "wx/wx.h"
76#endif
77
78#include "wx/evtloop.h"
79
80#include "resource.h"
81
82#include "mfctest.h"
83
84/////////////////////////////////////////////////////////////////////////////
85
86// theApp:
87// Just creating this application object runs the whole application.
88//
89CTheApp theApp;
90
91// wxWidgets elements
92
93// Define a new application type
94class MyApp: public wxApp
95{
96public:
97 virtual bool OnInit();
98
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
103 wxFrame *CreateFrame();
104};
105
106class MyCanvas: public wxScrolledWindow
107{
108public:
109 MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
110 void OnPaint(wxPaintEvent& event);
111 void OnMouseEvent(wxMouseEvent& event);
112 DECLARE_EVENT_TABLE()
113};
114
115class MyChild: public wxFrame
116{
117public:
118 MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
119 virtual ~MyChild();
120
121 void OnQuit(wxCommandEvent& event);
122 void OnNew(wxCommandEvent& event);
123 void OnActivate(wxActivateEvent& event);
124
125 MyCanvas *canvas;
126
127 DECLARE_EVENT_TABLE()
128};
129
130// ID for the menu quit command
131#define HELLO_QUIT 1
132#define HELLO_NEW 2
133
134DECLARE_APP(MyApp)
135
136// notice use of IMPLEMENT_APP_NO_MAIN() instead of the usual IMPLEMENT_APP!
137IMPLEMENT_APP_NO_MAIN(MyApp)
138
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
151CMainWindow::CMainWindow()
152{
153 LoadAccelTable( wxT("MainAccelTable") );
154 Create( NULL, wxT("Hello Foundation Application"),
155 WS_OVERLAPPEDWINDOW, rectDefault, NULL, wxT("MainMenu") );
156}
157
158void CMainWindow::OnPaint()
159{
160 CString s = wxT("Hello, Windows!");
161 CPaintDC dc( this );
162 CRect rect;
163
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 ),
169 s, s.GetLength() );
170}
171
172void CMainWindow::OnAbout()
173{
174 CDialog about( wxT("AboutBox"), this );
175 about.DoModal();
176}
177
178void CMainWindow::OnTest()
179{
180 wxMessageBox(wxT("This is a wxWidgets message box.\nWe're about to create a new wxWidgets frame."), wxT("wxWidgets"), wxOK);
181 wxGetApp().CreateFrame();
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 )
194//{{AFX_MSG_MAP( CMainWindow )
195ON_WM_PAINT()
196ON_COMMAND( IDM_ABOUT, OnAbout )
197ON_COMMAND( IDM_TEST, OnTest )
198//}}AFX_MSG_MAP
199END_MESSAGE_MAP()
200
201BOOL CTheApp::InitInstance()
202{
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;
211 wxChar **argv = NULL;
212 wxEntryStart(argc, argv);
213 if ( !wxTheApp || !wxTheApp->CallOnInit() )
214 return FALSE;
215
216#if START_WITH_MFC_WINDOW
217 // Demonstrate creation of an initial MFC main window.
218 m_pMainWnd = new CMainWindow();
219 m_pMainWnd->ShowWindow( m_nCmdShow );
220 m_pMainWnd->UpdateWindow();
221#else
222 // Demonstrate creation of an initial wxWidgets main window.
223 // Wrap wxWidgets window in a dummy MFC window and
224 // make the main window.
225 if (wxTheApp && wxTheApp->GetTopWindow())
226 {
227 m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
228 }
229#endif
230
231 return TRUE;
232}
233
234int CTheApp::ExitInstance()
235{
236#if !START_WITH_MFC_WINDOW
237 delete m_pMainWnd;
238#endif
239
240 if ( wxTheApp )
241 wxTheApp->OnExit();
242 wxEntryCleanup();
243
244 return CWinApp::ExitInstance();
245}
246
247// Override this to provide wxWidgets message loop compatibility
248BOOL CTheApp::PreTranslateMessage(MSG *msg)
249{
250 wxEventLoop * const
251 evtLoop = static_cast<wxEventLoop *>(wxEventLoop::GetActive());
252 if ( evtLoop && evtLoop->PreProcessMessage(msg) )
253 return TRUE;
254
255 return CWinApp::PreTranslateMessage(msg);
256}
257
258BOOL CTheApp::OnIdle(LONG WXUNUSED(lCount))
259{
260 return wxTheApp && wxTheApp->ProcessIdle();
261}
262
263/*********************************************************************
264* wxWidgets elements
265********************************************************************/
266
267bool MyApp::OnInit()
268{
269 if ( !wxApp::OnInit() )
270 return false;
271
272#if !START_WITH_MFC_WINDOW
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);
276
277 (void) CreateFrame();
278#endif
279
280 return true;
281}
282
283void MyApp::ExitMainLoop()
284{
285 // instead of existing wxWidgets main loop, terminate the MFC one
286 ::PostQuitMessage(0);
287}
288
289wxFrame *MyApp::CreateFrame()
290{
291 MyChild *subframe = new MyChild(NULL, wxT("Canvas Frame"), wxPoint(10, 10), wxSize(300, 300),
292 wxDEFAULT_FRAME_STYLE);
293
294 subframe->SetTitle(wxT("wxWidgets canvas frame"));
295
296 // Give it a status line
297 subframe->CreateStatusBar();
298
299 // Make a menubar
300 wxMenu *file_menu = new wxMenu;
301
302 file_menu->Append(HELLO_NEW, wxT("&New MFC Window"));
303 file_menu->Append(HELLO_QUIT, wxT("&Close"));
304
305 wxMenuBar *menu_bar = new wxMenuBar;
306
307 menu_bar->Append(file_menu, wxT("&File"));
308
309 // Associate the menu bar with the frame
310 subframe->SetMenuBar(menu_bar);
311
312 int width, height;
313 subframe->GetClientSize(&width, &height);
314
315 MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
316 canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
317 subframe->canvas = canvas;
318 subframe->Show(true);
319
320 // Return the main frame window
321 return subframe;
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
330MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size)
331 : wxScrolledWindow(parent, -1, pos, size)
332{
333}
334
335// Define the repainting behaviour
336void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
337{
338 wxPaintDC dc(this);
339
340 dc.SetFont(* wxSWISS_FONT);
341 dc.SetPen(* wxGREEN_PEN);
342 dc.DrawLine(0, 0, 200, 200);
343 dc.DrawLine(200, 0, 0, 200);
344
345 dc.SetBrush(* wxCYAN_BRUSH);
346 dc.SetPen(* wxRED_PEN);
347 dc.DrawRectangle(100, 100, 100, 50);
348 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
349
350 dc.DrawEllipse(250, 250, 100, 50);
351 dc.DrawLine(50, 230, 200, 230);
352 dc.DrawText(wxT("This is a test string"), 50, 230);
353}
354
355// This implements a tiny doodling program! Drag the mouse using
356// the left button.
357void MyCanvas::OnMouseEvent(wxMouseEvent& event)
358{
359 static long s_xpos = -1;
360 static long s_ypos = -1;
361
362 wxClientDC dc(this);
363 dc.SetPen(* wxBLACK_PEN);
364 wxPoint pos = event.GetPosition();
365 if (s_xpos > -1 && s_ypos > -1 && event.Dragging())
366 {
367 dc.DrawLine(s_xpos, s_ypos, pos.x, pos.y);
368 }
369
370 s_xpos = pos.x;
371 s_ypos = pos.y;
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
380MyChild::MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style)
381 : wxFrame(frame, -1, title, pos, size, style)
382{
383 canvas = NULL;
384}
385
386MyChild::~MyChild()
387{
388 if ( IsLastBeforeExit() )
389 PostQuitMessage(0);
390}
391
392void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
393{
394 Close(true);
395}
396
397void MyChild::OnNew(wxCommandEvent& WXUNUSED(event))
398{
399 CMainWindow *mainWin = new CMainWindow();
400 mainWin->ShowWindow( TRUE );
401 mainWin->UpdateWindow();
402}
403
404void MyChild::OnActivate(wxActivateEvent& event)
405{
406 if (event.GetActive() && canvas)
407 canvas->SetFocus();
408}
409
410// Dummy MFC window for specifying a valid main window to MFC, using
411// a wxWidgets HWND.
412CDummyWindow::CDummyWindow(HWND hWnd)
413{
414 Attach(hWnd);
415}
416
417// Don't let the CWnd destructor delete the HWND
418CDummyWindow::~CDummyWindow()
419{
420 Detach();
421}
422