Shoutbox

Tips - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: Tips (/showthread.php?tid=56747)

Tips by surfichris on 03-13-2006 at 12:06 PM

A collection of tips relating to scripting.

ActiveX Objects
You can access ActiveX objects just like you can using IE.

var ob = new ActiveXObject("name here");
if(ob == false)
{
    Debug.trace("ActiveX objection creation failed");
}

Starting a program:
var shell = new ActiveXObject("wscript.shell");
shell.Run("notepad.exe");

(Will start notepad.exe)

Changing a message being sent:
You can return a message from the ChatWndSendMessage function and it will change the message before it is sent. If you don't return a message, the intercepted message will be sent.

The following code will replace all instances of hi with test.

function OnEvent_ChatWndSendMessage(ChatWnd, sMessage)
{
   return sMessage.replace("hi", "test");
}


RE: Tips by -dt- on 03-13-2006 at 12:11 PM

To use send data to websites you use XMLHttpRequest

code:
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
xmlhttp.open("GET", "http://shoutbox.menthix.net", true);

    xmlhttp.onreadystatechange=function() {
          if (xmlhttp.readyState==4) {
              Debug.Trace(xmlhttp.responseText);
          }
         }
xmlhttp.send('');




:P that will print msghelp.net's html to your debug console

edit:
changed the async flag to true on the xmlhttprequest object (so it doesnt freeze the chats while doing its stuff)
RE: Tips by segosa on 03-13-2006 at 12:39 PM

Gah, finally figured out how to use what's in the IDL file.

First I was messing around with ActiveXObject() trying to create an instance, but it's much simpler.

For example,

code:
    //IMPMsgPlus interface
    [
        uuid(45C2DA37-53C8-4497-9C87-9E6A6DFF2B7C),
        helpstring("MPScript Messenger Plus! Interface")
    ]
    interface _IMPMsgPlus : IUnknown
    {
..snip..
        HRESULT DisplayToast([in] BSTR sTitle, [in] BSTR sMessage, [in,optional] VARIANT sCallback, [in,optional] VARIANT vCallbackParam, [out,retval] VARIANT_BOOL *bDisplayed);
        HRESULT DisplayToastContact([in] BSTR sTitle, [in] BSTR sContactName, [in] BSTR sMessage, [in,optional] VARIANT sCallback, [in,optional] VARIANT vCallbackParam, [out,retval] VARIANT_BOOL *bDisplayed);
    }


You take the name, which in this case is IMPMsgPlus and remove the IMP, making it MsgPlus. Then to, say, call DisplayToast you would simply use MsgPlus.DisplayToast()
RE: Tips by surfichris on 03-13-2006 at 01:13 PM

