獲取外部控件句柄學習日誌

 

獲取外部控件句柄學習日誌

前段時間小伊做的程序需要獲取外部控件句柄這樣的功能,以前雖然有接觸過spy++,平時用不上,沒有深入過... ...學無止境啊
進入主題...
//====================1
//獲取鼠標所處控件的信息
BOOL GetCurrentPosControl()
{
 POINT currentMousePos;
 GetCursorPos(&currentMousePos);//mouse point
 HWND wmControl=WindowFromPoint(currentMousePos);//handle control
 //實際情況中如果鼠標下的控件disabled 這裏得到的句柄將是該控件的上層容器
 //這種方法並不適合獲取disabled狀態的控件
 GetControlInfo(wmControl);
 return TRUE;
}
//======================================
這裏最直接的調用 WindowFromPoint  可以簡單的獲得鼠標下控件的句柄
MSDN對這個函數的解釋是The WindowFromPoint function retrieves a handle to the window that contains the specified point
大意是 獲的包含鼠標位置點的窗口句柄  兩個關鍵詞  包含 和 窗口
包含 我是這樣理解的:該窗口上包含這個鼠標點的第一控件 與RealChildWindowFromPoint有些類似了
窗口 這裏得到的是最上層窗口的句柄
這個函數不能得到disabled 的控件句柄
//================================2
//獲取鼠標所處的最小控件
BOOL SmallestWindowFromPoint()

 RECT rect, rcTemp;
 HWND hParent, hWnd, hTemp;
 POINT point;
 GetCursorPos(&point);
 hWnd = WindowFromPoint( point );
 if( hWnd != NULL )
 {
  GetWindowRect( hWnd, &rect );
  hParent = GetParent( hWnd );
  if( hParent != NULL )
  {
   hTemp = hWnd;
   do{
    //已獲得鼠標位置控件的下層控件
    hTemp = GetWindow( hTemp, GW_HWNDNEXT );
    //該控件屏幕座標
    GetWindowRect( hTemp, &rcTemp );
    //排除同容器但不在在當前鼠標位置的其他控件
    if(PtInRect(&rcTemp, point) && GetParent(hTemp) == hParent && IsWindowVisible(hTemp))
    {
     // 面積最小
     if(((rcTemp.right - rcTemp.left) * (rcTemp.bottom - rcTemp.top)) < ((rect.right - rect.left) * (rect.bottom - rect.top)))
     {
      // 循環下去!
      hWnd = hTemp;
      GetWindowRect(hWnd, &rect);
     }
    }
   }while( hTemp != NULL );
  }
 }
 GetControlInfo(hWnd);
 return TRUE;
}
//============================
看起來複雜些,簡單分解的步驟就是
1.WindowFromPoint 定位一下窗口控件
2.GetParent 得到父窗口句柄
3.從父窗口開始循環 GetWindow GW_HWNDNEXT 遞進下層窗口
4.判斷面積是否最小
這裏功能已經比較完善了,唯一的缺陷是依然不能得到 disabled 控件,原因在windowfrompoint getwindow 上
//===============================
Xisat@ 2008-03-06 轉載請保留作者信息,感謝
//==================================3
//獲取鼠標位置的最底層控件,包括disabled control
BOOL GetRealWindowFromPoint(HWND cHwnd)
{
 POINT point,WindowPos={0};
 GetCursorPos(&point);
 ClientToScreen(cHwnd,&WindowPos);//轉換成屏幕座標,表示客戶區窗口左上角的座標
 point.x-=WindowPos.x;
 point.y-=WindowPos.y;
 HWND wmControl=ChildWindowFromPoint(cHwnd,point);//客戶區座標
 
 //getlasterr(GetLastError());
 if (wmControl!=NULL)
 {
  if(wmControl!=cHwnd)//wmControl==cHwnd時表示已經到達RealChildWindowFromPoint所能取到的最底層
   GetRealWindowFromPoint(wmControl);//遞歸
   
  else
  {
   GetControlInfo(wmControl);
   return TRUE;
  }
 }
}
//===============================
Xisat@ 2008-03-06 轉載請保留作者信息,感謝
//===============================
主要的API ChildWindowFromPoint MSDN的說明是
The ChildWindowFromPoint function determines which, if any, of the child windows belonging to a parent window contains the specified point. The search is restricted to immediate child windows. Grandchildren, and deeper descendant windows are not searched.
大意是 獲取父窗口直接從屬的子窗口中包含鼠標位置的控件句柄,限制在直屬子窗口,不包括更深層窗口 --這沒關係,我們可以遞歸枚舉下去
實際使用中disabled控件句柄能正常獲取,但是
1
遇到重疊的控件,只能得到包含的控件句柄,事實上需要的是被包含的控件句柄
稍微作些修改
HWND wmControl=ChildWindowFromPoint(cHwnd,point);//客戶區座標
改爲
HWND wmControl=RealChildWindowFromPoint(cHwnd,point);//客戶區座標
2
可行
MSDN 對這個api的解釋是
The RealChildWindowFromPoint function retrieves a handle to the child window at the specified point. The search is restricted to immediate child windows; grandchildren and deeper descendant windows are not searched.
咋一看還真沒區別
關鍵詞是 at 而上面是 contains
at 在鼠標位置下的最直接控件 contains是包含鼠標位置的第一控件(老外學起來是不是沒這樣費力 BS^_^)
MS爲什麼不把這兩個api統一一下???
//============================
還有這方面幾個常用的API
WindowFromPhysicalPoint Vista下用的???
ChildWindowFromPointEx 和ChildWindowFromPoint類似 多了一個擴展參數
EnumChildWindows 枚舉子窗口內的所有控件,包括一個回調函數,實在找不到就枚舉吧
更多說明請參考MSDN,該做飯去咯^_^.
//===============================
Xisat@ 2008-03-06 轉載請保留作者信息,感謝
//===============================
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章