100分 VC 遍历所有窗口问题

wangweicmon236 2009-06-04 09:35:09
找了很多资料,应该是要用到EnumWindowsProc和EnumWindows
我的目的是要遍历所有窗口,将各窗口的句柄、标题等属性写到文件里,下面是我的一个测试程序,功能是:遍历所有窗口如果有类名是Notepad的窗口在运行,则发送消息关闭。我的程序如下:
char classname[128];
static bool IsFindWindow(HWND hwnd, LPARAM lParam) //如果是类函数,需要写成静态函数。
{
TCHAR buf[128]={0};
if(::IsWindow(hwnd)&&::IsWindowVisible(hwnd))
{
::GetClassName(hwnd, buf, sizeof(buf));
if(memcmp(buf,classname,10) != 0)
return false;
}
}
std::vector<HWND> g_AllWindow;

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) //注意:类型是BOOL 或INT,不是bool
{
if(IsFindWindow(hwnd, lParam))
{
g_AllWindow.push_back(hwnd);
}
return 1; //要一直return 1.因为需要遍历所有的窗口,一旦返回0 将停止遍历。
}
然后在button的click事件里
strcpy(classname,"Notepad");//给classname赋值
if(::EnumWindows((WNDENUMPROC)EnumWindowsProc,NULL))
{
HWND hwnd=g_AllWindow.back();
::SendMessage(hwnd,WM_CLOSE,0,0);如果有类名是Notepad的窗口在运行,关闭它
}
结果是虽然有类名是Notepad的窗口在运行,但是向量g_AllWindow总是为空,不知道为什么,请各位指教

或者大家谁有别的可以遍历所有窗口,得到其句柄的程序,麻烦贴上来,非常感谢!
...全文
1958 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
ggmfc 2009-06-05
  • 打赏
  • 举报
回复
顶!呵呵!
skyxie 2009-06-05
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wangweicmon236 的回复:]
skyxie,我把你的代码完全复制了运行,结果是g_AllWindow为空,窗口关不掉,郁闷,为什么我这里就不行
[/Quote]

你可以编译个exe到别人的机器上去试试,我这里是完全可以的哈~
zhihuizhilv 2009-06-05
  • 打赏
  • 举报
回复
可以先获得桌面窗口,然后遍历桌面窗口的所有子窗口。

需要的几个API:
HWND hWndDesktop = ::GetDesktopWindow(); //桌面窗口
HWND hWndChild = ::GetWindow(hWndParent, GW_CHILD); //得到一个窗口的第一个子窗口
hWndChild = ::GetWindow(hWndChild, GW_HWNDNEXT); //得到一个窗口的兄弟窗口

要遍历子窗口的子窗口,可以使用递归算法。
wangweicmon236 2009-06-05
  • 打赏
  • 举报
回复
CIni file=NULL;
file.SetPathName(L"F:\\Detect\\compare.ini");
TCHAR strBuff[100]={0};
TCHAR szClassName[100]={0};
HWND hChildWnd;
HWND hWnd = CWnd::GetDesktopWindow()->GetWindow(GW_CHILD)->m_hWnd;

for (;;)
{

if (hWnd == NULL) break;
else
{
hChildWnd=hWnd;

::GetWindowText(hChildWnd,strBuff,100);
::GetClassName(hChildWnd, szClassName, 100);
CString title=strBuff;
CString Property=szClassName;
file.AppendString(L"Information",Property,title+L"+"+Property);
hChildWnd=::GetWindow(hChildWnd,GW_CHILD);
while(hChildWnd!=NULL)
{
::GetWindowText(hChildWnd,strBuff,100);
::GetClassName(hChildWnd, szClassName, 100);
CString ControlTitle=strBuff;
CString ControlProperty=szClassName;
file.AppendString(L"Information",Property,L"+"+ControlTitle+L"+"+ControlProperty);
hChildWnd=::GetWindow(hChildWnd,GW_HWNDNEXT);
}

}
hWnd=::GetNextWindow(hWnd,GW_HWNDNEXT);
}

这样貌似实现了遍历所有窗口的所有控件,并写入一个ini文件里
wangweicmon236 2009-06-05
  • 打赏
  • 举报
回复
谢谢,不过我不想通过进程名来识别,因为进程名有可能会改,谢谢
yinyuanqings 2009-06-05
  • 打赏
  • 举报
回复
楼主可以考虑下使用NATIVE API,在ntdll.dll下面有个叫做 NtQuerySystemInformation的函数可以枚举当前System下面所有 Ring 3级别的所有HANDLE,通过一个HandleInformation结构返回,每一种handle对应一个handletype,这样只需要根据 窗口类的handle type筛选掉非 窗口类handle就可以得到当前system下面所有的HWND了.
NtQuerySystemInformation的函数使用网上可以找到文档的,虽然不是Microsoft放出的.
wangweicmon236 2009-06-05
  • 打赏
  • 举报
回复
skyxie,我把你的代码完全复制了运行,结果是g_AllWindow为空,窗口关不掉,郁闷,为什么我这里就不行
NTooL 2009-06-05
  • 打赏
  • 举报
回复
//这是我写的一段杀掉进程的代码,看看是不是你想要的,可以杀掉所有打开的notepad


