AutoHotkey Community

It is currently May 27th, 2012, 10:03 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 271 posts ]  Go to page 1, 2, 3, 4, 5 ... 19  Next

Do you think this tutorial is beneficial to the AHK Community?
Yeah, I think this tutorial is a great value-add to the Community.
Nope - I think this tutorial is a waste of web space.
I think this tutorial would be better if it incorporated AHK_L & COM_L.
You may select 1 option

View results
Author Message
PostPosted: November 12th, 2009, 1:51 am 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
Basic Webpage Controls with JavaScript / COM
This tutorial requires one of the following:Purpose
The purpose of this tutorial is to teach the intermediate AHK user how to start using COM to control webpages. My goal is to provide methods for controlling webpages, similar to how the AHK Control Commands can control Windows Applications. This tutorial is going to be high level, but will provide links to those who want to dig deeper into these concepts. You don't need to have much programming experience, but I will assume you feel comfortable writing and executing AHK scripts. We will be covering the following three topics:
  1. The HTML DOM - (Document Object Model) A basic understanding of the HTML DOM is essential for controlling webpages. This is because it's a "map" or "heirarchy" for accessing parts of the webpage. The HTML DOM is not language dependent, but rather the model for how the webpage document is constructed.
  2. JavaScript - We will cover some basic JavaScript because it is the scripting language of the web, and is supported by most web browsers. Controlling webpages using JavaScript is not the primary aim of this tutorial, but it will prove valuable because you should be able to find plenty of useful JavaScript examples online. This will be helpful because in my opinion, the simplest way to start using COM is to learn some basic JavaScript, and then "translate" that code to use with COM in AHK.
  3. COM - (Component Object Model) All you really need to know about COM for this tutorial is that Internet Explorer is a COM object - which means we can use COM to manipulate it. Using COM is the most effective way to control an Internet Explorer Webpage with AHK.
"Let me say it a different way: COM is the steering wheel - the HTML DOM is a road map - AHK is the car" ~tank

Disclaimers

For this tutorial, I will show you how to control webpages using JavaScript, along with the AHK COM "translations" (AutoHotkey_L in Black, AHK Basic in Green) - also, note Sean's post below. (Using COM requires Internet Explorer, but JavaScript can be used with most Web Browsers) The guidelines for "translating" JavaScript can be found in the first post of the COM Standard Library thread (for AHK Basic).
Color Legend wrote:
Javascript: dark blue
AutoHotkey_L: black
AHK Basic: green


Some other tutorials that helped me out, and inspired this tutorial can be found here:
- COM Tutorial by tank - Study the basics from this; I will not be covering them.
- W3Schools - Many links listed below will take you to this website, which is an excellent resource for learning JavaScript in depth.
    Thank You:
  • Chris Malet for creating AutoHotkey
  • Lexikos for AutoHotkey_L
  • Sean & fincs for helping with Native COM Support
  • Sean for creating the COM Standard Library
  • tank for the tutorial listed above, & daonlyfreez
  • tank, sinkfaze, & jaco0646 for reviewing this tutorial
Terms - The following terms will be used throughout this tutorial. You may use these links for a more in-depth description of each item.
HTML DOM, JavaScript, COM, Methods, document, value, element, form, name, ID, Input, Tag, selectedIndex, checked, innerText, innerHTML

Methods - The following Methods will be used throughout this tutorial. (comparable to built-in functions for AHK)
alert(), getElementById(), getElementsByName(), getElementsByTagName(), focus(), click()

Before we begin, this tutorial will be using examples that start with javascript: - which you will feed through the URL Address bar. These examples will be based on (and can be used with) the Search Forum webPage. Our first example will use the alert() method to pop-up a message box that says Hello World! Simply put this javascript in your URL Address bar and hit enter:
Code:
javascript: alert('Hello World!')
WB.Navigate("javascript: alert('Hello World!')")
COM_Invoke(pwb, "Navigate", "javascript: alert('Hello World!')")


