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