admin 管理员组

文章数量: 1184232

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

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

一、前言
一直以来都希望可以使用鼠标中键来拖动滚动条。个人认为这样的操作是高效的。
虽然某些软件如记事本浏览器按下中键都能拖动视图,但我认为那种效果不好。
最好是像平时按下左键拖动滚动条,想拖到哪里就哪里,定位准确。一开始学习编程
时尝试过实现这样的功能,但终究以失败告终。现在由于积累了一些经验,所以再次
攻关,终于有所收获了。
前段时间研究出了一种方法。请看:“鼠标中键按下拖动滚动条(平移视图)”

此方法虽然也不错,但不够通用,而且响应速度慢,所以觉得不完美。于是再次摸索,
就有了以下的方法了。
现在由于有了这个软件,我基本都不去点击窗口的滚动条    直接中键拖动视图。
愿和大家分享成果。

二、原理:
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
}



本文标签: 窗口 滚动条 编程