Shoutbox

CommonDialog help - 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: CommonDialog help (/showthread.php?tid=87451)

CommonDialog help by Otacon on 11-24-2008 at 06:46 PM

Ok, so I'm using this code:

jscript code:
function BrowseForPm(InitialDir)
{
    BrowseFilter = "Text Files (*.txt)|*.txt|All Files|*.*";
    var BrowseDialog = new ActiveXObject("UserAccounts.CommonDialog")
    BrowseDialog.Filter = BrowseFilter;
    BrowseDialog.InitialDir = InitialDir;
    BrowseDialog.Flags = "&H4";
    BrowseDialog.ShowOpen()
    return BrowseDialog.FilePath;
    pm = BrowseDialog.FilePath;
}

The dialog shows up fine, but it seems like the file path isn't being saved to the variable. Does anyone know what the problem is? I've been trying to make a dialog that works for days, searched this entire forum for anything related to CommonDialog and found nothing helpful.

Also, this type of dialog has been replaced with a new kind of dialog in Windows Vista, something called ItemDialog, so it won't even show up. So does anyone know the code that would be equivalent to this for the new Vista ItemDialog, because this won't work(I actually tested it just in case).

Thanks in advance for all your help.
RE: CommonDialog help by MeEtc on 11-24-2008 at 06:57 PM

I think I know what you're doing wrong. When you say 'the file path isn't being saved to the variable', I'm going to assume you mean the variable named 'pm'. It looks just fine to me, 'pm' IS being assigned the file path, but the variable is being destroyed on the very next line when the function ends.

What you need to do instead, is read the value of the function when its being called. Thats what the 'return' function does.
So somwhere else in your script i suppose you are calling the BrowseForPM() function, and then checking the value of pm on the next line. Instead, check the value of BrowseForPm(), and you shall get your file path.


RE: CommonDialog help by Matti on 11-24-2008 at 06:59 PM

That's very simple.

jscript code:
    return BrowseDialog.FilePath;
    pm = BrowseDialog.FilePath;
You are returning before setting the variable, that means you end the function right there. Everything else that comes afterwards won't be executed. So, this is very simple to fix: first set the pm variable, then return its value.
jscript code:
   pm = BrowseDialog.FilePath;
   return pm;
As for your second question: yes, have a look at matty's reply to Browse For File featuring an implementation of GetOpenFileName which works both on XP and Vista. You'll probably want to change some things, like getting it out of the OnEvent_Initialize function and such.

If you're having trouble with this, we'll help you with that, but it's better to experiment with it a bit first and try things yourself - it really is the best way to learn programming. :)
RE: CommonDialog help by Otacon on 11-24-2008 at 07:12 PM

Tried both solutions, and sadly neither of them work. What I forgot to say earlier is that pm is a global variable.

And I did see matty's thread earlier, but I have no idea whatsoever what to do with that code. Seems too complicated to me, I'm just a humble newbie :).


RE: CommonDialog help by Matti on 11-24-2008 at 07:38 PM

Heh, I could have seen that one coming. Well, have a look at my implementation of matty's code, used in my own script.

Some usage examples:

jscript code:
//Open File Dialog
//Opens C:\ first, file filters are text files (*.txt) and all files (*.*)
pm = BrowseForFile("Browse for PM", "C:\\", "Text Files (*.txt)|*.txt|All files (*.*)|*.*||");