Accessing WebPage Contents - HTML DOM
To understand how to use Javascript to control a webpage, you need a general understanding of the HTML DOM. It is similar to a "map" or "heirarchy" of the Webpage, as shown here:
*Image is from this website, which is another great resource for learning Javascript.
Image
In the image above, note the document object - you will be using this object quite often. To access the Webpage, you will need to navigate through the HTML DOM. Here are some simple ways to do this:
  • Object Name & Index
    Say you want to get the value of the 1st element in the 1st form, which will be the Search for Keywords Input Box. The path would look like this (a collection of objects starts at 0):
    Code:
    document.forms[0].elements[0].value
    Now if you want to show the value of the element in a pop-up, simply put this javascript in your URL Address bar and hit enter:
    Code:
    javascript: alert(document.forms[0].elements[0].value)
    MsgBox % WB.document.forms[0].elements[0].value
    MsgBox % COM_Invoke(pwb, "document.forms[0].elements[0].value")
  • Object's Name / ID Attribute
    You can also use the objects name or ID. For example, the 1st forms name is SearchForm, with its 1st elements name being search_keywords. The following javascript fed throught the address bar would produce the same results:
    Code:
    javascript: alert(document.SearchForm.search_keywords.value)
    MsgBox % WB.document.SearchForm.search_keywords.value
    MsgBox % COM_Invoke(pwb, "document.SearchForm.search_keywords.value")
    Or if you only know the elements name is search_keywords, you could display the value of that element using all, which references all the elements on the webpage:
    Code:
    javascript: alert(document.all.search_keywords.value)
    MsgBox % WB.document.all.search_keywords.value
    MsgBox % COM_Invoke(pwb, "document.all.search_keywords.value")
  • getElement Methods
    If you want to get an element(s) based on limited criteria, you can use the following 3 methods:
    • getElementById(id) - returns a reference to the first object with the specified ID
    • getElementsByName(name) - Returns a collection of objects with the specified name
    • getElementsByTagName(tagname) - Returns a collection of objects with the specified tagname
    The following example will display the value of the Search for Author Input Box, which is the 4th element on the webpage with an INPUT Tag:
    (Note - the item number may be dynamic)
    Code:
    javascript: alert(document.getElementsByTagName('input')[3].value)
    MsgBox % WB.document.getElementsByTagName("input")[3].value
    MsgBox % COM_Invoke(pwb, "document.getElementsByTagName[input].item[3].value")
Controlling the WebPage
So far we have just retrieved information from the webpage. Now lets start controlling the webpage. Note - if the JavaScript doesn't end with a Method, use void 0.
  • Focus on a Webpage Element - focus()
    Sets the focus to the Search for Keywords Input Box:
    Code:
    javascript: document.all.search_keywords.focus()
    WB.document.all.search_keywords.focus()
    COM_Invoke(pwb, "document.all.search_keywords.focus")
  • Click on a Webpage Element - click()
    Clicks the Search button:
    Code:
    javascript: document.getElementsByTagName('input')[11].click()
    WB.document.getElementsByTagName("input")[11].click()
    COM_Invoke(pwb, "document.getElementsByTagName[input].item[11].click")
  • Set Value of an Input Field - value
    Sets the value of the Search for Keywords Input Box:
    Code:
    javascript: document.all.search_keywords.value = 'Input Value'; void 0
    WB.document.all.search_keywords.value := "Input Value"
    COM_Invoke(pwb, "document.all.search_keywords.value", "Input Value")
  • Dropdown Box Selection - selectedIndex
    Quote:
    <SELECT class=post name=sort_by><OPTION selected value=0>Post Time</OPTION><OPTION value=1>Post Subject</OPTION><OPTION value=2>Topic Title</OPTION><OPTION value=3>Author</OPTION><OPTION value=4>Forum</OPTION></SELECT>
    This is the HTML for the Sort By Dropdown. The following will set the Dropdown to Author:
    Code:
    javascript: document.all.sort_by.selectedIndex = 3; void 0   ; Note - you could use value = 3
    WB.document.all.sort_by.selectedIndex := 3
    COM_Invoke(pwb, "document.all.sort_by.selectedIndex", 3)
  • Radio / Checkbox Selection - checked
    Quote:
    <INPUT value=ASC type=radio name=sort_dir> Ascending<BR><INPUT value=DESC CHECKED type=radio name=sort_dir> Descending
    This is the HTML for the Sort By Radio selection. The following will set the Radio to Ascending:
    Code:
    javascript: document.all.sort_dir[0].checked = true; void 0
    WB.document.all.sort_dir[0].checked := True
    COM_Invoke(pwb, "document.all.sort_dir[0].checked", True)
  • Get Text from a WebPage Element - innerText
    Say you want to get the text at the top of the page (innerHTML will give you all the HTML):
    Code:
    text := WB.document.getElementsByTagName("TD")[2].innerText
    text := COM_Invoke(pwb, "document.getElementsByTagName[TD].item[2].innerText")
    ... or if you want all the text (or html) from the page:
    Code:
    text := WB.document.documentElement.innerText
    text := COM_Invoke(pwb, "document.documentElement.innerText")
