Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Клик по координатам окна


Автор: lollollollol 23.8.2013, 22:14
Здравствуйте.
Подскажите пожалуйста, как передать клик мышкой окну, которое находится за пределами рабочего стола (например видна только половина окна, другая половина за пределми)
и при этом не перемещать курсор мышки (т.е. отправить сообщение о клики в окне на заданых координатах)


Автор: Sanchezzz 23.8.2013, 22:54

Код

var Pt = TPoint;
...
Mouse_Event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, Pt.x, Pt.y, 0, 0);







Этот ответ добавлен с нового Винграда - http://ru.vingrad.com//object-id5217b4b66ccc191179000002#findElement_E7045_5217bde46ccc192f7d0003bd_0

Автор: lollollollol 24.8.2013, 07:03
Дак ведь оно просто кликнет на заданых координатах, а мне нужно кликнуть по части окна, которая за границей монитора, при этом не переместив курсор мышки.
И при этом клик отправить в конкретное окно(указав хендл), ведь окон может быть множество, в пределах одних координат


т.е. по сути меня интересует вопрос, 
можно ли как-то окну сказать "Тебе нажли мышкой в таких-то координатах", 
на смотря на то что в очередь событий с вводных устройств действия добавляться не будет?

Автор: Sanchezzz 24.8.2013, 10:12
Кординаты передать нельзя(Вернее надо читать доку что бы узнать)  а вот сказать можно например через FindWindowEx + SendMessage

Автор: lollollollol 24.8.2013, 11:18
Код

procedure ClickByWindow(aHWindow : HWND; aX : Word; aY : Word);
var
  Coordinates : Longword;
begin
  Coordinates := 0;
  Coordinates := aX or (aY shl 16);
  SendMessage(aHWindow, WM_LBUTTONDOWN, MK_LBUTTON, Coordinates);
  SendMessage(aHWindow, WM_LBUTTONUP, MK_LBUTTON, Coordinates);
end;

ClickByWindow($0022043C,300,42);


Хендл окна посмотрел через WinSpy++, проверил это именно то окно(подвигал его), но на клик никак не реагирует.

Автор: Poseidon 24.8.2013, 12:03
А 300 и 42 откуда взял? По-моему там надо передавать координаты относительно рабочего стола. Нужно глянуть msdn. А еще по-моему есть сообщение WM_Click

Автор: lollollollol 24.8.2013, 12:08
Я координаты и относительно раб стола передавал, и относительно окна где выполняю клик, мне кажется проблема в дочерних окнах, могу ошибаться.

Для примера, попробуй открыть 5 вкладок в браузере.
Потом почти полностью передвинуть его за пределы раб стола.
(предварительно получив координаты, куда будешь кликать, я с помощью скриншота окна и фотошопа получаю координаты)
После этого передать клик по коодинатам, чтобы браузер показал другую вкладку.

Автор: Poseidon 24.8.2013, 14:20
Я бы экспериментировал не с фотошопом, а с самой программой. Для начала проверь получает ли программа в принципе твое сообщение (вдруг все-таки окно определил не правильно), а потом уже разбирайся с координатами. Получать Handle чужого окна можно прямо из своего кода без Spy++. Копай в сторону FindWindow.

Автор: lollollollol 24.8.2013, 15:15
я знаю, сообщение окно получает(ну когда перемещаю и т.д.) а значит и хендл верный

Автор: Poseidon 24.8.2013, 18:18
Значит не верно координаты передаешь. Откуда этот код?
Код

Coordinates := aX or (aY shl 16);

http://msdn.microsoft.com/en-us/library/aa924434.aspx читал?
Цитата

xPos 
Value of the low-order word of lParam. Specifies the x-coordinate of the cursor, relative to the upper-left corner of the client area. 

yPos 
Value of the high-order word of lParam. Specifies the y-coordinate of the cursor, relative to the upper-left corner of the client area.


Попробуй так
Код

