在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();
}
}
当然,根据实际项目情况自己调整下。示例下载链接。
这个只是个人的解决方案,主要是讲个思路,希望对遇到同样问题的你有帮助,期待交流。