获得当前鼠标位置下的Windows资源管理器路径
当前鼠标下的文件夹(桌面)路径
问题:获得获得鼠标下的资源管理器或者用户桌面的绝对路径
首先我们应该了解下面这些窗口句柄相关的函数:
WindowFromPoint 可以获得坐标对应的窗口的句柄,而这个句柄值是系统唯一的。
GetParent 可以获得给定窗口句柄的父窗口
GetWindow(hParent, GW_CHILD); 可以获得给定窗口的子窗口
::GetNextWindow(hChild,GW_HWNDNEXT); 结合上面的GetWindow函数就可以枚举特定窗口的子窗口,然后就可以枚举当前所有窗口
GetWindowText 和GetClassName分别可以获得窗口的类名和标题
GetDeskTopWindow 可以获得当前桌面句柄,这里的桌面并不是指用户桌面,而是当前桌面环境的第一个窗口,使用spy++观察如下:
由此我们可以首先得到桌面的句柄,然后通过上述函数枚举到当前所有的窗口。下面我们将会需要这一功能。
解决方案:捕获鼠标消息后利用WindowFromPoint 函数获得句柄,然后获得窗口标题即可获得相应路径
实际操作:
1. 使用spy++观察资源管理器类的结构层次如下:
对应资源管理器黑色部分
可以发现,此区域并没有文件夹路径的信息。在其它区域使用spy++后发现:
我们可以发现,在地址栏存在当前的绝对路径,而我们平时习惯使用的下方的区域则与地址栏在同一个类的子类下方。那么我们就可以得到鼠标下面的窗口的句柄和类,然后得到顶层的“CabinetWClass”类,然后再枚举其子类就可以得到地址栏的地址。
2那么如何确定当前为资源管理器呢?通过枚举所有“DirectUIHWND”和其父窗口观察窗口的层次结构如下:
系统有很多DirectUIHWND 类的窗口,但是当且仅当其父类窗口为“SHELLDLL_DefView”时代表的是一个资源管理器。
相应代码:
#include
#include
void EnumWindows(HWND hParent,LPCSTR szTargetClassName)
{CHAR szClass[0x100];HWND hChild = GetWindow(hParent, GW_CHILD);if (hChild){EnumWindows(hChild,szTargetClassName);while (hChild = GetWindow(hChild, GW_HWNDNEXT)){EnumWindows(hChild, szTargetClassName);}}GetClassNameA(hParent, szClass, 0x100);if (strcmpi(szTargetClassName,szClass) == 0){HWND hEnumParent = hParent;for (int i = 0; i < 6; i++){GetClassNameA(hEnumParent, szClass, 0x100);printf("%8p\t%s\r\n", hEnumParent, szClass);hEnumParent = GetParent(hEnumParent);}printf("\r\n");}
}int main()
{//EnumWindows(GetDesktopWindow(),"DirectUIHWND");EnumWindows(GetDesktopWindow(), "SHELLDLL_DefView");getchar();getchar();return 0;
}
通过查找窗口句柄可以发现其中三个句柄都属于同一个资源管理器窗口而另一个则同属于explorer 进程
3. 然后就是桌面窗口句柄的处理,同样使用spy++获得句柄并观察:
我们发现窗口使用的是SysListView32 类(CListCtrol控件也使用的这个类)而其父窗口类与资源管理器一样是SHELLDLL_DefView,通过枚举SHELLDLL_DefView 类及其父窗口发现:
系统中只有两个SHELLDLL_DefView 类的窗口,都是我们想要的^_~,另外:
如果上面的用户桌面是在桌面显示文件的情况下获得的,当用户桌面的图标不予显示,获得的将直接是SHELLDLL_DefView 类窗口。
接下来的工作比较简单,判断窗口类或其父窗口类是否为SHELLDLL_DefView,然后通过得到父类以及子类枚举即可获得相应路径:
核心代码:
// DemoDlg.cpp : 实现文件
//#include "stdafx.h"
#include "Demo.h"
#include "DemoDlg.h"
#include "afxdialogex.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// CDemoDlg 对话框CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/): CDialogEx(IDD_DEMO_DIALOG, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CDemoDlg::DoDataExchange(CDataExchange* pDX)
{CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CDemoDlg, CDialogEx)ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CDemoDlg::OnBnClickedButton1)ON_WM_LBUTTONUP()
END_MESSAGE_MAP()// CDemoDlg 消息处理程序BOOL CDemoDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动// 执行此操作SetIcon(m_hIcon, TRUE); // 设置大图标SetIcon(m_hIcon, FALSE); // 设置小图标// TODO: 在此添加额外的初始化代码return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。void CDemoDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDemoDlg::OnQueryDragIcon()
{return static_cast(m_hIcon);
}void CDemoDlg::OnBnClickedButton1()
{SetCapture();
}void CDemoDlg::OnLButtonUp(UINT nFlags, CPoint point)
{ReleaseCapture(); //释放鼠标的捕获CPoint Point(point); //获得当前鼠标的位置相对于整个屏幕的CHAR szClass[100];ClientToScreen(&Point); //转换成相对于当前用户的窗口的位置HWND hChooseHandle = ::WindowFromPoint(Point);HWND hParent = ::GetParent(hChooseHandle);CHAR path[255];// 得到当前鼠标所在的窗口,判断是桌面还是资源管理器GetClassNameA(hParent, szClass, 100);if (_stricmp(szClass, "SHELLDLL_DefView") == 0){hParent = ::GetParent(hParent);GetClassNameA(hParent, szClass, 100);if (_stricmp(szClass, "WorkerW") == 0){SHGetSpecialFolderPathA(0, path, CSIDL_DESKTOPDIRECTORY, 0);MessageBoxA(NULL, path, NULL, MB_OK);}else{hParent = hChooseHandle;for (int i = 0; i < 6; i++){hParent = ::GetParent(hParent);}CHAR* szBuffer[6] = { ("WorkerW"),("ReBarWindow32"),("Address Band Root"),("msctls_progress32"),("Breadcrumb Parent"),("ToolbarWindow32") };for (int i = 0; i < 6; i++){HWND hChild = ::GetWindow(hParent, GW_CHILD);while (hChild != NULL){GetClassNameA(hChild, szClass, 100);if (_stricmp(szClass, szBuffer[i]) == 0){hParent = hChild;break;}hChild = ::GetNextWindow(hChild, GW_HWNDNEXT);}}::GetWindowTextA(hParent, path, 100);//得到资源管理器所代表的文件夹路径MessageBoxA(NULL, path + strlen("路径:"), NULL, MB_OK);}}else{GetClassNameA(hChooseHandle, szClass, 100);if (_stricmp(szClass, "SHELLDLL_DefView") == 0){SHGetSpecialFolderPathA(0, path, CSIDL_DESKTOPDIRECTORY, 0);MessageBoxA(NULL, path, NULL, MB_OK);}else{}}CDialogEx::OnLButtonUp(nFlags, point);
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
