Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Embedded Windows Scripting (VBScript & JScript) and COM


  • Please log in to reply
68 replies to this topic
erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007
Include VBScript or JScript code directly in your Autohotkey program!
No temporary files. Full and easy access to COM.

Checkout the official homepage for the latest version, (old) demos, change log, and documentation:
<!-- m -->http://www.autohotkey.net/~easycom<!-- m -->


Note: ws4ahk is made for Autohotkey Basic. It may work with Autohotkey_L, but it is not supported.
------------------------------------
This topic was split off from the old topic "EasyCOM.dll" development.
Original post content is below.

------------------------------------

I've been thinking long and hard about using Microsoft Scripting Control to provide easy COM usage to AHK, and the more I have, the more it became the ultimate choice--far better than anything I could develop myself.

Pros
* Automatic objct management (objects are automatically deallocated--no memory leaks!)
* Able to use either VBScript or JScript to write COM related code
* ByRef argument handling is all taken care of
* Almost all VARIANT handling is taken care of
* Can very easily write compound COM statements (e.g. objExcel.Workbooks.Add().Sheets(1).Cells(1,1).Value = 50)
* There's no need for an extra dll (like EasyCOM.dll). It can be done entirely in AHK.
* Much more easily implemented!

The ONLY disadvantage with using Microsoft Scripting Control is that there may be some computers that do not have it installed (but probably not very many). HOWEVER, not only is it available to download from Microsoft and very easily installed, but thanks to that WS_CreateObjectFromDll() function, it doesn't even have to be installed! If a computer doesn't have Microsoft Scripting Control installed, you just need to supply the msscript.ocx file in the same folder as your script, and it will still work perfectly. No need to register the OCX. Your script remains completely portable!

Once this is better tested and found to really work, I think you can agree that there is no reason to continue making the not-so-easy EasyCOM.dll anymore. This is by far a better solution. :D

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

but thanks to that CreateObjectFromDll() function, it doesn't even have to be installed!

Hmm... Have you tested with this DllGetClassObject?
Actually MS discourages to call it directly. It's called always indirectly, through CoGetClassObject, probably the most important single function in COM.
Anyway, thanks for this very interesting idea, and I'm tempted to use with it CoLoadLibrary instead of LoadLibrary.

erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007
It's time for another hair-brained API scheme...

I've been working on using Microsoft Scripting Control for COM, and so far things seem to be ok. I'm not quite sure what to call it, so for now I've named it "EasyScript". The #Include file is looking to be a beefy 1000 lines. Right now the API looks something like this:
LoadEasyScript(Language)
UnloadEasyScript()

ES_Exec(VB or JS string) ; for no return value
ES_Eval(VB or JS string) ; for return value

ES_AddDispObject(IDispatchPtr)
ES_AddObject(ClsId, Name)
ES_AddObjectFromDll(ClsId, Name)

VBStr(String)
JSStr(String)

ES_AddObject() is useful for creating objects by ClassId, since you can't do that in VBScript/JScript. ES_AddObjectFromDll() is thrown in just because it's easy, but I can't imagine anyone actually using it. ES_AddDispObject() is useful for putting ActiveX controls under the care of VBScript/JScript (assuming that works).

VBStr() and JSStr() wrap strings in quote and escapes any quotes in the actual string.

Here's a short usage example
sFile := "C:\WINDOWS"
ES_Exec("Set oFSO = CreateObject('Scripting.FileSystemObject')")
IsFolder := ES_Eval( "oFSO.FolderExists(" VBStr(sFile) ")" )
; IsFolder = 1
ES_Exec("Set ByRefObj = CreateObject('Object.With.Byref.Param')")
ES_Exec("ByRefObj.ByRefMethod ", ByRefArg )

As you can see I'm using single quotes (') inside the strings. This isn't normally available in VBScript, but to make things easier I may try to allow for it. No guarantee it will end up in a final version.

ByRef arguments can be passed as variables between strings. After the call, the byref variable will be updated with the new value.

I still haven't looked into how to handle script errors.

All this may be too much encapsulation however. It may be better to just expose the Scripting Control methods and let the scripters write VBScript/JScript however they like.

I dunno, I'm still working on it. I'm curious what others think.


Also, It occurred to me that while this "EasyScript" API is handy for the COM basics, it still lacks support for creating ActiveX controls and handling COM Events. I haven't looked too closely at Sean's ActiveX control related scripts, so maybe those will be fine for handling that. I also haven't looked at COM event handling.

But I think those things are better suited for separate #Includes, and the separate APIs can be written to interface with each other.

In any case, I may have bitten off more than I can chew with all this COM stuff, so I'm going to have to pass on delving into COM Events, at least for now.


Hmm... Have you tested with this DllGetClassObject?

Yup, and it has worked flawlessly so far.

I'm tempted to use with it CoLoadLibrary instead of LoadLibrary.

Ah, you really are quite a COM master. I didn't even know about that function. I gave it a try, but it wasn't working in my tests. Have you had any luck using it?

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

I didn't even know about that function. I gave it a try, but it wasn't working in my tests. Have you had any luck using it?

Yes, I used it successfully to test DllGetClassObject which worked fine.
One thing you might miss is that you have to use always Unicode string with it.

PS. BTW, no real need to use it. Looks like exactly the same behavior with LoadLibrary.

Dashboard
  • Guests
  • Last active:
  • Joined: --