There you have it! These techniques should help get you started. Next, I would recommend the following:
  1. Try these Controls out on some of your favorite webpages.
  2. Find some more JavaScript examples, and then try "translating" them to COM. (JavaScript is well documented online)
  3. Learn additional ways to access the HTML DOM.
You may be wondering, "How do I find information about the element so I can access it?" Good question! The following tools can help you with that.



Helpful Tools
  • iWebBrowser2 Learner - This program will give you information about IE webpage elements as you hover over them.
  • IE HTML Element Spy - This program will show you the information and source code of each element by dragging the curser over the webpage.
Frequently Asked Questions

What is a WB/pwb?
- An object/variable that contains a pointer to the Web Browser object (Internet Explorer). Here is a simple script for creating one:

Code:
; AutoHotkey_L:

WB := ComObjCreate("InternetExplorer.Application") ; Create an IE object
WB.Visible := true ; Make the IE object visible
WB.Navigate("www.AutoHotkey.com") ; Navigate to a webpage
Code:
; AHK Basic:

COM_Init() ; Initialize COM
pwb := COM_CreateObject("InternetExplorer.Application") ; Create an IE object
COM_Invoke(pwb, "Visible=", true) ; Make the IE object visible
COM_Invoke(pwb, "Navigate", "www.AutoHotkey.com") ; Navigate to a webpage

; when finished
COM_Release(pwb) ; Always release COM objects
COM_Term() ; Always Uninitialize COM

How to access an existing IE object?
  1. Access an IE object by WinTitle & Internet Explorer_Server Number:
  2. Access an IE object by Window/Tab Name:
How to know when the webpage in done loading?
- Sean's IEReady() function is great for this, and can be found here. Here is an example using the ReadyState property, which should work in may scenarios:

Code:
; AutoHotkey_L:

WB.Navigate("www.AutoHotkey.com")
while, WB.ReadyState != 4
; while, WB.Busy
   Sleep, 10
Code:
; AHK Basic:

COM_Invoke(pwb, "Navigate", "www.AutoHotkey.com")
while, COM_Invoke(pwb, "ReadyState") != 4
; while, COM_Invoke(pwb, "Busy")
   Sleep, 10

- OR - here is an example using the DocumentComplete event:
Code:
; AutoHotkey_L:

WB := ComObjCreate("InternetExplorer.Application")
WB.Visible := True
ComObjConnect(WB, "IE_"), loading := true ; Connect IE object & set var "loading" as TRUE
WB.Navigate("www.AutoHotkey.com")
while, loading
   Sleep, 10
MsgBox, DONE!
WB := "" ; Release & Disconnect IE object
return

IE_DocumentComplete() { ; the "IE_" prefix corresponds to the ComObjConnect() function above
   global loading := false ; Break the While-Loop
}
Code:
; AHK Basic:

COM_Init()
pwb := COM_CreateObject("InternetExplorer.Application")
COM_Invoke(pwb, "Visible=", "True")
sink := COM_ConnectObject(pwb, "IE_"), loading := true ; Connect IE object & set var "loading" as TRUE
COM_Invoke(pwb, "Navigate", "www.AutoHotkey.com")
while, loading
   Sleep, 10
MsgBox, DONE!
COM_DisconnectObject(sink) ; Disconnect IE object
COM_Release(pwb), COM_Term()
return

IE_DocumentComplete() { ; the "IE_" prefix corresponds to the COM_ConnectObject() function above
   global loading := false ; Break the While-Loop
}

What if all this stuff is too confusing for me?

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Last edited by jethrow on May 2nd, 2012, 6:50 am, edited 25 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 12th, 2009, 2:16 am 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
BRAVO :!: :!: :idea:

Thanks for this. My threads are out of date and i just dont have the kind of patience and grammer to produce something like this.

Users should be directed to this thread in the future instead of my IE based COM threads. This work supercedes all of mine

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 1:56 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
Very nice. IMO, however, it would've been even more clear if done using COM_L for AHK_L than COM for the old AHK. COM_Invoke being explicit may distract users from the main point.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 2:51 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
Thanks for the feedback guys - I was hoping this would prove benificial to the community. :D

