Visual C#制作弹出窗口关闭程序

弹出窗口杀手是一个可以自动关闭IE弹出窗口的程序,它工作在系统的托盘中,按照一定的间隔来检测IE窗口,然后关闭弹出窗体。最后,还提供了用热键来杀掉弹出窗口的功能。

   虽然已经有类似的用C++写的程序,但是本文讲述的是用C#来实现这些功能,并且本文所讲的方案在查找窗口上的方法要比更快一些。

   这是一个崭新的话题,在Internet上我们还可以看到许多类似的程序。但是我也还是要借这个机会来讲述一些下面的技术在C#中如何实现:

   系统托盘
   程序切换
   计时控件
   查找窗口
   系统热键

生成一个系统托盘程序

   首先,产生一个新的C# Windows Form程序, 将NotifyIcon控件从工具箱中拖到窗体中,如下图所示:

在C# windows Form程序中添加托盘

   为了保证系统托盘的图标和应用程序的图标一致,我们用一个共同的图标文件a.ico来设置系统托盘的图标和应用程序的图标。

   为了使程序不显示在工具栏上,我们可以设置窗体的visible属性为false. 这个可以在窗体属性窗口中直接实现。

   this.ShowInTaskbar = false;

   到目前为止,系统托盘已基本好了,但是我们还没有设置右键菜单,也没有使程序显示和隐藏的功能。

程序切换

   首先,程序的主窗体可以根据不同的状态来选择显示或者是隐藏,除此之外,我们可以用WindowState设置窗体的状态:
public void HideApp()
{
this.WindowState = FormWindowState.Minimized;
Hide();
}
public void ShowApp()
{
Show();
this.WindowState = FormWindowState.Normal;
}
  一个非常有趣的功能是让用户关闭窗体的时候程序并不是退出,为了实现这个功能,我们必须要重写窗体的OnClosing事件。


protected override void OnClosing(CancelEventArgs e)
{
// 用最小化来代替关闭操作d
e.Cancel = true;
// 最小化,并且隐藏窗体
this.WindowState = FormWindowState.Minimized;
Hide();
}
当然,我们必须要提供一个必须的退出方法.这个可以在托盘的右键菜单的exit中实现,
private void menu_App_Exit(object sender, System.EventArgs e)
{
NativeWIN32.UnregisterHotKey(Handle, 100);
//隐藏托盘
notifyIcon1.Visible = false;
Application.Exit();
}
添加右键菜单

   添加一个右键菜单和添加托盘基本一样,从工具箱中添加context menu就可以.右键菜单在你鼠标右键按下的时候是会自动弹出的。

   当设置好右键菜单以后,我们必要要根据不同的情况来启用或停用右键菜单,这个可以通过在菜单的BeforePopup设置。Enabled属性来实现。


private void menu_App_BeforePopup(object sender, System.EventArgs e)
{
if ( this.WindowState == FormWindowState.Minimized )
{
App_Show.Enabled = true;
App_Hide.Enabled = false;
}
else
{
App_Show.Enabled = false;
App_Hide.Enabled = true;
}
}
计时工具

   .Net Framework的 Timer能和系统的Win32 timer实现一样的功能。我们要做的就是设置一个timer,然后合理的设置属性。
m_Timer = new System.Timers.Timer(); // explicit namespace (Timer also in System.Threading)
m_Timer.Elapsed += new ElapsedEventHandler(OnTimerKillPopup);
m_Timer.Interval = m_nInterval; // for instance 3000 milliseconds
m_Timer.Enabled = true; // start timer

protected void OnTimerKillPopup(Object source, ElapsedEventArgs e)
{
m_Timer.Enabled = false; // pause the timer

FindPopupToKill();

m_Timer.Enabled = true;
}
本地win32窗体查找

   本程序的实现原理是这样,先检查所有的IE窗口标题,然后于已经有的列表来比较,如果有相同的,我们就关闭这个窗口。

   按照上面的方法,我们每n妙使用KillPopup()来检查。比较遗憾的是我们无法使用安全代码来完成所有的工作。我们可以使用 System.Diagnostics.Proces来检查所有的IE进程,然后得到主窗体。但是每一个IE进程可以打开好几个窗口,虽然每一个窗体都于一个进程相关,但是还没有办法来使每一个窗体于进程对应起来。

   一个可行的办法使用System.Diagnostics.Process列举出所有的运行的进程,然后System.Diagnostics.ProcessThreadCollection 来得到他们的.Threads属性,为了得到thread Id,我们使用Win32 API EnumThreadWindows(DWORD threadId,WNDENUMPROC lpfn,LPARAM lParam) 来实现,这是一个回调(call back)函数,他可以列举出于进程相关的窗体。当我们得到了窗体的句柄以后,我们可以使用另一个API函数 GetWindowText(HWND hwnd,/*out*/LPTSTR lpString,int nMaxCount)来得到窗体的标题,然后根据已经有的窗体,调用API函数SendMessage(HWND hWnd,int msg,int wParam,int lParam)来关闭窗口。下面使演示代码


