鼠标中键拖动滚动条

鼠标中键拖动滚动条

更新日期:2010-12-14
程序下载:MouseScroll-exe.zip (请不要直接使用迅雷下载)
运行环境:WinXP
代码下载:MouseScroll-src.zip
测试环境:VC6.0+WinXP
图片预览:

━━━━━━━━━━━━━━━━━━━━━━━━

一、前言
    一直以来都希望可以使用鼠标中键来拖动滚动条。个人认为这样的操作是高效的。
    虽然某些软件如记事本浏览器按下中键都能拖动视图,但我认为那种效果不好。
    最好是像平时按下左键拖动滚动条,想拖到哪里就哪里,定位准确。一开始学习编程
    时尝试过实现这样的功能,但终究以失败告终。现在由于积累了一些经验,所以再次
    攻关,终于有所收获了。
    前段时间研究出了一种方法。请看:“鼠标中键按下拖动滚动条(平移视图)”
    http://hi.baidu.com/qiujiejia/blog/item/6a5903f85e216c1fd9f9fdf8.html
    此方法虽然也不错,但不够通用,而且响应速度慢,所以觉得不完美。于是再次摸索,
    就有了以下的方法了。
    现在由于有了这个软件,我基本都不去点击窗口的滚动条    直接中键拖动视图。
    愿和大家分享成果。

二、原理:
    1.安装了鼠标低级钩子捕获中键消息

    2.当鼠标中键按下时。
        1) 获取鼠标下面的窗口句柄WindowFromPoint(point);
        2) 如果窗口是预定义禁用此功能的窗口,直接返回默认操作
        3) 如果窗口是预定义的具有特殊滚动条的窗口,如Explorer,chrome
           按预先设置好的参数(滚动条在窗口内部还是外部)进行操作。
        4) 判断此窗口是否具有滚动条,如果没有,再调用GetCustomerScroll获取
           可能存在的自定义滚动条,再没有的话,就需要手动设定滚动条与当前
           窗口的位置关系了。
        5) 获取到滚动条的具体位置后,再获取滚动条的像素值,从滚动条最顶像素遍历
           到最底部像素,如果像素值的R分量小于200,说明当前是滑块的位置,因此
           也获得滑块在屏幕的位置。调用SerCursorPos把鼠标移动到滑块的位置,
           模拟左键按下 mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
           之后就可以拖动滚动条了

    3.当鼠标移动时。
        1) 用一个窗口画一个鼠标箭头,模拟出一个假的鼠标(真的鼠标按在滚动条上了)

    4.当鼠标中键弹起时。
        1) 如果发现鼠标没有移动,则再次模拟一个中键down up 的点击消息,让窗口
           执行默认中键操作,如Chrome的中键点击打开链接功能。
        2) 如果窗口拖动了滚动条,我们需要把鼠标的位置还原回来。

三、关键技术
    此功能的最关键技术是捕获滚动条的滑块位置,而我们这里是通过分析滚动条的
    背景像素和滑块像素的差别来实现的。滚动条背景色的像素R值一般都大于200(接近白色)
    我们认为像素R值小于200时,这个像素点就是滑块上的点。从而确定滑块的屏幕坐标。
    因此,如果是自绘的各种颜色的滚动条,那此程序就无能为力了。直到现在为止,我电脑
    里所有具有滚动条窗口的程序都能很好的识别滑块位置(系统是XP)。

四、具有特殊滚动条的窗口
    某些窗口的“滚动条”并不是窗口自带的滚动体,也不是自定义滚动条(有窗口句柄)
    就像Explorer,chrome,opera,此时我们需要手动设置滚动条在窗口的什么位置。
    比如拖动界面上的瞄准器到Explorer窗口,弹出配置对话框,注意此时Explorer窗口
    被黑色相框高亮了,我们发现滚动条在窗口(黑色线框)的里面,所以在配置对话框上
    选择“滚动条在此窗口的内部”。chrome也是同样道理。
    而opera的滚动条是在窗口(黑色线框)的右边。所以我们要在配置对话框上选择
    “滚动条在此窗口的外部”

 
五、部分主要代码

#include "stdafx.h"
#include "Resource.h"
#include "DemoDlg.h"
#include <vector>
using namespace std;

#include "MyClass.h"
#include "SetWnd.h"