I dunno, I'm still working on it. I'm curious what others think.

I think that I'd like to be able to use VBScript instructions internaly in AHK, especially those relative to COM, as I think that (for the moment), VBScript is more easy to use to have access to COM, with a well known syntax, than what I seen for the moment under AHK. But I'd like to be able to execute a full VBScript script (not line by line...) and to get back the result :!: :!: :!: Thanks to all those who work on COM integration in AHK for their work. :D :D :D

erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007

One thing you might miss is that you have to use always Unicode string with it.

Ah yes, I missed the need for a Unicode path--that got it working, thanks.

PS. BTW, no real need to use it. Looks like exactly the same behavior with LoadLibrary.

Is it possible that the library is automatically unloaded when CoUninitialize() is called? It would be really nice if it was.

I think that I'd like to be able to use VBScript instructions internally in AHK, especially those relative to COM .... But I'd like to be able to execute a full VBScript script (not line by line...) and to get back the result

Thanks for the feedback Dashboard. It does seem like this is the best approach.

The functions haven't really changed, but their parameters have. Plus I thought that adding a simple 'printf' style syntax would make the code much easier to write (no need for lots of ugly double quotes and string concatenation).
vbwmp := "oWMP"
If (!ES_Exec("Set %v = CreateObject(%s)", vbwmp, "WMPlayer.OCX"))
	Msgbox % ES_Error()
If (!ES_Eval(pwmp, vbwmp))
	Msgbox % ES_Error()
%v inserts the value, and %s inserts the value wrapped in quotes, with special characters escaped.

ES_Eval() will return the value of most script variables. I don't think I'll implement getting return values for Dates and Currency variables, and especially not for Arrays (you should write a script function to convert the array to something you can use before returning it).

You can create an object in the script, put that same object into a COM control, and then control from the script.
DEdit := "DEdit"
If (!ES_Exec("Set %v = CreateObject(%s)", DEdit, "DhtmlEdit.DhtmlEdit"))
		Msgbox % ES_Error()
If (!ES_Eval(ppvDEdit, "DEdit"))
		Msgbox % ES_Error()
		
hContainerCtrl := AtlAxCreateContainer(hWnd, 0, 25, 800, 575) 
AtlAxAttachControl(ppvDEdit, hContainerCtrl)

DE_LoadUrl(DEdit, "http://www.autohotkey.com")

DE_LoadUrl(sDhtmlEdit, url)
{
	If (!ES_Exec("%v.LoadUrl %s", sDhtmlEdit, url))
		Msgbox % ES_Error()
}
You could alternately create an object using one of the EasyScript's or Sean's create/get object functions, then pass the object into the script (via AddObject) to be controlled there.

You can always execute more than one line of code at a time.
DE_BrowseMode(sDHtmlEdit)
{
	sCode = 
(
If `%v.Browsemode = 0 Then
 `%v.Browsemode = 1
Else
 `%v.Browsemode = 0
End If
)
	If (!ES_Exec(sCode, sDHtmlEdit, sDHtmlEdit, sDHtmlEdit))
		Msgbox % ES_Error()
}
This allows you to add functions inside your script. Heck, you could even create classes inside the script, instantiate it, and return it for use in AHK. I haven't pondered just what this could mean. I wonder if it would help with COM event handling at all...?

But speaking of event handling: There is the VBScript GetRef() function which may be used to insert a script call-back function for objects that allow it. These are usually the "OnClick" kind of functions. From what I've seen, it's still limited to a subset of the available object events. There are many other events I can't get access to.


The code is currently working, but I'm still running tests.

I'm also pondering how this script and Sean's scripts should play together. EasyScript covers everything that his CoHelper.ahk does, but if you want to utilize COM controls then we'd need code from IEControl.ahk, which requires CoHelper.ahk...

So I'm thinking I should just include the core functions from IEControl.ahk in EasyScript. This will keep those functions available to script-writers. I hope no one minds if I rename some of them and maybe change their API a bit. My target script-writer is familiar with VB and has never seen Co* functions or Atl* functions, and my goal is that they never have to.

It is quite clear that EasyScript will be much larger than Sean's scripts, both in code size and memory usage. It will also be slower. BUT it will be easy (I hope). :)

Chris
  • Administrators
  • 10727 posts
  • Last active: Nov 15 2014 07:47 AM
  • Joined: 02 Mar 2004
Erictheturtle, this is a really provocative topic. I hope you continue to work on it because it would add a lot of often-requested functionality (e.g. embedding VBScript and other scripting languages).

Thanks!

erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007
Thanks Chris.

I've been working on "EasyScript" this whole time. Seems like every time I look at the code, there are a dozen things I need to add/change/remove/improve. Even just this morning I made an improvement to the API.

The code has grown into a massive 1500 lines, although it is worth noting that a few hundred of those lines are for comments and error checking.

This script contains a ton of error checking and reporting. While it is really nice for development, not everyone may want to have that extra bulk in their released code. Plus, it seems like most are content with Sean's scripts which have no error checking. So I've designed the EasyScript code so the error checking is easily removed via a simple AHK script (not made yet).

Even so, nothing will ever be as lean and mean as Sean's scripts.


There's still a bunch of things I want to clean up in the script. I would like to make the error handling more consistent between the different parts. Plus there is still more error checking to be added. But the script is fully functional.

So here's the first version: v0.01 beta (21Jul2007) I hope the API doesn't change anymore, but no promises.

I didn't think "EasyScript" was such a good name for it. The most accurate might be "Embedded Microsoft Windows Scripting Host for Autohotkey", but that's just silly. I'm leaning toward "Windows Scripting for AHK", abbreviated as WS4AHK or simply WS. A possible alternative is "COMscript", which emphasis its ability to access COM. Anyone have any thoughts/preferences?

Download

Here is also an example script. It's a conversion of ABCYourWay's DHTML edit program to use this new WS4AHK script.

WS_DEControl.ahk
WS_DEdemo.ahk


When I get around to it, I'll post a fresh new forum topic and include a link to API documentation.

ABCyourway
  • Guests
  • Last active:
  • Joined: --
Now I managed to insert table with old-school way(invoke),
but not with WS4AHK
If you find time to have a look at, please correct my script.

Now I added(working function)

numbered list/bullet list
Font/fontname/fontsize
Justify(left, center, right)
FindText/Cut/Paste/Delete/SelectAll/redo/undo/view properties.


Functions left to implement are only table/cell/row functions.
Row/cell functions are esay to add, but I have a problem with a table function.

Thanks.

WS_DEControl.ahk

#Include ws4ahk.ahk ; designed for ws4ahk.ahk v0.01

;        Command IDs

DECMD_BOLD =                      5000
DECMD_COPY =                      5002
DECMD_CUT =                       5003
DECMD_DELETE =                    5004
DECMD_DELETECELLS =               5005
DECMD_DELETECOLS =                5006
DECMD_DELETEROWS =                5007
DECMD_FINDTEXT =                  5008
DECMD_FONT =                      5009
DECMD_GETBACKCOLOR =              5010
DECMD_GETBLOCKFMT =               5011
DECMD_GETBLOCKFMTNAMES =          5012
DECMD_GETFONTNAME =               5013
DECMD_GETFONTSIZE =               5014
DECMD_GETFORECOLOR =              5015
DECMD_HYPERLINK =                 5016
DECMD_IMAGE =                     5017
DECMD_INDENT =                    5018
DECMD_INSERTCELL =                5019
DECMD_INSERTCOL =                 5020
DECMD_INSERTROW =                 5021
DECMD_INSERTTABLE =               5022
DECMD_ITALIC =                    5023
DECMD_JUSTIFYCENTER =             5024
DECMD_JUSTIFYLEFT =               5025
DECMD_JUSTIFYRIGHT =              5026
DECMD_LOCK_ELEMENT =              5027
DECMD_MAKE_ABSOLUTE =             5028
DECMD_MERGECELLS =                5029
DECMD_ORDERLIST =                 5030
DECMD_OUTDENT =                   5031
DECMD_PASTE =                     5032
DECMD_REDO =                      5033
DECMD_REMOVEFORMAT =              5034
DECMD_SELECTALL =                 5035
DECMD_SEND_BACKWARD =             5036
DECMD_BRING_FORWARD =             5037
DECMD_SEND_BELOW_TEXT =           5038
DECMD_BRING_ABOVE_TEXT =          5039
DECMD_SEND_TO_BACK =              5040
DECMD_BRING_TO_FRONT =            5041
DECMD_SETBACKCOLOR =              5042
DECMD_SETBLOCKFMT =               5043
DECMD_SETFONTNAME =               5044
DECMD_SETFONTSIZE =               5045
DECMD_SETFORECOLOR =              5046
DECMD_SPLITCELL =                 5047
DECMD_UNDERLINE =                 5048
DECMD_UNDO =                      5049
DECMD_UNLINK =                    5050
DECMD_UNORDERLIST =               5051
DECMD_PROPERTIES =                5052


;   Enums


;OLECMDEXECOPT  

OLECMDEXECOPT_DODEFAULT =         0 
OLECMDEXECOPT_PROMPTUSER =        1
OLECMDEXECOPT_DONTPROMPTUSER =    2

; DHTMLEDITCMDF

DECMDF_NOTSUPPORTED =             0 
DECMDF_DISABLED =                 1 
DECMDF_ENABLED =                  3
DECMDF_LATCHED =                  7
DECMDF_NINCHED =                  11

; DHTMLEDITAPPEARANCE

DEAPPEARANCE_FLAT =               0
DEAPPEARANCE_3D =                 1 

; OLE_TRISTATE
OLE_TRISTATE_UNCHECKED =          0
OLE_TRISTATE_CHECKED =            1
OLE_TRISTATE_GRAY =               2


; Error Return Values
;

DE_E_INVALIDARG =                 0x5
DE_E_ACCESS_DENIED =              0x46
DE_E_PATH_NOT_FOUND =             0x80070003
DE_E_FILE_NOT_FOUND =             0x80070002
DE_E_UNEXPECTED =                 0x8000ffff
DE_E_DISK_FULL =                  0x80070027
DE_E_NOTSUPPORTED =               0x80040100
DE_E_FILTER_FRAMESET =            0x80100001
DE_E_FILTER_SERVERSCRIPT =        0x80100002
DE_E_FILTER_MULTIPLETAGS =        0x80100004
DE_E_FILTER_SCRIPTLISTING =       0x80100008
DE_E_FILTER_SCRIPTLABEL =         0x80100010
DE_E_FILTER_SCRIPTTEXTAREA =      0x80100020
DE_E_FILTER_SCRIPTSELECT =        0x80100040
DE_E_URL_SYNTAX =                 0x800401E4
DE_E_INVALID_URL =                0x800C0002
DE_E_NO_SESSION =                 0x800C0003
DE_E_CANNOT_CONNECT =             0x800C0004
DE_E_RESOURCE_NOT_FOUND =         0x800C0005
DE_E_OBJECT_NOT_FOUND =           0x800C0006
DE_E_DATA_NOT_AVAILABLE =         0x800C0007
DE_E_DOWNLOAD_FAILURE =           0x800C0008
DE_E_AUTHENTICATION_REQUIRED =    0x800C0009
DE_E_NO_VALID_MEDIA =             0x800C000A
DE_E_CONNECTION_TIMEOUT =         0x800C000B
DE_E_INVALID_REQUEST =            0x800C000C
DE_E_UNKNOWN_PROTOCOL =           0x800C000D
DE_E_SECURITY_PROBLEM =           0x800C000E
DE_E_CANNOT_LOAD_DATA =           0x800C000F
DE_E_CANNOT_INSTANTIATE_OBJECT =  0x800C0010
DE_E_REDIRECT_FAILED =            0x800C0014
DE_E_REDIRECT_TO_DIR =            0x800C0015
DE_E_CANNOT_LOCK_REQUEST =        0x800C0016


; ------------------------- General functions ---------------------------------------------------------------

DE_Add(hWnd, x, y, w, h) 
{ 
   Return GetComControlInHWND( CreateComControlContainer(hWnd, x, y, w, h, "DhtmlEdit.DhtmlEdit") ) 
} 

DE_Move(pwb, x, y, w, h) 
{ 
   WinMove, % "ahk_id " . GetHWNDofComControl(pwb), , x, y, w, h 
} 

DE_BrowseMode(sDHtmlEdit)     ; toggle between Edit mode and View mode.
{
	sCode = 
(
If `%v.Browsemode = 0 Then
 `%v.Browsemode = 1
Else
 `%v.Browsemode = 0
End If
)
		   
	If (!WS_Exec(sCode, sDHtmlEdit, sDHtmlEdit, sDHtmlEdit))
		Msgbox % A_LineFile ":" ErrorLevel
}


