PDA

View Full Version : WinLUAEx V1.0.7 released



Mark F
August 25th, 2003, 08:06 PM
I have just released a new version of this plugin which adds Windows registry editing capabilities.

You can really mess up your system with some of these calls so PLEASE be careful.

Download here (http://prdownloads.sourceforge.net/girderplugins/WinLUAEx.1.0.7.zip?download)

Source (http://prdownloads.sourceforge.net/girderplugins/WinLUAEx.1.0.7.src.zip?download)

Report problems and feature requests here.

I have NOT forgotten about the Files/Folders dialog request. It is next on the list.

Promixis
August 26th, 2003, 05:16 PM
Mark,

Another useful function would be the ability to access the win32 api command SendMessage. The sendmessage plugin cannot use variables which makes using it from LUA difficult.

Mike

Mark F
August 26th, 2003, 05:49 PM
I'm not sure where I'd get the window handle of the destination window from???

Promixis
August 26th, 2003, 06:58 PM
Mark,

I don't know much about the actually sendmessage api but the plugin in girder has the following parameters...

Message Number
wParam
lParam

to tell zoom player to play the values are 32871,80,1 respectively. If zoom isn't running nothing happens..

Mike

Mark F
August 26th, 2003, 07:15 PM
Yes, I know. :) The Win32 API has one more parameter: the Window handle of the target window.

The SendMessage plugin uses the targeting feature of Girder to let you point it at ZoomPlayer. This is how it gets the window handle to pass through the actual Win32 API.

I have no idea how I, or the script developer, would get this window handle.

Promixis
August 26th, 2003, 07:50 PM
Hmm, I don't see where in the sendmessage plugin that the target window needs to be specified. Oh well, looks like I'll have to generate a long list of triggerevent commands... :)

Mark F
August 27th, 2003, 08:22 AM
When using the SendMessage plugin, you use the Target button to specify the window to which the message is sent.

After further review, I could do this with an interface like this:

int RETURNVALUE, int ERROR = WINDOWS_SendMessage( string CLASS, string TITLE, int MESSAGENUMBER, int WPARAM, int LPARAM )

This will use FindWindow(CLASS, TITLE) to get the window handle to pass to the SendMessage(handle, MESSAGENUBER, WPARAM, LPARAM) function.

I could do a similar thing with:

int ERROR = WINDOWS_PostMessage( string CLASS, string TITLE, int MESSAGENUMBER, int WPARAM, int LPARAM )

Promixis
August 27th, 2003, 11:24 AM
That would be cool. I have also looked to try and a COM object to use the win32 api to do this but I can't seem to find anything on MSDN.

Promixis
August 27th, 2003, 11:25 AM
Also, regarding dialog boxes, I try'd to use the ms dialog activex controls with luacom but without success. That would have been an easy way to allow for fileselection etc.

Bitmonster
August 27th, 2003, 12:13 PM
@Marc F

The idea of a sendmessage LUA command is great (but I like every addtional option to LUA). :)

BTW: Is the sendmessage plugin blocking? If I try to send a command to ZoomPlayer, sometimes the next events are not processed in girder. This happens for example if ZP has an error dialog open (not the red ones, but the normal win-api ones). To close this dialog I need to send a key to ZP but this does not work, because the sendmessage command that initiated this dialog blocks girder till the dialog is closed.

Would it then be possible to make the LUA-sendmessage-command non-blocking?

BTW2: What I really miss is some timing functions. Something like the alarm-timer-plugin, but that can be called from LUA with variable arguments. It would also be great, if this feature is not limited to 10 timers. It would be sufficient, if this function could simply trigger an event, but it would even be fantastic, if it could implement a kind of callback-function, that is called after the timer finishes.

I have managed to do this LUA-timing stuff with some LUA-code and one alarm timer. But this is really not very clearly. It generates lots of events
that make it heavy to follow the event-processing. So a real function would be very nice.

BTW3: Do you still plan to implement a file dialog? :)

Promixis
August 27th, 2003, 12:29 PM
Hey Mark, when you're done with our requests, I could use some help cutting the grass, raking leaves etc.... :D

Mark F
August 27th, 2003, 12:37 PM
BTW 1: The Win32 SendMessage() API blocks until the sent message is processed by the target window. PostMessage(), on the other hand, places the message in the target window message queue and returns immediately.

