Shoutbox

[Testing] CViewer (Version 1.0) - 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: [Testing] CViewer (Version 1.0) (/showthread.php?tid=81395)

[Testing] CViewer (Version 1.0) by Spunky on 02-02-2008 at 08:55 PM

Basically what the script does:
       Keeps a record of each string of text copied to the clipboard (may eventually include data) for easy recall later. It's similar to Word's clipboard and how it lets you have more than one of each type of data

Important:
       There are 3 exe files included with this to reduce the scripts size considerably. VB has easier access to the clipboard than JScript (which relies on a lot of API work and dealing with handles ¬_¬). One program listens for clipboard changes, one updates the clipboard with a specified argument and the last one tells the listener when to quit. As a result GetClipboard.exe (the listener) constantly runs in the background until the script is uninitialized, however it only uses ~3,600K, hardly anything worth noticing.  All files are created by me and are free from virii, but feel free to check if uncertain :p

I'm aware of a couple of errors, but let me know if you encounter them.




RE: [Testing] CViewer (Version 1.0) by felipEx on 02-03-2008 at 04:40 PM

It's really useful (Y), but when your script is initialized for first time an error is shown in the Scripting Debugging window and sometimes, one of the applications suddenly crashed ending with a #51 error.

code:
Script is starting
Script is now loaded and ready
Function called: OnEvent_Initialize
Error: Raíz no válida en la clave del registro "HKCU\SOFTWARE\Patchou\Messenger Plus! Live\GlobalSettings\Scripts\CViewer\Settings\Last_Text". (code: -2147024894)
       File: CViewer.js. Line: 86.
Function OnEvent_Initialize returned an error. Code: -2147352567
I've just taken a look at the source and made some changes for personal usage.
code:
var WM_DRAWCLIPBOARD = 0x308;
var CF_TEXT = 1;
var CF_OEMTEXT = 7;
var CF_UNICODETEXT = 13;

function OnEvent_Initialize(){
    wnd = MsgPlus.CreateWnd('Interface.xml', 'WndHistory');
    wnd.RegisterMessageNotification(WM_DRAWCLIPBOARD);
   
    Interop.Call('user32', 'SetClipboardViewer', wnd.Handle);
    MakeWndTransparent(wnd.Handle, trans);
}


function OnWndHistoryEvent_MessageNotification(PlusWnd, Message, wParam, lParam){
    switch (Message)    {
    case WM_DRAWCLIPBOARD:
        Interop.Call('user32', 'OpenClipboard', PlusWnd.Handle);
        if (Interop.Call('user32', 'IsClipboardFormatAvailable', CF_TEXT | CF_OEMTEXT ))
        {
            var handle=    Interop.Call('user32', 'GetClipboardData', CF_UNICODETEXT);
            var size    =    Interop.Call('kernel32', 'GlobalSize', handle);
            var str    =    Interop.Allocate(2 * (size + 1));
            Interop.Call('kernel32', 'RtlMoveMemory', str, handle, size);
            PlusWnd.LstView_AddItem('history', str.ReadString(0));
            str.Size=0;
        }
        Interop.Call('user32', 'CloseClipboard');   
    break;
    }
}
so you won't need to use any timer, or read/write data from/into the windows registry... anymore :)
RE: [Testing] CViewer (Version 1.0) by Spunky on 02-04-2008 at 07:33 AM

I tried using those APIs but got stuck after getting a handle to the clipboard data. So if your part works, I'm gonna need to write some credits I think :p



Ok, so I fixed up my script with your code to get the text into the PlusWnd, but now I'm struggling with the recall back to the clipboard.

So far I used this site and converted it to a valid script file:

code:
function SetClipBoard(txtString){
        var hGlobalMemory = Interop.Call("kernel32","GlobalAlloc",GHND /*0x0042*/,txtString.length+1);
        var lpGlobalMemory = Interop.Call("kernel32","GlobalLock",hGlobalMemory);
        lpGlobalMemory = Interop.Call("kernel32","lstrcpy",lpGlobalMemory,txtString);
        if(Interop.Call("kernel32","GlobalUnlock",hGlobalMemory)!==0){return false;}
        if(Interop.Call("user32","OpenClipboard",0)===0){return false;}
        Interop.Call("user32","EmptyClipboard");
        var hClipMemory = Interop.Call("user32.dll","SetClipboardData",CF_TEXT /* 1 */,hGlobalMemory);
        if(Interop.Call("user32","CloseClipboard")===0){return false;}
        return true;
}


The only problem is that it only seems to copy the first letter of any string thats passed to it to the clipboard.

Anybody got any ideas? :p
RE: [Testing] CViewer (Version 1.0) by felipEx on 02-05-2008 at 10:40 PM

I made some changes again.

