]> git.saurik.com Git - wxWidgets.git/blame - samples/mfc/mfctest.cpp
Update OpenVMS compile support
[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 4// Author: Julian Smart
7818a75c
JS
5// Copyright: (c) Julian Smart
6// Licence: wxWindows licence
7/////////////////////////////////////////////////////////////////////////////
bbf1f0e5 8
be5a51fb 9// This sample pops up an initial wxWidgets frame, with a menu item
bbf1f0e5 10// that allows a new MFC window to be created. Note that CDummyWindow
be5a51fb 11// is a class that allows a wxWidgets window to be seen as a CWnd
bbf1f0e5
KB
12// for the purposes of specifying a valid main window to the
13// MFC initialisation.
14//
15// You can easily modify this code so that an MFC window pops up
be5a51fb 16// initially as the main frame, and allows wxWidgets frames to be
22431134 17// created subsequently.
bbf1f0e5 18//
22431134
JS
19// (1) Make MyApp::OnInit not create a main window.
20// (2) Make MFC's InitInstance create a main window, and remove
bbf1f0e5 21// creation of CDummyWindow.
22431134
JS
22//
23// This can be accomplished by setting START_WITH_MFC_WINDOW to 1 below.
24
25#define START_WITH_MFC_WINDOW 0
26
bbf1f0e5 27//
3f8e5072
JS
28// IMPORTANT NOTES:
29//
885ebd2b
VZ
30// (1) You may need to set wxUSE_MFC to 1 in include/wx/msw/setup.h but
31// normally this shouldn't be needed any longer, i.e. it works without
32// it for me (VZ)
3f8e5072 33//
4d3923a7
JS
34// (2) You should link with MFC DLL, not static libraries: or, to use static
35// run-time libraries, use this command for both building wxWidgets and
36// the sample:
37//
38// nmake -f makefile.vc BUILD=debug SHARED=0 DEBUG_RUNTIME_LIBS=0 RUNTIME_LIBS=static all
39//
9f4905ae 40// Unless the run-time library settings match for wxWidgets and MFC, you
ce00f59b 41// will get link errors for symbols such as __mbctype, __argc, and __argv
9f4905ae
VZ
42//
43// (3) If you see bogus memory leaks within the MSVC IDE on exit, in this
44// sample or in your own project, you must be using __WXDEBUG__ +
45// WXUSINGDLL + _AFXDLL
46// Unfortunately this confuses the MSVC/MFC leak detector. To do away with
47// these bogus memory leaks, add this to the list of link objects, make it
48// first: mfc[version][u]d.lib
49// - [version] -> 42 or 70 or 80 etc
50// - u if using Unicode
885ebd2b 51
ed2da291
VZ
52// Disable deprecation warnings from headers included from stdafx.h for VC8+
53#ifndef _CRT_SECURE_NO_WARNINGS
54 #define _CRT_SECURE_NO_WARNINGS
55#endif
56
57// Also define WINVER to avoid warnings about it being undefined from the
58// platform SDK headers (usually this is not necessary because it is done by wx
59// headers but here we include the system ones before them)
60#ifndef WINVER
61 #define WINVER 0x0600
62#endif
63
885ebd2b 64#include "stdafx.h"
bbf1f0e5
KB
65
66// For compilers that support precompilation, includes "wx/wx.h".
67#include "wx/wxprec.h"
68
69#ifdef __BORLANDC__
70#pragma hdrstop
71#endif
72
885ebd2b
VZ
73#ifndef WX_PRECOMP
74 #include "wx/wx.h"
bbf1f0e5
KB
75#endif
76
885ebd2b 77#include "wx/evtloop.h"
bbf1f0e5
KB
78
79#include "resource.h"
80
81#include "mfctest.h"
82
bbf1f0e5
KB
83/////////////////////////////////////////////////////////////////////////////
84
85// theApp:
86// Just creating this application object runs the whole application.
87//
88CTheApp theApp;
89
be5a51fb 90// wxWidgets elements
bbf1f0e5
KB
91
92// Define a new application type
93class MyApp: public wxApp
885ebd2b
VZ
94{
95public:
96 virtual bool OnInit();
97
bb2775b9
VZ
98 // we need to override this as the default behaviour only works when we're
99 // running wxWidgets main loop, not MFC one
100 virtual void ExitMainLoop();
101
885ebd2b 102 wxFrame *CreateFrame();
22431134 103};
bbf1f0e5 104
bbf1f0e5
KB
105class MyCanvas: public wxScrolledWindow
106{
22431134 107public:
bbf1f0e5
KB
108 MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
109 void OnPaint(wxPaintEvent& event);
110 void OnMouseEvent(wxMouseEvent& event);
22431134 111 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
112};
113
114class MyChild: public wxFrame
115{
22431134 116public:
bbf1f0e5 117 MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
885ebd2b
VZ
118 virtual ~MyChild();
119
bbf1f0e5
KB
120 void OnQuit(wxCommandEvent& event);
121 void OnNew(wxCommandEvent& event);
122 void OnActivate(wxActivateEvent& event);
885ebd2b
VZ
123
124 MyCanvas *canvas;
125
22431134 126 DECLARE_EVENT_TABLE()
bbf1f0e5
KB
127};
128
bbf1f0e5
KB
129// ID for the menu quit command
130#define HELLO_QUIT 1
131#define HELLO_NEW 2
132
133DECLARE_APP(MyApp)
bbf1f0e5 134
885ebd2b
VZ
135// notice use of IMPLEMENT_APP_NO_MAIN() instead of the usual IMPLEMENT_APP!
136IMPLEMENT_APP_NO_MAIN(MyApp)
bbf1f0e5 137
0c9786de
VZ
138#ifdef _UNICODE
139// In Unicode build MFC normally requires to manually change the entry point to
140// wWinMainCRTStartup() but to avoid having to modify the project options to do
141// it we provide an adapter for it.
142extern "C" int wWinMainCRTStartup();
143
144int WINAPI WinMain(HINSTANCE, HINSTANCE, char *, int)
145{
146 wWinMainCRTStartup();
147}
148#endif // _UNICODE
149
bbf1f0e5
KB
150CMainWindow::CMainWindow()
151{
9a83f860
VZ
152 LoadAccelTable( wxT("MainAccelTable") );
153 Create( NULL, wxT("Hello Foundation Application"),
154 WS_OVERLAPPEDWINDOW, rectDefault, NULL, wxT("MainMenu") );
bbf1f0e5
KB
155}
156
bbf1f0e5
KB
157void CMainWindow::OnPaint()
158{
9a83f860 159 CString s = wxT("Hello, Windows!");
2f6c54eb
VZ
160 CPaintDC dc( this );
161 CRect rect;
885ebd2b 162
2f6c54eb
VZ
163 GetClientRect( rect );
164 dc.SetTextAlign( TA_BASELINE | TA_CENTER );
165 dc.SetTextColor( ::GetSysColor( COLOR_WINDOWTEXT ) );
166 dc.SetBkMode(TRANSPARENT);
167 dc.TextOut( ( rect.right / 2 ), ( rect.bottom / 2 ),
22431134 168 s, s.GetLength() );
bbf1f0e5
KB
169}
170
bbf1f0e5
KB
171void CMainWindow::OnAbout()
172{
9a83f860 173 CDialog about( wxT("AboutBox"), this );
2f6c54eb 174 about.DoModal();
bbf1f0e5
KB
175}
176
177void CMainWindow::OnTest()
178{
9a83f860 179 wxMessageBox(wxT("This is a wxWidgets message box.\nWe're about to create a new wxWidgets frame."), wxT("wxWidgets"), wxOK);
22431134 180 wxGetApp().CreateFrame();
bbf1f0e5
KB
181}
182
183// CMainWindow message map:
184// Associate messages with member functions.
185//
186// It is implied that the ON_WM_PAINT macro expects a member function
187// "void OnPaint()".
188//
189// It is implied that members connected with the ON_COMMAND macro
190// receive no arguments and are void of return type, e.g., "void OnAbout()".
191//
192BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
22431134
JS
193//{{AFX_MSG_MAP( CMainWindow )
194ON_WM_PAINT()
195ON_COMMAND( IDM_ABOUT, OnAbout )
196ON_COMMAND( IDM_TEST, OnTest )
197//}}AFX_MSG_MAP
bbf1f0e5
KB
198END_MESSAGE_MAP()
199
bbf1f0e5
KB
200BOOL CTheApp::InitInstance()
201{
885ebd2b
VZ
202 if ( !CWinApp::InitInstance() )
203 return FALSE;
204
205 // TODO: cmd line parsing
206 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
207 wxSetInstance(m_hInstance);
208 wxApp::m_nCmdShow = m_nCmdShow;
209 int argc = 0;
ff964839 210 wxChar **argv = NULL;
885ebd2b
VZ
211 wxEntryStart(argc, argv);
212 if ( !wxTheApp || !wxTheApp->CallOnInit() )
213 return FALSE;
214
22431134
JS
215#if START_WITH_MFC_WINDOW
216 // Demonstrate creation of an initial MFC main window.
2f6c54eb
VZ
217 m_pMainWnd = new CMainWindow();
218 m_pMainWnd->ShowWindow( m_nCmdShow );
219 m_pMainWnd->UpdateWindow();
885ebd2b 220#else
be5a51fb
JS
221 // Demonstrate creation of an initial wxWidgets main window.
222 // Wrap wxWidgets window in a dummy MFC window and
22431134 223 // make the main window.
bbf1f0e5
KB
224 if (wxTheApp && wxTheApp->GetTopWindow())
225 {
226 m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
227 }
22431134 228#endif
885ebd2b 229
2f6c54eb 230 return TRUE;
bbf1f0e5
KB
231}
232
233int CTheApp::ExitInstance()
234{
cc3bb83d
VZ
235#if !START_WITH_MFC_WINDOW
236 delete m_pMainWnd;
237#endif
238
885ebd2b
VZ
239 if ( wxTheApp )
240 wxTheApp->OnExit();
241 wxEntryCleanup();
242
22431134 243 return CWinApp::ExitInstance();
bbf1f0e5
KB
244}
245
885ebd2b 246// Override this to provide wxWidgets message loop compatibility
bbf1f0e5
KB
247BOOL CTheApp::PreTranslateMessage(MSG *msg)
248{
9f4905ae 249 wxEventLoop * const
81d3348a 250 evtLoop = static_cast<wxEventLoop *>(wxEventLoop::GetActive());
885ebd2b 251 if ( evtLoop && evtLoop->PreProcessMessage(msg) )
22431134 252 return TRUE;
885ebd2b
VZ
253
254 return CWinApp::PreTranslateMessage(msg);
bbf1f0e5
KB
255}
256
885ebd2b 257BOOL CTheApp::OnIdle(LONG WXUNUSED(lCount))
bbf1f0e5 258{
885ebd2b 259 return wxTheApp && wxTheApp->ProcessIdle();
bbf1f0e5
KB
260}
261
262/*********************************************************************
be5a51fb 263* wxWidgets elements
22431134
JS
264********************************************************************/
265
885ebd2b 266bool MyApp::OnInit()
bbf1f0e5 267{
45e6e6f8
VZ
268 if ( !wxApp::OnInit() )
269 return false;
270
22431134 271#if !START_WITH_MFC_WINDOW
bb2775b9
VZ
272 // as we're not inside wxWidgets main loop, the default logic doesn't work
273 // in our case and we need to do this explicitly
274 SetExitOnFrameDelete(true);
885ebd2b 275
22431134
JS
276 (void) CreateFrame();
277#endif
278
bb2775b9
VZ
279 return true;
280}
281
282void MyApp::ExitMainLoop()
283{
284 // instead of existing wxWidgets main loop, terminate the MFC one
285 ::PostQuitMessage(0);
bbf1f0e5
KB
286}
287
885ebd2b 288wxFrame *MyApp::CreateFrame()
bbf1f0e5 289{
9a83f860 290 MyChild *subframe = new MyChild(NULL, wxT("Canvas Frame"), wxPoint(10, 10), wxSize(300, 300),
22431134 291 wxDEFAULT_FRAME_STYLE);
885ebd2b 292
9a83f860 293 subframe->SetTitle(wxT("wxWidgets canvas frame"));
885ebd2b 294
22431134
JS
295 // Give it a status line
296 subframe->CreateStatusBar();
885ebd2b 297
22431134
JS
298 // Make a menubar
299 wxMenu *file_menu = new wxMenu;
885ebd2b 300
9a83f860
VZ
301 file_menu->Append(HELLO_NEW, wxT("&New MFC Window"));
302 file_menu->Append(HELLO_QUIT, wxT("&Close"));
885ebd2b 303
22431134 304 wxMenuBar *menu_bar = new wxMenuBar;
885ebd2b 305
9a83f860 306 menu_bar->Append(file_menu, wxT("&File"));
885ebd2b 307
22431134
JS
308 // Associate the menu bar with the frame
309 subframe->SetMenuBar(menu_bar);
885ebd2b 310
22431134
JS
311 int width, height;
312 subframe->GetClientSize(&width, &height);
885ebd2b 313
22431134
JS
314 MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
315 canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
885ebd2b 316 subframe->canvas = canvas;
bb2775b9 317 subframe->Show(true);
22431134
JS
318
319 // Return the main frame window
320 return subframe;
bbf1f0e5
KB
321}
322
323BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
324 EVT_PAINT(MyCanvas::OnPaint)
325 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
326END_EVENT_TABLE()
327
328// Define a constructor for my canvas
885ebd2b
VZ
329MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size)
330 : wxScrolledWindow(parent, -1, pos, size)
bbf1f0e5
KB
331{
332}
333
334// Define the repainting behaviour
885ebd2b 335void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
bbf1f0e5
KB
336{
337 wxPaintDC dc(this);
885ebd2b 338
f5e5bd66 339 dc.SetFont(* wxSWISS_FONT);
17b74d79 340 dc.SetPen(* wxGREEN_PEN);
bbf1f0e5
KB
341 dc.DrawLine(0, 0, 200, 200);
342 dc.DrawLine(200, 0, 0, 200);
885ebd2b 343
17b74d79
JS
344 dc.SetBrush(* wxCYAN_BRUSH);
345 dc.SetPen(* wxRED_PEN);
bbf1f0e5
KB
346 dc.DrawRectangle(100, 100, 100, 50);
347 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
885ebd2b 348
bbf1f0e5 349 dc.DrawEllipse(250, 250, 100, 50);
bbf1f0e5 350 dc.DrawLine(50, 230, 200, 230);
9a83f860 351 dc.DrawText(wxT("This is a test string"), 50, 230);
bbf1f0e5
KB
352}
353
354// This implements a tiny doodling program! Drag the mouse using
355// the left button.
356void MyCanvas::OnMouseEvent(wxMouseEvent& event)
357{
885ebd2b
VZ
358 static long s_xpos = -1;
359 static long s_ypos = -1;
360
bbf1f0e5 361 wxClientDC dc(this);
17b74d79 362 dc.SetPen(* wxBLACK_PEN);
3f8e5072 363 wxPoint pos = event.GetPosition();
885ebd2b 364 if (s_xpos > -1 && s_ypos > -1 && event.Dragging())
bbf1f0e5 365 {
885ebd2b 366 dc.DrawLine(s_xpos, s_ypos, pos.x, pos.y);
bbf1f0e5 367 }
885ebd2b
VZ
368
369 s_xpos = pos.x;
370 s_ypos = pos.y;
bbf1f0e5
KB
371}
372
373BEGIN_EVENT_TABLE(MyChild, wxFrame)
374 EVT_MENU(HELLO_QUIT, MyChild::OnQuit)
375 EVT_MENU(HELLO_NEW, MyChild::OnNew)
376 EVT_ACTIVATE(MyChild::OnActivate)
377END_EVENT_TABLE()
378
885ebd2b
VZ
379MyChild::MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style)
380 : wxFrame(frame, -1, title, pos, size, style)
bbf1f0e5 381{
22431134 382 canvas = NULL;
bbf1f0e5
KB
383}
384
885ebd2b 385MyChild::~MyChild()
bbf1f0e5 386{
cc3bb83d
VZ
387 if ( IsLastBeforeExit() )
388 PostQuitMessage(0);
bbf1f0e5
KB
389}
390
885ebd2b 391void MyChild::OnQuit(wxCommandEvent& WXUNUSED(event))
bbf1f0e5 392{
bb2775b9 393 Close(true);
bbf1f0e5
KB
394}
395
885ebd2b 396void MyChild::OnNew(wxCommandEvent& WXUNUSED(event))
bbf1f0e5
KB
397{
398 CMainWindow *mainWin = new CMainWindow();
399 mainWin->ShowWindow( TRUE );
400 mainWin->UpdateWindow();
401}
22431134 402
bbf1f0e5
KB
403void MyChild::OnActivate(wxActivateEvent& event)
404{
22431134
JS
405 if (event.GetActive() && canvas)
406 canvas->SetFocus();
bbf1f0e5
KB
407}
408
bbf1f0e5 409// Dummy MFC window for specifying a valid main window to MFC, using
be5a51fb 410// a wxWidgets HWND.
cc3bb83d 411CDummyWindow::CDummyWindow(HWND hWnd)
bbf1f0e5 412{
22431134 413 Attach(hWnd);
bbf1f0e5
KB
414}
415
416// Don't let the CWnd destructor delete the HWND
885ebd2b 417CDummyWindow::~CDummyWindow()
bbf1f0e5 418{
22431134 419 Detach();
bbf1f0e5
KB
420}
421