DE_LoadUrl(sDhtmlEdit, url)                 ;Load url(e.g. "http://www.autohotkey.com") and ready to edit in a WYSIWIG way
{
	If (!WS_Exec(sDhtmlEdit ".LoadUrl %s", url))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_NewDocument(sDhtmlEdit)                 ;clear current document and open blank html document
{
	If (!WS_Exec(sDhtmlEdit ".NewDocument"))
		Msgbox % A_LineFile ":" ErrorLevel
}


DE_LoadDocument(sDhtmlEdit, FileDir)   ;open file dialog and last parameter is prompt string.
{
	If (!WS_Exec(sDhtmlEdit ".LoadDocument", FileDir, prompt))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SaveDocument(sDhtmlEdit, Filedir)        ;save contents in html.
{
	If (!WS_Exec(sDhtmlEdit ".SaveDocument %s", FileDir))
		Msgbox % A_LineFile ":" ErrorLevel
}


DE_GetDocumentHtml(sDhtmlEdit)      ;get and return DOCUMENT'S htmlcode
{
	If (!WS_Eval(sRet, sDhtmlEdit ".DocumentHtml"))
		Msgbox % A_LineFile ":" ErrorLevel
	Return sRet
}

DE_SetDocumentHtml(sDhtmlEdit, sHtml)   ;set document's htmlcode
{
	If (!WS_Exec(sDhtmlEdit ".DocumentHtml = %s", sHtml))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_Refresh(sDhtmlEdit)   ;open file dialog and last parameter is prompt string.
{
	If (!WS_Exec(sDhtmlEdit ".Refresh"))   
		Msgbox % A_LineFile ":" ErrorLevel
}

; --- WYSIWYG Edit functions ----------------------------------------------------------------------------------------------


; Set property --> use ExecCommand(), Command ID
; Get Propery --> use QueryStatus(), command ID

DE_SetBOLD(sDhtmlEdit)         ; toggle selections bold/normal
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_BOLD))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SetUnderline(sDhtmlEdit)  ; toggle selections underline
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_UNDERLINE))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SetItalic(sDhtmlEdit)  ; toggle selections italic
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_ITALIC))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SetForeColor(sDhtmlEdit, sColor)    ; set font color string, e.g. "#55A0FF", "55A0FF", "Blue", "Red"
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
					, DECMD_SETFORECOLOR
					, OLECMDEXECOPT_DODEFAULT
					, sColor))
		Msgbox % A_LineFile ":" ErrorLevel
}


DE_SetBackColor(sDhtmlEdit, sColor)    ; 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
					, DECMD_SETBACKCOLOR
					, OLECMDEXECOPT_DODEFAULT
					, sColor))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_Font(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_FONT))
		Msgbox % A_LineFile ":" ErrorLevel
   
}

DE_SetFontName(sDhtmlEdit, sFont)    ; 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
					, DECMD_SETFONTNAME
					, OLECMDEXECOPT_DODEFAULT
					, sFont))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SetFontSize(sDhtmlEdit, iFontSize)    ; 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
					, DECMD_SETFONTSIZE
					, OLECMDEXECOPT_DODEFAULT
					, iFontSize))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_JustifyLeft(pDHtmlEdit)    ;  
{
   global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_JUSTIFYLEFT))
		Msgbox % A_LineFile ":" ErrorLevel
   
}