procedure ClickByWindow(aHWindow : HWND; aX : Word; aY : Word);
var
  Msg: TMessage;
begin
  Msg.LParamLo:= aX;
  Msg.LParamHi:= aY;
  SendMessage(aHWindow, WM_LBUTTONDOWN, MK_LBUTTON, Msg.LParam);
  SendMessage(aHWindow, WM_LBUTTONUP, 0, Msg.LParam);
end;


Автор: Чучмек 24.8.2013, 19:27
Если там,куда хочешь кликнуть, находится дочернее окно (button/edit/panel итп) то сообщение нужно слать ему, а не главному окну.

Добавлено через 13 минут и 5 секунд
Цитата(Poseidon @  24.8.2013,  18:18 Найти цитируемый пост)
Значит не верно координаты передаешь. Откуда этот код?
Выделить всёкод Pascal/Delphi
1:
    
Coordinates := aX or (aY shl 16);

MSDN читал?
Цитата

xPos 
Value of the low-order word of lParam. Specifies the x-coordinate of the cursor, relative to the upper-left corner of the client area. 

yPos 
Value of the high-order word of lParam. Specifies the y-coordinate of the cursor, relative to the upper-left corner of the client area.



Да все правильно здесь. Так и написано x - младшая часть, y - старшая.  

Автор: lollollollol 25.8.2013, 07:55
А как Windows тогда это делает?
Вот например делаю я клик по координатам 100,100, как windows определяет какое там дочернее окно?

Автор: lollollollol 25.8.2013, 08:37
т.е вопрос формулируется так:
1. Как можно получить хендл дочернего окна, по указаным координатам.
(неужели придёися перебирать все дочерние окна, и смотреть их позции? Мжет быть в системе есть функция готовая?)
2. Координаты нужно указывать относитьно рабочего стола(даже за педелами разрешения монитора?) или относительно основного окна?

Автор: Чучмек 25.8.2013, 10:37
Есть WindowFromPoint, но она работает только в пределах экрана. 
Цитата(lollollollol @  25.8.2013,  07:55 Найти цитируемый пост)
А как Windows тогда это делает?

А так и делает, какое окно сверху тому и шлет сообщение.
Цитата(lollollollol @  25.8.2013,  08:37 Найти цитируемый пост)
неужели придёися перебирать все дочерние окна, и смотреть их позции

Да скорей всего. Но ничего страшного здесь нет.
Кроме того, если ты хочешь кликнуть по нарисованной кнопке на web странице (клик обрабатывается через javascript), то прежде нужно послать WM_MOUSEMOVE.

Автор: Чучмек 25.8.2013, 12:28
Код

type
  TEnumData = record
    x,
    y:integer;
    result:cardinal;
  end;
function enumCBFunc(hwnd:hwnd;var EnumData:TEnumData):BOOL;stdcall;
var
  rct:TRect;
begin
  GetWindowRect(hwnd,rct);
  if (rct.Top<=EnumData.y)  and
     (rct.Bottom>EnumData.y)and
     (rct.Left<=EnumData.x) and
     (rct.Right>EnumData.x) and
     (GetWindowLong(hwnd,GWL_STYLE) AND WS_VISIBLE <>0)then
  begin
    EnumData.result:=hwnd;
    result:=false;
  end else result:=true;
end;
function MyWindowFromPoint(Point: TPoint):cardinal;
var
  EnumData:TEnumData;
  hwnd:cardinal;
begin
  EnumData.x:=Point.X;
  EnumData.y:=Point.Y;
  hwnd:=0;//dword(-1);
  EnumData.result:=hwnd;
  EnumWindows(@enumCBFunc,integer(@EnumData));
  while EnumData.result <> hwnd do
    begin
    hwnd:=EnumData.result;
    EnumChildWindows(EnumData.result,@enumCBFunc,integer(@EnumData));
    end;
  result:=hwnd;
end;


Автор: lollollollol 25.8.2013, 12:50
Спасибо, сейчас буду эксперементировать:) !

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)