伪破解 componentone silverlight 控件

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

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

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

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

伪破解 componentone silverlight 控件

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

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

用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();
}
}

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

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

你可能感兴趣的:(silverlight)