伪破解 componentone silverlight 控件

在silverlight开发中用到了多种控件,有时候现有的控件不能满足要求,于是很多第三方提供了丰富的控件。其中就有componentone,当然要收费,$895。

而如果未注册的话在引用C1控件的时候会在xaml里自动插入C1:C1NagScreen.Nag="True",如:

<C1DateTime:C1DateTimePicker C1:C1NagScreen.Nag="True" />

并最终在程序启动的时候弹出如下界面:

其实别的功能都挺正常,就是这个框比较讨厌,可恶的框框,还好只弹一次。

伪破解只是想办法把这个框给去掉,而不是真正的实现破解注册功能。

用reflector打开C1.Silverlight.dll找到C1NagScreen。见到如下代码:

private static bool AlreadyNagged;
public static readonly DependencyProperty NagProperty;

// Methods
static C1NagScreen()
{
NagProperty
= DependencyProperty.RegisterAttached("Nag", typeof(bool), typeof(C1NagScreen), new PropertyMetadata(delegate (DependencyObject s, DependencyPropertyChangedEventArgs e) {
FrameworkElement element
= (FrameworkElement) s;
element.Loaded
+= delegate {
if (!AlreadyNagged)
{
AlreadyNagged
= true;
new C1NagScreen().ShowModal();
}
};
}));
}

这就知道为什么虽然引用多个控件的话会多次设置NagProperty,而真正启动的时候也只会弹出一次框框。

多么冲动的想把AlreadyNagged字段设成true,运用反射吧,很不幸的是silverlight的安全机制阻止了我们设置私有字段。

继续往上看,C1NagScreen是继承自C1Window,而ShowModal正是C1Window的方法。

public void ShowModal()
{
this.VerifyCanShow();
if (this._canvas.Children.Contains(this) && (base.Visibility == Visibility.Visible))
{
throw new InvalidOperationException("ShowModal can be called only on hidden windows.");
}
if (!this._canvas.Children.Contains(this))
{
this._canvas.Children.Add(this);
}
VerifyDefaultCanvasInserted();
this._context.ModalWindow.Remove(this);
this._context.ModalWindow.Add(this);
base.TabNavigation = KeyboardNavigationMode.Cycle;
base.Visibility = Visibility.Visible;
if (!base.Focus())
{
base.Loaded += delegate (object s, RoutedEventArgs e) {
base.Focus();
};
}
this.IsActive = true;
this.fixWindowOrder();
this.BringPopupToFront();
}
private void BringPopupToFront()
{
base.Dispatcher.BeginInvoke(delegate {
_contexts[_defaultCanvas].Popup.IsOpen
= false;
_contexts[_defaultCanvas].Popup.IsOpen
= true;
});
}

仔细分析确定弹出的窗口是个Popup。略有思路,看看能否在popup窗口弹出的瞬间把它关掉。在MainPage中实现下思路:

public MainPage()
{
InitializeComponent();

var timer
= new DispatcherTimer();
timer.Interval
= TimeSpan.FromMilliseconds(1);
timer.Tick
+= new EventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
var pops
= VisualTreeHelper.GetOpenPopups();
if (pops.Count() > 0)
{
var pop
= pops.First();
pop.IsOpen
= false;
((DispatcherTimer)sender).Stop();
}
}

成功是成功了,只是会那么闪一下,不爽。继续分析下,怀疑_defaultCanvas有问题,并最终追踪到:

public static void AddDefaultPopupToVisualTree(Panel panel)
{
InitializeDefaultCanvas();
panel.Children.Add(_defaultCanvas.Parent
as UIElement);
}

private static void InitializeDefaultCanvas()
{
if (_defaultCanvas == null)
{
_defaultCanvas
= new Canvas();
Context context
= new Context();
_contexts[_defaultCanvas]
= context;
_defaultCanvas.SetValue(Canvas.ZIndexProperty,
-10000);
context.Popup
= new Popup { Child = _defaultCanvas, IsOpen = true };
AttachApplicationRoot();
}
}

所有的目光都投向了static的AddDefaultPopupToVisualTree方法,不清楚控件内部有没有调用这个方法,但如果我们在程序启动的时候调用下这个方法。并传递一个Visibility="Collapsed"的panel进去,能不能把弹出pop窗口隐藏起来呢?在MainPage加个隐藏了的Grid。

<UserControl x:Class="SLC1Window.MainPage">
<Grid x:Name="LayoutRoot" Background="White">
<Grid x:Name="popPanel" Visibility="Collapsed"/>
</Grid>
</UserControl>

后台代码如下:

public MainPage()
{
InitializeComponent();

C1Window.AddDefaultPopupToVisualTree(popPanel);
}

很简单是吧,而且的确如愿工作了,窗口不再显示。

不过也有个后遗症,C1MessageBox等弹出窗口以后也显示不出来的。当然,也可以把方法1和2整合起来,合理解决这个问题:

public MainPage()
{
InitializeComponent();

C1Window.AddDefaultPopupToVisualTree(popPanel);

var timer
= new DispatcherTimer();
timer.Interval
= TimeSpan.FromMilliseconds(1);
timer.Tick
+= new EventHandler(timer_Tick);
timer.Start();
}

void timer_Tick(object sender, EventArgs e)
{
var pops
= VisualTreeHelper.GetOpenPopups();
if (pops.Count() > 0)
{
var pop
= pops.First();
var panel
= pop.Child as Panel;
if (panel == null || panel.Children.Count == 0)
return;
var window
= panel.Children[0] as C1Window;
if (window == null)
return;
window.IsActive
= false;
window.Visibility
= Visibility.Collapsed;
pop.IsOpen
= false;
popPanel.Visibility
= Visibility.Visible;
((DispatcherTimer)sender).Stop();
}
}

当然,根据实际项目情况自己调整下。示例下载链接

这个只是个人的解决方案,主要是讲个思路,希望对遇到同样问题的你有帮助,期待交流。

posted @ 2011-02-24 11:30  超时空饭盒  阅读(4400)  评论(14编辑  收藏  举报