通知窗口-防止窗口获得焦点我在让通知框在c#中正常工作时遇到了一些问题。基本上我在屏幕右下角显示了一个无边框的表单,它显示一条消息几秒钟然后消失。问题是我需要它出现在其他窗口的顶部,而不是偷走焦点。理想情况下,我希望它是纯托管代码,尽管对于像这样的例子我怀疑这是可能的。目前我正在阻止它在调用带有覆盖的Form.Show()时窃取焦点:protectedoverrideboolShowWithoutActivation//stopsthewindowfromstealingfocus{get{returntrue;}}然后忽略鼠标点击:privateconstintWM_MOUSEACTIVATE=0x0021;私人常量MA_NOACTIVATEANDEAT=0x0004;protectedoverridevoidWndProc(refMessagem){if(m.Msg==WM_MOUSEACTIVATE){m.Result=(IntPtr)MA_NOACTIVATEANDEAT;返回;}base.WndProc(refm);,如果我将它们与TopMost=true(我需要)一起使用,它无论如何都会获得焦点,并且如果所有其他窗口都最小化。那么,有什么方法可以防止表单获得焦点(无论是通过鼠标单击、alt-tab等),同时仍然是最顶层/最顶层的表单?即使它只是立即将焦点放回到窗口上,它也会偷走它(尽管会引入闪烁)。任何建议将不胜感激,我真的很喜欢这个。编辑:好的,所以我最终决定让这个工作使用:protectedoverrideboolShowWithoutActivation//stopsthewindowfromstealingfocus{get{returntrue;}}//constintWS_EX_NOACTIVATE=0x08000000;constintWS_EX_TOPMOST=0x00000008;protectedoverrideCreateParamsCreateParams{get{CreateParamsparam=base.CreateParams;param.ExStyle|=WS_EX_TOPMOST;//使表单最顶层param.ExStyle|=WS_EX_NOACTIVATE;//防止表单被激活returnparam;}}//和[DllImport("user32.dll")]privateexternstaticIntPtrSetActiveWindow(IntPtrhandle);私人常量intWM_ACTIVATE=6;私人常量WA_INACTIVE=0;私人常量intWM_MOUSEACTIVATE=0x0021;私人常量MA_NOACTIVATEANDEAT=0x0004;protectedoverridevoidWndProc(refMessagem){if(m.Msg==WM_MOUSEACTIVATE){m.Result=(IntPtr)MA_NOACTIVATEANDEAT;//防止表单被点击获得焦点return;}if(m.Msg==WM_ACTIVATE)//如果收到消息通过以某种方式激活表单{if(((int)m.WParam&0xFFFF)!=WA_INACTIVE){if(m.LParam!=IntPtr.Zero){SetActiveWindow(m.LParam);}else{//找不到发件人,只需将其激活即可。SetActiveWindow(IntPtr.Zero);我还在GotFocus事件中添加了Form.Hide(),这样即使它以某种方式获得焦点,它也会关闭并退出ASAPUser此外,如果有人想知道,所有窗口样式常量等都可以在WINUSER中找到。H,或者如果找不到,请访问http://www.woodmann.com/fravia/sources/WINUSER.H。它。但是,如果有人能看到更优雅的方式,将不胜感激。在WPF中试试这个:ShowActivated="False"可能WS_EX_NOACTIVATE扩展窗口样式就是您正在寻找的样式。单击时不会激活具有此样式的窗口。例如,“虚拟键盘”窗口就是这种风格。要将此样式应用于窗口,请覆盖CreateParams函数并更改baseParams.ExStyle。我不是在寻找学分,因为原始发布者已经发布了适用于他们的解决方案,但我想分享我在这个问题上的经验。使用上面的解决方案(位于问题的底部而不是答案形式)给我一个Win32Exception:Errorcreatingwindowhandle错误。使用WndProc代码时,它会发布在那里。ShowWithoutActivation和CreateParams部分可以很好地防止表单被激活并仍然保持在最顶层。我想出了一个替代解决方案来防止使用SetWindowLong单击表单,它使表单透明以便可以单击它和SetLayeredWindowAttributes,它将透明度恢复为正常状态以便您可以再次看到表单,但仍然继续单击表单.注意:您在这种状态下与表单完全交互-即使尝试单击“X”按钮也只是单击该位置表单后面的任何内容,因此您需要使用代码关闭表单:publicpartialclassForm1:形式{privateenumGWL:int{ExStyle=-20}privateenumWS_EX:int{Transparent=0x20,Layered=0x80000}publicenumLWA:int{ColorKey=0x1,Alpha=0x2}[DllImport("user32.dll")]staticexternintSetWindowLong(IntPtrhWnd,intnIndex,intdwNewLong);[DllImport("user32.dll")]staticexternboolSetLayeredWindowAttributes(IntPtrhwnd,uintcrKey,bytebAlpha,uintdwFlags);protectedoverrideboolShowWithoutActivation{re{}}constintWS_EX_NOACTIVATE=0x08000000;constintWS_EX_TOPMOST=0x00000008;protectedoverrideCreateParamsCreateParams{get{CreateParamsparam=base.CreateParams;param.ExStyle|=WS_EX_TOPMOST;//使表单最顶层param.ExStyle|=WS_EX_NOACTIVATE;//防止表单被激活returnparam;}}publicForm1(){InitializeComponent();}privatevoidForm1_Load(objectsender,EventArgse){//阻止表单出现在任务栏中,这也阻止了Alt+Tab激活this.ShowInTaskbar=false;//允许单击表单,这样消息就不会在物理上干扰计算机上正在完成的工作SetWindowLong(this.Handle,(int)GWL.ExStyle,(int)WS_EX.Layered|(int)WS_EX.Transparent);//设置表单的不透明度bytenOpacity=255;//0=不可见,255=实心,介于两者之间的任何东西都将显示具有透明度的表单SetLayeredWindowAttributes(this.Handle,0,nOpacity,(uint)LWA.Alpha);通过对上面的WndProc代码进行一些小的更改,我能够使原始方法也能正常工作它的作用注意:这也使表单不可点击但行为不同,因为您实际上可以点击最小值、最大值和“X”按钮,但是当你这样做时没有任何反应。当你在窗体的边缘时,鼠标光标也会发生变化,就像resize但不允许resize:以上是C#学习教程:通知窗口——防止窗口获得焦点的全部内容分享,如果对大家有用,需要了解更多C#学习教程,希望大家多多关注——publicpartialclassForm1:Form{protectedoverrideboolShowWithoutActivation{get{returntrue;}}constintWS_EX_NOACTIVATE=0x08000000;constintWS_EX_TOPMOST=0x00000008;CreateParamsparam=base.CreateParams;param.ExStyle|=WS_EX_TOPMOST;//使表单最顶层param.ExStyle|=WS_EX_NOACTIVATE;//防止表单被激活returnparam;}}[DllImport("user32.dll")]privateexternstaticIntPtrSetActiveWindow(IntPtrhandle);私人常量intWM_ACTIVATE=6;私人常量WA_INACTIVE=0;私人常量intWM_MOUSEACTIVATE=0x0021;私人常量MA_NOACTIVATEANDEAT=0x0004;protectedoverridevoidWndProc(refMessagem){if(m.Msg==WM_MOUSEACTIVATE){m.Result=(IntPtr)MA_NOACTIVATEANDEAT;//防止表单被clicked并获得焦点返回;}if(m.Msg==WM_ACTIVATE)//如果消息通过以某种方式激活表单{if(((int)m.WParam&0xFFFF)!=WA_INACTIVE){if(m.LParam!=IntPtr.Zero){SetActiveWindow(m.LParam);}else{//找不到发件人,只需将其激活即可。SetActiveWindow(IntPtr.Zero);}}}else{base.WndProc(refm);}}publicForm1(){InitializeComponent();}privatevoidForm1_Load(objectsender,EventArgse){//阻止表单出现在任务栏中,这也阻止了Alt+Tab激活this.ShowInTaskbar=false;}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处:
