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