C#实现永无焦点的窗体,类似IME

jy02305022 2012-07-17 07:00:11
这个窗体类似与输入法窗体 就是获得不了焦点,比较常用的地方有"提示框","下拉框","浮动工具栏"等

其实这个问题困扰我很久了,在这里也问了不少人,得到了不少帮助,今天终于算完成了一个比较成熟的版本
唯三的限制就是
1 窗体不能有标题栏,不然点击标题栏一样会使窗体得到焦点
2 不能将窗体对象强转成Form后调用TopMost=true (因为这个属性不能重写,我用的是new关键字),当然更不能调用Activate()主动激活他
3 不能在窗体上放上可以接受焦点的控件,如Textbox





public partial class Form2 : Form
{
public Form2()
{
SetControlStyleMethod = typeof(Control).GetMethod("SetStyle",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod);
SetChildControlNoFocus(this);
this.FormBorderStyle = FormBorderStyle.None;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.SetStyle(ControlStyles.Selectable, false);
this.BackColor = Color.Red;
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
}

protected override void WndProc(ref Message m)
{
if (m.Msg == 0x21)
{
m.Result = new IntPtr(0x03);
return;
}
base.WndProc(ref m);
}

protected override bool ShowWithoutActivation
{
get
{
return true;
}
}


void SetChildControlNoFocus(Control ctrl)
{
foreach (Control c in ctrl.Controls)
{
SetControlNoFocus(c);
}
}

MethodInfo SetControlStyleMethod;
object[] SetControlStyleArgs = new object[] { ControlStyles.Selectable, false };
private void SetControlNoFocus(Control ctrl)
{
SetControlStyleMethod.Invoke(ctrl, SetControlStyleArgs);//设置控件无法获得焦点
SetChildControlNoFocus(ctrl); //同时设置其子控件
}

[DllImport("user32", EntryPoint = "SetWindowPos")]
static extern bool SetWindowPos(IntPtr hWnd, int hWndlnsertAfter, int X, int Y, int cx, int cy, int flags);

bool _TopMost = false;
public new bool TopMost
{
get
{
return _TopMost;
}
set
{
_TopMost = value;
SetWindowPos(Handle, TopMost ? -1 : -2, 0, 0, 0, 0, 19);
}
}
}

...全文
625 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangweiisme 2014-12-18
  • 打赏
  • 举报
回复
用这个方法好像窗口不能置顶?
「已注销」 2013-12-18
  • 打赏
  • 举报
回复
引用 9 楼 dongxinxi 的回复:
SetWindowText http://msdn.microsoft.com/en-us/library/ms633546(VS.85).aspx 其实你说的只是拦截IME焦点,可以禁用ImeMode,重写消息处理,拦截WM_IME_STARTCOMPOSITION(直接return)
SetWindowText 这个是设置窗口标题吧
「已注销」 2013-12-18
  • 打赏
  • 举报
回复
引用 9 楼 dongxinxi 的回复:
SetWindowText http://msdn.microsoft.com/en-us/library/ms633546(VS.85).aspx 其实你说的只是拦截IME焦点,可以禁用ImeMode,重写消息处理,拦截WM_IME_STARTCOMPOSITION(直接return)
这个到不是很清楚,我改天试试,谢谢
  • 打赏
  • 举报
回复
SetWindowText http://msdn.microsoft.com/en-us/library/ms633546(VS.85).aspx 其实你说的只是拦截IME焦点,可以禁用ImeMode,重写消息处理,拦截WM_IME_STARTCOMPOSITION(直接return)
「已注销」 2013-12-16
  • 打赏
  • 举报
回复
引用 5 楼 huyantong 的回复:
您好,有个疑问,我的单独软件界面(只有一个窗体,模拟键盘)已经隐藏了标题栏,也做了禁用焦点的动作,但是奇怪的是软件最上方同样可以获得焦点,这个获得焦点的区域大概是20个点高,类似标题栏大小,在整个节目的最上一条,如果没有禁用标题栏,这个区域点击后是不会有焦点的,但是隐藏标题栏后就有焦点了。 这个区域。
有没有用什么重置标题栏区域的API?
「已注销」 2013-12-16
  • 打赏
  • 举报
回复
引用 6 楼 dongxinxi 的回复:
输入法窗体获得不了焦点,那怎么用鼠标移动它的? 应该做成“穿透窗体”,就像QQ音乐的歌词被锁定后的效果 http://blog.163.com/y_p_xu/blog/static/17085710220111013101735546/
虽然这个帖子是几年前的了.... 不过穿透穿透和无焦点仍然是不同概念的,无焦点不代表不能点击不能操作,无焦点的意思是,对该窗体操作的时候焦点依然存在于之前的程序里 比如你在输入文字,你用鼠标移动输入法的框,但输入的光标仍然存在
  • 打赏
  • 举报
回复
输入法窗体获得不了焦点,那怎么用鼠标移动它的? 应该做成“穿透窗体”,就像QQ音乐的歌词被锁定后的效果 http://blog.163.com/y_p_xu/blog/static/17085710220111013101735546/
huyantong 2013-12-16
  • 打赏
  • 举报
回复
您好,有个疑问,我的单独软件界面(只有一个窗体,模拟键盘)已经隐藏了标题栏,也做了禁用焦点的动作,但是奇怪的是软件最上方同样可以获得焦点,这个获得焦点的区域大概是20个点高,类似标题栏大小,在整个节目的最上一条,如果没有禁用标题栏,这个区域点击后是不会有焦点的,但是隐藏标题栏后就有焦点了。

这个区域。
ttyp 2012-09-03
  • 打赏
  • 举报
回复
不错,谢谢了,正好用上
「已注销」 2012-07-17
  • 打赏
  • 举报
回复
这里可以多一步判断,当然,不判断也没问题

private void SetControlNoFocus(Control ctrl)
{
SetControlStyleMethod.Invoke(ctrl, SetControlStyleArgs);//设置控件无法获得焦点
if (ctrl.HasChildren)
{
SetChildControlNoFocus(ctrl); //同时设置其子控件
}
}
xixihaha_2011_098 2012-07-17
  • 打赏
  • 举报
回复
完成了,发布出来,大家一起学习.精神可嘉

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