目录
一. 枚举窗口EnumDialog
1. 枚举方式
(1) 方式一:GetWindow
HWND hChildWnd = ::GetWindow(GetDesktopWindow()->GetSafeHwnd(), GW_CHILD);
while (hChildWnd)
{
//Do something
hChildWnd = ::GetWindow(hChildWnd, GW_HWNDNEXT);
}
(2) 方式二:EnumWindows/EnumChildWindows
EnumWindows(EnumWindowsPro, (LPARAM)this);//枚举当前所有窗口
... ...
BOOL CALLBACK EnumWindowsPro(HWND hWnd, LPARAM lParam)
{
//Do something
return TRUE;
}
2. 查找窗口
(1) FindWindow
HWND hWnd = ::FindWindow(NULL, _T("计算器"));//类名, 窗口标题
(2) FindWindowEx
//父窗口句柄, 子窗口句柄, 窗口类名, 窗口标题
HWND hInputWnd = ::FindWindowEx(hWnd, NULL, _T("Window"), NULL);
3. 检测当前应用程序是否存在
(1) 检测当前应用程序是否存在的方法有几种,这里不一一说明,这里只介绍一种,满足如下功能:当检测到应用程序已存在时,直接弹出此程序并置顶。
TCHAR g_acProName[] = _T("{E91C1C60-DC70-460D-9299-FC67422ECA23}");
HANDLE g_hValue = (HANDLE)9527;
... ...
void CEnumDialogDlg::CheckProExist()
{
HWND hWnd = nullptr;
EnumWindows(EnumExistPro, (LPARAM)&hWnd);
if (nullptr != hWnd)//说明窗口存在了
{
AfxMessageBox(_T("已经有一个程序正在运行..."));
::ShowWindow(hWnd, SW_NORMAL);
::SetForegroundWindow(hWnd);
ExitProcess(0);
return;
}
::SetProp(m_hWnd, g_acProName, g_hValue);//设置属性
}
... ...
BOOL CALLBACK EnumExistPro(HWND hWnd, LPARAM lParam)
{
HANDLE hValue = ::GetProp(hWnd, g_acProName);
if (g_hValue == hValue)//获取值
{
*(HWND*)lParam = hWnd;//将窗口句柄传出去
return FALSE;
}
return TRUE;
}
二. 按钮激活ButtonActive
1. 原理
我们知道MFC里的所有控件其实本质都是窗口类,所以我们可以通过遍历当前程序的所有窗口,并把没有激活的窗口激活即可。此例子只对MFC开发的程序有用,原因是现在很多的UI都是用DirectUI开发,我们知道这种界面本质上只有一个窗口,控件都是画上去的。
2. 实现
EnumChildWindows(hWnd, EnumWindowsPro, NULL);
... ...
BOOL CALLBACK EnumWindowsPro(HWND hWnd, LPARAM lParam)
{
if (FALSE == IsWindowEnabled(hWnd))
{
EnableWindow(hWnd, TRUE);
}
return TRUE;
}
三. 星形查看器AsterPassword
1. 原理
MFC开发的Edit类是对win32原生控件Edit进行了封装,而我们知道原生控件获取Edit文本的方式是SendMessage(hWnd, WM_GETTEXT, lrTextLen + 1, (LPARAM)pcBuf),那么只要我们利用WindowFromPoint找到星形Edit窗口就可以获取到密码了。
界面模仿了spy++, 如果你拿来去试试QQ,YY你会发现完全没有效果(别做坏事),原因是QQ是用自己的DirectUI库,yy用的是qt,如果你熟悉他们的界面库,一样可以写对应的查看器。
2. 实现
HWND hWndParent = ::WindowFromPoint(pt);//获取当前点所在的窗口句柄
CRect stRect = { 0 };
HWND hWndCurrent = ::GetWindow(hWndParent, GW_CHILD);//获取父窗口的子窗口
while (NULL != hWndCurrent)
{
::GetWindowRect(hWndCurrent, &stRect);//获取当前窗口的大小
if (::PtInRect(stRect, pt))//检测鼠标位置是否在当前窗口内
break;
else
hWndCurrent = ::GetWindow(hWndCurrent, GW_HWNDNEXT);//获取当前窗口的下一个兄弟窗口
}
... ...
LRESULT lrTextLen = ::SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0);//获取Edit文本长度
四. 图片浏览器ImageExplore
1. 原理
利用ListCtrl获取文件夹的图片信息,再用PicCtrl来显示ListCtrl里的每个item,gif格式图片采用gdi+绘制。
2. 实现
(1) 正常图片的绘制:直接用CImage绘制
CImage objImage;
HRESULT hr = objImage.Load(lpFilePath);
if (SUCCEEDED(hr))
{
CRect stPicRect = { 0 };
GetDlgItem(IDC_STC_SHOW)->GetClientRect(stPicRect);//获取picControl的大小
//设置图片坐标
CRect stImagePos = { 0 };
AdjustImageRect(stImagePos, stPicRect, objImage.GetWidth(), objImage.GetHeight());
//开始绘图
CDC* pDC = CDC::FromHandle(::GetDC(GetDlgItem(IDC_STC_SHOW)->m_hWnd));
pDC->FillRect(stPicRect, CBrush::FromHandle(::CreateSolidBrush(GetSysColor(COLOR_3DFACE))));//背景填充
SetStretchBltMode(pDC->m_hDC, COLORONCOLOR);//在调用strechblt前需要设置设备上下文为拉伸模式
objImage.StretchBlt(pDC->m_hDC, stImagePos.left, stImagePos.top,
stImagePos.right - stImagePos.left, stImagePos.bottom - stImagePos.top, SRCCOPY);//可以拉伸
::ReleaseDC(GetDlgItem(IDC_STC_SHOW)->m_hWnd, pDC->m_hDC);
}
(2) gif格式图片绘制
void CImageExploreDlg::DrawGif(LPCTSTR lpFilePath)
{
if (nullptr == lpFilePath) return;
m_pGifImage = Gdiplus::Image::FromFile(lpFilePath);//加载图片
if (nullptr != m_pGifImage)
{
//获取picControl的大小
CRect stPicRect = { 0 };
GetDlgItem(IDC_ST