diff --git a/docs/doxygen/mainpages/samples.h b/docs/doxygen/mainpages/samples.h
index 90f8776afb..bfec6ec988 100644
--- a/docs/doxygen/mainpages/samples.h
+++ b/docs/doxygen/mainpages/samples.h
@@ -78,6 +78,7 @@ TODO: Organize them in a more human-readable way.
@li @sample{event}
@li @sample{except}
@li @sample{exec}
+@li @sample{flash}
@li @sample{font}
@li @sample{grid}
@@ -407,6 +408,23 @@ wxProcess::Exists().
@sampledir{exec}
+@section page_samples_flash Flash Sample
+
+The flash sample demonstrates embedding of Adobe Flash into a wxWidgets
+program. Currently it only works under Windows as it uses the Flash ActiveX
+control to achieve this but we hope to be able to extend it to also work under
+other platforms in the future. The sample also currently requires Microsoft
+Visual C++ compiler as it uses COM support extensions specific to this
+compiler.
+
+The sample comes with 2 Flash files (SWF), showing a simple Flash animation
+which can be controlled using the "Play", "Stop" and "Back"/"Forward" buttons
+in the sample as well as a Flash form which shows how Flash and wxWidgets
+program can exchange data: calling "GetText" function without arguments returns
+the text of the text control defined inside Flash and calling "SetText" with an
+argument sets the control contents to the given string. Finally clicking on the
+button generates an event which is caught by the C++ program.
+
@section page_samples_font Font Sample
The font sample demonstrates wxFont,
diff --git a/samples/flash/animation.swf b/samples/flash/animation.swf
new file mode 100644
index 0000000000..acb578f63e
Binary files /dev/null and b/samples/flash/animation.swf differ
diff --git a/samples/flash/flash.bkl b/samples/flash/flash.bkl
new file mode 100644
index 0000000000..f059b18c74
--- /dev/null
+++ b/samples/flash/flash.bkl
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+ flash.cpp
+ media
+ core
+ base
+ wx06
+
+
diff --git a/samples/flash/flash.cpp b/samples/flash/flash.cpp
new file mode 100644
index 0000000000..e0467ef5b9
--- /dev/null
+++ b/samples/flash/flash.cpp
@@ -0,0 +1,597 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name: flash.cpp
+// Purpose: Sample showing integration of Flash ActiveX control
+// Author: Vadim Zeitlin
+// Created: 2009-01-13
+// RCS-ID: $Id$
+// Copyright: (c) 2009 Vadim Zeitlin
+// Licence: wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+ Documentation for embedding Flash into anything other than a web browser is
+ not easy to find, here is the tech note which provided most of the
+ information used here: http://www.adobe.com/go/tn_12059
+ */
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#ifndef __WXMSW__
+ #error "ActiveX controls are MSW-only"
+#endif
+
+#ifndef WX_PRECOMP
+ #include "wx/wx.h"
+#endif
+
+#include "wx/cmdline.h"
+#include "wx/filename.h"
+
+#if !defined(__WXMSW__) && !defined(__WXPM__)
+ #include "../sample.xpm"
+#endif
+
+#include "wx/msw/ole/activex.h"
+
+// we currently use VC-specific extensions in this sample, it could be
+// rewritten to avoid them if there is real interest in doing it but compiler
+// COM support in MSVC makes the code much simpler to understand
+#ifndef __VISUALC__
+ #error "This sample requires Microsoft Visual C++ compiler COM extensions"
+#endif
+
+// import Flash ActiveX control by using its (standard) type library UUID
+//
+// no_auto_exclude is needed to import IServiceProvider interface defined in
+// this type library even though its name conflicts with a standard Windows
+// interface with the same name
+#import "libid:D27CDB6B-AE6D-11CF-96B8-444553540000" no_auto_exclude
+
+using namespace ShockwaveFlashObjects;
+
+const CLSID CLSID_ShockwaveFlash = __uuidof(ShockwaveFlash);
+const IID IID_IShockwaveFlash = __uuidof(IShockwaveFlash);
+
+inline wxString bstr2wx(const _bstr_t& bstr)
+{
+ return wxString(static_cast(bstr));
+}
+
+inline _bstr_t wx2bstr(const wxString& str)
+{
+ return _bstr_t(str.wc_str());
+}
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// taken from type library
+namespace
+{
+
+const int FLASH_DISPID_ONREADYSTATECHANGE = -609; // DISPID_ONREADYSTATECHANGE
+const int FLASH_DISPID_ONPROGRESS = 0x7a6;
+const int FLASH_DISPID_FSCOMMAND = 0x96;
+const int FLASH_DISPID_FLASHCALL = 0xc5;
+
+enum FlashState
+{
+ FlashState_Unknown = -1,
+ FlashState_Loading,
+ FlashState_Uninitialized,
+ FlashState_Loaded,
+ FlashState_Interactive,
+ FlashState_Complete,
+ FlashState_Max
+};
+
+} // anonymous namespace
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+// Define a new application type, each program should derive a class from wxApp
+class FlashApp : public wxApp
+{
+public:
+ FlashApp() { }
+
+ virtual bool OnInit();
+
+ virtual void OnInitCmdLine(wxCmdLineParser& parser);
+ virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
+
+ virtual bool OnExceptionInMainLoop();
+
+private:
+ wxString m_swf;
+
+ DECLARE_NO_COPY_CLASS(FlashApp)
+};
+
+// Define a new frame type: this is going to be our main frame
+class FlashFrame : public wxFrame
+{
+public:
+ // ctor takes ownership of the pointer which must be non-NULL and opens the
+ // given SWF file if it's non-empty
+ FlashFrame(IShockwaveFlash *flash, const wxString& swf);
+ virtual ~FlashFrame();
+
+ void SetMovie(const wxString& movie);
+
+ void Play();
+ void Stop();
+
+private:
+ enum
+ {
+ Flash_Play = 100,
+ Flash_Get,
+ Flash_Set,
+ Flash_Call,
+ Flash_CallWithArg
+ };
+
+ void OnOpen(wxCommandEvent& event);
+ void OnQuit(wxCommandEvent& event);
+ void OnAbout(wxCommandEvent& event);
+
+ void OnPlay(wxCommandEvent&) { Play(); }
+ void OnStop(wxCommandEvent&) { Stop(); }
+ void OnBack(wxCommandEvent& event);
+ void OnForward(wxCommandEvent& event);
+ void OnInfo(wxCommandEvent& event);
+ void OnVarGet(wxCommandEvent& event);
+ void OnVarSet(wxCommandEvent& event);
+ void OnCall(wxCommandEvent& event);
+ void OnCallWithArg(wxCommandEvent& event);
+
+ void OnActiveXEvent(wxActiveXEvent& event);
+
+ // give an error message if hr is not S_OK
+ void CheckFlashCall(HRESULT hr, const char *func);
+
+ // return the name of the Flash control state
+ wxString GetFlashStateString(int state);
+
+ // call CallFunction() with a single argument of the type specified by
+ // argtype or without any arguments if it is empty
+ void CallFlashFunc(const wxString& argtype,
+ const wxString& func,
+ const wxString& arg = wxString());
+
+
+ const IShockwaveFlashPtr m_flash;
+ wxLog *m_oldLog;
+ wxString m_swf;
+ FlashState m_state;
+
+ wxTextCtrl *m_varname,
+ *m_varvalue,
+ *m_funcname,
+ *m_funcarg;
+
+ DECLARE_EVENT_TABLE()
+ DECLARE_NO_COPY_CLASS(FlashFrame)
+};
+
+// ----------------------------------------------------------------------------
+// event tables and other macros for wxWidgets
+// ----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(FlashFrame, wxFrame)
+ EVT_MENU(wxID_OPEN, FlashFrame::OnOpen)
+ EVT_MENU(wxID_EXIT, FlashFrame::OnQuit)
+ EVT_MENU(wxID_ABOUT, FlashFrame::OnAbout)
+
+ EVT_BUTTON(Flash_Play, FlashFrame::OnPlay)
+ EVT_BUTTON(wxID_STOP, FlashFrame::OnStop)
+ EVT_BUTTON(wxID_BACKWARD, FlashFrame::OnBack)
+ EVT_BUTTON(wxID_FORWARD, FlashFrame::OnForward)
+
+ EVT_BUTTON(wxID_INFO, FlashFrame::OnInfo)
+ EVT_BUTTON(Flash_Get, FlashFrame::OnVarGet)
+ EVT_BUTTON(Flash_Set, FlashFrame::OnVarSet)
+ EVT_BUTTON(Flash_Call, FlashFrame::OnCall)
+ EVT_BUTTON(Flash_CallWithArg, FlashFrame::OnCallWithArg)
+
+ EVT_ACTIVEX(wxID_ANY, FlashFrame::OnActiveXEvent)
+END_EVENT_TABLE()
+
+IMPLEMENT_APP(FlashApp)
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// the application class
+// ----------------------------------------------------------------------------
+
+void FlashApp::OnInitCmdLine(wxCmdLineParser& parser)
+{
+ wxApp::OnInitCmdLine(parser);
+
+ parser.AddParam("SWF file to play",
+ wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL);
+}
+
+bool FlashApp::OnCmdLineParsed(wxCmdLineParser& parser)
+{
+ if ( parser.GetParamCount() )
+ m_swf = parser.GetParam(0);
+
+ return wxApp::OnCmdLineParsed(parser);
+}
+
+bool FlashApp::OnInit()
+{
+ if ( !wxApp::OnInit() )
+ return false;
+
+ IShockwaveFlash *flash = NULL;
+ HRESULT hr = ::CoCreateInstance
+ (
+ CLSID_ShockwaveFlash,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IShockwaveFlash,
+ (void **)&flash
+ );
+ if ( FAILED(hr) )
+ {
+ wxLogSysError(hr, "Failed to create Flash ActiveX control");
+ return false;
+ }
+
+ new FlashFrame(flash, m_swf);
+
+ return true;
+}
+
+bool FlashApp::OnExceptionInMainLoop()
+{
+ try
+ {
+ throw;
+ }
+ catch ( _com_error& ce )
+ {
+ wxLogMessage("COM exception: %s", ce.ErrorMessage());
+
+ return true;
+ }
+ catch ( ... )
+ {
+ throw;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// main frame creation
+// ----------------------------------------------------------------------------
+
+// frame constructor
+FlashFrame::FlashFrame(IShockwaveFlash *flash, const wxString& swf)
+ : wxFrame(NULL, wxID_ANY, "wxWidgets Flash sample"),
+ m_flash(flash, false /* take ownership */),
+ m_swf(swf),
+ m_state(FlashState_Unknown)
+{
+ // set the frame icon
+ SetIcon(wxICON(sample));
+
+ // create the new log target before doing anything with the Flash that
+ // could result in log messages
+ wxTextCtrl * const log = new wxTextCtrl(this, wxID_ANY, "",
+ wxDefaultPosition, wxSize(-1, 100),
+ wxTE_MULTILINE);
+ m_oldLog = wxLog::SetActiveTarget(new wxLogTextCtrl(log));
+
+#if wxUSE_MENUS
+ // create a menu bar
+ wxMenu *fileMenu = new wxMenu;
+ fileMenu->Append(wxID_OPEN);
+ fileMenu->AppendSeparator();
+ fileMenu->Append(wxID_EXIT);
+
+ wxMenu *helpMenu = new wxMenu;
+ helpMenu->Append(wxID_ABOUT);
+
+ wxMenuBar *menuBar = new wxMenuBar();
+ menuBar->Append(fileMenu, "&File");
+ menuBar->Append(helpMenu, "&Help");
+ SetMenuBar(menuBar);
+#endif // wxUSE_MENUS
+
+#if wxUSE_STATUSBAR
+ CreateStatusBar(2);
+ SetStatusText("Welcome to wxWidgets Flash embedding sample");
+ SetStatusText("No loaded file", 1);
+#endif // wxUSE_STATUSBAR
+
+ wxPanel * const panel = new wxPanel(this);
+ wxSizer * const sizerPanel = new wxBoxSizer(wxVERTICAL);
+ wxWindow * const activeXParent = new wxWindow(panel, wxID_ANY,
+ wxDefaultPosition,
+ wxSize(300, 200));
+ new wxActiveXContainer(activeXParent, IID_IShockwaveFlash, flash);
+ if ( !swf.empty() )
+ SetMovie(swf);
+
+ sizerPanel->Add(activeXParent,
+ wxSizerFlags(1).Expand().Border());
+
+ const wxSizerFlags flagsHorz(wxSizerFlags().Centre().HorzBorder());
+
+ wxSizer * const sizerBtns = new wxBoxSizer(wxHORIZONTAL);
+ sizerBtns->Add(new wxButton(panel, wxID_BACKWARD), flagsHorz);
+ sizerBtns->Add(new wxButton(panel, Flash_Play, "&Play"), flagsHorz);
+ sizerBtns->Add(new wxButton(panel, wxID_STOP), flagsHorz);
+ sizerBtns->Add(new wxButton(panel, wxID_FORWARD), flagsHorz);
+ sizerBtns->AddSpacer(20);
+ sizerBtns->Add(new wxButton(panel, wxID_INFO), flagsHorz);
+ sizerPanel->Add(sizerBtns, wxSizerFlags().Center().Border());
+
+ wxSizer * const sizerVar = new wxBoxSizer(wxHORIZONTAL);
+ sizerVar->Add(new wxStaticText(panel, wxID_ANY, "Variable &name:"),
+ flagsHorz);
+ m_varname = new wxTextCtrl(panel, wxID_ANY);
+ sizerVar->Add(m_varname, flagsHorz);
+ sizerVar->Add(new wxStaticText(panel, wxID_ANY, "&value:"),
+ flagsHorz);
+ m_varvalue = new wxTextCtrl(panel, wxID_ANY);
+ sizerVar->Add(m_varvalue, flagsHorz);
+ sizerVar->AddSpacer(10);
+ sizerVar->Add(new wxButton(panel, Flash_Get, "&Get"), flagsHorz);
+ sizerVar->Add(new wxButton(panel, Flash_Set, "&Set"), flagsHorz);
+ sizerPanel->Add(sizerVar, wxSizerFlags().Center().Border());
+
+ wxSizer * const sizerCall = new wxBoxSizer(wxHORIZONTAL);
+ sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&Function name:"),
+ flagsHorz);
+ m_funcname = new wxTextCtrl(panel, wxID_ANY);
+ sizerCall->Add(m_funcname, flagsHorz);
+ sizerCall->Add(new wxButton(panel, Flash_Call, "&Call"), flagsHorz);
+ sizerCall->Add(new wxStaticText(panel, wxID_ANY, "&argument:"),
+ flagsHorz);
+ m_funcarg = new wxTextCtrl(panel, wxID_ANY);
+ sizerCall->Add(m_funcarg, flagsHorz);
+ sizerCall->Add(new wxButton(panel, Flash_CallWithArg, "Call &with arg"),
+ flagsHorz);
+ sizerPanel->Add(sizerCall, wxSizerFlags().Center().Border());
+
+ panel->SetSizer(sizerPanel);
+
+ wxSizer * const sizerFrame = new wxBoxSizer(wxVERTICAL);
+ sizerFrame->Add(panel, wxSizerFlags(2).Expand());
+ sizerFrame->Add(log, wxSizerFlags(1).Expand());
+ SetSizerAndFit(sizerFrame);
+
+ Show();
+
+ m_flash->PutAllowScriptAccess(L"always");
+ wxLogMessage("Script access changed to \"%s\"",
+ bstr2wx(m_flash->GetAllowScriptAccess()));
+}
+
+FlashFrame::~FlashFrame()
+{
+ delete wxLog::SetActiveTarget(m_oldLog);
+}
+
+// ----------------------------------------------------------------------------
+// Flash API wrappers
+// ----------------------------------------------------------------------------
+
+void FlashFrame::CheckFlashCall(HRESULT hr, const char *func)
+{
+ if ( FAILED(hr) )
+ {
+ wxLogSysError(hr, "Call to IShockwaveFlash::%s() failed", func);
+ }
+}
+
+void FlashFrame::CallFlashFunc(const wxString& argtype,
+ const wxString& func,
+ const wxString& arg)
+{
+ wxString args;
+ if ( !argtype.empty() )
+ {
+ args = wxString::Format("<%s>%s%s>", argtype, arg, argtype);
+ }
+
+ // take care with XML formatting: there should be no spaces in it or the
+ // call would fail!
+ wxString request = wxString::Format
+ (
+ ""
+ ""
+ "%s"
+ ""
+ "",
+ func,
+ args
+ );
+
+ wxLogMessage("%s(%s) returned \"%s\"",
+ func, args,
+ bstr2wx(m_flash->CallFunction(wx2bstr(request))));
+}
+
+wxString FlashFrame::GetFlashStateString(int state)
+{
+ static const char *knownStates[] =
+ {
+ "Loading", "Uninitialized", "Loaded", "Interactive", "Complete",
+ };
+
+ if ( state >= 0 && state < WXSIZEOF(knownStates) )
+ return knownStates[state];
+
+ return wxString::Format("unknown state (%d)", state);
+}
+
+void FlashFrame::SetMovie(const wxString& movie)
+{
+ // Flash doesn't like relative file names
+ wxFileName fn(movie);
+ fn.MakeAbsolute();
+ const wxString swf = fn.GetFullPath();
+ if ( swf == m_swf )
+ m_flash->PutMovie(L"");
+ else
+ m_swf = swf;
+
+ m_flash->PutMovie(m_swf.wc_str());
+
+ SetStatusText("Loaded \"" + m_swf + '"', 1);
+}
+
+void FlashFrame::Play()
+{
+ CheckFlashCall(m_flash->Play(), "Play");
+}
+
+void FlashFrame::Stop()
+{
+ CheckFlashCall(m_flash->Stop(), "Stop");
+}
+
+// ----------------------------------------------------------------------------
+// event handlers
+// ----------------------------------------------------------------------------
+
+void FlashFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
+{
+ wxString swf = wxLoadFileSelector("Flash movie", ".swf", m_swf, this);
+ if ( swf.empty() )
+ return;
+
+ SetMovie(swf);
+}
+
+void FlashFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+ // true is to force the frame to close
+ Close(true);
+}
+
+void FlashFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+ wxMessageBox("Flash ActiveX control embedding sample\n"
+ "\n"
+ "(c) 2009 Vadim Zeitlin",
+ "About " + GetTitle(),
+ wxOK | wxICON_INFORMATION,
+ this);
+}
+
+void FlashFrame::OnActiveXEvent(wxActiveXEvent& event)
+{
+ switch ( event.GetDispatchId() )
+ {
+ case FLASH_DISPID_ONREADYSTATECHANGE:
+ {
+ const int state = event[0].GetInteger();
+ if ( state != m_state )
+ {
+ wxLogMessage("State changed to %s",
+ GetFlashStateString(state));
+
+ if ( state >= 0 && state < FlashState_Max )
+ m_state = static_cast(state);
+ else
+ m_state = FlashState_Unknown;
+ }
+ }
+ break;
+
+ case FLASH_DISPID_ONPROGRESS:
+ wxLogMessage("Progress: %d%%", event[0].GetInteger());
+ break;
+
+ case FLASH_DISPID_FSCOMMAND:
+ wxLogMessage("Flash command %s(%s)",
+ event[0].GetString(), event[1].GetString());
+ break;
+
+ case FLASH_DISPID_FLASHCALL:
+ wxLogMessage("Flash request \"%s\"", event[0].GetString());
+ break;
+
+ default:
+ wxLogMessage("Unknown event %ld", event.GetDispatchId());
+ }
+
+ event.Skip();
+}
+
+void FlashFrame::OnBack(wxCommandEvent& WXUNUSED(event))
+{
+ CheckFlashCall(m_flash->Back(), "Back");
+}
+
+void FlashFrame::OnForward(wxCommandEvent& WXUNUSED(event))
+{
+ CheckFlashCall(m_flash->Forward(), "Forward");
+}
+
+void FlashFrame::OnInfo(wxCommandEvent& WXUNUSED(event))
+{
+ const int state = m_flash->GetReadyState();
+ wxString msg = "State: " + GetFlashStateString(state);
+
+ if ( state == FlashState_Complete )
+ {
+ msg += wxString::Format(", frame: %ld/%ld",
+ m_flash->GetFrameNum() + 1,
+ m_flash->GetTotalFrames());
+ }
+
+ if ( m_flash->IsPlaying() )
+ msg += ", playing";
+
+ wxLogMessage("%s", msg);
+}
+
+void FlashFrame::OnVarGet(wxCommandEvent& WXUNUSED(event))
+{
+ m_varvalue->SetValue(bstr2wx(
+ m_flash->GetVariable(wx2bstr(m_varname->GetValue()))));
+}
+
+void FlashFrame::OnVarSet(wxCommandEvent& WXUNUSED(event))
+{
+ m_flash->SetVariable(wx2bstr(m_varname->GetValue()),
+ wx2bstr(m_varvalue->GetValue()));
+}
+
+void FlashFrame::OnCall(wxCommandEvent& WXUNUSED(event))
+{
+ CallFlashFunc("", m_funcname->GetValue());
+}
+
+void FlashFrame::OnCallWithArg(wxCommandEvent& WXUNUSED(event))
+{
+ CallFlashFunc("string", m_funcname->GetValue(), m_funcarg->GetValue());
+}
+
+
+
diff --git a/samples/flash/flash_vc7.vcproj b/samples/flash/flash_vc7.vcproj
new file mode 100644
index 0000000000..a5047ddd95
--- /dev/null
+++ b/samples/flash/flash_vc7.vcproj
@@ -0,0 +1,545 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/flash/flash_vc8.vcproj b/samples/flash/flash_vc8.vcproj
new file mode 100644
index 0000000000..ddabcf2a04
--- /dev/null
+++ b/samples/flash/flash_vc8.vcproj
@@ -0,0 +1,810 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/flash/flash_vc9.vcproj b/samples/flash/flash_vc9.vcproj
new file mode 100644
index 0000000000..11b6f5b536
--- /dev/null
+++ b/samples/flash/flash_vc9.vcproj
@@ -0,0 +1,782 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/flash/form.mxml b/samples/flash/form.mxml
new file mode 100644
index 0000000000..567ff1d89a
--- /dev/null
+++ b/samples/flash/form.mxml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/flash/form.swf b/samples/flash/form.swf
new file mode 100644
index 0000000000..7bd9d7ab2d
Binary files /dev/null and b/samples/flash/form.swf differ
diff --git a/samples/samples.bkl b/samples/samples.bkl
index 558f1feb4e..306651b15c 100644
--- a/samples/samples.bkl
+++ b/samples/samples.bkl
@@ -86,6 +86,7 @@
+
|