首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

C# 實作彈出視窗殺手(上):系統匣、定時器與 IE 視窗枚舉

     編輯:VC++

專案目標

開發常駐系統匣的工具,定期掃描並關閉 IE 彈出視窗,並支援熱鍵手動觸發。採用 C# 實作,視窗搜尋效能優於傳統 C++ 方案。

核心技術模組

  • 系統匣圖示 (NotifyIcon)
  • 視窗顯示/隱藏切換
  • 定時器 (System.Timers.Timer)
  • Win32 API 視窗枚舉 (EnumThreadWindows、FindWindowEx)
  • 系統熱鍵註冊 (RegisterHotKey)

1. 系統匣程式架構

// 主視窗隱藏不顯示在工作列
this.ShowInTaskbar = false;
this.Visible = false;

// 關閉鈕改為最小化到匣
protected override void OnClosing(CancelEventArgs e)
{
    e.Cancel = true;
    this.WindowState = FormWindowState.Minimized;
    this.Hide();
}

// 匣圖示右鍵選單動態啟用/停用
private void menu_App_BeforePopup(object sender, EventArgs e)
{
    if (this.WindowState == FormWindowState.Minimized)
    {
        App_Show.Enabled = true;
        App_Hide.Enabled = false;
    }
    else
    {
        App_Show.Enabled = false;
        App_Hide.Enabled = true;
    }
}

2. 定時掃描機制

m_Timer = new System.Timers.Timer();
m_Timer.Elapsed += OnTimerKillPopup;
m_Timer.Interval = 3000; // 3 秒
m_Timer.Enabled = true;

protected void OnTimerKillPopup(object source, ElapsedEventArgs e)
{
    m_Timer.Enabled = false;
    FindPopupToKill();
    m_Timer.Enabled = true;
}

3. IE 視窗枚舉與關閉(兩種做法)

做法 A:進程 → 執行緒 → 視窗 回呼

Process[] ies = Process.GetProcessesByName("IEXPLORE");
foreach (Process p in ies) FindPopupToKill(p);

void FindPopupToKill(Process p)
{
    foreach (ProcessThread t in p.Threads)
    {
        NativeWIN32.EnumThreadProc cb = MyEnumThreadWindowsProc;
        NativeWIN32.EnumThreadWindows(t.Id, cb, IntPtr.Zero);
    }
}

bool MyEnumThreadWindowsProc(IntPtr hwnd, IntPtr lParam)
{
    NativeWIN32.STRINGBUFFER title;
    NativeWIN32.GetWindowText(hwnd, out title, 256);
    string s = title.szText;
    if (s.Length == 0) return true;

    foreach (ListViewItem item in listView1.Items)
        if (s.StartsWith(item.Text))
            NativeWIN32.SendMessage(hwnd, NativeWIN32.WM_SYSCOMMAND,
                NativeWIN32.SC_CLOSE, IntPtr.Zero);
    return true;
}

做法 B:FindWindowEx 直接尋找 IEFrame 類別(更簡潔高效)

void FindPopupToKill()
{
    IntPtr hParent = IntPtr.Zero, hNext = IntPtr.Zero;
    const string IE_CLASS = "IEFrame";
    do
    {
        hNext = NativeWIN32.FindWindowEx(hParent, hNext, IE_CLASS, IntPtr.Zero);
        if (hNext != IntPtr.Zero)
        {
            NativeWIN32.STRINGBUFFER title;
            NativeWIN32.GetWindowText(hNext, out title, 256);
            string s = title.szText;
            if (s.Length > 0)
            {
                foreach (ListViewItem item in listView1.Items)
                    if (s.StartsWith(item.Text))
                        NativeWIN32.SendMessage(hNext, NativeWIN32.WM_SYSCOMMAND,
                            NativeWIN32.SC_CLOSE, IntPtr.Zero);
            }
        }
    } while (hNext != IntPtr.Zero);
}

P/Invoke 定義

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

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr next,
        string className, IntPtr windowTitle);

    [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 lpString, int nMaxCount);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SendMessage(IntPtr hWnd, int msg,
        int wParam, int lParam);

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

    public delegate bool EnumThreadProc(IntPtr hwnd, IntPtr lParam);
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved