如何"殺死"一個窗口--WindowKiller

我已經受不了了,當一個軟件有時會彈出對話框,能夠忍,可是若是一個軟件時不時的彈窗,你是否是會有一種衝動--"殺死"它.html

我說的是ORCAD LAYOUT的窗口,下面有圖爲證:

這個窗口進程名叫lsession.exe,每次打開圖檔都有
,這個每隔幾分鐘就提示一次,帶提示聲音,不過能夠設定掉

這個是打開時碰到

這個也是打開時偶爾碰到


那如何殺死它呢,
第一種方法,:關掉它.
第二種方法,不使用它.
第三種方法:念"咒語",用指令,用代碼片斷殺.
session

下面就開始擺道場了.
首先見人說人話,見鬼說鬼話,不一樣的窗口,用不一樣的方式招待.
函數


1.對於Orcad Layout窗口,就能夠發送WM_CLOSE消息:SendMessage( hwndOrcadLayout,WM_CLOSE,0,0 ),或者直接讓它隱身:ShowWindow(hwndOrcadLayout,SW_HIDE),可是無論你是用什麼方法,最終它的進程lsession.exe始終在後臺運行的,因此不會影響軟件的使用.
2.對於關閉按鈕失效的窗口,法術失靈了,怎麼辦呢?看不是還有按鈕!因而咱們能夠發按鍵消息: SendMessage(hwndLayoutPlus, WM_COMMAND, idChildButton,0);

學習

有了核心方法,接下來就是如何實現它.
測試

咱們要時時掃描窗口,查找咱們想要的那個,取得窗口句柄,或者按鈕ID.這就要請出this

BOOL EnumWindows(WNDENUMPROC EnumWindowsProc,LPARAM lParam);
BOOL EnumChildWindows(HWND hWndParent,WNDENUMPROC EnumChildProc,LPARAM lParam);

前者用於掃描主窗口,後者用於掃描子窗口,在WNDENUMPROC回調函數中取得窗口的標題,而後經過標題的對比,找到那個窗口.
spa

回調函數的原型以下:
BOOL CALLBACK EnumWindowsProc(  HWND hwnd,   LPARAM lParam);
第一個參數是不斷掃描到的窗口,第二個參數是用戶自定義的參數( 我用它來傳遞類的this指針)
咱們能夠在此函數裏調用GetWindowText(hwnd,lpszWindowTitle),來取得窗口的標題.

這就引出了一個問題:標題的查找是否是所有字符都要匹配?
.net

這就是爲何不用
FindWindow( NULL,lpszParent );
FindWindowEx(m_hParent,NULL,NULL,lpszChild );
這兩個函數的緣由,因它是全字匹配的,也就是我要實現的是
模糊匹配區分大小寫查找標題
獲得了標題,就動手寫個模糊比較函數吧
指針

inline bool isTextInStr(TCHAR* text,TCHAR *str) //查找str中是否含有text,若是有返回true,不然返回false;嚴格 區分大小寫
        {

                const int lenStr=lstrlen(str);
                const int lenText=lstrlen(text);
                bool bFound=false;
                TCHAR  *lpszSubStr=new TCHAR[ lenText+2];
                for(int i=0;i<=lenStr-lenText;++i)
                {

                        lstrcpyn( lpszSubStr ,&str[i], lenText+1);
                        if( 0==lstrcmp( lpszSubStr,text ) )//equal found return zero//嚴格 區分大小寫
                        {	
                                bFound=true;
                                break;
                        }
                }

                if( lpszSubStr!=0 )
                {
                        delete []lpszSubStr;
                        lpszSubStr=0;
                }
                return bFound;
        }


接下咱們要開始封裝一個類 WindowKiller ,這就又引出了另外一個問題:  像  EnumWindowsProc() 這樣的CALLBACK函數是不能做爲成員函數的.深刻的會涉及到thunk技術的東西,算了仍是下降點難度:把這樣的函數寫成靜態成員函數:
static BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM p_this)
調用時使用
EnumWindows( EnumWindowsProc,reinterpret_cast<LPARAM>(this) );將參數轉化爲this指針;
code

而後在EnumWindowsProc()中再變回來 WindowKiller *pthis=reinterpret_cast<WindowKiller*>(p_this);

因而咱們能夠想象它是這樣工做的:查找全部的窗口,檢查它們的標題,列舉子窗口,找到後,發送消息,以一種溫柔的方式"殺掉"它

//WindowKiller類
//by wisepragma
//軟件與代碼版權全部,僅用於我的測試學習用途,做者不對使用本軟件與代碼產生的任何結果負責
//HOMEPAGE:http://blog.csdn.net/wisepragma