int MouseState;
#define MOUSE_NOMAL 0
#define MOUSE_CAPTURE 1
#define GENERATE_CLICK 2

bool    IsCaptureMostLastMove=false;
bool    IsMoved=false;
POINT    MouseDownPoint;


vector<WNDINFO> ForbidWnd;    //禁止鼠标中键拖动滚动条的窗口
vector<WNDINFO> SpecialWnd;    //具有特殊滚动条的窗口,需手动配置滚动条的位置


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


CDemoDlg::CDemoDlg(CWnd* pParent)
    : CDialog(CDemoDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CDemoDlg)
        // NOTE: the ClassWizard will add member initialization here
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
}

void CDemoDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CDemoDlg)
    DDX_Control(pDX, IDC_LIST2, m_ListCtrl2);
    DDX_Control(pDX, IDC_LIST1, m_ListCtrl);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)
    //{{AFX_MSG_MAP(CDemoDlg)
    ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
    ON_NOTIFY(NM_RCLICK, IDC_LIST1, OnRclickList1)
    ON_NOTIFY(NM_RCLICK, IDC_LIST2, OnRclickList2)
    ON_BN_CLICKED(ID_SOURCE_CODE, OnSourceCode)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()







/****************************************************************************
获取指定窗口右边的自定义滚动条
****************************************************************************/
HWND GetCustomerScroll(HWND FocusWnd)
{
    //获取当前窗口的右边窗口
    RECT WndRect;
    ::GetWindowRect(FocusWnd,&WndRect);
    POINT pt={WndRect.right+9,WndRect.top+HEIGHTOF(WndRect)/2};
    HWND hWnd=::WindowFromPoint(pt);
               
    //判断是否为ScrollBar类
    TCHAR ClassName[10]={0};
    ::GetClassName(hWnd,ClassName,sizeof(ClassName)/sizeof(TCHAR));
    if (_tcscmp(ClassName,_T("ScrollBar"))==0)
    {
        trace("ScrollBar");
        //保证是同一进程里的滚动条
        DWORD ProcessId,ProcessId2;
        ::GetWindowThreadProcessId(hWnd,&ProcessId);
        ::GetWindowThreadProcessId(FocusWnd,&ProcessId2);
        if (ProcessId==ProcessId2)
            return hWnd;
    }
   
    return NULL;
}


/****************************************************************************
专门用于VC6 (因为vc6滚动条的背景不是单一颜色)
****************************************************************************/
int VCSCROLL(HWND hWnd,TCHAR* ClassName,POINT point)
{
    if (_tcscmp(ClassName,_T("Afx:400000:8"))==0)
    {
        //━━━━━━━━━━━━━━━━━━获取自定义滚动条窗口句柄
        RECT WndRect;
        ::GetWindowRect(hWnd,&WndRect);
        POINT pt={WndRect.right+9,WndRect.top+HEIGHTOF(WndRect)/2};
        hWnd=::WindowFromPoint(pt);
        //━━━━━━━━━━━━━━━━━━获取自定义滚动条窗口句柄

       
        RECT rect;
        ::GetWindowRect(hWnd,&rect);
        int top=rect.top+20;   //20去掉滚动条上面的箭头宽度
        int left=rect.right-9;
        int height=HEIGHTOF(rect)-40; //去掉上下两个箭头按钮
                               
        HDC hScrDC=::GetDC(NULL);                            //创建屏幕DC
        HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
        HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,1,height); //创建兼容位图
        ::SelectObject(hMemDC,bitmap);    //把位图选进内存DC
       
        //把rect指定的图块拷贝到内存设备描述表
        BitBlt(hMemDC,0,0,1,height,hScrDC,left,top,SRCCOPY); 
       
        int num=0;
       
        COLORREF rgb;
        for (int i=0; i< height;i++)
        {
            rgb=::GetPixel(hMemDC,0,i);
           
            if (236==GetRValue(rgb))    num++;
            else            num=0;
            if (num>=2)
            {
                MouseState=MOUSE_CAPTURE;
                IsCaptureMostLastMove=false;
                IsMoved=false;
                MouseDownPoint=point;
               
                CMyWindow::CreateWnd(point.x,top+i);
                ::SetCursorPos(left,top+i);
                RECT rect={left,top,left+4,top+height};
                ::ClipCursor(&rect);
                mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
                break;
            }
        }
       
        ::DeleteDC(hMemDC) ;            //删除内存DC
        ::ReleaseDC(NULL,hScrDC) ;    //释放屏幕DC
        ::DeleteObject(bitmap);   
       
        return 1;
    }
   
    return 0;
}



/****************************************************************************
        低级鼠标钩子
****************************************************************************/
HHOOK g_LowLevelMouseHook=NULL;    //钩子句柄
LRESULT CALLBACK LowLevelMouseProc(int nCode,WPARAM wParam, LPARAM lParam)
{
    if (nCode<0 )
        return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam);
   
    static POINT point;
    point=(POINT)((MSLLHOOKSTRUCT *)lParam)->pt;

    switch (wParam)
    {
    case WM_MBUTTONUP:
        {
            if (MouseState==MOUSE_CAPTURE)
            {
                //释放鼠标的矩形位置
                ClipCursor(NULL);

                //模拟鼠标左键弹起
                mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

                //关闭鼠标窗口
                CMyWindow::DestroyWnd();

                //重定位鼠标位置
                ::SetCursorPos(MouseDownPoint.x,(IsMoved?point.y:MouseDownPoint.y));



                //━━━━━━━━━━不产生默认点击━━━━━━━━━━━
                if (IsMoved)
                {
                    IsMoved=false;
                    /*MouseState=MOUSE_NOMAL;*/   trace("Button Up 结束CAPTURE,不产生默认点击");

                    //令下一次WM_MOUSEMOVE到来时,进入最后的清理工作。
                    //并置MouseState=MOUSE_NOMAL
                    IsCaptureMostLastMove=true;

                    return 1;
                }

                //━━━━━━━━━用mouse_event 模拟多一个鼠标点击━━━━━━━━━━━━━━━━━
                //MouseState一定要在最前面,顺序不能搞错,因为一调用mouse_event,时,会马上重新进入钩子
                //,这时如果MouseState还是等于MOUSE_CAPTURE的话会再次进入到这里并产生多一个mouse_event
                //而导致错误。而且某些默认处理的代码会产生WM_MOUSEMOVE,如SetCursorPos,
                //所以我们应该先MouseState=GENERATE_CLICK,然后再添加需要处理的代码,最后发送模拟按键
                MouseState=GENERATE_CLICK;    trace("Button Up 产生模拟多一个鼠标点击");
                mouse_event(MOUSEEVENTF_MIDDLEDOWN,0,0,0,0);
                mouse_event(MOUSEEVENTF_MIDDLEUP,0,0,0,0);
                return 1;
            }

            if (MouseState==GENERATE_CLICK)
            {
                MouseState=MOUSE_NOMAL;        trace("WM_RBUTTONUP 结束CAPTURE,已执行默认点击了 ");
                break;
            }

            //把MouseState置为MOUSE_NOMAL是防止意外错误。
            MouseState=MOUSE_NOMAL;
        }
        break;
    case WM_MOUSEMOVE:
        {
            if (MouseState==MOUSE_CAPTURE)
            {
                //━━━━━━━━━━━━━━━━━中键弹起后的第一个WM_MOUSEMOVE,进入最后的清理工作━
                if (IsCaptureMostLastMove==true)
                {
                    IsCaptureMostLastMove=false;     trace("");
                    MouseState=MOUSE_NOMAL;                   

                    //如果鼠标的位置没有重新调整,现在再调整
                    if ( point.x!=MouseDownPoint.x)
                    {
                        trace("IsCaptureMostLastMove==true 重新调整鼠标的位置");
                        ::SetCursorPos(MouseDownPoint.x,point.y);
                        return 1; //必须return 1,否则SetCursorPos不起作用
                    }
                    else
                        trace("IsCaptureMostLastMove==true 不需要重新调整鼠标的位置");


                    break;
                }
                //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
               
               
                ::SetWindowPos(CMyWindow::m_hWnd,HWND_TOPMOST,MouseDownPoint.x,point.y,0,0,SWP_NOSIZE|SWP_NOACTIVATE);
                IsMoved=true;
            }
        }
        break;
    case WM_MBUTTONDOWN:
        {
//            test(); return 1; //调试用

            //如果执行滚动条移动后,鼠标弹起,并且没有移动
            //那此时按下IsCaptureMostLastMove==true,
            if (IsCaptureMostLastMove==true)
            {
                IsCaptureMostLastMove=false;
                MouseState=MOUSE_NOMAL;
            }


            //━━━━━━━━━━━━━━━━━用于屏幕程序MozillaWindowClass的中键弹起
            if (MouseState!=MOUSE_NOMAL)
            {
                HWND hWnd=WindowFromPoint(point);
                TCHAR ClassName[CLASS_NAME_MAX]={0};
                ::GetClassName(hWnd,ClassName,sizeof(ClassName)/sizeof(TCHAR));
                trace(ClassName,_T("MozillaWindowClass"));
                if (_tcscmp(ClassName,_T("MozillaWindowClass"))==0 )
                {
                    trace("MozillaWindowClass");
                    return 1;
                }
            }
            //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


            //正常情况MouseState==MOUSE_NOMAL,当这个消息是用mouse_event模拟
            //的时候,MouseState=GENERATE_CLICK所以我们不处理此消息并且返回
            //下面代码除了最后一句外,都不要使用return 1,用goto NO_PASS_MSG
            if (MouseState!=MOUSE_NOMAL)
                break;
       
            //鼠标的目标位置和当前窗口的右边界关系,默认是-9
            int Offset_X=-9;

            HWND hWnd=WindowFromPoint(point);

            //获取窗口类名
            TCHAR ClassName[CLASS_NAME_MAX]={0};
            ::GetClassName(hWnd,ClassName,sizeof(ClassName)/sizeof(TCHAR));

            //━━━━━━━━━VC6 滚动条━━━━━━━━━
            if (1==VCSCROLL(hWnd,ClassName,point))   
                goto START_CAPTURE;
            //━━━━━━━━━━━━━━━━━━━━━━━


            //禁止使用鼠标中键拖动滚动条的窗口
            int i;
            for(i=0; i<ForbidWnd.size() ; i++)
            {
                if (_tcscmp(ClassName,ForbidWnd[i].ClassName)==0 )
                {
                    //不需要判断顶级父窗口类
                    if (ForbidWnd[i].TopWndClassName[0]==NULL)
                    {
                        trace("禁止使用鼠标中键拖动滚动条的窗口");
                        return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam);
                    }

                    //判断顶级父窗口类
                    TCHAR TopWndClassName[CLASS_NAME_MAX];
                    ::GetClassName(::GetTopWnd(hWnd),TopWndClassName,sizeof(TopWndClassName)/sizeof(TCHAR));
                    if (_tcscmp(TopWndClassName,ForbidWnd[i].TopWndClassName)==0 )
                    {
                        trace("禁止使用鼠标中键拖动滚动条的窗口");
                        return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam);
                    }
                }
            }

            //特殊窗口的处理
            for(i=0; i<SpecialWnd.size() ; i++)
            {
                trace(ClassName,SpecialWnd[i].ClassName);
                if (_tcscmp(ClassName,SpecialWnd[i].ClassName)==0 )
                {
                    //不需要判断顶级父窗口类
                    if (SpecialWnd[i].TopWndClassName[0]==NULL)
                    {
                        Offset_X=SpecialWnd[i].Offset_X;
                        goto CAN_SCROLL;
                    }

                    //判断顶级父窗口类
                    TCHAR TopWndClassName[CLASS_NAME_MAX];
                    ::GetClassName(::GetTopWnd(hWnd),TopWndClassName,sizeof(TopWndClassName)/sizeof(TCHAR));
                    if (_tcscmp(TopWndClassName,SpecialWnd[i].TopWndClassName)==0 )
                    {
                        trace("特殊窗口的处理");
                        Offset_X=SpecialWnd[i].Offset_X;
                        goto CAN_SCROLL;
                    }
                }
            }
           

            //如果窗口没有滚动条,则获取自定义垂直滚动条
            if((GetWindowLong(hWnd,GWL_STYLE)&WS_VSCROLL)!=WS_VSCROLL)
            {
                hWnd=GetCustomerScroll(hWnd);
                if (hWnd==NULL)
                    break;
            }

