更新日期: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 } |