Process[] myProcesses = Process.GetProcessesByName(\"IEXPLORE\");

foreach(Process myProcess in myProcesses)
{
FindPopupToKill(myProcess);
}

protected void FindPopupToKill(Process p)
{
// traverse all threads and enum all windows attached to the thread
foreach (ProcessThread t in p.Threads)
{
int threadId = t.Id;

NativeWIN32.EnumThreadProc callbackProc =
new NativeWIN32.EnumThreadProc(MyEnumThreadWindowsProc);
NativeWIN32.EnumThreadWindows(threadId, callbackProc, IntPtr.Zero /*lParam*/);
}
}

// callback used to enumerate Windows attached to one of the threads
bool MyEnumThreadWindowsProc(IntPtr hwnd, IntPtr lParam)
{

public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;


// get window caption
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
NativeWIN32.GetWindowText(hwnd, out sLimitedLengthWindowTitle, 256);

String sWindowTitle = sLimitedLengthWindowTitle.szText;
if (sWindowTitle.Length==0) return true;

// find this caption in the list of banned captions
foreach (ListViewItem item in listView1.Items)
{
if ( sWindowTitle.StartsWith(item.Text) )
NativeWIN32.SendMessage(hwnd, NativeWIN32.WM_SYSCOMMAND,
NativeWIN32.SC_CLOSE,
IntPtr.Zero); // try soft kill
}

return true;
}

public class NativeWIN32
{
public delegate bool EnumThreadProc(IntPtr hwnd, IntPtr lParam);

[DllImport(\"user32.dll\", CharSet=CharSet.Auto)]
public static extern bool EnumThreadWindows(int threadId, EnumThreadProc pfnEnum, IntPtr lParam);

// used for an output LPCTSTR parameter on a method call
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct STRINGBUFFER
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public string szText;
}

[DllImport(\"user32.dll\", CharSet=CharSet.Auto)]
public static extern int GetWindowText(IntPtr hWnd, out STRINGBUFFER ClassName, int nMaxCount);

[DllImport(\"user32.dll\", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
}
  上面的方法在性能上是不错的,因为他过滤了其他非IE的窗口.但是我们可以用一个更简单的方法来实现,就是调用API FindWindowEx(HWND hWndParent, HWND hWndNext, /*in*/LPCTSTR szClassName, /*in*/LPCTSTR szWindowTitle)方法.比较有用的是这句,我们可以使用registered window class name来找到IE窗口(IEFrame是所有打开的IE的标识).


protected void FindPopupToKill()
{
IntPtr hParent = IntPtr.Zero;
IntPtr hNext = IntPtr.Zero;
String sClassNameFilter = \"IEFrame\"; // 所有IE窗口的类
do
{
hNext = NativeWIN32.FindWindowEx(hParent,hNext,sClassNameFilter,IntPtr.Zero);

// we\'ve got a hwnd to play with
if ( !hNext.Equals(IntPtr.Zero) )
{
// get window caption
NativeWIN32.STRINGBUFFER sLimitedLengthWindowTitle;
NativeWIN32.GetWindowText(hNext, out sLimitedLengthWindowTitle, 256);

String sWindowTitle = sLimitedLengthWindowTitle.szText;
if (sWindowTitle.Length>0)
{
// find this caption in the list of banned captions
foreach (ListViewItem item in listView1.Items)
{
if ( sWindowTitle.StartsWith(item.Text) )
NativeWIN32.SendMessage(hNext, NativeWIN32.WM_SYSCOMMAND,
NativeWIN32.SC_CLOSE,
IntPtr.Zero); // try soft kill
}
}
}
}
while (!hNext.Equals(IntPtr.Zero));

}

public class NativeWIN32
{
[DllImport(\"user32.dll\", CharSet=CharSet.Auto)]
public static extern IntPtr FindWindowEx(IntPtr parent /*HWND*/,
IntPtr next /*HWND*/,
string sClassName,
IntPtr sWindowTitle);

}
代码下载:

演示程序:

注册系统热键

   系统热键用在像弹出窗口杀手这种应用程序非常有用, Ctrl+Shift+J是缺省热键。

   说道实现,我们继续用RegisterHotkey(HWND hWnd, int id, UINT fsModifiers, UINT vkey)。完成,代码如下:


public void SetHotKey(Keys c, bool bCtrl, bool bShift, bool bAlt, bool bWindows)
{
m_hotkey = c;
m_ctrlhotkey = bCtrl;
m_shifthotkey = bShift;
m_althotkey = bAlt;
m_winhotkey = bWindows;

// update hotkey
NativeWIN32.KeyModifiers modifiers = NativeWIN32.KeyModifiers.None;
if (m_ctrlhotkey)
modifiers |= NativeWIN32.KeyModifiers.Control;
if (m_shifthotkey)
modifiers |= NativeWIN32.KeyModifiers.Shift;
if (m_althotkey)
modifiers |= NativeWIN32.KeyModifiers.Alt;
if (m_winhotkey)
modifiers |= NativeWIN32.KeyModifiers.Windows;

NativeWIN32.RegisterHotKey(Handle, 100, modifiers, m_hotkey); //Keys.J);
}
一般的,注册热键要一下几步

/* ------- using HOTKEYs in a C# application -------

-- code snippet by James J Thompson --

在Form的load 中 : Ctrl+Shift+J

bool success = RegisterHotKey(Handle,
100,
KeyModifiers.Control | KeyModifiers.Shift,
Keys.J);
  在 form的closing中 :

   UnregisterHotKey(Handle, 100);

   如何处理热键 :


protected override void WndProc( ref Message m )
{
const int WM_HOTKEY = 0x0312;

switch(m.Msg)
{
case WM_HOTKEY:

MessageBox.Show(\"Hotkey pressed\");

ProcessHotkey();

break;
}
base.WndProc(ref m );
}


public class NativeWIN32
{
[DllImport(\"user32.dll\", SetLastError=true)]
public static extern bool RegisterHotKey( IntPtr hWnd, // handle to window
int id, // hot key identifier
KeyModifiers fsModifiers, // key-modifier options
Keys vk // virtual-key code
);

[DllImport(\"user32.dll\", SetLastError=true)]
public static extern bool UnregisterHotKey( IntPtr hWnd, // handle to window
int id // hot key identifier
); Flags()]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8
}

}
------- using HOTKEYs in a C# application ------- */

  当我们按下热键以后,流程是这样:首先用HWND GetForegroundWindow()来得到窗体,然后要抓出窗体的标题, GetWindowText(HWND hwnd, /*out*/LPTSTR lpString, int nMaxCount). 具体如下:

protected void ProcessHotkey()
{
IntPtr hwnd = NativeWIN32.GetForegroundWindow();
if (!hwnd.Equals(IntPtr.Zero))
{
NativeWIN32.STRINGBUFFER sWindowTitle;
NativeWIN32.GetWindowText(hwnd, out sWindowTitle, 256);

if (sWindowTitle.szText.Length>0)
AddWindowTitle( sWindowTitle.szText ); // add to the ListView (Form)
}
}

转载于:https://www.cnblogs.com/chenbg2001/archive/2009/01/15/1376553.html

使用命令行编译并运行应用程序 如何使用命令行工具来编译一个C#源文件呢? 前提条件:必须安装一个Visual Stdio,版本自选;建议安装2010以后的版本,本示例以Visual Stdio 2013为例; 打开记事本文件,编写代码如下,并保存为 Frist.cs; using System; namespace MyFirstProgram { class Program 阅读详情

相关推荐

C#实现Windows系统关机拦截:工业控制与关键业务防误操作方案

在工业控制、金融交易等关键业务场景中,系统稳定性至关重要。Windows操作系统通过消息机制管理应用程序生命周期,其中WM_QUERYENDSESSION消息是系统在关机、重启或注销前向所有程序发出的协商请求。理解这一机制的技术价值在于,开发者可以通过编程方式介入系统关机流程,为关键业务提供保护层。通过C#的WndProc消息处理机制,应用程序能够拦截并响应系统关机请求,实现业务连续性的保障。这一技术特别适用于上位机开发、桌面客户端维护等场景,能有效防止因误操作导致的非计划停机。本文以C#体应用为例,详细

weixin_30439067的博客 381

asp.net(C#)里弹出对话框并在设定时间内关闭

asp.net(C#)里点击页面某一项,弹出对话框显示其详细信息,并可以设置自动关闭对话框的时间。

Unity资源逆向实战:AssetRipper核心原理与资产提取全流程详解

在游戏开发与数字内容创作领域,资源管理与复用是核心技术环节。Unity引擎通过序列化与打包机制,将模型、贴图、音频等资产封装为特定格式文件,以优化运行时性能与保护知识产权。其核心原理涉及二进制序列化、依赖关系分析与资源包(如.assets、.bundle)的生成。理解这一流程对于技术研究、美术资源学习、项目灾难恢复及二次创作(如Mod制作)具有重要价值。AssetRipper作为一款高性能开源工具,通过逆向解析Unity资源包结构,重建资产引用关系,支持从纹理、网格到脚本的完整提取,并能输出为OBJ、PNG

weixin_33841503的博客 435

C# WinForm 弹出窗口

仿照qq弹做的不规则图形弹出窗口,可以作为消息提示等应用。 窗口底图可以自己设置,标题,内容可以设置位置,并提供点击事件开放。

C# 弹出窗口 show()和showdialog()

   我们在构建C# Form窗口的时候经常需要到弹出新的窗口,那么接着就会如何弹出窗口的疑问。这里介绍最常见的两种弹方法show()和showdialog()。我在VS2019中构建一个简单的工程来讲解让他们之间的区别。大家也可以动手建一个体验他们之间的区别。  ...

C/C#、Android driver、STM32、Linux等等。 1万+

Visual C#弹出窗口杀手

     弹出窗口杀手是一个可以自动关闭IE弹出窗口的程序,它工作在系统的托盘中,按照一定的间隔来检测IE窗口,然后关闭弹出体。最后,还提供了用热键来杀掉弹出窗口的功能。    虽然已经有类似的用C++写的程序,但是本文讲述的是用C#来实现这些功能,并且本文所讲的方案在查找窗口上的方法要比更快一些。    这是一个崭新的话题,在Internet上我们还可以看到许多类似的程序。但是我也

lgb571的专栏 693

C#利用弹关闭程序时,会出现多次弹原因与解决办法

每一个_isSave.ShowDialog()都会打开一次弹,所以为了解决这个问题,应只打开一次。

weixin_63170615的博客 491

C#制作软件时体的弹出与嵌入

C#制作软件时体的弹出与嵌入

wanganqiqi的博客 2631

php study计算闰年,C#_简单实现C#体程序判断是否闰年,利用VS2010的C#.NET能够很简单创 - phpStudy...

简单实现C#体程序判断是否闰年利用VS2010的C#.NET能够很简单创建一个体。同时可以很轻松地为这个体布局,添加事件,下面用一个简单的体程序,判断是否闰年,来说明这个问题。同时加一个关闭事件,在用户关闭体之前弹出对话框询问用户是否关闭此体?如下图:具体做法如下。1、打开VS2010之后,文件->新建->项目->选择其它语言中的->Visual C# -&gt...

weixin_28811227的博客 648

C#】简单体程序,判断是否闰年,禁止体调整大小,关闭体前的判断

利用VS2010的C#.NET能够很简单创建一个体。同时可以很轻松地为这个体布局,添加事件,下面用一个简单的体程序,判断是否闰年,来说明这个问题。同时加一个关闭事件,在用户关闭体之前弹出对话框询问用户是否关闭此体?如下图: 具体做法如下。 1、打开VS2010之后,文件->新建->项目->选择其它语言中的->Visual C# ->Windows->Windows 体应用程

编程记录,亲测有效 7531

Visual Studio 2010 Ultimate 中文版安装教程(ISO文件安装步骤附安装包下载)​

​(可以自己选要装哪些工具,比如只装 C# 不装 C++)如果你不确定,选 ​。

IDOlaoluo的博客 1108

Traymond完全指南:从安装到自定义快捷键,新手也能轻松上手

Traymond是一款简单实用的Windows应用程序,能够帮助用户将窗口最小化到系统托盘图标,有效释放任务栏空间,提升工作效率。本文将为新手用户提供从安装到自定义快捷键的完整操作指南,让你轻松掌握这款窗口管理工具的使用方法。 ## 一、Traymond简介:让窗口管理更高效 Traymond的核心功能是将任意窗口最小化到系统托盘,通过点击托盘图标即可快速恢复窗口。这对于需要同时打开多个窗口

gitblog_00320的博客 732

C# WinForm开发中Settings.settings的深度解析与高效应用

应用程序配置管理是软件开发中的基础环节,它关乎软件的健壮性与用户体验。其核心原理在于通过标准化的方式持久化应用状态与用户偏好,实现数据的类型安全存储与便捷访问。在C# WinForm开发领域,.NET框架内置的Settings.settings机制提供了强大的技术价值,它将配置抽象为强类型属性,支持设计时数据绑定,并能自动处理作用域(应用程序与用户)隔离。这一特性极大地简化了开发流程,减少了手动处理XML或注册表的繁琐与潜在错误。其典型应用场景包括管理窗口状态、用户主题偏好、业务参数及会话缓存等。本文将聚焦

weixin_30516243的博客 400

如何把网易云NCM文件转成MP3:ncmdumpGUI免费指南

在网易云音乐里下载的歌,换到别的播放器就提示"无法识别的文件格式",车机更是直接拒绝播放。问题不在文件损坏,而在 NCM——网易云私有的加密格式。ncmdumpGUI 是一款免费开源的 Windows 图形界面工具,能把 NCM 转成 MP3、FLAC、WAV 等常见音频格式。 ## 批量把 NCM 转成通用音频格式 ncmdumpGUI 做的事只有一件:把你下载好的 NCM 文件,变成普通播

gitblog_00700的博客 1181

一步一步学习Winform系列1:登陆验证模块(初级入门)

阅读目录: 0. Visual Studio 2010开发环境 1. 体属性的设置 2. 体控件与布局 3. 按钮事件代码示例 4. MessageBox.show()消息框的使用 5. 数据库初始连接方式(即用即开)——查询1:验证用户名密码是否匹配 6. 数据库操作方式——查询2:通过用户名获取雇员姓名和职务 延伸知识——数据库连接字符串大解析 延伸知识——数据库注...

weixin_30443075的博客 291

C++ Win32 API实现无限弹整蛊程序:从原理到防御

在Windows桌面开发中,消息循环机制是GUI应用程序与操作系统交互的核心。通过事件驱动模型,程序可以响应用户输入和系统事件,实现动态界面更新。掌握这一原理对于深入理解Windows系统编程至关重要,它不仅揭示了应用程序如何与底层系统通信,也为构建健壮、响应迅速的桌面软件奠定基础。在技术实践中,Win32 API提供了最直接的控制力,允许开发者精细管理窗口行为,例如通过拦截WM_CLOSE消息实现窗口的“顽固”驻留。这种底层控制能力在特定场景下具有独特价值,例如模拟软件异常状态进行测试,或用于无害的整蛊玩

weixin_33785108的博客 397

MoeGoe_GUI语音合成TTS保姆级教程:从文本输入到音频保存播放一步到位

MoeGoe_GUI 是一款免费的 MoeGoe 语音合成 TTS 图形界面工具(GUI),专为 Windows 打造,让你在完全不用敲命令行的情况下,就能完成文本输入、说话人选择、语音合成、音频保存与播放,一站式打通文本转语音(Text-to-Speech)全流程。 本教程面向零基础新手,跟着 6 步操作走,几分钟即可合成出第一条自己的 TTS 语音。 ## 一、先认识 MoeGoe_GUI

gitblog_00609的博客 776

Windows 10 强制更新太烦人?用开源工具 WuMgr 三步夺回更新管理主动权

如果你正在被 Windows 10 的强制更新折腾到崩溃,那么开源工具 WuMgr(Windows Update Manager)就是为你准备的答案——这个用 C# 编写的 Windows 更新管理工具,能把"什么时候装、装哪些、装不装"的决定权,重新交还到你手上。它没有花哨的界面,却做了一件很多人盼了很久的事:让 Win10 找回 Win7 时代那种"更新由我说了算"的体验。 ## 一次刻骨铭

gitblog_00724的博客 324
上一篇: 用Tablediff把表數據生成SQL腳本
下一篇: 老师语录
weixin_30492601
博客等级 码龄11年 119粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值