CAN_SCROLL:
            {
                RECT rect;
                ::GetWindowRect(hWnd,&rect);
                int top=rect.top+20;   //20去掉滚动条上面的箭头宽度
                int left=rect.right+Offset_X;
                int height=HEIGHTOF(rect)-40; //去掉上下两个箭头按钮
               
                HDC hScrDC=::GetDC(NULL);                            //创建屏幕DC
                HDC hMemDC=CreateCompatibleDC(hScrDC);                //创建内存DC
                HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,1,height); //创建兼容位图
                ::SelectObject(hMemDC,bitmap);    //把位图选进内存DC
               
                //把rect指定的图块拷贝到内存设备描述表
                BitBlt(hMemDC,0,0,1,height,hScrDC,left,top,SRCCOPY); 
               
               
                //━━━━━━━━━━━━━━━━━━━━━━━━━━计算鼠标的y坐标━━━━
                int NewY,BeginPos,EndPos;
               
                //获取滑块的起始坐标
                for (BeginPos=0; BeginPos< height;BeginPos++)
                {
                    if (GetRValue(::GetPixel(hMemDC,0,BeginPos))<200)
                        break;
                }
               
                //如果找不到滑块则跳出
                if (BeginPos==height)
                {
                    ::DeleteDC(hMemDC) ;            //删除内存DC
                    ::ReleaseDC(NULL,hScrDC) ;    //释放屏幕DC
                    ::DeleteObject(bitmap);
                    break;
                }
               
                //获取滑块的结束坐标,20是去掉最小面有可能出现的水平滚动条占用的高度
                for (EndPos=height-20; EndPos>0 ;EndPos--)
                {
                    if (GetRValue(::GetPixel(hMemDC,0,EndPos))<200)
                        break;
                }
               
                if (BeginPos>=EndPos)  //EndPos出错时,当滑块在最底端时可能会出现这种情况
                    NewY=top+BeginPos;
                else if ( ((top+BeginPos)<point.y) && (point.y<(top+EndPos)))
                    NewY=point.y;
                else
                    NewY=top+(BeginPos+EndPos)/2;
                //━━━━━━━━━━━━━━━━━━━━━━━━━━计算鼠标的y坐标━━━━
               
               
                MouseState=MOUSE_CAPTURE;
                IsCaptureMostLastMove=false;
                IsMoved=false;
                MouseDownPoint=point;
               
                CMyWindow::CreateWnd(point.x,NewY);
                ::SetCursorPos(left,NewY);
                SET_RECT(rect,left,top+(NewY-(top+BeginPos))-10,left+2,top+height-((top+EndPos)-NewY)+10);
                //                SET_RECT(rect,left,top,left+2,top+height);
                ::ClipCursor(&rect);
                mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
               
               
                ::DeleteDC(hMemDC) ;        //删除内存DC
                ::ReleaseDC(NULL,hScrDC) ;    //释放屏幕DC
                ::DeleteObject(bitmap);
            }
