该有的都有了,包括了WM_*和参数Enum
Win32.cs
鼠标键盘模拟操作
Simulation.cs
鼠标键盘Hook
MouseKeyboardHook.dll
该有的都有了,包括了WM_*和参数Enum
Win32.cs
鼠标键盘模拟操作
Simulation.cs
鼠标键盘Hook
MouseKeyboardHook.dll
BItmapImage默认情况下是不会进行Preload,之前google竟然也没有什么办法,本来考虑尝试一下thumbnail,隔天再想这个问题突然灵光一闪,Yes,MemoryStream。
<MediaElement x:Name=”video” MediaEnded=”video_MediaEnded” Stretch=”Fill” LoadedBehavior=”Manual” />
增加MediaEnded事件响应,事件响应代码如下:
private void video_MediaEnded(object sender, RoutedEventArgs e) {
this.video.Position = TimeSpan.FromSeconds(0);
this.video.Play();
}
关键是需要重置video的Position。
原先Winform只需要在Toolbox中choose加入Shockwave Flash Object即可,可到了WPF则变得有些麻烦,需要通过Winform来做跳板,具体如下:
1. 通过原先Winfrom的引入方式,将Flash控件拖入Winform中,VS会自动生成下面2个dll:
2. 将这两个dll copy到wpf的project中,在project新建2个目录分别是Lib和Runtime,将Interop…dll放入Lib,Ax…dll放入Runtime,在project编写Post Build Event,如下:
copy “$(ProjectDir)Runtime\*.dll” “$(TargetDir)”
将AxInterop.ShockwaveFlashObjects.dll在build后copy到最终exe生成的目录,因为运行exe需要它。
3. 在wpf project中add reference:
4. 开始编写放入flash的代码:
private void Window_Loaded(object sender, RoutedEventArgs e) {
System.Windows.Forms.Integration.WindowsFormsHost host = new System.Windows.Forms.Integration.WindowsFormsHost();
flash = new AxShockwaveFlashObjects.AxShockwaveFlash();
flash.FSCommand += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEventHandler(flash_FSCommand);
host.Child = flash;
this.Stage.Children.Add(host);
flash.Movie = @"c:\users\nonocast\desktop\hello.swf";
flash.Play();
flash.BackgroundColor = 0x000000;
flash.SetVariable("testValue", "Hello World");
}
private void flash_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e) {
string cmd = e.command.ToString();
MessageBox.Show(cmd);
}
private AxShockwaveFlashObjects.AxShockwaveFlash flash;
以Flash8 AS2为例(:(我也没办法),可以通过FsCommand事件接收flash中fscommand的调用,反之可以通过SetVariable给flash ’send message’.
5. 上面说到的Flash很简单,在第一帧中放入一个Label,然后F9编写’动作’,如下:
var testValue:String = "";
watchCallback = function (id, oldval, newval):String {
mylabel.text = newval;
fscommand("GotIT");
return newval;
};
_root.watch("testValue", watchCallback);
另外一种情况就是,直接采用动态文本,然后在’变量’中填上相应的变量名,然后直接就可以在.NET中Set,这个非常方便。
6. 参考Url:
Using the External API for Flash–JavaScript Communication
如何在 WPF 中嵌入 Flash (ActiveX)
7. 附上我的代码,有点乱糟糟,擦
WPF采用DispatcherObject作为UI对象的Base Class,DispactcherObject继承自Object,那什么是DispatcherObject以及DispatcherObject和我们又有什么关系呢?
MSDN对DispatcherObject给出的Remark是这样的:
Only the thread that the Dispatcher was created on may access the DispatcherObject directly. To access a DispatcherObject from a thread other than the thread the DispatcherObject was created on, call Invoke or BeginInvoke on the Dispatcher the DispatcherObject is associated with.
这次我们克制一下,不去挖Source Code,从黑盒的角度来说,Dispatcher是一个ThreadLocal的优先级消息队列,通过消息机制可以使得对象内部数据做到Thread-Safe。
我们通过简单代码来DIY一个具备’消息队列’能力的ActiveObject,
public class DispatcherWorker : DispatcherObject, IDisposable {
public void DoWork() {
Console.Write("BEGIN");
Thread.Sleep(2000);
Console.WriteLine(" ... END");
}
public static DispatcherWorker Create() {
DispatcherWorker result = null;
AutoResetEvent e = new AutoResetEvent(false);
new Thread(new ThreadStart(() => {
result = new DispatcherWorker();
e.Set();
Dispatcher.Run();
})).Start();
e.WaitOne();
return result;
}
public void Dispose() {
this.Dispatcher.InvokeShutdown();
}
public void Close() { Dispose(); }
}
然后就可以在任意线程中对这个对象进行Invoke/BeginInvoke DoWork而确保DoWork的完整性。
Console的输出能确保是BEGIN…END BEGIN…END BEGIN…END,而不会是BEGIN BEGIN BEGIN…END…END…END
最后把DispatcherWorker做成一个Template,
public class ActiveObject< T > : DispatcherObject, IDisposable where T : new() {
protected ActiveObject() { }
public static T Create() {
T result = default(T);
AutoResetEvent e = new AutoResetEvent(false);
new Thread(new ThreadStart(() => {
result = new T();
e.Set();
Dispatcher.Run();
})).Start();
e.WaitOne();
return result;
}
public virtual void Invoke(Action method) {
this.Dispatcher.Invoke(method);
}
public virtual void BeginInvoke(Action method) {
this.Dispatcher.BeginInvoke(method);
}
public virtual void Dispose() {
this.Dispatcher.InvokeShutdown();
}
public virtual void Close() { Dispose(); }
}
Applying Template,
public class MyWorker : ActiveObject< MyWorker > {
public void DoWork() {
Console.Write("BEGIN");
Thread.Sleep(2000);
Console.WriteLine(" ... END");
}
}
At last,
MyWorker worker = MyWorker.Create();
for (int i = 0; i < 5; ++i) {
new Thread(new ThreadStart(() => {
worker.BeginInvoke(() => worker.DoWork());
})).Start();
}
That’s all. Hope it helps!
Download SourceCode: ActiveObject.7z
由于需要对程序输出做几何校正,所以需要对一些方案进行比较,包括
先看一下WPF 3D,步骤和传统的DirectX开发步骤相似,代码会简洁一些,以下图为例,
Xaml如下
由Viewport3D开始,然后需要简单的一下设置摄像机和灯光,模型由MeshGeometry3D负责定义,可以在Xaml中直接定义,也可以在后台中用代码生成对象再加入Viewport3D中。
MeshGeometry3D mesh = new MeshGeometry3D();
List<Point3D> points = new List<Point3D>();
points.Add(new Point3D(0, 2, 0));
points.Add(new Point3D(1, 2, 0.5));
points.Add(new Point3D(2, 2, 1));
points.Add(new Point3D(0, 1, 0));
points.Add(new Point3D(1, 1, 0.5));
points.Add(new Point3D(2, 1, 1));
points.Add(new Point3D(0, 0, 0));
points.Add(new Point3D(1, 0, 0.5));
points.Add(new Point3D(2, 0, 1));
foreach (var each in points) {
mesh.Positions.Add(each);
}
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(0);
mesh.TriangleIndices.Add(3);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(5);
mesh.TriangleIndices.Add(2);
mesh.TriangleIndices.Add(1);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(5);
mesh.TriangleIndices.Add(3);
mesh.TriangleIndices.Add(7);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(3);
mesh.TriangleIndices.Add(6);
mesh.TriangleIndices.Add(7);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(8);
mesh.TriangleIndices.Add(5);
mesh.TriangleIndices.Add(4);
mesh.TriangleIndices.Add(7);
mesh.TriangleIndices.Add(8);
VisualBrush brush = new VisualBrush(new MediaElement() { Source = new Uri(@"D:\4Video\Sample\Coral_Reef_Adventure_1080.wmv") });
Material material = new DiffuseMaterial(brush);
List<Point3D> ps = new List<Point3D>();
ps.Add(new Point(0, 0));
ps.Add(new Point(.5, 0));
ps.Add(new Point(1, 0));
ps.Add(new Point(0, .5));
ps.Add(new Point(.5, .5));
ps.Add(new Point(1, .5));
ps.Add(new Point(0, 1));
ps.Add(new Point(0.5, 1));
ps.Add(new Point(1, 1));
mesh.TextureCoordinates = new PointCollection(ps);
ModelVisual3D model = new ModelVisual3D();
model.Content = new GeometryModel3D(mesh, material);
mGeometry = model.Content as GeometryModel3D;
model.Content.Transform = new Transform3DGroup();
this.mainViewport.Children.Add(model);
上面这段代码就是一个生成模型的例子,分为以下几个步骤:
1. 创建MeshGeometry3D对象
2. 向Mesh中添加需要用到的顶点坐标(Point3D),这里通过9个点构成一个2×2的网格,共8个三角形
3. 向Mesh中声明三角形的顶点序列,3个一组,表示一个3角色,考虑DirectX采用右手坐标系,所以三角形坐标必须逆时针顺序,当然对于故意需要朝后的facet则采用顺时针顺序
4. 创建贴图,这里采用VisualBrush,将视频贴到Mesh上
5. 为了使贴图和Mesh建立对应关系,就必须指定顶点与贴图的对应关系,需要指定TextureCoordinates
6. 通过ModelVisual3D包装Mesh送进Viewport中即可
最后给出上面的源代码,戳这里
ENV: .NET 4,VS2010
Bezier曲线是一种spline,是一种”用光滑连续函数逼近离散数据”的曲线。三次Bezier曲线由四个点定义,这些点可以被标示为p0,p1,p2,p3。曲线从p0开始,结束于p3。p1,p2称为控制点,通过调整控制点来达到你想要的曲线。
用WPF来实现bezier的显示和控制需要以下几步:
1. 采用BezierSegment显示Bezier曲线
<Path Stroke="DarkGray" StrokeThickness="3">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="100,50">
<BezierSegment Point1="300,50" Point2="50,300" Point3="400, 400"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
2. 增加控制点
public class BezierPoint : FrameworkElement { }
具体实现参考附件中BezierPoint.cs
3. 将控制点绑定到曲线上
<Canvas>
<my:BezierPoint x:Name="ptStart" Fill="DarkOrange" Stroke="{x:Null}" Canvas.Left="304" Canvas.Top="50" Canvas.ZIndex="10" />
<my:BezierPoint x:Name="ptCtrl2" Stroke="SkyBlue" Canvas.Left="124" Canvas.Top="320" Canvas.ZIndex="11" />
<my:BezierPoint x:Name="ptCtrl1" Stroke="DarkOrange" Canvas.Left="658" Canvas.Top="98" Canvas.ZIndex="12" />
<my:BezierPoint x:Name="ptEnd" Fill="SkyBlue" Stroke="{x:Null}" Canvas.Left="504" Canvas.Top="380" Canvas.ZIndex="13" />
<Path Stroke="DarkGray" StrokeThickness="3">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="{Binding ElementName=ptStart,Path=Center}">
<BezierSegment Point1="{Binding ElementName=ptCtrl1,Path=Center}"
Point2="{Binding ElementName=ptCtrl2,Path=Center}"
Point3="{Binding ElementName=ptEnd,Path=Center}"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
OVER.代码这里下载,戳
ENV:.NET4.0/VS2010