Dashboard > Watir > ... > Advanced Examples > Right Click an Element
Watir Log In View a printable version of the current page.
Right Click an Element
Added by Alan Baird, last edited by Raj on Oct 22, 2008  (view change)
Labels: 

Work in Progress

This example is still being worked on, if you have any comments please add them to the page.

This example uses the getBoundingClientRect method and AutoIt to effectively achieve a right click on an element. In this example, I added a method to the Element class in Watir (originally provided by Paul Rogers here) and then use AutoIt's MouseClick method to send the right click. Subsequent to that you can use the Send method to navigate the context menu. In my example, I want to do a "Save Target As" in order to save the source of a link I want to follow (in my case it was a huge XML file).

UPDATE:
With some help from Bill Agee (see this thread - thanks Bill!), we have come across a workable solution which you see below. I have done some limited testing on this and it seems to work but YMMV. This method has some better recognition for where the element is in relation to the IE page (which was tripping me up before). If you have any feedback on this please leave a comment on this page.

require 'watir'

module Watir
  class Element
    def top_edge
      assert_exists
      assert_enabled
      ole_object.getBoundingClientRect.top.to_i
    end

    def top_edge_absolute
      top_edge + page_container.document.parentWindow.screenTop.to_i
    end

    def left_edge
      assert_exists
      assert_enabled
      ole_object.getBoundingClientRect.left.to_i
    end

    def left_edge_absolute
      left_edge + page_container.document.parentWindow.screenLeft.to_i
    end

    def right_click
      x = left_edge_absolute
      y = top_edge_absolute
      #puts "x: #{x}, y: #{y}"
      WindowsInput.move_mouse(x, y)
      WindowsInput.right_click
    end
  end
end 

module WindowsInput
  # Windows API functions
  SetCursorPos = Win32API.new('user32','SetCursorPos', 'II', 'I')
  SendInput = Win32API.new('user32','SendInput', 'IPI', 'I') 
  # Windows API constants
  INPUT_MOUSE = 0 
  MOUSEEVENTF_LEFTDOWN = 0x0002 
  MOUSEEVENTF_LEFTUP = 0x0004 
  MOUSEEVENTF_RIGHTDOWN = 0x0008 
  MOUSEEVENTF_RIGHTUP = 0x0010 

  module_function
  
  def send_input(inputs) 
    n = inputs.size 
    ptr = inputs.collect {|i| i.to_s}.join # flatten arrays into single string 
    SendInput.call(n, ptr, inputs[0].size) 
  end

  def create_mouse_input(mouse_flag) 
    mi = Array.new(7, 0) 
    mi[0] = INPUT_MOUSE 
    mi[4] = mouse_flag 
    mi.pack('LLLLLLL') # Pack array into a binary sequence usable to SendInput 
  end 

  def move_mouse(x, y)
    SetCursorPos.call(x, y)
  end

  def right_click
    rightdown = create_mouse_input(MOUSEEVENTF_RIGHTDOWN) 
    rightup = create_mouse_input(MOUSEEVENTF_RIGHTUP) 
    send_input( [rightdown, rightup] )
  end
end

def main()
  # Open google index page, and send a right click to the logo image
  ie = Watir::IE.new()
  ie.goto('http://www.tsa.gov/travelers/airtravel/prohibited/permitted-prohibited-items.shtm')
  ie.link(:text, 'Click here').focus
  ie.link(:text, 'Click here').right_click
  # Then, bring up the properties menu (works with IE6, at least)
  ie.send_keys("{DOWN}{DOWN}{DOWN}{ENTER}")
end

if __FILE__ == $0
  main
end


Kept getting this error
"initialize': unknown OLE server: `AutoItX3.Control' (WIN32OLERuntimeError)
HRESULT error code:0x800401f3
Invalid class string"

I guess its bcos of this

Is there a work around to this? Or am i doin it all wrong?
Pls Advice

you have 2 or 3 options here I think:
1) re-install Watir with admin privileges

or

2) install AutoIt independent of Watir (not bad because you get the helpfile for the API and the Window Info tool)

or

3) you may be able to just register AutoIt from the command line. See this post from Charley Baker here
"You need to register AutoIt. In a command window, navigate to the directory
where you've put AutoIt and type:
regsvr32 AutoItX3.dll"

Thanks a Lot Alan!! It works now

Hi Alan - After we discussed a solution that doesn't use a magic number, I got an example working. It also uses SendInput for the mouse motion bits. Let me know what you think:

http://pastie.org/218919

Hi Alan,

I have tried with this code for right clicking on a link but i was inconstantly getting following error

NameError: uninitialized constant WindowsInput::API

Can you tell me what is the problem.

Thanks,
Chethan

Chethan -

I ran this on my computer tonight with no problems. The error you are getting leads me to believe that you might have a cut and paste mistake. I have changed the example so it is executable for anyone (I had to get creative with the example, having traveled recently - it was the first downloadable pdf example I could think of).

Let me know if you are still getting the error message after making sure that you have completely pasted the example correctly.

Alan

Alan,

I tried with modified script you have provided, Still unable to resolve the error message.
I tried with IRE even, same error message getting popped-up.
do I need to add any more require other than 'watir' or any other windows plugins..?

Suggest me on this.

Chethan

Chethan -

Sorry I didn't see this earlier, I don't always see updates to the wiki. I'm not sure how else to help. Maybe you can post to watir-general on the google groups list and let me know what specific problems you are having so I can help. You shouldn't need to require anything else other than what is normally required for watir. Also, can you tell me what line number in the above code is generating the error?

Alan

Hello Chethan

I too received similar issue with this code.

After days of troubleshooting, I found out this,

change this,
SetCursorPos = API.new('SetCursorPos', 'II', 'I', 'user32')
SendInput = API.new('SendInput', 'IPI', 'I', 'user32')

to,
SetCursorPos = Win32API.new('user32','SetCursorPos', 'II', 'I')
SendInput = Win32API.new('user32','SendInput', 'IPI', 'I')

works flawless to me

Alan,
thank you for the code. I am a fresher to watir, so i dont understand the logic behind your code. However, I tried my best to troubleshoot using my guess and guts method

Thank you

Posted by Raj at Oct 22, 2008 06:27

Raj -

Sounds like you got it to work. I'm not sure why the previous example didn't though. If you still have questions let me know and I will try and answer.

Alan

Site running on a free Atlassian Confluence Community License granted to OpenQA. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.6 Build:#812 Aug 06, 2007) - Bug/feature request - Contact Administrators