DE_JustifyCenter(pDHtmlEdit)    ;  
{
   global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_JUSTIFYCENTER))
		Msgbox % A_LineFile ":" ErrorLevel
   
}

DE_JustifyRight(pDHtmlEdit)    ;  
{
   global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_JUSTIFYRIGHT))
		Msgbox % A_LineFile ":" ErrorLevel
   
}

DE_SetHyperLink(sDhtmlEdit)    ; insert hyperlink property in selection 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
					, DECMD_HYPERLINK
					, OLECMDEXECOPT_DODEFAULT
					, ""))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SetImage(sDhtmlEdit)    ; insert image in selection 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
				, DECMD_IMAGE
				, OLECMDEXECOPT_DODEFAULT
				, ""))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_UnLink(sDhtmlEdit)    ; insert image in selection 
{
	global
	If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
				, DECMD_UNLINK
				, OLECMDEXECOPT_DODEFAULT
				, ""))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_SelectAll(pDHtmlEdit)    ;  
{
   global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_SELECTALL))
		Msgbox % A_LineFile ":" ErrorLevel
   
}


DE_Paste(pDHtmlEdit)    ;  
{
   global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v"
					, DECMD_HYPERLINK
					, OLECMDEXECOPT_DODEFAULT))
		Msgbox % A_LineFile ":" ErrorLevel
   
}

DE_Properties(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_PROPERTIES))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_UnDo(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_UNDO))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_ReDo(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_REDO))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_FindText(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_FINDTEXT))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_Delete(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_DELETE))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_Cut(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_CUT))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_COPY(pDHtmlEdit)    ;  
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_COPY))
		Msgbox % A_LineFile ":" ErrorLevel
}

; ------- LIST AND TABLE FUNCTIONS

DE_OrderList(pDHtmlEdit)    ;   NUMBERED LIST
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_ORDERLIST))
		Msgbox % A_LineFile ":" ErrorLevel
}

DE_UnorderList(pDHtmlEdit)    ;   BULLET LIST
{
  global
  If (!WS_Exec(sDhtmlEdit ".ExecCommand " DECMD_UNORDERLIST))
		Msgbox % A_LineFile ":" ErrorLevel
}


;DE_InsertTable(numrows, numcols, TableAttr = "100%", CellAttr = "" , Caption = "")

; DE_InsertTable(numrows, numcols)  --> I don't know what's the problem here
; {
;   WS_Exec("Set %v = CreateObject(%s)", tParam, "DEInsertTableParam.DEInsertTableParam")
;   ; create a table object
;   WS_Exec("tParam.NumRows = %v", numrows)  -> set the table property.
;   WS_Exec("tParam.NumCols = %v", numcols)
;   return
;   ;WS_Exec("Set tParam.TableAttrs = 100%")
;   
;   global DECMD_INSERTTABLE, OLECMDEXECOPT_DODEFAULT
;   If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, %s"
;   				, DECMD_INSERTTABLE
;  					, OLECMDEXECOPT_DODEFAULT
;  					, tParam))
;     Msgbox % A_LineFile ":" ErrorLevel
; 
; }

; }


; --------- USING DOM ------------------------------------------------------------------------------------------

DE_DOM(sDHtmlEdit)
{
   iret := WS_Exec("Set DHTMLDOM = %v.DOM", sDHtmlEdit)
   return "DHTMLDOM"
}

; GetSelection(pDhtmlEdit)  --> I don't know what's the problem. I can do it with easycom.ahk but not with ws4ahk
; {
;   WS_Exec("Set SelType = %v.DOM.%s.%s", pDhtmlEdit, "selection", "type"))
;   if seltype = text
;   {
;       WS_Exec("Set SelectedText = %v.DOM.%s.%s.%s.%s", 
;               pDhtmlEdit, 
;               "selection", 
;               "CreateRange()",
;               "htmltext"))
;      return SelectedText
;   }
; }


WS_DEDemo



#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#include WS_DEControl.ahk

If (!WS_Initialize("VBScript"))
{
	Msgbox % "Error initializing EasyScript"
	ExitApp
}
InitComControls()


Gui, +Resize +LastFound +theme
Gui, Add, Button, x0 y0 gSetBold, Bold
Gui, Add, Button, xp+40 gSetItalic,italic
Gui, Add, Button, xp+50 gSetUnderLine, underline
gui, Add, Button, xp+75 gSetBlue, Blue
Gui, Add, Button, xp+40 gSetImageLink, Image
Gui, Add, Button, xp+50 gSetHyperLink, Link
Gui, Add, Button, xp+50 gLoadUrl, LoadURL
Gui, Add, Button, xp+70 gGetDocument, GetHtml
gui, add, button, xp+70 gSetDocument, SetHtml
Gui, Add, button, xp+70 gSaveDocument, SaveHtml
Gui, Add, button, xp+80 gBrowseMode, BrowseMode Toggle
Gui, add, button, xp+140 gNewDocument, New
Gui, add, button, xp+40 gFindText, FindText
Gui, add, button, xp+70 gSetBackColor, SetBackColor
Gui, add, button, x0 yp+25 gSetFontName, SetFontName
Gui, add, button, xp+90 gSetFontSize, SetFontSize
Gui, add, button, xp+90 gSetFont, SetFont
Gui, add, button, xp+50 gList1, List1
Gui, add, button, xp+50 gList2, List2
gui, Add, Button, xp+50 gInsertTable, InsertTable