Reading the contents of a file:
(This code contains no error handling - you're expected to add it yourself)

- See note below on file paths.

code:
function get_file_contents(file)
{
    var fileSys = new ActiveXObject("Scripting.FileSystemObject");
    var fileH = fileSys.OpenTextFile(file, 1, 0);
    var text = fileH.ReadAll();
    fileH.close();
    return text;
}

Checking if a file exists:

- See note below on file paths.

code:
function file_exists(file)
{
    var fileSys = new ActiveXObject("Scripting.FileSystemObject");
    if(fileSys.FileExists(file))
    {
        return true;
    }
    else
    {
        return false;
    }
}

Note:
You need double slashes in the path - ex, C:\\test\\file.txt.

Also - when reading files, the base path is actually your windows profile directory (C:\Documents and Settings\....). If you need to read something from your scripts directory, then you would use:

myFile = MsgPlus.ScriptFilesPath+"\\file.txt";
RE: Tips by Volv on 04-19-2006 at 06:29 AM

Just a simple module for perhaps making Plus Menus easier to create.

Download Module: util_MsgPlus.js


Example Usage:

Generating the Menu

code:
function OnGetScriptMenu(){
    //Create new menu
    var myMenu = new PlusMenu;
   
    //Populate menu
        //Add a menu item
        myMenu.addItem("mnuItem1", "Item #1");
        myMenu.addItem("mnuItem2", "Item #2", false); //Disabled menu item
       
        //Add a separator because separators are pretty cool...
        myMenu.addSeparator();
       
        //Create a sub menu
        myMenu.openSubMenu("My 1st Sub Menu!");
            //Add a menu item to the sub menu
            myMenu.addItem("mnuItem3", "Item #3");
        myMenu.closeSubMenu();
       
        //Create a disabled sub menu
        myMenu.openSubMenu("My 2nd Sub Menu!", false);
        myMenu.closeSubMenu();
   
    //Build menu
    return myMenu.build();
}

Detecting when a menu item is clicked
code:
function OnEvent_MenuClicked(sMenuId){
    if(sMenuId=="mnuItem1"){
        MsgPlus.DisplayToast("Menu Click", "Menu Item #1 was clicked!");
    }
}


RE: Tips by -dt- on 04-19-2006 at 06:57 AM

Showing those crazy MS agent characters


First the user must have a MS agent installed for this example we will use Merlin
Download him here...
http://download.microsoft.com/download/1/d/b/1dbe...f3c4669/Merlin.exe

for more agents see here http://www.msagentring.org/chars.htm


Code to load your character

code:
//open a new object of the agent control
var Agents = new ActiveXObject("agent.control.2");
Agents.Connected = true;

//now to load our character into that control.
Agents.Characters.Load("Merlin","C:\\WINDOWS\\msagent\\chars\\Merlin.acs");
var merlin = Agents.Characters.Character("Merlin");




To show him you do
code:
merlin.Show();


To hide him you do
code:
merlin.Hide();



To make him speak you do (must be showing to speak this)
code:
merlin.Speak('dt is your master now');


To make him think
code:
merlin.Think("Oh wow im thinking :P");


each character also has gestures which they can do like...
to make merlin lift his arms and then point to the right..
code:
merlin.Play("GestureUp");
merlin.Play("GestureRight");



To move a character you do
code:
merlin.MoveTo(300,200);

which makes merlin to a crazy flying animation to that point



This code shows merlin  makes him fly to a point  then say hello , raise his hands and then hide.
code:
//open a new object of the agent control
var Agents = new ActiveXObject("agent.control.2");
Agents.Connected = true;

//now to load our character into that control.
Agents.Characters.Load("Merlin","C:\\WINDOWS\\msagent\\chars\\Merlin.acs");
var merlin = Agents.Characters.Character("Merlin");

merlin.Show();
merlin.MoveTo(300,200);
merlin.Speak('Hello');
merlin.Play("GestureUp");
merlin.Hide();




To make your agent speak what hes saying outloud you need to install the MS speech stuff
http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe
http://activex.microsoft.com/activex/controls/sapi/spchapi.exe

RE: Tips by davidt on 08-15-2006 at 09:21 AM

If you are calling an XML service and expecting a reply in XML form parse it with MSXML...

code:
// -------------------------------------------------------------------
// XML request
function NewRequest(service)
{
    xmlFile = service;
    Debug.Trace("Calling: "+xmlFile);
    var xml = new ActiveXObject("MSXML2.DOMDocument.4.0");
    xml.validateOnParse = false;
    xml.async = false;
    xml.load(xmlFile);
    var resp = xml.documentElement;
   
    return resp;
}

The object returned represents the root tag in the document. To get its first child tag

code:
var root = NewRequest("http://...");
var child = root.childNodes.item(0);
Debug.Trace("First child's text: " + child.text);

For more information on DOMDocument object... http://msdn.microsoft.com/library/default.asp?url...lrfdomdocument.asp

hope it helps
RE: RE: Tips by CookieRevised on 10-21-2006 at 01:44 AM

To show how things can be made shorter:


As an example I'll take the 'file existing' routine shown by Chris Boulton.

code:
// Checking if a file exists:

function file_exists(file)
{
    var fileSys = new ActiveXObject("Scripting.FileSystemObject");
    if(fileSys.FileExists(file))
    {
        return true;
    }
    else
    {
        return false;
    }
}
If you use an IF THEN ELSE structure to check on a function which only returns true or false on its own, you can do:
code:
return fileSys.FileExists(file)
Since filesys is an object which you have defined before and since this is only used once, you don't specifically need it to be defined as a variable but you can use it directly:
code:
return new ActiveXObject("Scripting.FileSystemObject").FileExists(file)
All this makes that the function is reduced to only 1 line:
code:
function file_exists(file)
{
    return new ActiveXObject("Scripting.FileSystemObject").FileExists(file);
}


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

Various short functions derived from VB6:

see "CookieRevised's reply to [I help them] VB2JS"
RE: Tips by Plan-1130 on 10-25-2006 at 08:15 PM

Accessing the registry, without getting errors (see attachment):

Both variable and path should not begin with a slash (/).

ExistsRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable  in the script's registry key
)
Returns true if exists, false if not exists

DeleteRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to remove, if not set, the whole directory will be removed
)
Deletes a variable or key.

ReadRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to read from,
[optional string] default value in case the variable is not set yet
)
Reads the value of a key or variable, returns the value if found, returns default value if set, returns null if failed.

WriteRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to read from,
[string] value to write,
[boolean] whether or not to overwrite if set already
)
Writes a value to a key or variable, returns the written value if overwrite is true or value did not exist, returns original value if overwrite is false and value did exist, returns null if failed.


Examples:

code:
ExistsRegistry("example", "MyAge");
// returns false

ReadRegistry("example", "MyAge");
// returns null

WriteRegistry("example", "MyAge", 16);
// writes 16, returns 16

ExistsRegistry("example", "MyAge");
// returns true

WriteRegistry("example", "MyAge", 17, false);
// does not write, returns 16

DeleteRegistry("example", "MyAge");
// deletes value

ReadRegistry("example", "MyAge", 17);
// writes 17, returns 17

WriteRegistry("example", "MyAge", 18);
// writes 18, returns 18

DeleteRegistry("example");
// deletes whole example key

both
code:
WriteRegistry("example", "MyAge", 16, false);
and
code:
ReadRegistry("example", "MyAge", 16);
will write and return 16 if value does not exist, and won't write but will return the original value if it does exist.
RE: Tips by matty on 10-25-2006 at 08:21 PM

quote:
Originally posted by Plan-1130
Accessing the registry, without getting errors (see attachment):

Both variable and path should not begin with a slash (/).

ExistsRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable  in the script's registry key
)
Returns true if exists, false if not exists

DeleteRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to remove, if not set, the whole directory will be removed
)
Deletes a variable or key.

ReadRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to read from,
[optional string] default value in case the variable is not set yet
)
Reads the value of a key or variable, returns the value if found, returns default value if set, returns null if failed.

WriteRegistry (
[optional string] sub directory in the script's registry key,
[optional string] variable to read from,
[string] value to write,
[boolean] whether or not to overwrite if set already
)
Writes a value to a key or variable, returns the written value if overwrite is true or value did not exist, returns original value if overwrite is false and value did exist, returns null if failed.


Examples:
code:
ExistsRegistry("example", "MyAge");
// returns false

ReadRegistry("example", "MyAge");
// returns null

WriteRegistry("example", "MyAge", 16);
// writes 16, returns 16

ExistsRegistry("example", "MyAge");
// returns true

WriteRegistry("example", "MyAge", 17, false);
// does not write, returns 16

DeleteRegistry("example", "MyAge");
// deletes value

ReadRegistry("example", "MyAge", 17);
// writes 17, returns 17

WriteRegistry("example", "MyAge", 18);
// writes 18, returns 18

DeleteRegistry("example");
// deletes whole example key


I posted a registry module already that uses the Windows API http://shoutbox.menthix.net/attachment.php?pid=738349
RE: Tips by tryxter on 01-08-2007 at 06:46 PM

JScript Reference

Since I'm starting using JScript for creating the plugins, I found a good JScript reference. It contains some examples too, so I though it could be useful to other programmers. ;)

You can download it here here.

Continue the great work!