// 提升权限
HANDLE handleToken;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &handleToken);
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid))
return;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(handleToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if (GetLastError() != ERROR_SUCCESS)
{
return;
}

// TODO: Add your control notification handler code here
CStringArray strArrToBeKilled;
strArrToBeKilled.Add("notepad");


HANDLE handleSnapshot; //定义CreateToolhelp32Snapshot系统快照句柄
HANDLE handleTobeKilled; //定义要结束进程句柄

handleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //获得系统快照句柄
PROCESSENTRY32 *info; //定义PROCESSENTRY32结构字指

//PROCESSENTRY32 结构的 dwSize 成员设置成 sizeof(PROCESSENTRY32)
info = new PROCESSENTRY32;
info->dwSize = sizeof(PROCESSENTRY32);

//调用一次 Process32First 函数,从快照中获取进程列表
Process32First(handleSnapshot, info);

//重复调用 Process32Next,直到函数返回 FALSE 为止
while(Process32Next(handleSnapshot, info) != FALSE)
{
//strcmp字符串比较函数同要结束相同
for (int i = 0; i < strArrToBeKilled.GetSize(); i++)
{
CString str = info->szExeFile;//指向进程名字
str.MakeLower();
if (!str.Find(strArrToBeKilled[i]))
{
//PROCESS_TERMINATE表示为结束操作打开,FALSE=可继承,info->th32ProcessID=进程ID
handleTobeKilled = OpenProcess(PROCESS_TERMINATE, FALSE, info->th32ProcessID);

//结束进程
TerminateProcess(handleTobeKilled, 4);
CloseHandle(handleTobeKilled);
}
}
}

CloseHandle(handleSnapshot);
delete info;
info = NULL;
saiyaman5 2009-06-05
  • 打赏
  • 举报
回复
up
jyh_baoding 2009-06-05
  • 打赏
  • 举报
回复
帮顶
liduan274 2009-06-05
  • 打赏
  • 举报
回复
一个很牛的技术论坛。。
很多原创教程
http://www.mzjslt.com/?u=63
arthur____ 2009-06-05
  • 打赏
  • 举报
回复
顶了。。好好看看程序思路。。。在头脑里运行一下。。比较好
danxuezx 2009-06-05
  • 打赏
  • 举报
回复
虽然之前没写过,但这个应该不难,应该就是FindWindow等等之类的函数兜下逻辑就好了。
cnzdgs 2009-06-04
  • 打赏
  • 举报
回复
for (;;)
{
HWND hwnd = ::FindWindowA("Notepad", NULL);
if (hwnd == NULL) break;
::SendMessage(hwnd, WM_CLOSE, 0, 0);
}
skyxie 2009-06-04
  • 打赏
  • 举报
回复
当然上面的代码只关了最后找到那个
skyxie 2009-06-04
  • 打赏
  • 举报
回复
我晕,试了一下,就上面的代码就完全可以啊~~~


char classname[128];
static bool IsFindWindow(HWND hwnd, LPARAM lParam) //如果是类函数,需要写成静态函数。
{
TCHAR buf[128]={0};
if(::IsWindow(hwnd)&&::IsWindowVisible(hwnd))
{
::GetClassName(hwnd, buf, sizeof(buf));
if(memcmp(buf,classname,10) == 0)
return true;
}

return false;
}

std::vector <HWND> g_AllWindow;

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) //注意:类型是BOOL 或INT,不是bool
{
if(IsFindWindow(hwnd, lParam))
{
g_AllWindow.push_back(hwnd);
}
return 1; //要一直return 1.因为需要遍历所有的窗口,一旦返回0 将停止遍历。
}





void CtestCloseNotepadDlg::OnBnClickedOk()
{
strcpy(classname,"Notepad");//给classname赋值
if(::EnumWindows((WNDENUMPROC)EnumWindowsProc,NULL))
{
HWND hwnd=g_AllWindow.back();
::SendMessage(hwnd,WM_CLOSE,0,0); //如果有类名是Notepad的窗口在运行,关闭它
}
}

skyxie 2009-06-04
  • 打赏
  • 举报
回复
你这个应该就可以哈,
你再把代码贴出来看看
wangweicmon236 2009-06-04
  • 打赏
  • 举报
回复
改了之后运行,出来关机的对话框“待机”、“关机”、“重启”……
如果不方便在此基础上改,可以把别的只要能够遍历到所有窗口的程序发到我邮箱 wangweicmon@126.com 谢谢
最好能有一个遍历所有窗口所有控件的程序,不胜感激
skyxie 2009-06-04
  • 打赏
  • 举报
回复
打错了,上面应该是

if(memcmp(buf,classname,10) == 0)
skyxie 2009-06-04
  • 打赏
  • 举报
回复

char classname[128];
static bool IsFindWindow(HWND hwnd, LPARAM lParam) //如果是类函数,需要写成静态函数。
{
TCHAR buf[128]={0};
if(::IsWindow(hwnd)&&::IsWindowVisible(hwnd))
{
::GetClassName(hwnd, buf, sizeof(buf));
if(memcmp(buf,classname,10) 0= 0)
return true;
}

return false;
}

std::vector <HWND> g_AllWindow;

BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) //注意:类型是BOOL 或INT,不是bool
{
if(IsFindWindow(hwnd, lParam))
{
g_AllWindow.push_back(hwnd);
}
return 1; //要一直return 1.因为需要遍历所有的窗口,一旦返回0 将停止遍历。
}
然后在button的click事件里
strcpy(classname,"Notepad");//给classname赋值
if(::EnumWindows((WNDENUMPROC)EnumWindowsProc,NULL))
{
HWND hwnd=g_AllWindow.back();
::SendMessage(hwnd,WM_CLOSE,0,0);如果有类名是Notepad的窗口在运行,关闭它
}


你的IsFindWindow有问题

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