2011-06-14 4 views
1

버튼을 눌렀는지 확인하고 싶습니다. 이것은 버튼의 공식 속성이 아닌 것 같습니다 (버튼 스타일 체크 박스가 아닙니다!), 접근 가능한 것처럼 보이지만 예를 들어 원하는 결과를 얻는 BM_GETSTATE 메시지가 있습니다.UIAutomation을 통해 버튼을 눌렀는지 여부를 결정하는 방법은 무엇입니까?

자주 발생하는 문제는 단추에 대한 창 핸들이없는 것입니다.이 단추는 AutomationElement에 의해 구분 될 수 있지만 다른 도구 모음의 일부입니다. 그리고 SendMessage 함수에 대한 핸들이 필요합니다.

그래서 .. 저 재산에 접근 할 수있는 방법이 있습니까? 나는 다른 자동화 프로그램에서 그것을 보았 기 때문에 접근이 가능하다는 것을 안다. 나는 그것에 접근하는 법을 모른다.

C#을 사용할 예정이지만 모든 C 코드가 좋을 것입니다.

많은 감사

답변

1

(편집 :. 그래서 마침내 제대로 여기에 코드 형식으로 만들어 관리 - 단지 시작에 4 공백을 삽입)

이 그것을 즐기을, 그것을 얻기 위해 나에게 꽤 오랜 시간이 걸렸습니다 그것은 작동합니다 ..하지만 지금은 새로운 수준에 도달 한 것 같아요. :)

(어떻게 만드는 제대로 형식을 말해 줘요 - 모두 인용 및 코드 나 실패)

int res; 
#region direct method 
int hwnd = ae.Current.NativeWindowHandle; 
if (hwnd != 0) 
{ 
    const UInt32 BM_GETSTATE = 0x00F2; 
    res = SendMessage(hwnd, BM_GETSTATE, 0, 0); 
} 
#endregion 
else 
#region method via toolbar 
{ 
    AutomationElement parent = TreeWalker.RawViewWalker.GetParent(ae); 
    while ((parent != null) && (parent.Current.ControlType != ControlType.ToolBar)) 
     parent = TreeWalker.RawViewWalker.GetParent(ae); 
    if (parent != null) 
    { 
     int toolBarHandle = parent.Current.NativeWindowHandle; 
     #region defines 
     const int WM_USER = 0x400; 
     const int TB_GETSTATE = (WM_USER + 18); 
     const int TB_GETBUTTON = (WM_USER + 23); 
     const int TB_BUTTONCOUNT = (WM_USER + 24); 
     #endregion 

     #region get correct child number 
     int numButtons = SendMessage(toolBarHandle, TB_BUTTONCOUNT, 0, 0); 
     AutomationElement sibling = ae; 
     int cnt = -1; 
     while (sibling != null) 
     { 
      sibling = TreeWalker.RawViewWalker.GetPreviousSibling(sibling); 
      ++cnt; 
     } 
     if (cnt >= numButtons) 
      cnt = 0; // nonsense value, but pass a valid one 
     #endregion 

     #region get command id 
     TBBUTTON butInfo = new TBBUTTON(); 
     butInfo.idCommand = 1234; 
     uint pid; 
     GetWindowThreadProcessId((IntPtr)toolBarHandle, out pid); 
     IntPtr process = OpenProcess(ProcessAccessFlags.VMOperation | ProcessAccessFlags.VMRead | 
     ProcessAccessFlags.VMWrite | ProcessAccessFlags.QueryInformation, false, pid); 

     IntPtr p = VirtualAllocEx(process, IntPtr.Zero, (uint)Marshal.SizeOf(typeof(TBBUTTON)), AllocationType.Commit 
            , MemoryProtection.ReadWrite); 

     int _res = SendMessage(toolBarHandle, TB_GETBUTTON, cnt, p.ToInt32()); 

     #region getresult 
     int read; 
     IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TBBUTTON))); 
     Marshal.StructureToPtr(butInfo, ptr, true); 
     bool __res = ReadProcessMemory(process, p, ptr, Marshal.SizeOf(typeof(TBBUTTON)), out read); 
     System.Diagnostics.Debug.Assert(read == Marshal.SizeOf(typeof(TBBUTTON))); 
     butInfo = (TBBUTTON)Marshal.PtrToStructure(ptr, typeof(TBBUTTON)); 
     #endregion 

     int commandId = butInfo.idCommand; 
     VirtualFreeEx(process, p, 0, FreeType.Release); 

     #endregion 

     //!define BST_UNCHECKED  0 
     //!define BST_CHECKED  1 
     //!define BST_INDETERMINATE 2 
     //!define BST_PUSHED   4 
     //!define BST_FOCUS   8 

     #region get state 
     res = SendMessage(toolBarHandle, TB_GETSTATE, commandId, 0); 
     #endregion 
    } 
} 
#endregion 

편집 : 여기 http://www.andreas-reiff.de/2011/06/c-speicher-anderen-prozess-befullen-lassen-checken-ob-ein-button-gedruckt/ 읽을 수있는 코드와 이상한, 외국어 설명과 함께 .. 코드 주석은 영어입니다. 유용하다고 생각하길 바랍니다. 또한이 정보가 없으면이 문제를 해결할 수 없었습니다. How come some controls don't have a windows handle?.

관련 문제