(Thank's markee :))


RE: Tips by CookieRevised on 01-28-2007 at 01:15 AM

quote:
Originally posted by tryxter
JScript Reference

Since I'm starting using JScript for creating the plugins, I found a good JScript reference. It contains some examples too, so I though it could be useful to other programmers. ;)

You can download it here here.

Continue the great work!

(Thank's markee :))
Please never attach such official documentation. If MS updates it, people wont have the latest version... Instead only link to it.

Though, as a matter of fact, that official JScript 5.6 documentation is already available since a long time ago in the download section of the scripting database:
http://www.msgpluslive.net/scripts/browse/9/Others/
RE: Tips by Matti on 06-02-2007 at 05:02 PM

Change a ListViewControl's column header in real-time
When you're developing a big script for the mass, one day you'll want to add multilingual support. Most of the time, you can change the text of a control this with PlusWnd::SetControlText, but what if you have a nice ListViewControl with column headers to display interesting information? Formerly, developers simply re-wrote the XML file to make the change in the ListViewControl's <Columns> element, but this method can slow down your computer and is very impractical. Today, I'll show you a much more interesting way to do it. :)

The following method uses the LVM_SETCOLUMN message to set the column header's information. Not all options of the LVCOLUMN structure need to be used because we only want to change the text. Therefore, we also need to create a buffer to hold the string. The comments will clarify this. :)

code:
/*
[bool] SetColumnHeader(
   [hWnd] hWnd: Handle of the ListViewControl, retrieved with PlusWnd::GetControlHandle
   [number] iCol: Column id, the first column is 0, second is 1 etc.
   [string] sHeader: The new column header
)
Returns true if LVM_SETCOLUMNW succeeded, otherwise false.
*/


function SetColumnHeader(hWnd, iCol, sHeader) {

//Message constants
var LVM_FIRST = 0x1000;
var LVM_SETCOLUMNW = (LVM_FIRST + 96); //We'll use the Unicode instead of the ANSI version to have more characters supported
var LVCF_TEXT = 0x4;

//Create a buffer for the header
var pszText = Interop.Allocate((sHeader.length+1)*2); //Make a DataBloc where the header fits in perfectly
pszText.WriteString(0, sHeader); //Write the header in the DataBloc

//Create an LVCOLUMN structure
var LVCOLUMN = Interop.Allocate(16);
LVCOLUMN.WriteDWord(0, LVCF_TEXT); //mask: pszText is valid
LVCOLUMN.WriteDWord(12, pszText.DataPtr); //pszText: pointer to our buffer

//Call LVM_SETCOLUMNW to change the header and save the result
var Result = Interop.Call("user32", "SendMessageW", hWnd, LVM_SETCOLUMNW, iCol, LVCOLUMN);

//Clear the DataBlocs
pszText.Size = 0;
LVCOLUMN.Size = 0

//Return the result
return Result;

}
You may use and edit this snippet for your own scripts, but if you're going to release your script it'd be nice if you put a little credit in your script. :)

EDIT: Snippet now placed in a function for easier access.
RE: Tips by Matti on 06-07-2007 at 05:38 PM

Show a popup menu when you right-click a ListViewControl's item
This snippet will show you how you can create a popup menu which will pop up when the user right-clicks a ListViewControl's item, and how you should retrieve the response of the menu. It uses CreatePopupMenu to create the mnu, AppendMenuW to add items and TrackPopupMenu to open it and get the clicked menu item.

This snippet uses some parts of Matty's tray icon script, which initially was meant to create a tray icon with a popup menu. In this snippet, it was modified to only create a menu and show it on right-click. Much thanks to Matty to let me use his code in this snippet!

code:
//Message constants for menu
//These should be declared on global scope, so at the top of your script, outside any function

var MF_CHECKED = 0x8;
var MF_APPEND = 0x100;
var MF_DISABLED = 0x2;
var MF_GRAYED = 0x1;
var MF_SEPARATOR = 0x800;
var MF_STRING = 0x0;
var TPM_LEFTALIGN = 0x0;
var TPM_RETURNCMD = 0x0100;
var TPM_VERNEGANIMATION = 0x2000;

