获得当前鼠标位置下的Windows资源管理器路径

当前鼠标下的文件夹(桌面)路径

 

 

问题:获得获得鼠标下的资源管理器或者用户桌面的绝对路径

首先我们应该了解下面这些窗口句柄相关的函数:

WindowFromPoint 可以获得坐标对应的窗口的句柄,而这个句柄值是系统唯一的。

GetParent                          可以获得给定窗口句柄的父窗口

GetWindow(hParent, GW_CHILD); 可以获得给定窗口的子窗口

::GetNextWindow(hChild,GW_HWNDNEXT);         结合上面的GetWindow函数就可以枚举特定窗口的子窗口,然后就可以枚举当前所有窗口

GetWindowText 和GetClassName分别可以获得窗口的类名和标题

GetDeskTopWindow       可以获得当前桌面句柄,这里的桌面并不是指用户桌面,而是当前桌面环境的第一个窗口,使用spy++观察如下:

 获得当前鼠标位置下的Windows资源管理器路径_第1张图片

由此我们可以首先得到桌面的句柄,然后通过上述函数枚举到当前所有的窗口。下面我们将会需要这一功能。

解决方案:捕获鼠标消息后利用WindowFromPoint 函数获得句柄,然后获得窗口标题即可获得相应路径

实际操作:

1.      使用spy++观察资源管理器类的结构层次如下:

对应资源管理器黑色部分

 获得当前鼠标位置下的Windows资源管理器路径_第2张图片

 

 

可以发现,此区域并没有文件夹路径的信息。在其它区域使用spy++后发现:

获得当前鼠标位置下的Windows资源管理器路径_第3张图片获得当前鼠标位置下的Windows资源管理器路径_第4张图片

我们可以发现,在地址栏存在当前的绝对路径,而我们平时习惯使用的下方的区域则与地址栏在同一个类的子类下方。那么我们就可以得到鼠标下面的窗口的句柄和类,然后得到顶层的“CabinetWClass”类,然后再枚举其子类就可以得到地址栏的地址

 

2那么如何确定当前为资源管理器呢?通过枚举所有“DirectUIHWND”和其父窗口观察窗口的层次结构如下:

获得当前鼠标位置下的Windows资源管理器路径_第5张图片

系统有很多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 进程

 获得当前鼠标位置下的Windows资源管理器路径_第6张图片获得当前鼠标位置下的Windows资源管理器路径_第7张图片

3. 然后就是桌面窗口句柄的处理,同样使用spy++获得句柄并观察:


我们发现窗口使用的是SysListView32 类(CListCtrol控件也使用的这个类)而其父窗口类与资源管理器一样是SHELLDLL_DefView,通过枚举SHELLDLL_DefView 类及其父窗口发现:

获得当前鼠标位置下的Windows资源管理器路径_第8张图片

系统中只有两个SHELLDLL_DefView 类的窗口,都是我们想要的^_~,另外:

如果上面的用户桌面是在桌面显示文件的情况下获得的,当用户桌面的图标不予显示,获得的将直接是SHELLDLL_DefView 类窗口。

 

 

接下来的工作比较简单,判断窗口类或其父窗口类是否为SHELLDLL_DefView,然后通过得到父类以及子类枚举即可获得相应路径:

 获得当前鼠标位置下的Windows资源管理器路径_第9张图片获得当前鼠标位置下的Windows资源管理器路径_第10张图片

核心代码:

// 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);
}


你可能感兴趣的:(windows编程)