Sean wrote:
IMO, however, it would've been even more clear if done using COM_L for AHK_L than COM for the old AHK. COM_Invoke being explicit may distract users from the main point.

I agree 100% :D If fact, that distraction was one of the main reasons I had originally decided to write this tutorial - to help bridge users gap in understanding. I had just finished writing this when Lexikos released AHK_L with object support. Then, when you released COM_L, I thought this tutorial would become rapidly outdated (which I still think). However, who knows when Chris will implement object support into the regular AHK release? Once that happens, I'll probably update this tutorial.

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 3:36 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
It's a DOM tutorial, so, there are a lot to clarify other than just syntax. When, using JavaScript the top/base object is the Window object, not WebBrowser object. In fact, WebBrowser object is neither part of nor essential for DOM manipulation. So, in strict sense,
Code:
javascript: document.all[11].click()
is actually equivalent to
Code:
COM_Invoke(window, "document.all[11].click()")
not to
Code:
COM_Invoke(pwb, "document.all[11].click()")

However, this tutorial uses pwb in all of the examples, which might lead readers to believe that using WebBrowser object is inevitable for DOM manipulation, not a mere convenience.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 4:06 pm 
Offline
User avatar

Joined: May 24th, 2009, 5:35 am
Posts: 2099
Location: Iowa, USA
Sean wrote:
When, using JavaScript the top/base object is the Window object, not WebBrowser object.

Thank you for pointing this out Sean. I hadn't even thought about, nor fully understood this. In your example, this would be technically accurate, right?
Code:
window := COM_Invoke(pwb, "contentWindow")


EDIT - :oops: and these are the ignorant questions I end up asking if I don't study & test the code before I ask questions. See tank's answer in the next post.

_________________
Image
Recommended: AutoHotkey_L
Basic Webpage Controls


Last edited by jethrow on November 13th, 2009, 5:15 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 4:09 pm 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
Contentwindow is not accessable from the browser object but from a frame object

to get a window object from a pwb is done as thus
Code:
window:=com_invoke(pwb,"document.parentwindow")
window:=COM_QueryService(pwb,   "{332C4427-26CB-11D0-B483-00C04FD90119}",   "{332C4427-26CB-11D0-B483-00C04FD90119}")
contentWindow is typically used to aquire a window handle from a frame

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 4:25 pm 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
Even more confusing because Document must be accessed with COM prior to accessing Window.

I generally dont climb back up to or query DOM for the window unles i need to use the execScript method

For sheer convenience I am going to post some JScript and VBS that as far as I can tell isn’t easily found elsewhere.
The main thing to know is the browser encompasses the toolbars and address bar while the window object refers only to the content area
JScript that creates a new browser and navigates
Code:
<script language="jscript">
var  pwb = new ActiveXObject("InternetExplorer.Application");
pwb.visible=true;
pwb.Navigate("www.AutoHotkey.com");
</script>

Same as above but in VBS
Code:
<script language="vbscript">
set pwb = CreateObject("InternetExplorer.Application")
pwb.visible=true
pwb.Navigate("www.AutoHotkey.com")
set pwb =  nothing ' releases the variable
</script>


Replicates most of the functionality of the IEGet function posted above in AHK.
Code:
<script language="vbscript">
Function IEGet(Title)
   ''Gets window by the title
   ''Title is case sensitive
   Set oShellApplication = CreateObject( "Shell.Application" )
   Set oWindows = oShellApplication.Windows
   For Each oWindow In oWindows
      if   InStr(1,oWindow.LocationName,Title,1) > 0 and InStr(1,oWindow.FullName,"iexplore.exe",1) > 0 then
         set IEGet=oWindow '' create an object variable
         exit for
      end if
   next
   Set oWindows = nothing   
   Set oShellApplication = nothing   
End Function
</script>
obviously this can be done in JScript as well but I will not bother. From here we can begin to see the similarities in the code structure

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Last edited by tank on November 24th, 2009, 5:22 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 4:38 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
I guess its possible to create script and framework from the scripts around the forum that:

1. Loads given HTML into the IE control.
2. Crates the tree presentation of DOM or all automatable objects with user filter.
3. Let the user associate some code with the objectl; some hardcoded operations would be nice for start and plugin architecture to add more; click, send, size for the start. Dynamic function calls could be used as plugins for new operations if desired.
4. Let the user save such project and run it.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 4:49 pm 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
are you refering to an ahk Browser in a GUI that functions much the same as HTA applications?
If so of course IMO triggering an ahk script to run from an html page is super easy if its a trusted source