START_CAPTURE:
            //屏蔽鼠标按下消息
            MouseState=MOUSE_CAPTURE;    trace("Button Down 开始Capture");
            return 1;    //不往下传递消息
           
        }
        break;
    }
    return CallNextHookEx(g_LowLevelMouseHook,nCode,wParam,lParam); //传递钩子信息    
}


BOOL CDemoDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);            // Set big icon
    //-----------------------------------------------------------------------------

    //start Low Level mouse hook
    g_LowLevelMouseHook=SetWindowsHookEx(WH_MOUSE_LL,LowLevelMouseProc,GetModuleHandle(NULL),0);
    if(!g_LowLevelMouseHook)
        ::MessageBox(m_hWnd,TEXT("SetWindowsHookEx LowLevelMouseProc failed"),NULL,MB_OK);

    ::SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(m_hWnd,GWL_EXSTYLE)&~WS_EX_APPWINDOW|WS_EX_TOOLWINDOW);
    ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,10,10,SWP_NOSIZE); //设置窗口最顶

    {
        //设置扩展样式
        DWORD dwStyle = m_ListCtrl.GetExtendedStyle();    //获取当前扩展样式
        dwStyle |= LVS_EX_FULLROWSELECT;                //选中某行使整行高亮(report风格时)
        dwStyle |= LVS_EX_GRIDLINES;                    //网格线(report风格时)
        m_ListCtrl.SetExtendedStyle(dwStyle);            //设置扩展风格
       
        //设置列
        m_ListCtrl.InsertColumn(0, "目标窗口类",             LVCFMT_LEFT,   150);  
        m_ListCtrl.InsertColumn(1, "目标窗口的顶级父窗口类", LVCFMT_LEFT,   150);  
        m_ListCtrl.InsertColumn(2, "滚动条位置情况",         LVCFMT_LEFT,   150);  
    }
   
    {
        //设置扩展样式
        DWORD dwStyle = m_ListCtrl2.GetExtendedStyle();    //获取当前扩展样式
        dwStyle |= LVS_EX_FULLROWSELECT;                //选中某行使整行高亮(report风格时)
        dwStyle |= LVS_EX_GRIDLINES;                    //网格线(report风格时)
        m_ListCtrl2.SetExtendedStyle(dwStyle);            //设置扩展风格
       
        //设置列
        m_ListCtrl2.InsertColumn(0, "目标窗口类",             LVCFMT_LEFT,   150);  
        m_ListCtrl2.InsertColumn(1, "目标窗口的顶级父窗口类", LVCFMT_LEFT,   150);  
    }
   

    if (!read())
    {
        ::MessageBox(m_hWnd,TEXT("读取文件失败"),NULL,MB_OK);
        SpecialWnd.clear();
        ForbidWnd.clear();
        CMyFile file(_T("MouseScroll.dat"),_T("wb"));
    }

    //加载数据
    trace(SpecialWnd.size());
    int i;
    for(i=0; i<SpecialWnd.size() ; i++)
    {
        int count=m_ListCtrl.GetItemCount();
        //第一列
        m_ListCtrl.InsertItem(count,SpecialWnd[i].ClassName);
        //第二列
        if (SpecialWnd[i].TopWndClassName[0]==NULL)
            m_ListCtrl.SetItemText(count,1,_T("不需要判断顶级父窗口类"));
        else
            m_ListCtrl.SetItemText(count,1, SpecialWnd[i].TopWndClassName);
        //第三列
        if (SpecialWnd[i].Offset_X==-9)
            m_ListCtrl.SetItemText(count,2,_T("在此窗口的内部"));
        else if (SpecialWnd[i].Offset_X==9)
            m_ListCtrl.SetItemText(count,2,_T("在此窗口的外部"));
    }

    for(i=0; i<ForbidWnd.size() ; i++)
    {
        int count=m_ListCtrl2.GetItemCount();
        //第一列
        m_ListCtrl2.InsertItem(count,ForbidWnd[i].ClassName);
        //第二列
        if (ForbidWnd[i].TopWndClassName[0]==NULL)
            m_ListCtrl2.SetItemText(count,1, _T("不需要判断顶级父窗口类"));
        else
            m_ListCtrl2.SetItemText(count,1, ForbidWnd[i].TopWndClassName);
    }
   

    return TRUE; 
}


