VC++ 项目中使用 FLEX
1, http://hi.baidu.com/qinpc/blog/item/58253df3f9a04654352acc36.html
复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。我们知道父窗口上被子窗口挡住的部分其实没必要重画的。
解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。如果同级窗口之间有重叠,那么需要再加上 WS_CLIPSIBLINGS 风格
What?
Nothing explains it like code. Take a look at the following C++ snippet1:
//addeventlistener to call a cpp function oRootObj.Call("getbutton1").Call("addEventListener", "click", SampleCallback); //where SampleCallback is: void SampleCallback(CASObject& obj, CFlexBridge* pBridge) { CASObject oRootObj; pBridge->Root(oRootObj); oRootObj.Call("getpanel1").Call("settitle", "Title from CPP"); } //c++ way of saying Alert.show("StaticClassCalled") pBridge->ClassRef("mx.controls.Alert").Call("show", "StaticClassCalled"); //create a datagrid and add it to the flex app CASObject oDGrid = pBridge->Create("mx.controls.DataGrid"); oRootObj.Call("addChild", oDGrid);
Flex C++ Bridge is a C++ library that lets you communicate with Flex in a manner more suited for the normal C++ programmer, i.e, you can communicate to flex from c++ by writing code like shown above.
Once you put the Flex Ajax bridge into a Flex application, it is exposed to scripting in the browser. You can use a slightly modified version of the same FABridge.as2 (or even the same one) on the actionscript side and the flex application is exposed to the Flex C++ Bridge.
Flex is for the web, AIR is for the desktop. What is this for?
This is for C++ applications that need an awesome UI but do not want to re-write their existing c++ code and libraries to actionscript / javascript. It's a normal desktop application, you can interact with all your favorite C++ libraries and APIs and still have all the rich expressiveness that flex can deliver.
You could do all this before as well, but the bridge makes it really easy to use Flex from C++. A lot of the reasons for FABridge applies to this as well, but this is outside the browser realm so those reasons have to be filtered to suit that particular fact.
Where can I get it from?
The project is licensed under MPL 1.1 and both the C++ and actionscript source code is available at code.google.com.
It's open source, so feel free to participate and contribute to it.
Sample Applications
Note: The source (both flex and cpp) is available for all the examples.
AdvancedDataGrid that supports Excel formulae computation:
Here, each individual cells in the ADG are editable. You can type in any Excel formula into it and hit the "Compute" button. The application invokes Excel using COM, computes the results and populates the result into the ADG.
Scan images right into flexbook:
When the Scan button is clicked, a TWAIN dialog pops up letting you use your scanner to scan images directly into the pages of the flexbook component.
Sample app showing two flash player instances each with a flex application:
The bridge supports multiple flash player instances. It can talk to each instance in a different manner. If you look at the screenshot, both the instances are loading the same swf file. But the C++ code for one instance adds a datagrid and removes an element shown in the pie chart.
How does it work?
The flash player ActiveX control is added to a MFC dialog. Now the content in the flash player can talk to the C++ application via ExternalInterface. ExternalInterface.call("fnname") will dispatch a FlashCall message on the C++ side which will have the arguments passed to call() in XML. This XML has to be parsed to understand what the message was from the actionscript side.
All this complexity is hidden by the bridge. The bridge talks with the actionscript side of Ely's FABridge and facilitates calling and referencing to actionscript objects, classes and methods.
There are multiple worker threads waiting to process incoming or outgoing flash requests so that the main MFC thread does not block. The bridge can even support multiple flash player instances each with it's own bridge back to the C++ application.
Also, Actionscript exceptions are serialized and thrown on the C++ side.
C++ Syntax Rules
To start off, you need the root object which is the main application object of your flex application. Now you can access the public methods and properties of your application.
Getters and setters are treated differently: A property "width" will be translated to "getwidth" for retrieving the value and "setwidth" for setting the value. Ely's FABridge had camel casing here, but that has been removed so that constants like MOUSE_DOWN don't confuse the bridge.
The "Call" method shown in the snippets above take a string as the first argument that is the name of the method or property (suitably modified using above defined rules) and the arguments for it. Common types like string, int, reference to an AS object, custom anonymous AS object etc are converted internally to an ASObject thanks to copy constructors and operator overloads.
For more examples of the syntax, take a look at the Worker() method in ASWorkSample.cpp.
FABridge did not originally have support for accessing methods and variables of static classes. This was added by Devin Garner and I have incorporated his code into FABridge.as along with some of my changes.
Fine Print
Currently, it supports only Windows since it embeds the internet explorer flash ActiveX control in a MFC dialog.
But it's an open source project and I hope I'll get contributors to help me make it more platform agnostic.
I'd love to know what you guys think about this and how it's being used.
CategoryFlexCPPBridge Comment(s)
[1] Now, this is a better way to communicate rather than saying m_Shockwave.CallFunction("asfnname") where asfnname has to be exposed by using ExternalInterface.addCallback on the actionscript side.
[2] Minor changes to support passing of primitives from me and additional support for accessing static classes, variables and methods thanks to Devin Garner)
3.
Flex与Win32通信实例之ExternalInterface
关键字: flex win32 vc++ vc externalinterface
项目中要实现Flex打开文件夹选择框(Flex做为桌面程序的UI),没办法,如果不用AIR只能在下面加一层Container了。网上搜来搜去差不多都是讲FSCommand怎样与VC++交互,可是FSCommand不能及时返回值呀。经过一番摸索,终于调通了ExternalInterface在VC++中的处理流程,看代码。
Cpp代码
void CMyBicapDlg::OnFlashCallShockwaveflash1(LPCTSTR request)
{
// TODO: Add your control notification handler code here
// "<invoke name='%s' returntype='xml'><arguments><string>%s</string></arguments></invoke>"
// parse request
TiXmlDocument request_xml;
request_xml.Parse(request);
const char* request_name = request_xml.RootElement()->Attribute("name");
if (strcmp(request_name,"savedVideosDirectory") == 0 || strcmp(request_name,"bufferDirectory") == 0 || strcmp(request_name,"preferredExportDirectory") == 0)
{
// choose path
CoInitialize(NULL);
BROWSEINFO bi;
bi.hwndOwner = this->GetSafeHwnd();
bi.pidlRoot = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = NULL;
bi.ulFlags = BIF_BROWSEFORCOMPUTER|BIF_RETURNONLYFSDIRS|BIF_STATUSTEXT;
bi.lpfn = NULL;
LPCITEMIDLIST pidl = SHBrowseForFolder(&bi);
if(pidl != NULL)
{
TCHAR tpath[MAX_PATH] = _T("");
BOOL bresult = SHGetPathFromIDList(pidl, tpath);
if (bresult)
{
std::string re_value = "<string>";
re_value = re_value+tpath+"</string>";
m_FlashPlayer.SetReturnValue(re_value.c_str());
}
}
CoUninitialize();
}
}
首先,需要在项目中嵌入Flash player插件,网上有很多例子。另外Flex也要写好代码,这里略掉。
添加一个ExternalInterface的事件处理函数,对于Flash player来讲就是FlashCall事件(跟FSCommand不同的),这里的事件处理函数是void CMyBicapDlg::OnFlashCallShockwaveflash1(LPCTSTR request)。没有返回值(下面会讲到),参数是一个XML格式的字符串。格式是"<invoke name='%s' returntype='xml'><arguments><string>%s</string></arguments></invoke>",去查查帮助就知道了。
处理request:标准C++没有处理XML的库,我去下载了tinyxml,小巧好用。下面就是按照个人需要处理request了,我这里是,打开一个文件夹选择对话框然后选择一个路径。
返回值。事件处理函数是没有返回值的,但是flash player提供了一个方法:m_FlashPlayer.SetReturnValue(re_value.c_str());,专门传递返回值,格式是<string>%s</string>(也可以是别的AS结构,具体看帮助)。
需要提醒的是,在处理期间要block掉Flex,ExternalInterface.call是有返回值的,如果不阻塞Flex,可能返回就是NULL,呵呵,不知道深层原因。另外,反过来调用格式也是一样的。
调试环境:win xp, VC++6.0, Flex builder 2.0