mfctest.cpp 11 KB

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