//Variable to store our subclass window in, needed to retrieve messages from the menu
//We don't need those messages, but MSDN says that we must pass a window handle
//Therefore, you should add a new window to your XML file, like this:
/*
<Window Id="WndSubclass" Version="1">
   <Attributes>
      <ShowInTaskbar>False</ShowInTaskbar>
   </Attributes>
   <DialogTmpl/>
   <Position Width="0" Height="0"/>
</Window>
*/

var subclass = false;

//This is an example function.
//It is just to demonstrate how you should place the menu creation code
//Original CreatePopupMenu and AppendMenuW code by Matty

function WindowOpen() {
   var PlusWnd = MsgPlus.CreateWnd("Windows.xml", "MyWindow"); //Create our window
   
   hMenu = Interop.Call("user32", "CreatePopupMenu"); //Create a new popup menu and get its handle
   //Add menu items
   Interop.Call("user32", "AppendMenuW", hMenu, MF_STRING, 101 /*This can be any number you want, and is identifier of the item*/, "Do this");
   Interop.Call("user32", "AppendMenuW", hMenu, MF_STRING, 102, "Do that");
   Interop.Call("user32", "AppendMenuW", hMenu, MF_SEPARATOR, 0, 0);
   Interop.Call("user32", "AppendMenuW", hMenu, MF_CHECKED, 103, "I'm checked!");
   
   //Do anything you want to do with your window after its creation...
}

//A sample function to process the menu click
function ProcessMenuItem(PlusWnd, LVItem, MnuItem) {
   //Let's see what item is clicked and react on it
   switch(MnuItem) {
      case 101: //Do this
         DoThis();
         break;
      case 102: //Do that
         DoThat(PlusWnd.LstView_GetItemText("LVThing", LVItem, 0)); //Send the item text of the 1st column of the right-clicked item to the function
         break;
      case 103: //I'm checked
         ToggleCheck();
         break;
   }
}

//The right-click event, probably the most important piece of this snippet
function OnMyWindowEvent_LstViewRClicked(PlusWnd, CtrlId, Index) {
   if(CtrlId == "LVThing") { //If our ListViewControl is clicked...
      if(Index < 0) { //If the click didn't occur on an item...
         return; //...do nothing
      } else {
         //Original GetCursorPos and TrackPopupMenu code by Matty
         if(!subclass) subclass = MsgPlus.CreateWnd("Windows.xml", "WndSubclass", 2); //Create our subclass window, if it's not yet created
         
         var POINTAPI = Interop.Allocate(8); //Create a structure to store the position of the cursor
         Interop.Call("user32", "GetCursorPos", POINTAPI); //Get the position of the cursor and store it
         
         var Result = Interop.Call("user32", "TrackPopupMenu", hMenuMore, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_VERNEGANIMATION, POINTAPI.ReadDWORD(0), POINTAPI.ReadDWORD(4), 0, subclass.Handle, 0); //Open the menu and store the result
         
         ProcessMenuItem(PlusWnd, Index, Result); //Send the result to a function for further processing
      }
   }
}

RE: Tips by henry1817 on 12-30-2009 at 04:13 PM

can any1 tell me how to open debugging window again when i closed it????


RE: Tips by matty on 12-30-2009 at 04:20 PM

Click the Script icon on the main contact list window. Then click Show Script Debugging

Or in code by using:

Javascript code:
Debug.DebuggingWindowVisible = true;


RE: Tips by whiz on 06-24-2010 at 10:53 AM

Creating a Modal Window

Create a modal dialog window, and keep it focused over a parent window.

Windows.xml

Spoiler:
XML code:
<Interfaces xmlns="urn:msgplus:interface" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:msgplus:interface PlusInterface.xsd">
 