Gui, Show, w800 h600 Center, DhtmlEdit_Test
hWnd := WinExist()

DEdit := "DEdit"

; Method #1
ppvDEdit := DE_Add(hWnd, 0, 50, 800, 550)
WS_AddObject(ppvDEdit, DEdit)

; Method #2
; If (!WS_Exec("Set %v = CreateObject(%s)", DEdit, "DhtmlEdit.DhtmlEdit"))
; 		Msgbox % ErrorLevel
; If (!WS_Eval(ppvDEdit, DEdit))
; 		Msgbox % ErrorLevel
; 
; hContainerCtrl := CreateComControlContainer(hWnd, 0, 25, 800, 575) 
; AttachComControlToHWND(ppvDEdit, hContainerCtrl)


Gosub, SetDocument

Return ; end of auto-run




1::

;msgbox, % GetSelection(Dedit)

return

SetBold:
;iret := Invoke(DEdit, "ExecCommand()", DECMD_BOLD)
DE_SetBold(DEdit)  

Return

SetItalic:

;iret := Invoke(DEdit, "ExecCommand()", DECMD_ITALIC)
DE_SetItalic(DEdit) 

Return

SetBlue:


;iret := Invoke(DEdit, "ExecCommand()", DECMD_SETFORECOLOR, OLECMDEXECOPT_DODEFAULT, "Blue")

;DE_SetForeColor(DEdit, "0000FF") 
DE_SetForeColor(DEdit, "Blue") ; possible way
;DE_SetForeColor(pDHtmlEdit, "#0000FF") ; also possible


Return


SetUnderline:

;iret := Invoke(DEdit, "ExecCommand()", DECMD_UNDERLINE)
DE_SetUnderline(DEdit) 

Return

SetImageLink:

;iret := Invoke(DEdit, "ExecCommand()", DECMD_IMAGE, OLECMDEXECOPT_DODEFAULT, "")
DE_SetImage(DEdit) 

Return

SetHyperLink:

;iret := Invoke(DEdit, "ExecCommand()", DECMD_HYPERLINK, OLECMDEXECOPT_DODEFAULT, "")
DE_SetHyperLink(DEdit)  

Return

LoadUrl:
url := "http://www.autohotkey.com"
DE_LoadUrl(DEdit, url) 
Return

NewDocument:
DE_NewDocument(DEdit) 
Return

SaveDocument:

Filedir = %A_ScriptDir%\DhtmlEdit_%A_Now%.htm 
DE_SaveDocument(DEdit, FileDir)

Return

GetDocument:

msgbox, % DE_GetDocumentHtml(DEdit)

Return

SetDocument:

htmlcode =
(
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html; charset=ISO-8859-1"
 http-equiv="content-type">
  <title></title>
</head>
<body
 style="COLOR: rgb(0,0,0); BACKGROUND-COLOR: rgb(255,204,51)" alink   
 ="#ee0000" link="#0000ee" vlink="#551a8b">
<P>
<big style="FONT-FAMILY: Verdana"><big><EM><STRONG>Forgive</STRONG></EM> my <span
 style="FONT-WEIGHT: bold; COLOR: rgb(51,51,255)"  >poor</span> coding style! Yes?
</big></big></P>
<P><BIG style="FONT-FAMILY: Verdana"><BIG>This File is Edited with 
<STRONG>DhtmlEdit_Demo</STRONG>
  .
</P></BIG></BIG>
<ul style="FONT-FAMILY: Verdana">
  <li><STRONG><U>First List</U></STRONG> 
  <li><FONT color=blue>second List</FONT> 
  <li><A href="http://www.autohotkey.com">what 
  now?(</A>click then go to AutohotKey)</li>
</ul>

<table
 style="WIDTH: 440px; FONT-FAMILY: Verdana; HEIGHT: 52px; TEXT-ALIGN: left"
 border="1" cellpadding="2" cellspacing="2">
  <tbody>
    <tr>
      <td>This is a table
and  the right image is directly from AutoHotKey Forum.</td>
      <td><A href="http://www.autohotkey.com"><img style="WIDTH: 228px; HEIGHT: 133px"
 alt="image cannot be loaed for some reason"
 src="http://www.autohotkey.com/docs/images/AutoHotkey_logo.gif"></A></td>
    </tr>
  </tbody>
</table>
</body>
</html>
)


DE_SetDocumentHtml(DEdit, htmlcode)
htmlcode =


Return


BrowseMode:

DE_BrowseMode(DEdit)

Return


FindText:

DE_FindText(DEdit)

Return

SetBackColor:

DE_SetBackColor(DEdit, "Yellow")

Return


SetFontName:

DE_SetFontName(DEdit, "Arial Black")

Return

SetFontSize:

DE_SetFontSize(DEdit, "4")

Return

SetFont:

DE_Font(DEdit)

Return

List1:

DE_OrderList(DEdit)

Return

List2:

DE_UnOrderList(DEdit)
Return

InsertTable:

DE_InsertTable(2,2)