#pragma once 
 
enum ACTION
{	   	 
        ACTION_NULL,ACTION_PRESSBUTTON_BYID,ACTION_SHOW_WIN,ACTION_HIDE_WIN,ACTION_HIDE_WIN_CHILD,ACTION_SHOW_WIN_CHILD,ACTION_CLOSE_WIN,ACTION_CLOSE_WIN_CHILD,ACTION_PRESSBUTTON_BYTXT
};
struct WININFO
{
        HWND hwnd;
        TCHAR *title;
        UINT id;
};
struct ACTIONINFO 
{
        bool bEnable;
        ACTION  act;
        WININFO parent,child,button;
};
struct rule
{
        ACTIONINFO actinfo;
        rule *next;
public:
        rule(ACTION act=ACTION_NULL,TCHAR *lpszParent=NULL,TCHAR* lpszChild=NULL,TCHAR *lpszButtonText=NULL,UINT idButton=0,bool bEnable=true)
        {
                memset(&actinfo,0,sizeof(actinfo));
                next=NULL;
                actinfo.act=act;
                actinfo.parent.title=lpszParent;
                actinfo.child.title=lpszChild;
                actinfo.button.title=lpszButtonText;
                actinfo.button.id=idButton;
                actinfo.bEnable=bEnable;
        }       

};

class	WindowKiller
{
private:

public:
        rule *head,*tail;

        WindowKiller()
        {

                head=NULL;
                tail=NULL;
        }
        ~WindowKiller()
        {

                while(NULL!=head)
                {
                        rule *index=head;
                        head=head->next;
                        delete index;
                                
                        //error
                        // rule *index=head;
                        //delete head;//不要走到馬路中間再看兩邊有沒有車
                        //head=index->next;//不能先拆橋再過河
                        
                }
        }
        void addrule(ACTION act=ACTION_NULL,TCHAR *lpszParent=NULL,TCHAR* lpszChild=NULL,TCHAR *lpszButtonText=NULL,UINT idButton=0)
        {
                rule *index=new rule(act,lpszParent,lpszChild,lpszButtonText,idButton);         
                if(NULL==head) 
                {
                        head=index;
                        tail=head;
                }
                else
                {
                        tail->next=index;
                        tail=index;
                }
        }        

        void action()
        {
                EnumWindows( EnumWindowsProc,reinterpret_cast<LPARAM>(this) );
        }