<Window Id="WndParent" Version="1">
<!-- no specific guidelines for the parent window -->
 
    <Attributes>
        <Caption>Modal Test</Caption>
    </Attributes>
 
    <TitleBar>
        <Title>
            <Prefix>Image</Prefix>
            <Text>Modal Test</Text>
        </Title>
    </TitleBar>
 
    <Position Width="300" Height="250">
        <IsAbsolute>true</IsAbsolute>
    </Position>
 
    <DialogTmpl/>
 
    <Controls>
        <Control xsi:type="CodeEditControl" Id="EdtCode">
            <Position Left="3" Top="0" Width="280" Height="171">
                <Units>AllPixels</Units>
            </Position>
        </Control>
        <Control xsi:type="ButtonControl" Id="BtnConfirm">
            <Position Left="3" Top="177" Width="70">
                <Units>AllPixels</Units>
            </Position>
            <Attributes>
                <IsDefault>true</IsDefault>
            </Attributes>
            <StandardLook Template="Blue"/>
            <Caption>&amp;Confirm...</Caption>
            <Help>Display the confirmation...</Help>
        </Control>
        <Control xsi:type="ButtonControl" Id="BtnCancel">
            <Position Left="228" Top="177" Width="55">
                <Units>AllPixels</Units>
            </Position>
            <Caption>&amp;Close</Caption>
            <Help>Close the window...</Help>
        </Control>
    </Controls>
 
</Window>
 
<Window Id="WndChild" Version="1">
<!-- child window should not have taskbar button, and should not be allowed to minimize -->
 
    <Attributes>
        <Caption>Confirm?</Caption>
        <ShowInTaskbar>false</ShowInTaskbar>
    </Attributes>
 
    <TitleBar>
        <AllowMinimize>false</AllowMinimize>
        <AllowClose>false</AllowClose>
        <Title>
            <Prefix>Image</Prefix>
            <Text>Confirm?</Text>
        </Title>
    </TitleBar>
 
    <Position Width="120" Height="73">
        <IsAbsolute>true</IsAbsolute>
    </Position>
 
    <DialogTmpl/>
 
    <Controls>
        <Control xsi:type="ButtonControl" Id="BtnOk">
            <Position Left="2" Top="0" Width="40">
                <Units>AllPixels</Units>
            </Position>
            <StandardLook Template="Blue"/>
            <Caption>Ok</Caption>
        </Control>
        <Control xsi:type="ButtonControl" Id="BtnCancel">
            <Position Left="44" Top="0" Width="60">
                <Units>AllPixels</Units>
            </Position>
            <Caption>Cancel</Caption>
        </Control>
    </Controls>
 
</Window>
 
</Interfaces>


Modal Test.js
Spoiler:
Javascript code:
// make the parent window, make a variable for the child window
var WndParent = MsgPlus.CreateWnd("Interface.xml", "WndParent");
var WndChild = null;
 
// use any event here, this is just an example
function OnWndParentEvent_CtrlClicked(PlusWnd, ControlId)
{
    if (ControlId === "BtnConfirm")
    {
        // create the child, disable and monitor the parent
        WndChild = MsgPlus.CreateWnd("Interface.xml", "WndChild");
        Interop.Call("user32", "EnableWindow", WndParent.Handle, false);
        WndParent.RegisterMessageNotification(0x0006);
    }
}
 
// when the parent window is focused
function OnWndParentEvent_MessageNotification(PlusWnd, Message, wParam, lParam)
{
    if (wParam !== 0)
    {
        try
        {
            // focus the child window
            Interop.Call("user32", "SetFocus", WndChild.Handle);
            Interop.Call("user32", "BringWindowToTop", WndChild.Handle);
        }
        catch (error)
        {
        }
    }
}
 
function OnWndChildEvent_CtrlClicked(PlusWnd, ControlId)
{
    switch (ControlId)
    {
        case "BtnOk":
            // do whatever here, then close the child
            PlusWnd.Close(1);
            break;
    }
}
 
function OnWndChildEvent_Destroyed(PlusWnd, ExitCode)
{
    // enable and focus the parent window
    Interop.Call("user32", "EnableWindow", WndParent.Handle, true);
    Interop.Call("user32", "SetFocus", WndParent.Handle);
}