//Save File Dialog
//Opens C:\ first, file filters are PNG files (*.png) and all files (*.*)
var file = BrowseForFile("Save picture as", "C:\\", "PNG Files (*.png)|*.png|All files (*.*)|*.*||", true);
if(!file) {
   //User didn't specify a file to save to or pressed Cancel.
} else {
   //User specified a valid save location. Do something useful here.
}
And here's the implementation:
jscript code:
/* FUNCION: BrowseForFile
    Original code by Choli from the Messenger Plus! Translator script
    Desc: Opens a "Browse for file" dialog with the given settings
    Parameters:
        title      Dialog title
        dir        Start directory
        filter     Filter message. Example: "JavaScript file|*.js|Text file|*.txt||"
        save       True is "Save as", false is "Open"
        ext        Default extension to append to the filename when no extension is specified
        file       File to display as default
        hwnd_owner Handle of the owner window, used to copy window icon etc.
    Return value: File path to open or save to
*/
function BrowseForFile(title, dir, filter, save, ext, file, hwnd_owner) {
    save = (save == true);
    hwnd_owner = 1*hwnd_owner;
    var OFN_ALLOWMULTISELECT = 0x200;
    var OFN_ENABLESIZING = 0x800000;
    var OFN_EXPLORER = 0x80000;
    var OFN_FILEMUSTEXIST = 0x1000;
    var OFN_HIDEREADONLY = 0x4;
    var OFN_LONGNAMES = 0x200000;
    var OFN_PATHMUSTEXIST = 0x800;
    var OFN_OVERWRITEPROMPT = 0x2;

    var OpenFileName = Interop.Allocate(88);

    with (OpenFileName) {
        WriteDWORD(0, Size); // lStructSize
        WriteDWORD(4, hwnd_owner); // hwndOwner
        WriteDWORD(8, 0); // hInstance
        if(typeof filter !== "string") filter = "All files (*.*)|*.*||";
        var s_filter = Interop.Allocate(2 * (filter.length + 1));
        WriteMultiStringW(s_filter, filter);
        WriteDWORD(12, s_filter.DataPtr); // lpstrFilter
        WriteDWORD(16, 0); // lpstrCustomFilter
        WriteDWORD(20, 0); // nMaxCustomFilter
        WriteDWORD(24, 1); // nFilterIndex
        if(typeof file !== "string") file = "";
        var s_file = Interop.Allocate(2 * (1024 + 1));
        s_file.WriteString(0, file);
        WriteDWORD(28, s_file.DataPtr); // lpstrFile
        WriteDWORD(32, (s_file.Size / 2 - 1)); // nMaxFile
        WriteDWORD(36, 0); // lpstrFileTitle
        WriteDWORD(40, 0); // nMaxFileTitle
        if(typeof dir === "string") {
            var s_dir = Interop.Allocate(2 * (dir.length + 1));
            s_dir.WriteString(0, dir);
            WriteDWORD(44, s_dir.DataPtr); // lpstrInitialDir
        }
        if(typeof title === "string") {
            var s_title = Interop.Allocate(2 * (title.length + 1));
            s_title.WriteString(0, title);
            WriteDWORD(48, s_title.DataPtr); // lpstrTitle
        }
        WriteDWORD(52, OFN_ENABLESIZING | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_PATHMUSTEXIST | (save ? OFN_OVERWRITEPROMPT : OFN_FILEMUSTEXIST)); // flags
        WriteWORD(56, 0); // nFileOffset
        WriteWORD(58, 0); // nFileExtension
        if(typeof ext === "string") {
            var s_ext = Interop.Allocate(2 * (ext.length + 1));
            s_ext.WriteString(0, ext);
            WriteDWORD(60, s_ext.DataPtr);
        } else WriteDWORD(60, 0); // lpstrDefExt
        WriteDWORD(64, 0); // lCustData
        WriteDWORD(68, 0); // lpfnHook
        WriteDWORD(72, 0); // lpTemplateName
        WriteDWORD(76, 0); // pvReserved
        WriteDWORD(80, 0); // dwReserved
        WriteDWORD(84, 0); // FlagsEx
    }
    var result = Interop.Call("comdlg32.dll", (save ? "GetSaveFileNameW" : "GetOpenFileNameW"), OpenFileName);
    var s_return = false;
    if (result) {
        var p_path = s_file.ReadString(0);
        var p_files = new Array();
        var p_file = "";
        var pos = 2 * (p_path.length + 1);
        if(!save) {
            while(true) {
                p_file = s_file.ReadString(pos);
                if(p_file.length > 0) {
                    p_files.push(p_file);
                    pos += 2 * (p_file.length + 1);
                } else break;
            }
        }
        s_return = (p_files.length > 0) ? new Array(p_path).concat(p_files) : p_path;

    }
    OpenFileName.Size = 0;
    s_filter.Size = 0;
    s_file.Size = 0;
    s_dir.Size = 0;
    return s_return;

    function WriteMultiStringW (datablock, string) {
        var pos = 0;
        datablock.WriteString(0, string);
        pos = string.indexOf("|", pos);
        while (pos !== -1) {
            datablock.WriteWORD(2 * pos, 0);
            pos = string.indexOf("|", pos + 1);
        }
    }
    function Space (number) {
        var i;
        var s = "";
        for (i = 0; i < number; i++) {
            s += " ";
        }
        return s;
    }
}

