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