flash.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: flash.cpp
  3. // Purpose: Sample showing integration of Flash ActiveX control
  4. // Author: Vadim Zeitlin
  5. // Created: 2009-01-13
  6. // Copyright: (c) 2009 Vadim Zeitlin
  7. // Licence: wxWindows licence
  8. /////////////////////////////////////////////////////////////////////////////
  9. /*
  10. Documentation for embedding Flash into anything other than a web browser is
  11. not easy to find, here is the tech note which provided most of the
  12. information used here: http://www.adobe.com/go/tn_12059
  13. */
  14. // ============================================================================
  15. // declarations
  16. // ============================================================================
  17. // ----------------------------------------------------------------------------
  18. // headers
  19. // ----------------------------------------------------------------------------
  20. #include "wx/wxprec.h"
  21. #ifdef __BORLANDC__
  22. #pragma hdrstop
  23. #endif
  24. #ifndef __WXMSW__
  25. #error "ActiveX controls are MSW-only"
  26. #endif
  27. #ifndef WX_PRECOMP
  28. #include "wx/wx.h"
  29. #endif
  30. #include "wx/cmdline.h"
  31. #include "wx/filename.h"
  32. #ifndef wxHAS_IMAGES_IN_RESOURCES
  33. #include "../sample.xpm"
  34. #endif
  35. #include "wx/msw/ole/activex.h"
  36. // we currently use VC-specific extensions in this sample, it could be
  37. // rewritten to avoid them if there is real interest in doing it but compiler
  38. // COM support in MSVC makes the code much simpler to understand
  39. #ifndef __VISUALC__
  40. #error "This sample requires Microsoft Visual C++ compiler COM extensions"
  41. #endif
  42. // import Flash ActiveX control by using its (standard) type library UUID
  43. //
  44. // no_auto_exclude is needed to import IServiceProvider interface defined in
  45. // this type library even though its name conflicts with a standard Windows
  46. // interface with the same name
  47. #import "libid:D27CDB6B-AE6D-11CF-96B8-444553540000" no_auto_exclude
  48. using namespace ShockwaveFlashObjects;
  49. const CLSID CLSID_ShockwaveFlash = __uuidof(ShockwaveFlash);
  50. const IID IID_IShockwaveFlash = __uuidof(IShockwaveFlash);
  51. inline wxString bstr2wx(const _bstr_t& bstr)
  52. {
  53. return wxString(static_cast<const wchar_t *>(bstr));
  54. }
  55. inline _bstr_t wx2bstr(const wxString& str)
  56. {
  57. return _bstr_t(str.wc_str());
  58. }
  59. // ----------------------------------------------------------------------------
  60. // constants
  61. // ----------------------------------------------------------------------------
  62. // taken from type library
  63. namespace
  64. {
  65. const int FLASH_DISPID_ONREADYSTATECHANGE = -609; // DISPID_ONREADYSTATECHANGE
  66. const int FLASH_DISPID_ONPROGRESS = 0x7a6;
  67. const int FLASH_DISPID_FSCOMMAND = 0x96;
  68. const int FLASH_DISPID_FLASHCALL = 0xc5;
  69. enum FlashState
  70. {
  71. FlashState_Unknown = -1,
  72. FlashState_Loading,
  73. FlashState_Uninitialized,
  74. FlashState_Loaded,
  75. FlashState_Interactive,
  76. FlashState_Complete,
  77. FlashState_Max
  78. };
  79. } // anonymous namespace
  80. // ----------------------------------------------------------------------------
  81. // private classes
  82. // ----------------------------------------------------------------------------
  83. // Define a new application type, each program should derive a class from wxApp
  84. class FlashApp : public wxApp
  85. {
  86. public:
  87. FlashApp() { }
  88. virtual bool OnInit();
  89. virtual void OnInitCmdLine(wxCmdLineParser& parser);
  90. virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
  91. virtual bool OnExceptionInMainLoop();
  92. private:
  93. wxString m_swf;
  94. wxDECLARE_NO_COPY_CLASS(FlashApp);
  95. };
  96. // Define a new frame type: this is going to be our main frame
  97. class FlashFrame : public wxFrame
  98. {
  99. public:
  100. // ctor takes ownership of the pointer which must be non-NULL and opens the
  101. // given SWF file if it's non-empty
  102. FlashFrame(IShockwaveFlash *flash, const wxString& swf);
  103. virtual ~FlashFrame();
  104. void SetMovie(const wxString& movie);
  105. void Play();
  106. void Stop();
  107. private:
  108. enum
  109. {
  110. Flash_Play = 100,
  111. Flash_Get,
  112. Flash_Set,
  113. Flash_Call,
  114. Flash_CallWithArg
  115. };
  116. void OnOpen(wxCommandEvent& event);
  117. void OnQuit(wxCommandEvent& event);
  118. void OnAbout(wxCommandEvent& event);
  119. void OnPlay(wxCommandEvent&) { Play(); }
  120. void OnStop(wxCommandEvent&) { Stop(); }
  121. void OnBack(wxCommandEvent& event);
  122. void OnForward(wxCommandEvent& event);
  123. void OnInfo(wxCommandEvent& event);
  124. void OnVarGet(wxCommandEvent& event);
  125. void OnVarSet(wxCommandEvent& event);
  126. void OnCall(wxCommandEvent& event);
  127. void OnCallWithArg(wxCommandEvent& event);
  128. void OnActiveXEvent(wxActiveXEvent& event);
  129. // give an error message if hr is not S_OK
  130. void CheckFlashCall(HRESULT hr, const char *func);
  131. // return the name of the Flash control state
  132. wxString GetFlashStateString(int state);
  133. // call CallFunction() with a single argument of the type specified by
  134. // argtype or without any arguments if it is empty
  135. void CallFlashFunc(const wxString& argtype,
  136. const wxString& func,
  137. const wxString& arg = wxString());
  138. const IShockwaveFlashPtr m_flash;
  139. wxLog *m_oldLog;
  140. wxString m_swf;
  141. FlashState m_state;
  142. wxTextCtrl *m_varname,
  143. *m_varvalue,
  144. *m_funcname,
  145. *m_funcarg;
  146. wxDECLARE_EVENT_TABLE();
  147. wxDECLARE_NO_COPY_CLASS(FlashFrame);
  148. };
  149. // ----------------------------------------------------------------------------
  150. // event tables and other macros for wxWidgets
  151. // ----------------------------------------------------------------------------
  152. wxBEGIN_EVENT_TABLE(FlashFrame, wxFrame)
  153. EVT_MENU(wxID_OPEN, FlashFrame::OnOpen)
  154. EVT_MENU(wxID_EXIT, FlashFrame::OnQuit)
  155. EVT_MENU(wxID_ABOUT, FlashFrame::OnAbout)
  156. EVT_BUTTON(Flash_Play, FlashFrame::OnPlay)
  157. EVT_BUTTON(wxID_STOP, FlashFrame::OnStop)
  158. EVT_BUTTON(wxID_BACKWARD, FlashFrame::OnBack)
  159. EVT_BUTTON(wxID_FORWARD, FlashFrame::OnForward)
  160. EVT_BUTTON(wxID_INFO, FlashFrame::OnInfo)
  161. EVT_BUTTON(Flash_Get, FlashFrame::OnVarGet)
  162. EVT_BUTTON(Flash_Set, FlashFrame::OnVarSet)
  163. EVT_BUTTON(Flash_Call, FlashFrame::OnCall)
  164. EVT_BUTTON(Flash_CallWithArg, FlashFrame::OnCallWithArg)
  165. EVT_ACTIVEX(wxID_ANY, FlashFrame::OnActiveXEvent)
  166. wxEND_EVENT_TABLE()
  167. IMPLEMENT_APP(FlashApp)
  168. // ============================================================================
  169. // implementation
  170. // ============================================================================
  171. // ----------------------------------------------------------------------------
  172. // the application class
  173. // ----------------------------------------------------------------------------
  174. void FlashApp::OnInitCmdLine(wxCmdLineParser& parser)
  175. {
  176. wxApp::OnInitCmdLine(parser);
  177. parser.AddParam("SWF file to play",
  178. wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
  179. }
  180. bool FlashApp::OnCmdLineParsed(wxCmdLineParser& parser)
  181. {
  182. if ( parser.GetParamCount() )
  183. m_swf = parser.GetParam(0);
  184. return wxApp::OnCmdLineParsed(parser);
  185. }
  186. bool FlashApp::OnInit()
  187. {
  188. if ( !wxApp::OnInit() )
  189. return false;
  190. IShockwaveFlash *flash = NULL;
  191. HRESULT hr = ::CoCreateInstance
  192. (
  193. CLSID_ShockwaveFlash,
  194. NULL,
  195. CLSCTX_INPROC_SERVER,
  196. IID_IShockwaveFlash,
  197. (void **)&flash
  198. );
  199. if ( FAILED(hr) )
  200. {
  201. wxLogSysError(hr, "Failed to create Flash ActiveX control");
  202. return false;
  203. }
  204. new FlashFrame(flash, m_swf);
  205. return true;
  206. }
  207. bool FlashApp::OnExceptionInMainLoop()
  208. {
  209. try
  210. {
  211. throw;
  212. }
  213. catch ( _com_error& ce )
  214. {
  215. wxLogMessage("COM exception: %s", ce.ErrorMessage());
  216. return true;
  217. }
  218. catch ( ... )
  219. {
  220. throw;
  221. }
  222. }
  223. // ----------------------------------------------------------------------------
  224. // main frame creation
  225. // ----------------------------------------------------------------------------
  226. // frame constructor
  227. FlashFrame::FlashFrame(IShockwaveFlash *flash, const wxString& swf)
  228. : wxFrame(NULL, wxID_ANY, "wxWidgets Flash sample"),
  229. m_flash(flash, false /* take ownership */),
  230. m_swf(swf),
  231. m_state(FlashState_Unknown)
  232. {
  233. // set the frame icon
  234. SetIcon(wxICON(sample));
  235. // create the new log target before doing anything with the Flash that
  236. // could result in log messages
  237. wxTextCtrl * const log = new wxTextCtrl(this, wxID_ANY, "",
  238. wxDefaultPosition, wxSize(-1, 100),
  239. wxTE_MULTILINE);
  240. m_oldLog = wxLog::SetActiveTarget(new wxLogTextCtrl(log));
  241. #if wxUSE_MENUS
  242. // create a menu bar
  243. wxMenu *fileMenu = new wxMenu;
  244. fileMenu->Append(wxID_OPEN);
  245. fileMenu->AppendSeparator();
  246. fileMenu->Append(wxID_EXIT);
  247. wxMenu *helpMenu = new wxMenu;
  248. helpMenu->Append(wxID_ABOUT);
  249. wxMenuBar *menuBar = new wxMenuBar();
  250. menuBar->Append(fileMenu, "&File");
  251. menuBar->Append(helpMenu, "&Help");
  252. SetMenuBar(menuBar);
  253. #endif // wxUSE_MENUS
  254. #if wxUSE_STATUSBAR
  255. CreateStatusBar(2);
  256. SetStatusText("Welcome to wxWidgets Flash embedding sample");
  257. SetStatusText("No loaded file", 1);
  258. #endif // wxUSE_STATUSBAR
  259. wxPanel * const panel = new wxPanel(this);
  260. wxSizer * const sizerPanel = new wxBoxSizer(wxVERTICAL);
  261. wxWindow * const activeXParent = new wxWindow(panel, wxID_ANY,
  262. wxDefaultPosition,
  263. wxSize(300, 200));
  264. new wxActiveXContainer(activeXParent, IID_IShockwaveFlash, flash);
  265. if ( !swf.empty() )
  266. SetMovie(swf);
  267. sizerPanel->Add(activeXParent,
  268. wxSizerFlags(1).Expand().Border());
  269. const wxSizerFlags flagsHorz(wxSizerFlags().Centre().HorzBorder());
  270. wxSizer * const sizerBtns = new wxBoxSizer(wxHORIZONTAL);
  271. sizerBtns->Add(new wxButton(panel, wxID_BACKWARD), flagsHorz);
  272. sizerBtns->Add(new wxButton(panel, Flash_Play, "&Play"), flagsHorz);
  273. sizerBtns->Add(new wxButton(panel, wxID_STOP), flagsHorz);
  274. sizerBtns->Add(new wxButton(panel, wxID_FORWARD), flagsHorz);
  275. sizerBtns->AddSpacer(20);
  276. sizerBtns->Add(new wxButton(panel, wxID_INFO), flagsHorz);
  277. sizerPanel->Add(sizerBtns, wxSizerFlags().Center().Border());
  278. wxSizer * const sizerVar = new wxBoxSizer(wxHORIZONTAL);
  279. sizerVar->Add(new wxStaticText(panel, wxID_ANY, "Variable &name:"),
  280. flagsHorz);
  281. m_varname = new wxTextCtrl(panel, wxID_ANY);
  282. sizerVar->Add(m_varname, flagsHorz);
  283. sizerVar->Add(new wxStaticText(panel, wxID_ANY, "&value:"),
  284. flagsHorz);
  285. m_varvalue = new wxTextCtrl(panel, wxID_ANY);
  286. sizerVar->Add(m_varvalue, flagsHorz);
  287. sizerVar->AddSpacer(10);
  288. sizerVar->Add(new wxButton(panel, Flash_Get, "&Get"), flagsHorz);
  289. sizerVar->Add(new wxButton(panel, Flash_Set, "&Set"), flagsHorz);
  290. sizerPanel->Add(sizerVar, wxSizerFlags().Center().Border());
  291. wxSizer * const sizerCall = new wxBoxSizer(wxHORIZONTAL);
  292. sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&Function name:"),
  293. flagsHorz);
  294. m_funcname = new wxTextCtrl(panel, wxID_ANY);
  295. sizerCall->Add(m_funcname, flagsHorz);
  296. sizerCall->Add(new wxButton(panel, Flash_Call, "&Call"), flagsHorz);
  297. sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&argument:"),
  298. flagsHorz);
  299. m_funcarg = new wxTextCtrl(panel, wxID_ANY);
  300. sizerCall->Add(m_funcarg, flagsHorz);
  301. sizerCall->Add(new wxButton(panel, Flash_CallWithArg, "Call &with arg"),
  302. flagsHorz);
  303. sizerPanel->Add(sizerCall, wxSizerFlags().Center().Border());
  304. panel->SetSizer(sizerPanel);
  305. wxSizer * const sizerFrame = new wxBoxSizer(wxVERTICAL);
  306. sizerFrame->Add(panel, wxSizerFlags(2).Expand());
  307. sizerFrame->Add(log, wxSizerFlags(1).Expand());
  308. SetSizerAndFit(sizerFrame);
  309. Show();
  310. m_flash->PutAllowScriptAccess(L"always");
  311. wxLogMessage("Script access changed to \"%s\"",
  312. bstr2wx(m_flash->GetAllowScriptAccess()));
  313. }
  314. FlashFrame::~FlashFrame()
  315. {
  316. delete wxLog::SetActiveTarget(m_oldLog);
  317. }
  318. // ----------------------------------------------------------------------------
  319. // Flash API wrappers
  320. // ----------------------------------------------------------------------------
  321. void FlashFrame::CheckFlashCall(HRESULT hr, const char *func)
  322. {
  323. if ( FAILED(hr) )
  324. {
  325. wxLogSysError(hr, "Call to IShockwaveFlash::%s() failed", func);
  326. }
  327. }
  328. void FlashFrame::CallFlashFunc(const wxString& argtype,
  329. const wxString& func,
  330. const wxString& arg)
  331. {
  332. wxString args;
  333. if ( !argtype.empty() )
  334. {
  335. args = wxString::Format("<%s>%s</%s>", argtype, arg, argtype);
  336. }
  337. // take care with XML formatting: there should be no spaces in it or the
  338. // call would fail!
  339. wxString request = wxString::Format
  340. (
  341. "<invoke name=\"%s\" returntype=\"xml\">"
  342. "<arguments>"
  343. "%s"
  344. "</arguments>"
  345. "</invoke>",
  346. func,
  347. args
  348. );
  349. wxLogMessage("%s(%s) returned \"%s\"",
  350. func, args,
  351. bstr2wx(m_flash->CallFunction(wx2bstr(request))));
  352. }
  353. wxString FlashFrame::GetFlashStateString(int state)
  354. {
  355. static const char *knownStates[] =
  356. {
  357. "Loading", "Uninitialized", "Loaded", "Interactive", "Complete",
  358. };
  359. if ( state >= 0 && state < WXSIZEOF(knownStates) )
  360. return knownStates[state];
  361. return wxString::Format("unknown state (%d)", state);
  362. }
  363. void FlashFrame::SetMovie(const wxString& movie)
  364. {
  365. // Flash doesn't like relative file names
  366. wxFileName fn(movie);
  367. fn.MakeAbsolute();
  368. const wxString swf = fn.GetFullPath();
  369. if ( swf == m_swf )
  370. m_flash->PutMovie(L"");
  371. else
  372. m_swf = swf;
  373. m_flash->PutMovie(m_swf.wc_str());
  374. SetStatusText("Loaded \"" + m_swf + '"', 1);
  375. }
  376. void FlashFrame::Play()
  377. {
  378. CheckFlashCall(m_flash->Play(), "Play");
  379. }
  380. void FlashFrame::Stop()
  381. {
  382. CheckFlashCall(m_flash->Stop(), "Stop");
  383. }
  384. // ----------------------------------------------------------------------------
  385. // event handlers
  386. // ----------------------------------------------------------------------------
  387. void FlashFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
  388. {
  389. wxString swf = wxLoadFileSelector("Flash movie", ".swf", m_swf, this);
  390. if ( swf.empty() )
  391. return;
  392. SetMovie(swf);
  393. }
  394. void FlashFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  395. {
  396. // true is to force the frame to close
  397. Close(true);
  398. }
  399. void FlashFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  400. {
  401. wxMessageBox("Flash ActiveX control embedding sample\n"
  402. "\n"
  403. "(c) 2009 Vadim Zeitlin",
  404. "About " + GetTitle(),
  405. wxOK | wxICON_INFORMATION,
  406. this);
  407. }
  408. void FlashFrame::OnActiveXEvent(wxActiveXEvent& event)
  409. {
  410. switch ( event.GetDispatchId() )
  411. {
  412. case FLASH_DISPID_ONREADYSTATECHANGE:
  413. {
  414. const int state = event[0].GetInteger();
  415. if ( state != m_state )
  416. {
  417. wxLogMessage("State changed to %s",
  418. GetFlashStateString(state));
  419. if ( state >= 0 && state < FlashState_Max )
  420. m_state = static_cast<FlashState>(state);
  421. else
  422. m_state = FlashState_Unknown;
  423. }
  424. }
  425. break;
  426. case FLASH_DISPID_ONPROGRESS:
  427. wxLogMessage("Progress: %d%%", event[0].GetInteger());
  428. break;
  429. case FLASH_DISPID_FSCOMMAND:
  430. wxLogMessage("Flash command %s(%s)",
  431. event[0].GetString(), event[1].GetString());
  432. break;
  433. case FLASH_DISPID_FLASHCALL:
  434. wxLogMessage("Flash request \"%s\"", event[0].GetString());
  435. break;
  436. default:
  437. wxLogMessage("Unknown event %ld", event.GetDispatchId());
  438. }
  439. event.Skip();
  440. }
  441. void FlashFrame::OnBack(wxCommandEvent& WXUNUSED(event))
  442. {
  443. CheckFlashCall(m_flash->Back(), "Back");
  444. }
  445. void FlashFrame::OnForward(wxCommandEvent& WXUNUSED(event))
  446. {
  447. CheckFlashCall(m_flash->Forward(), "Forward");
  448. }
  449. void FlashFrame::OnInfo(wxCommandEvent& WXUNUSED(event))
  450. {
  451. const int state = m_flash->GetReadyState();
  452. wxString msg = "State: " + GetFlashStateString(state);
  453. if ( state == FlashState_Complete )
  454. {
  455. msg += wxString::Format(", frame: %ld/%ld",
  456. m_flash->GetFrameNum() + 1,
  457. m_flash->GetTotalFrames());
  458. }
  459. if ( m_flash->IsPlaying() )
  460. msg += ", playing";
  461. wxLogMessage("%s", msg);
  462. }
  463. void FlashFrame::OnVarGet(wxCommandEvent& WXUNUSED(event))
  464. {
  465. m_varvalue->SetValue(bstr2wx(
  466. m_flash->GetVariable(wx2bstr(m_varname->GetValue()))));
  467. }
  468. void FlashFrame::OnVarSet(wxCommandEvent& WXUNUSED(event))
  469. {
  470. m_flash->SetVariable(wx2bstr(m_varname->GetValue()),
  471. wx2bstr(m_varvalue->GetValue()));
  472. }
  473. void FlashFrame::OnCall(wxCommandEvent& WXUNUSED(event))
  474. {
  475. CallFlashFunc("", m_funcname->GetValue());
  476. }
  477. void FlashFrame::OnCallWithArg(wxCommandEvent& WXUNUSED(event))
  478. {
  479. CallFlashFunc("string", m_funcname->GetValue(), m_funcarg->GetValue());
  480. }