you can use the FileRun function with an onclick event to trigger scripts even pass command line parameters the below i copied from my own proprietary library. I use this in a call center environment with great reliability
IF not obvious the below is VBS
Code:
Set oShell = CreateObject( "WScript.Shell" )
Set objFSO = CreateObject("Scripting.FileSystemObject")
Function FileRun(strFile,filename,async)
'' strFile - full run command line example format """C:\Program Files\AutoHotkey\AutoHotkey.exe"" /ErrorStdOut ""C:\Documents and Settings\nbk64jq\Desktop\MyHots.ahk"" CMDArg"""
'' filename - path and filename
   FileRun=false
'' async - wait for file to exit before continuing accepts true false
   e=FileExists(filename)
   if   e then
      r=isRunning(filename)
      if   not r then
         oShell.Run strFile, 6, async
         FileRun=true
         
      end if
   end if
End Function

Function isRunning(CmdTitle)
   isRunning=false
   For Each strProcess In GetObject("winmgmts:").InstancesOf("win32_process")
      if   InStr(1,strProcess.CommandLine,CmdTitle,1) > "2" then
         isRunning=true
      end if
   next

End Function


Function FileExists(strFile)
   FileExists = objFSO.FileExists(strFile)
   
End Function


Edit I have tried using events from ahk for this but in non standard deployment if IE these fail and in the past caused the gui to crash if to many events were triggered

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 8:31 pm 
Offline
User avatar

Joined: March 19th, 2008, 12:43 am
Posts: 5482
Location: the tunnel(?=light)
So given the discussion in this thread about "recursing" through frames to a page element, is it possible to amend some of the current iWeb functions or create a new iWeb function(s) to accommodate frame recursion? Or is it just something worth mentioning in the course of this tutorial, for example?

BTW - Excellent tutorial jethrow, glad I could help in whatever small way I could. :wink:

_________________
Image
Try Quick Search for Autohotkey or see the tutorial for newbies.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 8:57 pm 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
edit i spose your refering to this library
iWeb functions
i have considered recurse into frames for some time now but unfortunately the options and depth of recursion seem a bit complex to make reliable I might get around to it sometime in the future but it really seems that frames might be somthing we want to leave ot users more versed in DOM and using Invoke exclusively

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Last edited by tank on November 14th, 2009, 9:36 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 10:25 pm 
Offline
User avatar

Joined: March 19th, 2008, 12:43 am
Posts: 5482
Location: the tunnel(?=light)
Would something like this be feasible? Obviously the user will be responsible for obtaining the frames themselves:

Code:
iWeb_clickDomObj(pwb,obj,frame="") { ; frame is comma delimited list of frames by name/id/number

  If pWin:=iWeb_DomWin(pwb) {
    if frame {
      Loop, Parse, frame, `,
        framePath.="document.all[" A_LoopField "].contentwindow."
      COM_Invoke(pWin,framePath . "document.all.item[" obj "].click")
    }

    else
      COM_Invoke(pWin,"Document.all.item[" obj "].click")
    d=1
    COM_Release(pWin), VarSetCapacity(framePath,0)
  }
  Return d
}

; example usage
iWeb_clickDomObj(pwb,"username","_sweclient,_swecontent,_sweview,_svf1")


Probably very sloppy code by your standards but you get the general idea.

_________________
Image
Try Quick Search for Autohotkey or see the tutorial for newbies.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 11:08 pm 
Offline

Joined: December 24th, 2008, 3:25 am
Posts: 1401
Location: :noitacoL
Does this mean I have to change my Sig now? :(


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 13th, 2009, 11:28 pm 
Offline
User avatar

Joined: December 21st, 2007, 3:14 pm
Posts: 3826
Location: Louisville KY USA
Very astute my young padawan :D
I spose if you want to update the other functions I havent time right now ill update the zip file with it or you can wait months (perhaps years :oops: ) tll i get around to it


@Carcophan no probably not the vast majority still wont follow this tutorial since they have no interest whatsoever in actually learning javascript or DOM. This tutorial is still aimed at folks who know at least that much and to help them convert similar javascript to compatable COM.AHK

Most still wont understand COM DOM or scripting so I think the quote still applies

_________________
No matter what your oppinion Please join this discussion
Formal request to Polyethene
Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 271 posts ]  Go to page 1, 2, 3, 4, 5 ... 19  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: sks and 22 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group