BTW 2: Timer functions - these sound fun. :D Would the same type of interface as the current plugin exposes (routines to call on start, end, cancel written in LUA, timeout (ms), repeat switch) be OK or something different? I wouldn't impose a limit on the number you could create.

BTW 3: Yes, I still plan on implementing the standard File Open, File Save, Directory Choose dialogs. I have investigated this and plan on adding some code to call the Windows shell interfaces to do this. I've never used these functions before and it is a bit different from the stuff I normally use so it will take a bit longer for me to get it right.

Please be patient. :)

Mike - :lol: Go on outside and start and I'll be right there to help. ;)

Bitmonster
August 27th, 2003, 01:43 PM
BTW 1: The Win32 SendMessage() API blocks until the sent message is processed by the target window. PostMessage(), on the other hand, places the message in the target window message queue and returns immediately.
Ouch, that's a big problem. ZP crashes very often. So it will also break down Girder. Postmessage seems not to work with ZP. That's awfull. :cry:


BTW 2: Timer functions - these sound fun. :D Would the same type of interface as the current plugin exposes (routines to call on start, end, cancel written in LUA, timeout (ms), repeat switch) be OK or something different? I wouldn't impose a limit on the number you could create.

Actually I don't need start and cancel. Some of my code repeats, but does use another timeout value on the next turn. So it would be great, if the callback function could modify the next timeout value for itself (and of course cancel it's own repeat if needed).
Sounds like you want to give some kind of handle to the calling code back, that could be modified after the timer has started. For example to increase the timeout-value or cancel it at all. A handle for some addtional table would also be great. So the calling code can give some information to the callback-function, that's private to them. Or maybe one table for all data.



BTW 3: Yes, I still plan on implementing the standard File Open, File Save, Directory Choose dialogs. I have investigated this and plan on adding some code to call the Windows shell interfaces to do this. I've never used these functions before and it is a bit different from the stuff I normally use so it will take a bit longer for me to get it right.

Please be patient. :)
That's fine. :)

Bitmonster
August 27th, 2003, 02:53 PM
BTW 1: The Win32 SendMessage() API blocks until the sent message is processed by the target window. PostMessage(), on the other hand, places the message in the target window message queue and returns immediately.
Just found this (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/Windowing/MessagesandMessageQueues/MessagesandMessageQueuesReference/MessagesandMessageQueuesFunctions/SendMessageTimeout.asp)

Would this make a non-blocking SendMessage possible, if the timeout value is set to a very short value? Or would the message been discarded from the targets queue, if the target does not respond fast enough?

Mark F
August 27th, 2003, 04:25 PM
I had never seen the SendMessageTimeout() function before. :D Thanks. That would seem to be another interface I should support.

Mark F
August 27th, 2003, 07:16 PM
Just so no one gets their hopes up ...

I will be celebrating the holiday this weekend and not working on plugins so a new update will not appear for a while.

Bitmonster
September 1st, 2003, 11:02 AM
Marc,

I have another problem. It's a little complicated to explain. Hopefully you understand the point.

I want to write a function that dumps a table in a way, that it can directly be imported by LUA afterwards. This works so far, but there is one design-limitation I can't find a good workaround:

LUA-tables are allways used by reference. So the following table:

a = {"test1"}
b = {}
b[1] = a
b[2] = a

will result in a structure where every change in b[1] will also change b[2]. If I now want to dump such table, I need to know which sub-tables are actually referenced (as they could be referenced more than one time). The only way to find same references is by using the == comparison. But this is rather time consuming for a big structure (as I would have to compare every reference with all other references). Sadly LUA didn't implement the "lt" tag for tables. If so I could use binary-search to speed things up.

The best way to work with references would be, if I could get a reference ID as an integer value. Let us call this function LUA_GetReferenceID. So
LUA_GetReferenceID(b[1])
will give me an integer value that is the same for
LUA_GetReferenceID(b[2])
and
LUA_GetReferenceID(a)
but completely a unique for
LUA_GetReferenceID(b)
as b is a unique reference. Then I could store the references in a temporary table and find out double-references by binary-search.

Would it be possible to implement such function?
Actually it's a mystery why LUA don't has such mechanism, or do I overlooked something?

Bitmonster
September 1st, 2003, 12:21 PM
BTW:
For the timer-stuff I suggest the following interface (Actually this is nearly the interface I allready use for my selfbuild stuff):

table = LUA_AddTimer(func, delay [, data])

The parameter func is a function that is called after "delay" milliseconds. If the parameter data is supplied to LUA_AddTimer, this will be given to the func as a parameter also. If func returns an integer value, this is used as the repeat time for the next call. If func returns nil, this is an one-shot-timer. A simple but fully generic func could look like this:



function myFunc(data)
TriggerEvent(data.event, data.deviceID)
return data.repeatDelay
end

So you can use something like this:


data = {
event = "myEventString",
deviceID = 18,
repeatDelay = 10000
}

handle = LUA_AddTimer(myFunc, 1000, data)


This will fire a girder-event "myEventString" after 1 second and will repeat every 10 seconds afterwards.

If you want to get rid of the timer, use
LUA_RemoveTimer(handle)
where handle is the reference you first received from LUA_AddTimer.

Advanced Suggestion :)
Would be nice if the handle is actually a table and the parameters func, delay and data are fields of this table. So one could also use the following fancy syntax:



handle = LUA_AddTimer(
function (data)
TriggerEvent(data.event, data.deviceID)
return data.repeatDelay
end,
1000,
{
event = "myEventString",
deviceID = 18,
repeatDelay = 10000
}
)



and then modify for example the eventstring with:
handle.data.event = "myNewEventString"

or setup a new delay with:

handle.delay = 100
LUA_RemoveTimer(handle)
handle = LUA_AddTimer(handle.func, handle.delay, handle.data)

Bitmonster
September 1st, 2003, 01:25 PM
Stupid me! :)

Forget the stuff about LUA_GetReferenceID.
If I convert a table to a string I get a reference value like "table: 00E1BE18".
This should work for my problem.

EDIT:
-------

And if I use this reference as a key for my temp table, I don't even need to use a search routine.



temp[tostring(table)] = table

-----[SNIP]------

-- to test if we allready have stored the reference:
if temp[tostring(table_to_test)] then
-- table reference is allready stored
else
-- it's a new table
end


Sometimes it's hard to see how easy some tasks can be in LUA, if you think to much in terms of other languages. :)

LUA for president! 8)

Promixis
September 1st, 2003, 03:55 PM
Mark,

The author of luacom has released a new version which will allow access to MS Common Dialogs. It should work for using the standard file selection dialog.

I need Ron to recompile the library so I can try it with Girder. He seems to be lying low these days - maybe work is busy or something.

Mike

BeRnA
September 1st, 2003, 04:32 PM
What is the diference between use the new registry functions added to WinLuaEx and the funtions alredy in LUA like RegGetStringValue...

Thanks in advance.

Bitmonster
September 1st, 2003, 04:43 PM
What is the diference between use the new registry functions added to WinLuaEx and the funtions alredy in LUA like RegGetStringValue...

Thanks in advance.

The new interface allows you to delete and list registry keys for example.

Mark F
September 1st, 2003, 04:59 PM
BeRnA -

It also allows you to open a key read only in cases where you need to read from keys but don't have the authority to write new values.

Mike -

Ron is extremely busy working on his next degree and doing an internship in California. Last I heard, he was visiting home (the Netherlands) for a couple of weeks.

Bitmonster -

I have the timer stuff just about complete. The interface returns an "object" which contains some opaque data and some methods to work on that data. The LUA "object" is, at it's heart, a table so you can add any data you want to it.

I think you will be able to wrap it any way you'd like. :)

Here is a preview of the readme:


TIMER Function:

TIMEROBJ = TIMER_CreateObject()
Creates a new timer object and returns it.

NOTE: The returned TIMEROBJ object will be destroyed if the variable containing it goes out of scope (is destroyed). If you want a TIMEROBJ object to survive the life of a subroutine,do not leave it in a local variable!

The TIMEROBJ object has 4 methods: Create, Destroy, Arm, Cancel

string ERROR = TIMEROBJ.Create(string START, string TRIGGER, string CANCEL, int RECCURING)