return




GuiSize:

DE_Move(ppvDEdit, 0, 50, A_GuiWidth, A_GuiHeight-50)


Return



GuiClose:
Gui, %A_Gui%:Destroy
ReleaseObject(ppvDEdit)
UninitComControls()
WS_Uninitialize()
ExitApp



erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007
Thanks for trying out the WS script ABCyourway. You've found a bug I'll have to try to fix later.

There are a few things you need to correct.

DE_JustifyLeft([color=red]s[/color]DHtmlEdit)    ;
DE_JustifyCenter([color=red]s[/color]DHtmlEdit)    ;

DE_JustifyRight([color=red]s[/color]DHtmlEdit)    ;
This same correction needs to be made on these functions as well.
DE_SelectAll
DE_Paste
DE_Properties
DE_UnDo
DE_ReDo
DE_FindText
DE_Delete
DE_Cut
DE_COPY
DE_OrderList
DE_UnorderList

I renamed the variable from pDHtmlEdit to sDHtmlEdit because you need to pass in the name of the object in the scripting environment (which is a string).

DE_InsertTable([color=red]sDhtmlEdit,[/color] numrows, numcols)
{
  [color=red]If (![/color]WS_Exec("Set [color=red]tParam[/color] = CreateObject(%s)", "DEInsertTableParam.DEInsertTableParam")[color=red])[/color]
     [color=red]Msgbox % A_LineFile ":" ErrorLevel[/color]
  ; create a table object
  [color=red]If (![/color]WS_Exec("tParam.NumRows = %v", numrows)[color=red])[/color] ; -> set the table property.
     [color=red]Msgbox % A_LineFile ":" ErrorLevel[/color]
  [color=red]If (![/color]WS_Exec("tParam.NumCols = %v", numcols)[color=red])[/color]
     [color=red]Msgbox % A_LineFile ":" ErrorLevel[/color]
  ;WS_Exec("Set tParam.TableAttrs = 100%")
  
  global DECMD_INSERTTABLE, OLECMDEXECOPT_DODEFAULT
  If (!WS_Exec(sDhtmlEdit ".ExecCommand %v, %v, [color=red]tParam[/color]"
              , DECMD_INSERTTABLE
                , OLECMDEXECOPT_DODEFAULT))
    Msgbox % A_LineFile ":" ErrorLevel
}

In the GetSelection() function, you seem to be mixing AHK and scripting code, and using %s when you should be using %v. It might be easiest to just change all that code into scripting code. I'll post a fixed function later when I have time.

Since this WS version of the script is a translation from your original code, I kept most of the code structure the same. However, since there is only one DHtml edit control, much of the code could be simplified by removing the sDhtmlEdit variable and just refer to the object's name directly in the scripting code. I'll post a rewrite later for an example.

erictheturtle
  • Members
  • 101 posts
  • Last active: Sep 04 2011 02:07 PM
  • Joined: 27 Jun 2007
This GetSelection() function should work:
GetSelection(sDHtmlEdit)
{
	sVBCode =
	(
		SelType = `%v.DOM.Selection.Type
		If SelType = "Text" Then
			SelectedText = `%v.DOM.Selection.CreateRange().HtmlText
		Else
			SelectedText = ""
		End If
	)

	; Execute the VB code
	If (!WS_Exec(sVBCode, sDHtmlEdit, sDHtmlEdit))
		Msgbox % A_LineFile ":" ErrorLevel

	; The variable "SelectedText" in the scripting environment holds the
	; selected text. This gets the value out of the scripting environment.
	If (!WS_Eval(SelectedText, "SelectedText"))
		Msgbox % A_LineFile ":" ErrorLevel
	
	Return SelectedText
}
If you include this, your script should fully work.


I've updated ws4ahk.ahk to fix the bug (now v0.02). See the new very unglamorous site.

I also uploaded new variations of WS_DEControl2.ahk and WS_DEDemo2.ahk that removes the need to pass the object name into every function.

Chris
  • Administrators
  • 10727 posts
  • Last active: Nov 15 2014 07:47 AM
  • Joined: 02 Mar 2004
I hope you don't mind, but I've split this topic off from your topic "EasyCOM.dll" development. Hopefully it will make things easier. Feel free to revise the topmost post of this topic as you see fit.

I've been working on "EasyScript" this whole time.

I've reviewed your code and tried the demo. It's all very impressive, and it's obvious you put a lot of thought into the interface. Also, it's great that you included clear, concise documentation at the top of the file.

I didn't think "EasyScript" was such a good name for it. The most accurate might be "Embedded Microsoft Windows Scripting Host for Autohotkey", but that's just silly. I'm leaning toward "Windows Scripting for AHK", abbreviated as WS4AHK or simply WS. A possible alternative is "COMscript", which emphasis its ability to access COM. Anyone have any thoughts/preferences?

All the candidates have some appeal, but I think I prefer "Windows Scripting for AHK" for its greater accuracy. Another idea is "Windows Scripting and COM (WS+COM)" because the "for AHK" part might not add much value in the contexts it's likely to be mentioned in.

Once you decide on a name, feel free to rename your homepage from ~easycom to the new name (unless it's too much trouble). I can update the links throughout the forum.

Even so, nothing will ever be as lean and mean as Sean's scripts.

Since I still know so little about COM, I'd like to rely on you and Sean for the following (to the extent you have time):

1) Can/should COM Helper be merged into this Windows Scripting API in a way that gives the best of both worlds? (Maybe that would cause too many compromises.)

