Shoutbox

[WHAT??] Array pointers - 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: [WHAT??] Array pointers (/showthread.php?tid=85501)

[WHAT??] Array pointers by SmokingCookie on 08-20-2008 at 04:28 PM

Hi,

I have seen "Pointer to an array ..." several times on MSDN, like here (see "pButtons").

How can one point to an Array object?


RE: [WHAT??] Array pointers by Eljay on 08-20-2008 at 04:43 PM

You don't point to an Array object (as in a native JScript array), you use DataBlocs like you would for any other type.

e.g. for your TASKDIALOG_BUTTON array you would create a DataBloc the size of one item (8 bytes I think) times however many buttons there are.

Maybe a bit more complicated within that huge struct though :P or not, it's a pointer, not inline like I thought. Just create a seperate DataBloc for the array and write the .DataPtr into the main struct.


RE: [WHAT??] Array pointers by SmokingCookie on 08-20-2008 at 04:57 PM

Does that mean:

Interop.Allocate(arrButtons.lenght * 8);


RE: [WHAT??] Array pointers by Matti on 08-20-2008 at 07:03 PM

To make such array, you basically make a structure with all elements inserted the one after the other. It's easier to explain this by code:

code:
var cButtons = 2; //The number of buttons
var pButtons = Interop.Allocate(cButtons * 8); //8 bytes per button

//First button
var nButtonID1 = 0x100; //Identifier for this button
var sButtonText1 = "Button Text 1";
var pszButtonText1 = Interop.Allocate(sButtonText1.length*2+2);
pszButtonText1.WriteString(0, sButtonText1);
pButtons.WriteDWORD(0*4, nButtonID1);
pButtons.WriteDWORD(1*4, pszButtonText1.DataPtr);

//Second button
var nButtonId2 = 0x101; //Identifier for this button
var sButtonText2 = "Button Text 2";
var pszButtonText2 = Interop.Allocate(sButtonText2.length*2+2);
pszButtonText2.WriteString(0, sButtonText2);
pButtons.WriteDWORD(2*4, nButtonID);
pButtons.WriteDWORD(3*4, pszButtonText2.DataPtr);

//Use in your structure
TASKDIALOGCONFIG.WriteDWORD(/* position here */, cButtons); //cButtons
TASKDIALOGCONFIG.WriteDWORD(/* position here */, pButtons.DataPtr); //pButtons

//After calling TaskDialogIndirect
pszButtonText1.Size = 0;
pszButtonText2.Size = 0;
pszButtons.Size = 0;
TASKDIALOGCONFIG.Size = 0;
So what you're doing here is putting the contents of all TASKDIALOG_BUTTON structures into one big structure. You'll probably want to make this a bit more flexible, such as making a function to create such a structure from a JScript Array, but don't forget to implement a way to get the pszButtonText structures so you can clear them after calling TaskDialogIndirect. Maybe do it like this: return an object with the created structure in it along with an array of all created pszButtonText structures, then you can save these results and loop through the array and clear the psz's when you're done.

Ah well, it's easier for me to make such function. Here you go:
code:
/*
    FUNCTION CreateTaskDialogButtonsConfig
    aButtons    - Array with button texts.
    nBaseID    - Number to use as base for the identifiers. Optional.
                  Each button's ID will be set to: nBaseID + index.
                  Defaults to 0x100. (just an easy random number)
    Return value: Object with the following syntax:
        {
            struct: The pButtons structure.
            psz:    Array of psz's which need to be destroyed after use.
        }
*/
function CreateTaskDialogButtonsConfig(aButtons, nBaseID) {
    nBaseID = (typeof nBaseID === 'number') ? nBaseID : 0x100;
    var Result = {};
    var pszArray = [];

    var pButtons = Interop.Allocate(aButtons.length * 8);
    for(var i=0; i<aButtons.length; i++) {
        var sButtonText = aButtons[i];
        var psz = Interop.Allocate(sButtonText.length*2+2);
        psz.WriteString(0, sButtonText);
        pszArray.push(psz);
        pButtons.WriteDWORD(i*8, nBaseID + i);
        pButtons.WriteDWORD(i*8+4, psz.DataPtr);
    }

    return {
        struct: pButtons,
        psz: pszArray
    };
}
Usage:
code:
var aButtons = ["Text 1", "Text 2"];

var TaskDialogButtons = CreateTaskDialogButtonsConfig(aButtons, 0x100);
var pButtons = TaskDialog.struct;
var pszArray = TaskDialog.psz;

//Use in your structure
TASKDIALOGCONFIG.WriteDWORD(/* position here */, aButtons.length); //cButtons
TASKDIALOGCONFIG.WriteDWORD(/* position here */, pButtons.DataPtr); //pButtons

//After calling TaskDialogIndirect
for(var i=0; i<pszArray.length; i++) pszArray[i].Size = 0;
pButtons.Size = 0;
TASKDIALOGCONFIG.Size = 0;

Heh, you're quick at implementing code. :P Although I didn't check my own function, I think you're better off trying to use my function. :)
RE: [WHAT??] Array pointers by SmokingCookie on 08-20-2008 at 08:05 PM

It appears to me that I've got a code quite similar to that, but a bit more flexible:

code:
        // Create the BUTTONS "array"
        var BUTTONS = Interop.Allocate(Math.min(arrButtonIds.length,arrButtonLabels.length) * 8);
   
        // Create the array for the buttons and the button labels
        var BUTTONS_ARRAY = new Array();
        var BUTTONTEXTS = new Array();
   
        // Write'em all into a DataBlock object
        for(var i = 0; i < Math.min(arrButtonIds.length,arrButtonLabels.length); i++) {
            // Write the current button's label into a DataBlock object
            BUTTONTEXTS[i] = Interop.Allocate((arrButtonLabels[i].length + 1) * 2);
            BUTTONTEXTS[i].writeSTRING(0,arrButtonLabels[i]);
   
            // Write the remaining required data into a DataBlock object
            BUTTONS_ARRAY[i] = Interop.Allocate(4 + Math.min(arrButtonIds.length,arrButtonLabels.length) * 8);
            with(BUTTONS_ARRAY[i]) {
                writeDWORD(0,arrButtonIds[i]);
                writeDWORD(4,BUTTONTEXTS[i].DataPtr);
            }
        }
    }


Just an additional note: I'm pretty tired ATM, so I may start to make big mistakes over time..

EDIT::

Matti,

I've implemented your code (thank you for giving me another half hour of work :P ), yet nothing happens, neither on my screen, nor in the debugger. I'm not going to sort this out today any more (like I said before, I'm tired).

EDIT::

I seem to get E_INVALIDARG errors, an indication of either a stupid typo, or a major error..
RE: [WHAT??] Array pointers by Matti on 08-22-2008 at 10:36 AM

quote:
Originally posted by SmokingCookie
I seem to get E_INVALIDARG errors, an indication of either a stupid typo, or a major error..
Well, I had a go with TaskDialogIndirect myself too, and it seems like it isn't working too great too. :P I'm afraid I have my TASKDIALOGCONFIG wrong somewhere, either in the size of the structure or something with the actual contents...

If anyone wants to have a go with it, my current progress is attached. It'd be great if we could get this working, as the task dialog in Vista is an awesome tool. :)

NOTE: Windows Vista is required to call TaskDialog and TaskDialogIndirect. Do not download this if you don't have Vista or higher installed.

NOTE: I fixed it. Please check Mattike's reply to [WHAT??] Array pointers.
RE: [WHAT??] Array pointers by Eljay on 08-22-2008 at 11:40 AM

I'll have a look in detail later, because task dialogs are quite interesting :P
First thing I noticed was that you are using both members of the icon unions, that's not how unions work.

Unions (C++)


RE: [WHAT??] Array pointers by Matti on 08-22-2008 at 11:57 AM

Aha, that explains a lot. So basically, that parameter is "overloaded" with a UINT and a HICON?
I'll see if that fixes something... :)

EDIT: I FIXED IT!!! :D
It is WORKING!!! WAAHOOO!!! <:o)

This post will soon be updated with the TaskDialogIndirect implementation script. I'm currently working on getting everything right. :)

Allright, I need some help. I'm looking for the value of the following constants:

code:
TD_WARNING_ICON
TD_ERROR_ICON
TD_INFORMATION_ICON
TD_SHIELD_ICON
TD_QUESTION_ICON
Could someone give me their values? And, in case I forgot one, add the missing TD_***_ICON's?
It seems like those constants are defined with a call to the MAKEINTRESOURCEW macro, but I have no idea how this should be implemented in a Plus! script. :S

NOTE: I fixed it. Please check Mattike's reply to [WHAT??] Array pointers.
RE: [WHAT??] Array pointers by andrewdodd13 on 08-22-2008 at 03:53 PM

code:
#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i))))

#define TD_WARNING_ICON         MAKEINTRESOURCEW(-1)
#define TD_ERROR_ICON           MAKEINTRESOURCEW(-2)
#define TD_INFORMATION_ICON     MAKEINTRESOURCEW(-3)
#define TD_SHIELD_ICON          MAKEINTRESOURCEW(-4)

TD_QUESTION_ICON is not in the SDK headers I'm afraid. It seems Microsoft recommend against its use.
RE: [WHAT??] Array pointers by Matti on 08-22-2008 at 04:04 PM

@andrewdodd13:
Yes, I already found those #define things. The only problem is: what the heck do I have to do with the MAKEINTRESOURCEW? Is it like writing a WORD in a DataBloc and then what? I don't quite understand how I should go on implementing the MAKEINTRESOURCEW...

I've updated the attachment in my original post with the working version of the TaskDialogIndirect implementation. Feel free to have a go with it.

NOTE: I fixed it. Please check Mattike's reply to [WHAT??] Array pointers.


RE: [WHAT??] Array pointers by SmokingCookie on 08-22-2008 at 04:05 PM

Hours of research have given me these nothing


By the way, about unions: I;ve read the C++ article about them, and I understand that I can omit either the hIcon or the TD_X_ICON?


RE: [WHAT??] Array pointers by Matti on 08-22-2008 at 04:50 PM

I FIXED IT!!! (v2.0)

This time it's for real. I found the actual values of the constants and by removing the hInstance in the structure, the icons load fine! :D

This is just a proof that it's working. I'll probably make a class from this soon. I don't care what you do with this demonstration, I'm too excited it's finally working! :D