code:
var wnd
var trans = 75
var WS_EX_LAYERED        =    0x80000
var LWA_ALPHA            =    0x2
var GWL_STYLE            =    -20
var LVNI_SELECTED        =    0x2
var LVM_FIRST            =    0x1000
var LVM_GETITEM        =    LVM_FIRST + 5
var LVM_GETNEXTITEM        =    LVM_FIRST + 12
var LVM_DELETEITEM        =    0x1008
var WM_DRAWCLIPBOARD    =    0x308
var CF_TEXT            =    1
var CF_OEMTEXT            =    7
var CF_UNICODETEXT        =    13

function OnEvent_Initialize(){
    wnd = MsgPlus.CreateWnd('Interface.xml', 'WndHistory');
    wnd.RegisterMessageNotification(WM_DRAWCLIPBOARD);
    MakeWndTransparent(wnd.Handle, trans);
    Interop.Call('user32', 'SetClipboardViewer', wnd.Handle);
}
function OnWndHistoryEvent_MessageNotification(PlusWnd, Message, wParam, lParam){
    switch (Message)    {
    case WM_DRAWCLIPBOARD:
        Interop.Call('user32', 'OpenClipboard', PlusWnd.Handle);
        if (Interop.Call('user32', 'IsClipboardFormatAvailable', CF_TEXT | CF_OEMTEXT ))
        {
            var handle=    Interop.Call('user32', 'GetClipboardData', CF_UNICODETEXT);
            var size    =    Interop.Call('kernel32', 'GlobalSize', handle);
            var str    =    Interop.Allocate(2 * (size + 1));
            var f    =    false;
           
            Interop.Call('kernel32', 'RtlMoveMemory', str, handle, size);           
           
            // a dodgy way to find an item before add data into 'history' listview and prevent many data repeated
            for (var i = 0; i < PlusWnd.LstView_GetCount('history'); i++)
                if (PlusWnd.LstView_GetItemText('history', i, 0) == str.ReadString(0)){
                    f = true;
                    PlusWnd.LstView_SetSelectedState('history', i, true);
                    break;
                }
           
            if (!f){
            PlusWnd.LstView_AddItem('history', str.ReadString(0));
            }
            str.Size = 0;
        }
        Interop.Call('user32', 'CloseClipboard');   
    break;
    }
}
function OnWndHistoryEvent_CtrlClicked(PlusWnd, ControlId){
var d = 'On' + PlusWnd.WindowId + 'Event_' + ControlId + 'Clicked';
if (eval('typeof(' + d + ')') == 'function')    eval(d + '(PlusWnd);');
}
function OnWndHistoryEvent_BtnCopyClicked(PlusWnd){
    var i = PlusWnd.SendControlMessage('history', LVM_GETNEXTITEM, -1, LVNI_SELECTED);
    if (i < 0)return;
   
    var str    =    PlusWnd.LstView_GetItemText('history', i, 0);
    var size    =    2*(str.length+1);
   
        if (Interop.Call('user32', 'OpenClipboard', PlusWnd.Handle)){
            var heap        =    Interop.Call('kernel32', 'GlobalAlloc', 0, size);
            var pointer    =    Interop.Call('kernel32', 'GlobalLock', heap);

            Interop.Call('kernel32', 'RtlMoveMemory', pointer, str, size);
            Interop.Call('kernel32', 'GlobalUnlock', heap);
           
                if (Interop.Call('user32', 'OpenClipboard', PlusWnd.Handle)){
                    Interop.Call('user32', 'EmptyClipboard');
                    Interop.Call('user32', 'SetClipboardData', CF_UNICODETEXT, heap);
                    Interop.Call('user32', 'CloseClipboard');
                }
        }
}
function OnWndHistoryEvent_BtnDeleteClicked(PlusWnd){
    var i = PlusWnd.SendControlMessage('history', LVM_GETNEXTITEM, -1, LVNI_SELECTED);
    if (i < 0)return;
    PlusWnd.SendControlMessage('history', LVM_DELETEITEM, i, 0);
}
function OnWndHistoryEvent_LstViewDblClicked(PlusWnd,ControlId,Index){
    OnWndHistoryEvent_BtnCopyClicked(PlusWnd);
}
function OnWndHistoryEvent_Cancel(PlusWnd){
    PlusWnd.RegisterMessageNotification(WM_DRAWCLIPBOARD, false);
}
function MakeWndTransparent(hWnd, lTransparencyLevel){
     var nMsg = Interop.Call('user32', 'GetWindowLongW', hWnd, GWL_STYLE);
     nMsg |= WS_EX_LAYERED;
     Interop.Call('user32', 'SetWindowLongW', hWnd, GWL_STYLE, nMsg);
     Interop.Call('user32', 'SetLayeredWindowAttributes', hWnd, 0, (lTransparencyLevel/100)*255, LWA_ALPHA);
}
As you can see at line 37, there's a loop to check the entire listview and prevent data repeated... Does anyone know a better way? (A)