2) I realize that you intend to improve the API and documentation (as time permits). When you're ready, perhaps you or someone else can update the following wiki page (and/or make a new page):
<!-- m -->http://www.autohotke...t/~easycom/<!-- m -->)

See the new very unglamorous site.

In an effort to bring more attention to the homepage above, I've linked to it from a couple of old COM/OLE topics. At some point, I'll also add some links to it from the AHK docs (e.g. DllCall).

Finally, it might be helpful to put a link on <!-- m -->http://www.autohotke...c21674.html<!-- m --> (i.e. this topic) so that people have a way to contact you and leave feedback.

Thanks for spending all this time to provide this often-requested capability!

Boo
  • Guests
  • Last active:
  • Joined: --
I'm a perfect noob in these matters. Would it be possible to have a working example that show how to read/write a value in an Excel cell, and in a Word field of form, please ?
Thanks by advance.

BoBo¨
  • Guests
  • Last active:
  • Joined: --
@ erictheturtle
I haven't digested your code completely (and there's quite a good chance that I'll understand only a fraction of it :oops:)

My current point of view is (unfortunately) a plain user pespective, therefore my highest priority is the usability in regards of a quite simple to adopt command set. What I remember from the past is a 'embed VB'-syntax used within MacroScheduler (a Shareware).
It looks quite simple, isn't it?

//Put this VBSTART..VBEND block at top of script to declare the functions once
VBSTART
Dim xlApp
Dim xlBook

'Opens the Excel file in Excel
Sub OpenExcelFile(filename)
Set xlApp = CreateObject("Excel.Application")
xlApp.visible = true
Set xlBook = xlApp.Workbooks.open(filename)
end sub

'Use this to close Excel later
Sub CloseExcel
xlApp.quit
Set xlApp = Nothing
End Sub

'Retrieves a cell value from the specified worksheet
Function GetCell(Sheet,Row,Column)
Dim xlSheet
Set xlSheet = xlBook.Worksheets(Sheet)
GetCell = xlSheet.Cells(Row, Column).Value
End Function

'Sets specified cell of specified worksheet
Function SetCell(Sheet,Row,Column,NewValue)
Dim xlSheet
Set xlSheet = xlBook.Worksheets(Sheet)
xlSheet.Cells(Row,Column).Value = NewValue
End Function

VBEND

//Do the business
VBRun>OpenExcelFile,%SCRIPT_DIR%example.xls
VBEval>GetCell("Sheet1",5,4),theValue
MessageModal>Cell value: %thevalue%
VBEval>SetCell("Sheet1",28,2,998),nul
//VBRun>CloseExcel


@ Boo
its about Excel 8)

BoBo¨
  • Guests
  • Last active:
  • Joined: --
@ erictheturtle
I thought about to (slightly) improve the GUI of WS_DEDemo2.ahk.
Well, desperately waiting for your sign off :)
Gui, +Resize +LastFound +theme
Gui, Add, Button, x0 		 y2 		w110 	h22 gSetBold, Bold
Gui, Add, Button, xp+111 	yp 		wp	 	hp gSetItalic,italic
Gui, Add, Button, xp+111 	yp 		wp 		hp gSetUnderLine, underline
gui, Add, Button, xp+111 	yp 		wp 		hp gSetBlue, Blue
Gui, Add, Button, xp+111 	yp 		wp 		hp gSetImageLink, Image
Gui, Add, Button, xp+111 	yp 		wp 		hp gSetHyperLink, Link
Gui, Add, Button, xp+111 	yp 		wp 		hp gLoadUrl, LoadURL
Gui, Add, Button, x0 		 yp+23 	wp 		hp gGetDocument, GetHtml
gui, add, button, xp+111 	yp 		wp 		hp gSetDocument, SetHtml
Gui, Add, button, xp+111 	yp 		wp 		hp gSaveDocument, SaveHtml
Gui, Add, button, xp+111 	yp 		wp 		hp gBrowseMode, BrowseMode Toggle
Gui, add, button, xp+111 	yp 		wp 		hp gNewDocument, New
Gui, add, button, xp+111 	yp 		wp 		hp gFindText, FindText
Gui, add, button, xp+111 	yp 		wp 		hp gSetBackColor, SetBackColor
Gui, add, button, x0 		 yp+23 	wp 		hp gSetFontName, SetFontName
Gui, add, button, xp+111 	yp 		wp 		hp gSetFontSize, SetFontSize
Gui, add, button, xp+111 	yp 		wp 		hp gSetFont, SetFont
Gui, add, button, xp+111 	yp 		wp 		hp gList1, List1
Gui, add, button, xp+111 	yp 		wp 		hp gList2, List2
gui, Add, Button, xp+111 	yp 		wp 		hp gInsertTable, InsertTable
	ShowW = 776
	ShowH = 600
Gui, Show, % "w" ShowW " h" ShowH Center, DhtmlEdit_Test
hWnd := WinExist()

; Create the COM control
  ppvDEdit := DE_Add(hWnd, 0, 72, ShowW-1, ShowH-72)

   .
   .
   .

GuiSize:
	DE_Move(ppvDEdit, 0, 72, A_GuiWidth, A_GuiHeight-72)
Return