]> git.saurik.com Git - wxWidgets.git/blob - samples/mfc/mfctest.cpp
correcting a missing redraw area on certain resize operations when window has a border
[wxWidgets.git] / samples / mfc / mfctest.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mfctest.cpp
3 // Purpose: Sample to demonstrate mixing MFC and wxWindows 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 wxWindows 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 wxWindows 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 wxWindows 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 need to set wxUSE_MFC to 1 in include/wx/msw/setup.h, which switches
32 // off some debugging features and also removes the windows.h inclusion
33 // in wxprec.h (MFC headers don't like this to have been included previously).
34 // Set to 'Use MFC in a shared DLL' or add _AFXDLL to preprocessor settings.
35 // Then recompile wxWindows and this sample.
36 //
37 // (2) I can't get the sample to link and run using a static MFC library, only the DLL
38 // version. Perhaps someone else is a wizard at working out the required settings
39 // in the wxWin library and the sample; then debugging the assert problem may be
40 // easier.
41 //
42 // (3) Compiling wxWindows in DLL mode currently includes windows.h, so you must only
43 // try linking wxWindows statically.
44
45 // For compilers that support precompilation, includes "wx/wx.h".
46 #include "wx/wxprec.h"
47
48 #ifdef __BORLANDC__
49 #pragma hdrstop
50 #endif
51
52 #include "wx/wx.h"
53
54 #if defined(_WINDOWS_) || !wxUSE_MFC
55 #error Sorry, you need to edit include/wx/msw/setup.h, set wxUSE_MFC to 1, and recompile.
56 #endif
57
58 #ifdef new
59 #undef new
60 #endif
61
62 #include "stdafx.h"
63
64 #ifdef DrawText
65 #undef DrawText
66 #endif
67
68 #include "resource.h"
69
70 #include "mfctest.h"
71
72 /////////////////////////////////////////////////////////////////////////////
73
74 // theApp:
75 // Just creating this application object runs the whole application.
76 //
77 CTheApp theApp;
78
79 // wxWindows elements
80
81 // Define a new application type
82 class MyApp: public wxApp
83 { public:
84 bool OnInit(void);
85 wxFrame *CreateFrame(void);
86 };
87
88 class MyCanvas: public wxScrolledWindow
89 {
90 public:
91 MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size);
92 void OnPaint(wxPaintEvent& event);
93 void OnMouseEvent(wxMouseEvent& event);
94 DECLARE_EVENT_TABLE()
95 };
96
97 class MyChild: public wxFrame
98 {
99 public:
100 MyCanvas *canvas;
101 MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style);
102 ~MyChild(void);
103
104 void OnQuit(wxCommandEvent& event);
105 void OnNew(wxCommandEvent& event);
106 void OnActivate(wxActivateEvent& event);
107
108 DECLARE_EVENT_TABLE()
109 };
110
111 // For drawing lines in a canvas
112 long xpos = -1;
113 long ypos = -1;
114
115 // ID for the menu quit command
116 #define HELLO_QUIT 1
117 #define HELLO_NEW 2
118
119 DECLARE_APP(MyApp)
120 IMPLEMENT_APP(MyApp)
121
122 /////////////////////////////////////////////////////////////////////////////
123
124 // CMainWindow constructor:
125 // Create the window with the appropriate style, size, menu, etc.
126 //
127 CMainWindow::CMainWindow()
128 {
129 LoadAccelTable( "MainAccelTable" );
130 Create( NULL, "Hello Foundation Application",
131 WS_OVERLAPPEDWINDOW, rectDefault, NULL, "MainMenu" );
132 }
133
134 // OnPaint:
135 // This routine draws the string "Hello, Windows!" in the center of the
136 // client area. It is called whenever Windows sends a WM_PAINT message.
137 // Note that creating a CPaintDC automatically does a BeginPaint and
138 // an EndPaint call is done when it is destroyed at the end of this
139 // function. CPaintDC's constructor needs the window (this).
140 //
141 void CMainWindow::OnPaint()
142 {
143 CString s = "Hello, Windows!";
144 CPaintDC dc( this );
145 CRect rect;
146
147 GetClientRect( rect );
148 dc.SetTextAlign( TA_BASELINE | TA_CENTER );
149 dc.SetTextColor( ::GetSysColor( COLOR_WINDOWTEXT ) );
150 dc.SetBkMode(TRANSPARENT);
151 dc.TextOut( ( rect.right / 2 ), ( rect.bottom / 2 ),
152 s, s.GetLength() );
153 }
154
155 // OnAbout:
156 // This member function is called when a WM_COMMAND message with an
157 // IDM_ABOUT code is received by the CMainWindow class object. The
158 // message map below is responsible for this routing.
159 //
160 // We create a ClDialog object using the "AboutBox" resource (see
161 // hello.rc), and invoke it.
162 //
163 void CMainWindow::OnAbout()
164 {
165 CDialog about( "AboutBox", this );
166 about.DoModal();
167 }
168
169 void CMainWindow::OnTest()
170 {
171 wxMessageBox("This is a wxWindows message box.\nWe're about to create a new wxWindows frame.", "wxWindows", wxOK);
172 wxGetApp().CreateFrame();
173 }
174
175 // CMainWindow message map:
176 // Associate messages with member functions.
177 //
178 // It is implied that the ON_WM_PAINT macro expects a member function
179 // "void OnPaint()".
180 //
181 // It is implied that members connected with the ON_COMMAND macro
182 // receive no arguments and are void of return type, e.g., "void OnAbout()".
183 //
184 BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd )
185 //{{AFX_MSG_MAP( CMainWindow )
186 ON_WM_PAINT()
187 ON_COMMAND( IDM_ABOUT, OnAbout )
188 ON_COMMAND( IDM_TEST, OnTest )
189 //}}AFX_MSG_MAP
190 END_MESSAGE_MAP()
191
192 /////////////////////////////////////////////////////////////////////////////
193 // CTheApp
194
195 // InitInstance:
196 // When any CTheApp object is created, this member function is automatically
197 // called. Any data may be set up at this point.
198 //
199 // Also, the main window of the application should be created and shown here.
200 // Return TRUE if the initialization is successful.
201 //
202 BOOL CTheApp::InitInstance()
203 {
204 SetDialogBkColor(); // hook gray dialogs (was default in MFC V1)
205
206 wxEntry((WXHINSTANCE) m_hInstance, (WXHINSTANCE) m_hPrevInstance, m_lpCmdLine, m_nCmdShow, FALSE);
207
208 #if START_WITH_MFC_WINDOW
209 // Demonstrate creation of an initial MFC main window.
210 m_pMainWnd = new CMainWindow();
211 m_pMainWnd->ShowWindow( m_nCmdShow );
212 m_pMainWnd->UpdateWindow();
213 #else
214 // Demonstrate creation of an initial wxWindows main window.
215 // Wrap wxWindows window in a dummy MFC window and
216 // make the main window.
217 if (wxTheApp && wxTheApp->GetTopWindow())
218 {
219 m_pMainWnd = new CDummyWindow((HWND) wxTheApp->GetTopWindow()->GetHWND());
220 }
221 #endif
222
223 return TRUE;
224 }
225
226 int CTheApp::ExitInstance()
227 {
228 // OnExit isn't called by CleanUp so must be called explicitly.
229 wxTheApp->OnExit();
230 wxApp::CleanUp();
231
232 return CWinApp::ExitInstance();
233 }
234
235 // Override this to provide wxWindows message loop
236 // compatibility
237
238 BOOL CTheApp::PreTranslateMessage(MSG *msg)
239 {
240 if (wxTheApp && wxTheApp->ProcessMessage((WXMSG*) msg))
241 return TRUE;
242 else
243 return CWinApp::PreTranslateMessage(msg);
244 }
245
246 BOOL CTheApp::OnIdle(LONG lCount)
247 {
248 if (wxTheApp)
249 return wxTheApp->ProcessIdle();
250 else
251 return FALSE;
252 }
253
254 /*********************************************************************
255 * wxWindows elements
256 ********************************************************************/
257
258 bool MyApp::OnInit(void)
259 {
260 #if !START_WITH_MFC_WINDOW
261
262 // Exit app when the top level frame is deleted
263 SetExitOnFrameDelete(TRUE);
264
265 (void) CreateFrame();
266 #endif
267
268 return TRUE;
269 }
270
271 wxFrame *MyApp::CreateFrame(void)
272 {
273 MyChild *subframe = new MyChild(NULL, "Canvas Frame", wxPoint(10, 10), wxSize(300, 300),
274 wxDEFAULT_FRAME_STYLE);
275
276 subframe->SetTitle("wxWindows canvas frame");
277
278 // Give it a status line
279 subframe->CreateStatusBar();
280
281 // Make a menubar
282 wxMenu *file_menu = new wxMenu;
283
284 file_menu->Append(HELLO_NEW, "&New MFC Window");
285 file_menu->Append(HELLO_QUIT, "&Close");
286
287 wxMenuBar *menu_bar = new wxMenuBar;
288
289 menu_bar->Append(file_menu, "&File");
290
291 // Associate the menu bar with the frame
292 subframe->SetMenuBar(menu_bar);
293
294 int width, height;
295 subframe->GetClientSize(&width, &height);
296
297 MyCanvas *canvas = new MyCanvas(subframe, wxPoint(0, 0), wxSize(width, height));
298 canvas->SetCursor(wxCursor(wxCURSOR_PENCIL));
299 subframe->canvas = canvas;
300 subframe->Show(TRUE);
301
302 // Return the main frame window
303 return subframe;
304 }
305
306 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
307 EVT_PAINT(MyCanvas::OnPaint)
308 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
309 END_EVENT_TABLE()
310
311 // Define a constructor for my canvas
312 MyCanvas::MyCanvas(wxWindow *parent, const wxPoint& pos, const wxSize& size):
313 wxScrolledWindow(parent, -1, pos, size)
314 {
315 }
316
317 // Define the repainting behaviour
318 void MyCanvas::OnPaint(wxPaintEvent& event)
319 {
320 wxPaintDC dc(this);
321
322 dc.SetFont(* wxSWISS_FONT);
323 dc.SetPen(* wxGREEN_PEN);
324 dc.DrawLine(0, 0, 200, 200);
325 dc.DrawLine(200, 0, 0, 200);
326
327 dc.SetBrush(* wxCYAN_BRUSH);
328 dc.SetPen(* wxRED_PEN);
329 dc.DrawRectangle(100, 100, 100, 50);
330 dc.DrawRoundedRectangle(150, 150, 100, 50, 20);
331
332 dc.DrawEllipse(250, 250, 100, 50);
333 dc.DrawSpline(50, 200, 50, 100, 200, 10);
334 dc.DrawLine(50, 230, 200, 230);
335 dc.DrawText("This is a test string", 50, 230);
336 }
337
338 // This implements a tiny doodling program! Drag the mouse using
339 // the left button.
340 void MyCanvas::OnMouseEvent(wxMouseEvent& event)
341 {
342 wxClientDC dc(this);
343 dc.SetPen(* wxBLACK_PEN);
344 wxPoint pos = event.GetPosition();
345 if (xpos > -1 && ypos > -1 && event.Dragging())
346 {
347 dc.DrawLine(xpos, ypos, pos.x, pos.y);
348 }
349 xpos = pos.x;
350 ypos = pos.y;
351 }
352
353 BEGIN_EVENT_TABLE(MyChild, wxFrame)
354 EVT_MENU(HELLO_QUIT, MyChild::OnQuit)
355 EVT_MENU(HELLO_NEW, MyChild::OnNew)
356 EVT_ACTIVATE(MyChild::OnActivate)
357 END_EVENT_TABLE()
358
359 MyChild::MyChild(wxFrame *frame, const wxString& title, const wxPoint& pos, const wxSize& size, const long style):
360 wxFrame(frame, -1, title, pos, size, style)
361 {
362 canvas = NULL;
363 }
364
365 MyChild::~MyChild(void)
366 {
367 }
368
369 void MyChild::OnQuit(wxCommandEvent& event)
370 {
371 Close(TRUE);
372 }
373
374 void MyChild::OnNew(wxCommandEvent& event)
375 {
376 CMainWindow *mainWin = new CMainWindow();
377 mainWin->ShowWindow( TRUE );
378 mainWin->UpdateWindow();
379 }
380
381 void MyChild::OnActivate(wxActivateEvent& event)
382 {
383 if (event.GetActive() && canvas)
384 canvas->SetFocus();
385 }
386
387 // Dummy MFC window for specifying a valid main window to MFC, using
388 // a wxWindows HWND.
389 CDummyWindow::CDummyWindow(HWND hWnd):CWnd()
390 {
391 Attach(hWnd);
392 }
393
394 // Don't let the CWnd destructor delete the HWND
395 CDummyWindow::~CDummyWindow(void)
396 {
397 Detach();
398 }
399