void CDemoDlg::OnButton1()
{
    ::ShowWindow(m_hWnd,SW_HIDE);
}


void CDemoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
    CFinder::MouseDown(m_hWnd);
    CDialog::OnLButtonDown(nFlags, point);
}

void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point)
{
    CFinder::MouseMove();
    CDialog::OnMouseMove(nFlags, point);
}

void CDemoDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (CFinder::MouseUp() )
    {
        WNDINFO TempWndInfo;
        CSetWnd tempwnd(this,CFinder::FindWnd,TempWndInfo);
        int rel=tempwnd.DoModal();
        trace(rel);
        if (rel==101)
        {
            ForbidWnd.push_back(TempWndInfo);
            int count=m_ListCtrl2.GetItemCount();
            //第一列
            m_ListCtrl2.InsertItem(count,TempWndInfo.ClassName);
            //第二列
            if (TempWndInfo.TopWndClassName[0]==NULL)
                m_ListCtrl2.SetItemText(count,1, _T("不需要判断顶级父窗口类"));
            else
                m_ListCtrl2.SetItemText(count,1, TempWndInfo.TopWndClassName);

            //height light the selected item
            LVITEM lviItem;
            lviItem.stateMask=LVIS_SELECTED ;
            lviItem.state=LVIS_SELECTED;
            ::SendMessage(m_ListCtrl2.m_hWnd, LVM_SETITEMSTATE, count,(LPARAM) &lviItem);
        }
        else
        {
            if (rel==102)
            {
                TempWndInfo.Offset_X=-9;
                SpecialWnd.push_back(TempWndInfo);
                int count=m_ListCtrl.GetItemCount();
                //第一列
                m_ListCtrl.InsertItem(count,TempWndInfo.ClassName);
                //第二列
                if (TempWndInfo.TopWndClassName[0]==NULL)
                    m_ListCtrl.SetItemText(count,1,_T("不需要判断顶级父窗口类"));
                else
                    m_ListCtrl.SetItemText(count,1, TempWndInfo.TopWndClassName);
                //第三列
                m_ListCtrl.SetItemText(count,2,_T("在此窗口的内部"));
               
            }
            else if (rel==103)
            {
                TempWndInfo.Offset_X=9;
                SpecialWnd.push_back(TempWndInfo);
                int count=m_ListCtrl.GetItemCount();
                //第一列
                m_ListCtrl.InsertItem(count,TempWndInfo.ClassName);
                //第二列
                if (TempWndInfo.TopWndClassName[0]==NULL)
                    m_ListCtrl.SetItemText(count,1,_T("不需要判断顶级父窗口类"));
                else
                    m_ListCtrl.SetItemText(count,1, TempWndInfo.TopWndClassName);
                //第三列
                m_ListCtrl.SetItemText(count,2,_T("在此窗口的外部"));
            }

            //height light the selected item
            LVITEM lviItem;
            lviItem.stateMask=LVIS_SELECTED ;
            lviItem.state=LVIS_SELECTED;
            ::SendMessage(m_ListCtrl.m_hWnd, LVM_SETITEMSTATE, SpecialWnd.size()-1,(LPARAM) &lviItem);

        }
       
        //save file
        write();
       
        //reflash window
        CFinder::HeightLightWnd(CFinder::FindWnd);
    }



    CDialog::OnLButtonUp(nFlags, point);
}





