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