WindowFromPoint 可以獲得坐標(biāo)對(duì)應(yīng)的窗口的句柄,而這個(gè)句柄值是系統(tǒng)唯一的。
GetParent 可以獲得給定窗口句柄的父窗口
GetWindow(hParent, GW_CHILD); 可以獲得給定窗口的子窗口
::GetNextWindow(hChild,GW_HWNDNEXT); 結(jié)合上面的GetWindow函數(shù)就可以枚舉特定窗口的子窗口,然后就可以枚舉當(dāng)前所有窗口
GetWindowText 和GetClassName分別可以獲得窗口的類名和標(biāo)題
GetDeskTopWindow 可以獲得當(dāng)前桌面句柄,這里的桌面并不是指用戶桌面,而是當(dāng)前桌面環(huán)境的第一個(gè)窗口,使用spy++觀察如下:

由此我們可以首先得到桌面的句柄,然后通過上述函數(shù)枚舉到當(dāng)前所有的窗口。下面我們將會(huì)需要這一功能。
對(duì)應(yīng)資源管理器黑色部分

可以發(fā)現(xiàn),此區(qū)域并沒有文件夾路徑的信息。在其它區(qū)域使用spy++后發(fā)現(xiàn):


我們可以發(fā)現(xiàn),在地址欄存在當(dāng)前的絕對(duì)路徑,而我們平時(shí)習(xí)慣使用的下方的區(qū)域則與地址欄在同一個(gè)類的子類下方。那么我們就可以得到鼠標(biāo)下面的窗口的句柄和類,然后得到頂層的“CabinetWClass”類,然后再枚舉其子類就可以得到地址欄的地址。

系統(tǒng)有很多DirectUIHWND 類的窗口,但是當(dāng)且僅當(dāng)其父類窗口為“SHELLDLL_DefView”時(shí)代表的是一個(gè)資源管理器。
相應(yīng)代碼:
#include <Windows.h>#include <stdio.h>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;}通過查找窗口句柄可以發(fā)現(xiàn)其中三個(gè)句柄都屬于同一個(gè)資源管理器窗口而另一個(gè)則同屬于explorer 進(jìn)程


3. 然后就是桌面窗口句柄的處理,同樣使用spy++獲得句柄并觀察:

我們發(fā)現(xiàn)窗口使用的是SysListView32 類(CListCtrol控件也使用的這個(gè)類)而其父窗口類與資源管理器一樣是SHELLDLL_DefView,通過枚舉SHELLDLL_DefView 類及其父窗口發(fā)現(xiàn):

系統(tǒng)中只有兩個(gè)SHELLDLL_DefView 類的窗口,都是我們想要的^_~,另外:
如果上面的用戶桌面是在桌面顯示文件的情況下獲得的,當(dāng)用戶桌面的圖標(biāo)不予顯示,獲得的將直接是SHELLDLL_DefView 類窗口。

接下來的工作比較簡單,判斷窗口類或其父窗口類是否為SHELLDLL_DefView,然后通過得到父類以及子類枚舉即可獲得相應(yīng)路徑:


核心代碼:
// DemoDlg.cpp : 實(shí)現(xiàn)文件//#include "stdafx.h"#include "Demo.h"#include "DemoDlg.h"#include "afxdialogex.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// CDemoDlg 對(duì)話框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(); // 設(shè)置此對(duì)話框的圖標(biāo)。 當(dāng)應(yīng)用程序主窗口不是對(duì)話框時(shí),框架將自動(dòng) // 執(zhí)行此操作 SetIcon(m_hIcon, TRUE); // 設(shè)置大圖標(biāo) SetIcon(m_hIcon, FALSE); // 設(shè)置小圖標(biāo) // TODO: 在此添加額外的初始化代碼 return TRUE; // 除非將焦點(diǎn)設(shè)置到控件,否則返回 TRUE}// 如果向?qū)υ捒蛱砑幼钚』粹o,則需要下面的代碼// 來繪制該圖標(biāo)。 對(duì)于使用文檔/視圖模型的 MFC 應(yīng)用程序,// 這將由框架自動(dòng)完成。void CDemoDlg::OnPaint(){ if (IsIconic()) { CPaintDC dc(this); // 用于繪制的設(shè)備上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使圖標(biāo)在工作區(qū)矩形中居中 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; // 繪制圖標(biāo) dc.DrawIcon(x, y, m_hIcon); } else { CDialogEx::OnPaint(); }}//當(dāng)用戶拖動(dòng)最小化窗口時(shí)系統(tǒng)調(diào)用此函數(shù)取得光標(biāo)//顯示。HCURSOR CDemoDlg::OnQueryDragIcon(){ return static_cast<HCURSOR>(m_hIcon);}void CDemoDlg::OnBnClickedButton1(){ SetCapture();}void CDemoDlg::OnLButtonUp(UINT nFlags, CPoint point){ ReleaseCapture(); //釋放鼠標(biāo)的捕獲 CPoint Point(point); //獲得當(dāng)前鼠標(biāo)的位置相對(duì)于整個(gè)屏幕的 CHAR szClass[100]; ClientToScreen(&Point); //轉(zhuǎn)換成相對(duì)于當(dāng)前用戶的窗口的位置 HWND hChooseHandle = ::WindowFromPoint(Point); HWND hParent = ::GetParent(hChooseHandle); CHAR path[255]; // 得到當(dāng)前鼠標(biāo)所在的窗口,判斷是桌面還是資源管理器 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);}
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注