Attempts to assign resources for this timer object. The variables START, TRIGGER and CANCEL should be fully formed LUA statements. The START routine will be called as soon as the timer object is armed. The TRIGGER routine will be called when the timeout expires. The CANCEL routine will be called if the timer object is canceled. If the variable RECCURING is non-0, the timer will be re-armed after every call to the TRIGGER routine until canceled or destroyed.

If successful, ERROR will be nil. For any errors, ERROR will be a formatted error string.

TIMEROBJ.Destroy()

Releases all resources for this timer object.

string ERROR = TIMEROBJ.Arm(int MILLISECONDS)

Causes the START routine to be called and schedules the TRIGGER to be called in MILLISECONDS amount of time.

If successful, ERROR will be nil. For any errors, ERROR will be a formatted error string.

TIMEROBJ.Cancel()

Stops the TRIGGER routine from being called and causes the CANCEL routine to be called.


Here is a sample:


--
-- Sample LUA code for the included TIMER_* functions in Girder
--

--
-- These are the routines that are called on Arm, Cancel and when the timer expires
--
function Arm ( object )
print ( "Arm with "..object.Count )
object.Count = object.Count -1
end

function Expire ( object )
print ( "Expired with "..object.Count )
if (object.Count == 0) then
object.Cancel()
else
object.Count = object.Count -1
end
end

function Cancel ( object )
print ( "Canceled with "..object.Count )
end

--
-- Main Code
--

-- create a timer object (in a global variable!)
TIMEROBJ = TIMER_CreateObject()
-- TIMEROBJ is a table and can have data added to it
TIMEROBJ.Count = 10
-- set up the LUA code to use on the different events
-- NOTE: each call passes the global variable "TIMEROBJ" to the routine
TIMEROBJ.Create ( "Arm(TIMEROBJ)", "Expire(TIMEROBJ)", "Cancel(TIMEROBJ)", 1 )
-- trigger the recurring event every 1000 milliseconds (1 second)
TIMEROBJ.Arm ( 1000 )

Bitmonster
September 1st, 2003, 05:09 PM
Very nice. :)

I see you go more to OO-like structures.

Is it possible for the TRIGGER routine to modify it's own re-arm time and RECCURING flag?

Mark F
September 1st, 2003, 05:28 PM
The Arm method can be called, any time, to change the trigger time.

The recurring flag is static. Sorry. I couldn't visualize a reason to change a timer from recurring to one-shot (or vice versa) vs creating a different timer.

Bitmonster
September 1st, 2003, 05:34 PM
I use this for my mouse-function for example. After the user has released a mouse-direction-button, the actual mouse-movement-function continues to move the mouse. After the pointer comes to a complete halt, the routine discards itself by going to one-shot.
Actually I have some more functions, that repeat but also discard theirself at some point.

Is it possible to call TIMEROBJ.Cancel() inside the TRIGGER routine?

Bitmonster
September 1st, 2003, 05:51 PM
Argh, it's to late here in Germany. :)

OK, the sample-source already includes the .Cancel() call, so I will have no problem.

Promixis
September 1st, 2003, 07:24 PM
Looks great Mark! (the timer functions)

I got in touch with Ron. Luacom has been upgraded to do WMI. The version for doing dialogs is ready but needs to be recompiled by Ron for use with Girder.

This might save you the time to code this interface.

Mark F
September 1st, 2003, 08:09 PM
Bitmonster -

Ahhh, I see what you want to do. I believe the current interface will allow you to discard or disable the timer when you want. However, there is nothing like using an interface to find all the limitations. If you see or think of something I may have missed, please let me know. :D

Mike -

This would certainly save me time. Thanks a bunch for running this down. :)

Mark F
September 2nd, 2003, 08:54 AM
I wanted to release the timer functions last night but uncovered a threading issue in the destruction code. I need to re-design the code that does timer object garbage collection.

This will be after work stuff so may take a couple of days to complete. Sorry for the delay. :(

EDIT: I have released the WinLUAEx 1.0.8 version. Please see this (http://www.girder.nl/phpBB2/viewtopic.php?t=5057) thread.

Bitmonster
September 5th, 2003, 10:28 AM
Mark has released WinLUAEx 1.0.8:

http://www.girder.nl/phpBB2/viewtopic.php?t=5057&highlight=