RE: CommonDialog help by Otacon on 11-24-2008 at 07:57 PM

Just as I thought everything was going to work this time, I got:

code:
Error: Overflow (code: -2146828282)
       File: file_browse.js. Line: 135.
after I pressed my button which calls the function.

Line 135:
jscript code:
WriteDWORD(4, hwnd_owner); // hwndOwner

Damn, I'm never going to get this working. Thanks for all your help so far, guys.

RE: CommonDialog help by matty on 11-24-2008 at 08:03 PM

Try passwing 0 as the hwndOwner see if it works. Passing an actual value (numerical) causes the window to be modal to the calling window. When pressing the button you can use:

jscript code:
pPlusWnd.Handle
as the hwndOwner now pPlusWnd is dependent on what the variable name is that is a parameter to
code:
function OnWindowIdEvent_CtrlClicked(pPlusWnd, sControlId) {
    ...
}

What value were you passing to the function?
RE: CommonDialog help by Otacon on 11-24-2008 at 08:16 PM

Oh man, this is so confusing... Do you mind if I send you the .plsc file so you can check it out? Because I'm honestly very confused at this point. But don't try to do anything for me, just check it out and tell me where I went wrong so I can correct it? I actually want to learn something from this.

EDIT: Uploaded the file just in case you want to check it out.


RE: CommonDialog help by Spunky on 11-24-2008 at 08:48 PM

jscript code:
BrowseDialog.Flags = "&H4";

I thought we had to use hex equivalents? Shouldn't it be:

jscript code:
BrowseDialog.Flags = 0x04;

Just a bit confused myself
RE: CommonDialog help by matty on 11-24-2008 at 09:20 PM

Why do you have two of the exact same functions just with different names?

Anyways one of your problems is that you are not passing anything to hwnd_owner. This causes a problem because in the code it says hwnd_owner = 1*hwnd_owner;

However when you don't specify anything it is null. So you have two options. Either pass a value to the parameter or add this to the top of the function

jscript code:
if (typeof hwnd_owner === 'undefined') hwnd_owner = 0;

RE: CommonDialog help by Otacon on 11-24-2008 at 09:23 PM

Yeah, already figured that one out, I just wasn't thinking straight. Did you find any other problems? Because I'm still getting the overflow error.


RE: CommonDialog help by Matti on 11-25-2008 at 05:20 PM

Hmm, okay, that was my bad. I assumed that 1*undefined would result in 0, but it gave me NaN. Well, you can change that line to something like:

jscript code:
hwnd_owner = hwnd_owner ? 1*hwnd_owner : 0;
which this time has been tested and I confirm that it works. :P Just trying to make that parameter optional. :)

As already mentioned: don't make two identical features with just different names, that completely ruins the idea of grouping code in a function! Simply keep one BrowseForFile function, call it when necessary and do stuff with the result afterwards. ;)
RE: CommonDialog help by Otacon on 11-25-2008 at 06:02 PM

Thanks for all the help, that works perfectly.  Just one last question - The file path should be saved for future use. For example, if I disable and enable the script, it's supposed to read the path that was last saved by the Browse Dialog. I'm guessing the only way to do this is to write the path to an external file and read it when the script starts?


RE: CommonDialog help by matty on 11-25-2008 at 06:27 PM

quote:
Originally posted by Otacon
Thanks for all the help, that works perfectly.  Just one last question - The file path should be saved for future use. For example, if I disable and enable the script, it's supposed to read the path that was last saved by the Browse Dialog. I'm guessing the only way to do this is to write the path to an external file and read it when the script starts?
Yes or the registry.
RE: CommonDialog help by Otacon on 11-25-2008 at 06:29 PM

OK, thanks for all the help mate, it means a lot.


RE: CommonDialog help by CookieRevised on 04-11-2011 at 07:51 AM

quote:
Originally posted by Matti
Heh, I could have seen that one coming. Well, have a look at my implementation of matty's code, used in my own script.
I made a revision of this openfile dialog code based on yours.
See CookieRevised's reply to Browse For File