创建类似于输入法窗口的非激活窗口
2012-05-15 07:45
253 查看
前两日,偶见博客“创建类似于输入法窗口的非激活窗口”,觉得内容不错,决定试了试,发现有瑕疵,现将自己的测试过程赋予其后(本文测试用的是VS2005),和各位网友交流。
按照那篇的博文的第一种方法,新建了Form1,改写了Form1的CreateParams属性,将FormBorderStyle设置为 System.Windows.Forms.FormBorderStyle.None。
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim tC As CreateParams = MyBase.CreateParams
tC.ExStyle = tC.ExStyle Or &H8000000
Return tC
End Get
End Property
复制代码
测试了一下,不错,和打开的“记事本”做了比较,当我单击Form1的时候,光标还在“记事本”里。
于是,又新建Form2,并改为启动窗口,上面添加了Textbox1控件,在该控件的双击事件,启动Form1
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
End Sub
复制代码
按照设想,双击文本框的时候,弹出Form1,光标仍然在文本框内。
不成想,光标不见了,文本框失去焦点,焦点在Form1上(后来将Form1的FormBorderStyle设置为 System.Windows.Forms.FormBorderStyle.FixedToolWindow后证实了这一点。焦点的确移到Form1 上)
后来想想,在启动Form1后,强制将焦点切回来后能不能好一点呢,于是,将上面的代码改为
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
Me.Activate()
End Sub
复制代码
启动Form1后,光标的确在文本框,但单击Form1后,光标又没了,焦点在Form1上。“杯具”呀。
如此努力了若干次,均没有效果,貌似单个程序里有两个Form(或者超过两个),这个效果就出不来。
后来查了查&H8000000代表的含义是WS_DISABLED,也没整明白是什么意思。
后来在网上查找到一篇文章,通篇的英文,没有细看,将里面的代码测试了一下,能成功。网址如下:On-screen Keyboards,相关代码如下:
private const int
WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams =
base.CreateParams;
createParams.ExStyle = createParams.ExStyle & WS_EX_NOACTIVATE;
return createParams;
}
}
Finally, you need to prevent the form getting focus or being activated
when it or the keyboard control are clicked on. This is as easy as
adding the following code to the host form;
private const int WM_MOUSEACTIVATE
= 0x0021;
private const int MA_NOACTIVATE
= 0x0003;
protected override void WndProc(ref Message m)
{
//If we're being activated because
the mouse clicked on us...
if (m.Msg == WM_MOUSEACTIVATE)
{
//Then refuse to be activated, but
allow the click event to pass through (don't use MA_NOACTIVATEEAT)
m.Result = (IntPtr)MA_NOACTIVATE;
}
else
base.WndProc(ref m);
}
复制代码
他的代码中,添加了一段修改Form的WndProc代码,拦截WM_MOUSEACTIVATE消息,改为MA_NOACTIVATE。
代码如下:
Private Const WM_MOUSEACTIVATE As Integer = &H21
Private Const MA_NOACTIVATE As Integer = &H3
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_MOUSEACTIVATE Then
m.Result = MA_NOACTIVATE
Else
MyBase.WndProc(m)
End If
End Sub
复制代码
经测试,终于达到了效果,启动Form1,光标在文本框内,无论怎么点击Form1,光标都不曾发生变化。
上面这段的代是有效的,甚至去掉一开始的改写CreateParams的代码,仍然有效。
再做了若干测试,发现上面的代码效果,如果要成功,还必不可少的是Form上没有能接受焦点的控件(Button,TextBox等),而且还不能有标题栏。解决的办法,就是去掉Form的标题栏,不使用能接受焦点的控件(或者是改写控件的WndProc过程,拦截接受焦点的消息,使之不能接受焦点)。虽然Form不能接受焦点,但是经过测试,控件还是能接受其他的事件(例如:Click,DoubleClick,MouseHover,MouseLeave 等事件),合理运用的话,还是能产生不错的效果。(文/万仓一黍)
上文中提到假如窗体上有可以获得焦点的Control时,改写控件的WndProc过程,拦截接受焦点的消息,使之不能接受焦点,
补充代码如下:
[DllImport("user32.dll")]
private extern static IntPtr SetActiveWindow(IntPtr handle);
private const int WM_ACTIVATE = 0x006;
private const int WM_ACTIVATEAPP = 0x01C;
private const int WM_NCACTIVATE = 0x086;
private const int WA_INACTIVE = 0;
private const int WM_MOUSEACTIVATE = 0x21;
private const int MA_NOACTIVATE = 3;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = new IntPtr(MA_NOACTIVATE);
return;
}
else if (m.Msg == WM_NCACTIVATE)
{
if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
{
if (m.LParam != IntPtr.Zero)
{
SetActiveWindow(m.LParam);
}
else
{
SetActiveWindow(IntPtr.Zero);
}
}
}
base.WndProc(ref m);
}
这样即使窗体上有可获得焦点的Control,键盘也不会抢占焦点了~
按照那篇的博文的第一种方法,新建了Form1,改写了Form1的CreateParams属性,将FormBorderStyle设置为 System.Windows.Forms.FormBorderStyle.None。
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
Dim tC As CreateParams = MyBase.CreateParams
tC.ExStyle = tC.ExStyle Or &H8000000
Return tC
End Get
End Property
复制代码
测试了一下,不错,和打开的“记事本”做了比较,当我单击Form1的时候,光标还在“记事本”里。
于是,又新建Form2,并改为启动窗口,上面添加了Textbox1控件,在该控件的双击事件,启动Form1
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
End Sub
复制代码
按照设想,双击文本框的时候,弹出Form1,光标仍然在文本框内。
不成想,光标不见了,文本框失去焦点,焦点在Form1上(后来将Form1的FormBorderStyle设置为 System.Windows.Forms.FormBorderStyle.FixedToolWindow后证实了这一点。焦点的确移到Form1 上)
后来想想,在启动Form1后,强制将焦点切回来后能不能好一点呢,于是,将上面的代码改为
Private Sub TextBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.DoubleClick
Form1.Show()
Me.Activate()
End Sub
复制代码
启动Form1后,光标的确在文本框,但单击Form1后,光标又没了,焦点在Form1上。“杯具”呀。
如此努力了若干次,均没有效果,貌似单个程序里有两个Form(或者超过两个),这个效果就出不来。
后来查了查&H8000000代表的含义是WS_DISABLED,也没整明白是什么意思。
后来在网上查找到一篇文章,通篇的英文,没有细看,将里面的代码测试了一下,能成功。网址如下:On-screen Keyboards,相关代码如下:
private const int
WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
{
get
{
CreateParams createParams =
base.CreateParams;
createParams.ExStyle = createParams.ExStyle & WS_EX_NOACTIVATE;
return createParams;
}
}
Finally, you need to prevent the form getting focus or being activated
when it or the keyboard control are clicked on. This is as easy as
adding the following code to the host form;
private const int WM_MOUSEACTIVATE
= 0x0021;
private const int MA_NOACTIVATE
= 0x0003;
protected override void WndProc(ref Message m)
{
//If we're being activated because
the mouse clicked on us...
if (m.Msg == WM_MOUSEACTIVATE)
{
//Then refuse to be activated, but
allow the click event to pass through (don't use MA_NOACTIVATEEAT)
m.Result = (IntPtr)MA_NOACTIVATE;
}
else
base.WndProc(ref m);
}
复制代码
他的代码中,添加了一段修改Form的WndProc代码,拦截WM_MOUSEACTIVATE消息,改为MA_NOACTIVATE。
代码如下:
Private Const WM_MOUSEACTIVATE As Integer = &H21
Private Const MA_NOACTIVATE As Integer = &H3
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_MOUSEACTIVATE Then
m.Result = MA_NOACTIVATE
Else
MyBase.WndProc(m)
End If
End Sub
复制代码
经测试,终于达到了效果,启动Form1,光标在文本框内,无论怎么点击Form1,光标都不曾发生变化。
上面这段的代是有效的,甚至去掉一开始的改写CreateParams的代码,仍然有效。
再做了若干测试,发现上面的代码效果,如果要成功,还必不可少的是Form上没有能接受焦点的控件(Button,TextBox等),而且还不能有标题栏。解决的办法,就是去掉Form的标题栏,不使用能接受焦点的控件(或者是改写控件的WndProc过程,拦截接受焦点的消息,使之不能接受焦点)。虽然Form不能接受焦点,但是经过测试,控件还是能接受其他的事件(例如:Click,DoubleClick,MouseHover,MouseLeave 等事件),合理运用的话,还是能产生不错的效果。(文/万仓一黍)
上文中提到假如窗体上有可以获得焦点的Control时,改写控件的WndProc过程,拦截接受焦点的消息,使之不能接受焦点,
补充代码如下:
[DllImport("user32.dll")]
private extern static IntPtr SetActiveWindow(IntPtr handle);
private const int WM_ACTIVATE = 0x006;
private const int WM_ACTIVATEAPP = 0x01C;
private const int WM_NCACTIVATE = 0x086;
private const int WA_INACTIVE = 0;
private const int WM_MOUSEACTIVATE = 0x21;
private const int MA_NOACTIVATE = 3;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOUSEACTIVATE)
{
m.Result = new IntPtr(MA_NOACTIVATE);
return;
}
else if (m.Msg == WM_NCACTIVATE)
{
if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
{
if (m.LParam != IntPtr.Zero)
{
SetActiveWindow(m.LParam);
}
else
{
SetActiveWindow(IntPtr.Zero);
}
}
}
base.WndProc(ref m);
}
这样即使窗体上有可获得焦点的Control,键盘也不会抢占焦点了~
要下载例程请点这里
相关文章推荐
- 创建类似于输入法窗口的非激活窗口
- 创建类似于输入法窗口的非激活窗口
- 创建类似于输入法窗口的非激活窗口--续
- 创建类似于输入法窗口的非激活窗口
- 再议“创建类似于输入法窗口的非激活窗口”
- 创建一个真正隐藏的窗口(永不被激活,永不获取焦点)
- 如何在游戏窗口中激活当前输入法
- MFC控件的不创建窗口也允许激活的选项查探
- 一个关于如何创建类似于QQ客户端聊天窗口的模拟小项目
- Doc的窗口就创建一个,如果已经存在就激活那个窗口,不存在就建立Doc(转自CSDN)
- windows mobile 1.如何真正的退出程序而不隐藏窗体。2.让窗体跟着输入法窗口上移。3.如何创建非全屏Form
- 创建类似于iTunes的窗口
- Jquery之Boxy插件--创建模态窗口
- 导致CreateWindow创建窗口失败的一种原因
- 如何创建一个用弹出窗口来查看详细信息的超链接列
- Eclipse 启动时弹出无法创建Java虚拟机窗口,解决办法
- 转-JS子窗口创建父窗口操作父窗口
- VC++自己创建窗口时禁止窗口拉伸改变大小
- Android应用程序窗口(Activity)的视图对象(View)的创建过程分析
- 创建一个窗口