/****************************************************************************
保存和读取
****************************************************************************/
bool CDemoDlg::write()
{   
    try
    {
        CMyFile file(_T("config.txt"),_T("wb"));

        file.WriteVector(ForbidWnd);
        file.WriteVector(SpecialWnd);

        trace("write file successful");
        return true;
    }
    catch(int ErrorCode)
    {
        trace("Write File Fault",ErrorCode);
        return false;
    }
}

bool CDemoDlg::read()
{
    try
    {
        CMyFile file(_T("config.txt"),_T("rb"));

        file.ReadVector(ForbidWnd);
        file.ReadVector(SpecialWnd);

        trace("read file successful");
        return true;
    }
    catch(int ErrorCode)
    {
        trace("Read File Fault",ErrorCode);
        return false;
    }
}

//delete item of clistctrl
void CDemoDlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
    //如果ListCtrl是单选的,就用这种方式判断选中的项
    int SelectItem=::SendMessage(m_ListCtrl.m_hWnd,LVM_GETNEXTITEM,-1,MAKELPARAM(LVNI_SELECTED,0));
    if (SelectItem!=-1)
    {
        if(IDOK==::MessageBox(m_hWnd,TEXT("确定要删除这项吗"),TEXT(""),MB_OKCANCEL))
        {
            m_ListCtrl.DeleteItem(SelectItem);
            SpecialWnd.erase(SpecialWnd.begin()+SelectItem);
            write();
        }
    }
   
    *pResult = 0;
}

//delete item of clistctrl
void CDemoDlg::OnRclickList2(NMHDR* pNMHDR, LRESULT* pResult)
{
    //如果ListCtrl是单选的,就用这种方式判断选中的项
    int SelectItem=::SendMessage(m_ListCtrl2.m_hWnd,LVM_GETNEXTITEM,-1,MAKELPARAM(LVNI_SELECTED,0));
    if (SelectItem!=-1)
    {
        if(IDOK==::MessageBox(m_hWnd,TEXT("确定要删除这项吗"),TEXT(""),MB_OKCANCEL))
        {
            m_ListCtrl2.DeleteItem(SelectItem);
            ForbidWnd.erase(ForbidWnd.begin()+SelectItem);
            write();
        }
    }
    *pResult = 0;
}

void CDemoDlg::OnSourceCode()
{
    ShellExecute(NULL,_T("open"),_T("D://MyProjects"),NULL,NULL,SW_SHOWNORMAL);    //最终形式,可以打开exe和folder
}



 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值