        static BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM p_this)
        {
                WindowKiller *pthis=reinterpret_cast<WindowKiller*>(p_this);
                TCHAR lpszWinTitle[MAX_PATH]={0};    
                ::GetWindowText(hwnd,lpszWinTitle,MAX_PATH);
                rule *index=pthis->head;
                while(NULL!= index)
                {



                        if( pthis->isTextInStr( index->actinfo.parent.title,lpszWinTitle) )
                        {
                                index->actinfo.parent.hwnd=hwnd;
                                if(index->actinfo.bEnable)
                                {
                                        switch(index->actinfo.act)
                                        {
                                        case ACTION_HIDE_WIN:
                                                ::ShowWindow(hwnd,SW_HIDE);
                                                break;
                                        case ACTION_SHOW_WIN:
                                                ::ShowWindow(hwnd,SW_SHOW);
                                                break;
                                        case ACTION_CLOSE_WIN:
                                                ::SendMessage(hwnd,WM_CLOSE,0,0);
                                                break;
                                        case ACTION_HIDE_WIN_CHILD:
                                        case ACTION_SHOW_WIN_CHILD:
                                        case ACTION_PRESSBUTTON_BYTXT:
                                        case ACTION_PRESSBUTTON_BYID:
                                        case ACTION_CLOSE_WIN_CHILD:
                                                EnumChildWindows(hwnd, &WindowKiller::EnumChildProc, (LPARAM)pthis); 
                                                break;
                                        }
                                }
                        }
                        index=index->next;
                }	   	
                return TRUE;
        }

        static BOOL CALLBACK EnumChildProc(HWND hwndChild,LPARAM p_this)
        {
                WindowKiller *pthis=reinterpret_cast<WindowKiller*>(p_this);

                TCHAR lpszChildText[MAX_PATH];   
                ::GetWindowText(hwndChild,lpszChildText,MAX_PATH);

                rule *index=pthis->head;
                while(NULL!= index)
                {
                        if(index->actinfo.bEnable)
                        {
                                switch(index->actinfo.act)
                                {
                                case ACTION_SHOW_WIN_CHILD:
                                        if( pthis->isTextInStr( index->actinfo.child.title,lpszChildText)  )
                                        {   
                                                index->actinfo.child.hwnd=hwndChild;
                                                if(NULL!=index->actinfo.parent.hwnd)::ShowWindow(index->actinfo.parent.hwnd,SW_SHOW);
                                        }
                                        break;
                                case ACTION_HIDE_WIN_CHILD:
                                        if( pthis->isTextInStr( index->actinfo.child.title,lpszChildText)  )
                                        {   
                                                index->actinfo.child.hwnd=hwndChild;
                                                if(NULL!=index->actinfo.parent.hwnd)::ShowWindow(index->actinfo.parent.hwnd,SW_HIDE);
                                        }
                                        break;

                                case ACTION_PRESSBUTTON_BYTXT:

                                        if( pthis->isTextInStr( index->actinfo.button.title,lpszChildText) )
                                        {
                                                index->actinfo.button.hwnd=hwndChild;
                                        }
                                        if(  pthis->isTextInStr(  index->actinfo.child.title,lpszChildText) ) //equal return zero
                                        {  
                                                if(NULL!=index->actinfo.parent.hwnd  && 
                                                        NULL!=index->actinfo.button.hwnd ) 
                                                {
                                                        UINT idChild=::GetDlgCtrlID(index->actinfo.button.hwnd);
                                                        SendMessage( index->actinfo.parent.hwnd,   WM_COMMAND, idChild,0);	//

                                                }
                                        }			
                                        break;
                                case ACTION_PRESSBUTTON_BYID:
                                        if(  pthis->isTextInStr( index->actinfo.child.title,lpszChildText) ) //equal return zero
                                        { 
                                                if( NULL!=index->actinfo.parent.hwnd  ) 
                                                {
                                                        SendMessage( index->actinfo.parent.hwnd,WM_COMMAND,index->actinfo.button.id,0 );	//(WPARAM)(BN_CLICKED<<16) |
                                                }
                                        }			
                                        break;	
                                case ACTION_CLOSE_WIN_CHILD:   				
                                        if( pthis->isTextInStr( index->actinfo.child.title,lpszChildText)  )
                                        {		
                                                index->actinfo.child.hwnd =hwndChild;
                                                if(NULL!=index->actinfo.parent.hwnd )SendMessage( index->actinfo.parent.hwnd,WM_CLOSE,0,0 );
                                        }
                                        break;
                                }
                        }
                        index=index->next;
                }
                return TRUE;
        }	

        ///////////////////////////////////////////////////////
        inline bool isTextInStr(TCHAR* text,TCHAR *str) //查找str中是否含有text,若是有返回true,不然返回false;嚴格 區分大小寫
        {

                const int lenStr=lstrlen(str);
                const int lenText=lstrlen(text);
                bool bFound=false;
                TCHAR  *lpszSubStr=new TCHAR[ lenText+2];
                for(int i=0;i<=lenStr-lenText;++i)
                {

                        lstrcpyn( lpszSubStr ,&str[i], lenText+1);
                        if( 0==lstrcmp( lpszSubStr,text ) )//equal found return zero//嚴格 區分大小寫
                        {	
                                bFound=true;
                                break;
                        }
                }

                if( lpszSubStr!=0 )
                {
                        delete []lpszSubStr;
                        lpszSubStr=0;
                }
                return bFound;
        }


};


最後的工程中加入定時器,每隔一時間掃描一次窗口
在程序初始化時加入

SetTimer(1,100,NULL);
killer.addrule(ACTION_PRESSBUTTON_BYTXT,TEXT("Layout Plus"),TEXT("This job's netlist has changed.") ,TEXT("否(&N)") );
//killer.addrule(ACTION_HIDE_WIN,TEXT("OrCAD Layout"));//方式1
killer.addrule(ACTION_CLOSE_WIN,TEXT("OrCAD Layout"));//方式2
killer.addrule(ACTION_PRESSBUTTON_BYTXT,TEXT("Layout Plus"),TEXT("Unable to write backup."),TEXT("肯定"));
killer.addrule(ACTION_PRESSBUTTON_BYTXT,TEXT("Layout Plus"),TEXT("Enter new name?") ,TEXT("否") );


最後還在工程中加入了托盤圖標及右鍵菜單,這是整個軟件能夠看得見的東西,還加入註冊表修改自啓動

軟件運行時的提示是這樣子的
右鍵菜單是這樣子的



軟件示例及完整代碼:下載頁面

相關文章
相關標籤/搜索