/*
* -----
* Screenshot Sender - __listview.js
* -----
* Class for working with list-view controls.
* -----
*/
//List-view control messages
var LVM_FIRST = 0x1000;
var LVM_DELETEITEM = (LVM_FIRST + 8);
var LVM_DELETEALLITEMS = (LVM_FIRST + 9);
var LVM_ENSUREVISIBLE = (LVM_FIRST + 19);
var LVM_FINDITEMW = (LVM_FIRST + 83);
var LVM_GETHEADER = (LVM_FIRST + 31);
var LVM_GETIMAGELIST = (LVM_FIRST + 2);
var LVM_GETITEMCOUNT = (LVM_FIRST + 4);
var LVM_GETITEMTEXTW = (LVM_FIRST + 115);
var LVM_GETITEMW = (LVM_FIRST + 75);
var LVM_INSERTITEMW = (LVM_FIRST + 77);
var LVM_SETCOLUMNW = (LVM_FIRST + 96);
var LVM_SETIMAGELIST = (LVM_FIRST + 3);
var LVM_SETITEMW = (LVM_FIRST + 76);
var LVM_SORTITEMS = (LVM_FIRST + 48);
//LVITEM masks
var LVIF_IMAGE = 0x2;
var LVIF_PARAM = 0x4;
var LVIF_STATE = 0x8;
var LVIF_TEXT = 0x1;
//LVCOLUMN masks
var LVCF_FMT = 0x1;
var LVCF_IMAGE = 0x10;
var LVCF_ORDER = 0x20;
var LVCF_SUBITEM = 0x8;
var LVCF_TEXT = 0x4;
var LVCF_WIDTH = 0x2;
//LVCOLUMN fmt
var LVCFMT_IMAGE = 0x800;
//LVFINDINFO flags
var LVFI_NEARESTXY = 0x40;
var LVFI_PARAM = 0x1;
var LVFI_PARTIAL = 0x8;
var LVFI_STRING = 0x2;
var LVFI_WRAP = 0x20;
//LVFINDINFO vkDirection values
var VK_LEFT = 0x25;
var VK_RIGHT = 0x27;
var VK_UP = 0x26;
var VK_DOWN = 0x28;
var VK_HOME = 0x24;
var VK_END = 0x23;
var VK_PRIOR = 0x21;
var VK_NEXT = 0x22;
//Header control messages
var HDM_FIRST = 0x1200;
var HDM_GETITEMW = (HDM_FIRST + 11);
var HDM_SETITEMW = (HDM_FIRST + 12);
//HDITEM mask
var HDI_FORMAT = 0x4;
//HDITEM fmt
var HDF_SORTDOWN = 0x200;
var HDF_SORTUP = 0x400;
//Image list types
var LVSIL_NORMAL = 0;
var LVSIL_SMALL = 1;
//Global object to store the ListViews in, identified by handle.
ListViews = {};
/**
* LISTVIEW CLASS
* by Mattias Buelens
* Version: 1.0.001(30 Mar 2008)
*
* Description: This class contains several functions for Plus! Live script developers who use ListView controls in their windows,
* but can't accomplish everything they need by only using the methods from Plus! Live. This class contains functions
* to do list-view sorting, add images to the list-view control and use them for list items, modify list-view columns
* and more.
* Installation: Copy this script file(ListView.js) to your script's directory.
* Usage: Create a new instance of this class with "new ListView(PlusWnd, CtrlId) " where PlusWnd is a Plus! Live window and
* CtrlId is the ID of the list-view control, or with "new ListView(hWnd) " where hWnd is the list-view control handle.
* Then, you can use any child method of this class in your script.
* Copyright: You can use this class in any of your scripts, both private and public scripts, modify this class in any way and
* release modifications of this class in any way, as long as you provide some credit to the original creator(Mattias
* Buelens) to show your appreciation, you don't even need to keep this whole header and function descriptions.
*
* Happy scripting!;-)
*/
var ListView = function (PlusWnd, CtrlId) {
this.Helpers.AssignParent(this);
this.SortOptions.Callback = this.SortOptions.Callback_Default;
//Check the given parameters
if (this.Helpers.IsWindow(PlusWnd) && typeof CtrlId === "string") {
//PlusWnd and CtrlId are given
this.Handle = PlusWnd.GetControlHandle(CtrlId);
} else if (typeof PlusWnd === "number") {
//hWnd is given
this.Handle = PlusWnd;
}
//Save this class in a global array, for outside access(e.g. list-view sorting)
ListViews[this.Handle] = this;
//Load ImageList
this.hImageList = this.Helpers.SendMessage(this.Handle, LVM_GETIMAGELIST, LVSIL_NORMAL, 0);
//Create ImageList if it doesn't exist
if (this.hImageList === 0) this.hImageList = Interop.Call("comctl32", "ImageList_Create", 100, 100, 0x20 /* ILC_COLOR32 */, 0, 10);
}
ListView.prototype = {
/**
* Handle(number)
*
* Desc: Contains the handle of the list-view control after class creation
*/
"Handle" : 0,
/**
* SortOptions(object)
*
* Desc: Specifies the current options for the sorting
*/
"SortOptions" : {
"Column" : -1,
"Ascending" : true,
"Flags" : 0,
"Callback_Default" : function (sText1, sText2, bAscending) {
sText1 = String(sText1).toLowerCase();
sText2 = String(sText2).toLowerCase();
var Result = (sText1 == sText2) ? 0 : (sText1 < sText2) ? -1 : 1;
if (!bAscending) Result *= -1;
return Result;
},
"Callback" : null
},
/**
* InsertItem
*
* Desc: Inserts an item to the list with the specified options.
* Params: ItemText Text to be inserted in the first column of the list for the item.
* ImageIdx Index of the image in the small image list to use for this item.
* ItemIdx Optional. The index at which the item should be inserted. Defaults to the end of the list.
* Return value: The index of the new item when successful, otherwise -1.
*/
"InsertItem" : function (ItemText, ImageIdx, ItemIdx) {
//Make sure the parameters are alright
ItemText = (typeof ItemText === "string") ? ItemText : "";
ImageIdx = (typeof ImageIdx === "number") ? ImageIdx : false;
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : this.GetItemCount();
lParam = ItemIdx; //Set the lParam to be the item index, used for sorting and identifying the item
//Do it!!!
var LVITEM = this.Helpers.LVITEM(0, ItemIdx, ItemText, ImageIdx, lParam);
var Result = this.Helpers.SendMessage(LVM_INSERTITEMW, 0, LVITEM.DataPtr);
//Clean up
LVITEM.Size = 0;
return Result;
},
/**
* SetSubItem
*
* Desc: Sets the subitem for an item in the list.
* Params: ItemIdx Index of the item to set the subitem of.
* SubItemIdx Subitem index to set the subitem. If the column wasn't modified, this is the same as the column index.
* SubItemText Text to be set for the subitem.
* Return value: True indicates success, false otherwise.
*/
"SetSubItem" : function (ItemIdx, SubItemIdx, SubItemText) {
//Make sure the parameters are alright
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : 0;
SubItemIdx = (typeof SubItemIdx === "number") ? SubItemIdx : 0;
SubItemText = (typeof SubItemText === "string") ? SubItemText : false;
//Do it!!!
var LVITEM = this.Helpers.LVITEM(0, ItemIdx, SubItemText, false, false, SubItemIdx);
var Result = this.Helpers.SendMessage(LVM_SETITEMW, 0, LVITEM.DataPtr);
//Clean up
LVITEM.Size = 0;
return Result;
},
/**
* SetColumn
*
* Desc: Sets various options, such as text and image, for a column in the list.
* Params: ColumnIdx Index of the column to modify.
* ColumnText Text to set as column header. Set to false or leave blank if you don't want to modify this.
* ImageIdx Index of the image in the small image list to use for this column.
* Set to false or leave blank if you don't want to modify this.
* SubItemIdx Index of the subitem to assign the column with. Set to false or leave blank if you don't want to modify this.
* Return value: True indicates success, false otherwise.
*/
"SetColumn" : function (ColumnIdx, ColumnText, ImageIdx, SubItemIdx) {
//Make sure the parameters are alright
ColumnIdx = (typeof ColumnIdx === "number") ? ColumnIdx : 0;
ColumnText = (typeof ColumnText === "string") ? ColumnText : false;
ImageIdx = (typeof ImageIdx === "number") ? ImageIdx : false;
SubItemIdx = (typeof SubItemIdx === "number") ? SubItemIdx : false;
//Do it!!!
var LVCOLUMN = this.Helpers.LVCOLUMN(0, ColumnText, SubItemIdx, ImageIdx);
var Result = this.Helpers.SendMessage(LVM_SETCOLUMNW, ColumnIdx, LVCOLUMN);
//Clean up
LVCOLUMN.Size = 0;
return Result;
},
/**
* SortList
*
* Desc: Sorts the list using a callback function. For more information, go to
* http://msdn2.microsoft.com/en-us/library/bb761227(VS.85).aspx
* Params: ColumnIdx Index of the column to sort. If this is a negative number, the current sorted column is used.
* Callback Callback function to determine the sorting order.
* This function receives the text of two subitems in it first two parameters and a boolean as third parameter
* whether the sorting should be done ascending or descending. The function should return a negative value if the
* first item should precede the second, a positive value if the first item should follow the second, or zero if
* the items are equivalent. This function will also be bound to the ListView class instance it was called on, that
* means that any "this" references will refer to this ListView object, thus it can read and change properties and
* call functions from the ListView class. Defaults to the last callback function used or, if this is the first time
* this function was called, a default callback function.
* Ascending Boolean specifying whether the new sorting should be ascending (true) or descending (false).
* If this is a negative number, the default behaviour for sorting is followed, i.e. the sorting order will be
* ascending when a new column is sorted, else the order is reversed.
* Flags Extra flags. Defaults to the last used flag. This can be (only) one of the following values:
* 0x0 - Default value. Pass the subitem text to the callback function as first and second parameters.
* 0x1 - Pass the original index of the item to the callback function, i.e. the index the item had when
* it was created.
* 0x2 - Pass the current index of the item to the callback function, i.e. the index the item has with the current
* sorting and other changes made.
* Return value: True indicates success, false otherwise.
*/
"SortList" : function (ColumnIdx, CallbackFunc, Ascending, Flags) {
//Make sure the parameters are alright
ColumnIdx = (typeof ColumnIdx === "number") ? ( (ColumnIdx < 0) ? ( (this.SortOptions.Column >= 0) ? this.SortOptions.Column : 0) : ColumnIdx) : 0;
CallbackFunc = (typeof CallbackFunc === "function") ? CallbackFunc : this.SortOptions.Callback_Default;
Flags = (typeof Flags === "undefined") ? this.SortOptions.Flags : 1*Flags;
//Set the sort order
if (typeof Ascending === "number" && Ascending < 0) {
//Unset the sort header
this.SetColumnSort(this.SortOptions.Column, false);
} else if (typeof Ascending !== "undefined") {
//Set the sort order to the given order
this.SortOptions.Ascending = (Ascending == true);
//Unset the sort header
this.SetColumnSort(this.SortOptions.Column, false);
} else {
if (this.SortOptions.Column === ColumnIdx) {
//Inverse the order
this.SortOptions.Ascending = !this.SortOptions.Ascending;
} else {
//Start ascending
this.SortOptions.Ascending = true;
//Unset the sort header
this.SetColumnSort(this.SortOptions.Column, false);
}
}
//Set the sort options
this.SortOptions.Column = ColumnIdx;
this.SortOptions.Flags = Flags;
this.SortOptions.Callback = this.Helpers.BindFunction(CallbackFunc, this);
//Get a function pointer - This will fail on Plus! versions who don't have the Interop.GetCallbackPtr function.
try {
var FuncPtr = Interop.GetCallbackPtr("ListViewCallback_Sort");
} catch (e) {
return false;
}
//Sort the list
var Result = this.Helpers.SendMessage(LVM_SORTITEMS, this.Handle, FuncPtr);
//Set the sort header
this.SetColumnSort(ColumnIdx, true, this.SortOptions.Ascending);
return Result;
},
/**
* SetColumnSort
*
* Desc: Sets the column header to reflect the current sorting state.
* Params: ColumnIdx Index of the column to modify.
* Sort Boolean defining if this column should reflect a sorted state.
* SortDown Boolean specifying whether this column should reflect an ascending (true) or descending (false) sort state.
* Return value: True indicates success, false otherwise.
*/
"SetColumnSort" : function (ColumnIdx, Sort, SortDown) {
//Make sure the parameters are alright
ColumnIdx = (typeof ColumnIdx === "number") ? ColumnIdx : 0;
Sort = (typeof Sort === "undefined") ? false : (Sort == true);
SortDown = (typeof SortDown === "undefined") ? false : (SortDown == true);
//Get the header control
hHeader = this.Helpers.SendMessage(LVM_GETHEADER);
//Create a HDITEM structure
var HDITEM = Interop.Allocate(24);
HDITEM.WriteDWORD(0, HDI_FORMAT);
//Get the HDITEM information
Interop.Call("user32", "SendMessageW", hHeader, HDM_GETITEMW, ColumnIdx, HDITEM.DataPtr);
//Unset the sort down and sort up flags
var fmt = HDITEM.ReadDWORD(20) & ~(HDF_SORTDOWN | HDF_SORTUP);
//If the column should be set, set the correct flag.
HDITEM.WriteDWORD(20, fmt | (Sort ? (SortDown ? HDF_SORTDOWN : HDF_SORTUP) : 0) );
//Set the HDITEM
var Result = Interop.Call("user32", "SendMessageW", hHeader, HDM_SETITEMW, ColumnIdx, HDITEM.DataPtr);
//Clean up
HDITEM.Size = 0;
return Result;
},
/**
* GetItemText
*
* Desc: Gets the text from an item or subitem.
* Params: ItemIdx Index of the item.
* SubItemIdx Index of the subitem.
* Return value: The text assigned with the item or subitem.
*/
"GetItemText" : function (ItemIdx, SubItemIdx) {
//Make sure the parameters are alright
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : 0;
SubItemIdx = (typeof SubItemIdx === "number") ? SubItemIdx : 0;
//Get an LVITEM structure
var LVITEM = this.Helpers.LVITEM(0, false, false, false, false, SubItemIdx);
//Create a text buffer
var nTextLength = 1024;
var pszText = Interop.Allocate(nTextLength);
LVITEM.WriteDWORD(20, pszText.DataPtr); //pszText
LVITEM.WriteDWORD(24, nTextLength); //cchTextMax
LVITEM.WriteDWORD(0, LVITEM.ReadDWORD(0) | LVIF_TEXT); //mask
//Do it!!!
var Result = this.Helpers.SendMessage(LVM_GETITEMTEXTW, ItemIdx, LVITEM.DataPtr);
var sItemText = pszText.ReadString(0, true);
//Clean up
LVITEM.Size = 0;
pszText.Size = 0;
return sItemText;
},
/**
* GetItemData
*
* Desc: Gets the item data from an item.
* Params: ItemIdx Index of the item.
* Return value: The item data assigned with the item, as a number.
*/
"GetItemData" : function (ItemIdx) {
//Make sure the parameters are alright
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : 0;
//Get an LVITEM structure
var LVITEM = this.Helpers.LVITEM(0, ItemIdx);
//Prepare the structure
LVITEM.WriteDWORD(0, LVITEM.ReadDWORD(0) | LVIF_PARAM); //mask
//Do it!!!
var Result = this.Helpers.SendMessage(LVM_GETITEMW, 0, LVITEM.DataPtr);
var lParam = LVITEM.ReadDWORD(32); //lParam
//Clean up
LVITEM.Size = 0;
return lParam;
},
/**
* EnsureVisible
*
* Desc: Ensures that an item is either entirely or partially visible, scrolling the list-view control if necessary.
* Params: ItemIdx The index of the item which has to be made visible.
* PartialOK Boolean specifying if the item must be entirely visible. False means that it must be entirely visible,
* true means that the item can be only partially visible. Default is false (entirely visible).
* Return value: True indicates success, false otherwise.
*/
"EnsureVisible" : function (ItemIdx, PartialOK) {
//Make sure the parameters are alright
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : 0;
PartialOK = (typeof PartialOK === "undefined") ? false : (PartialOK == true);
//Do it!!!
return this.Helpers.SendMessage(LVM_ENSUREVISIBLE, ItemIdx, PartialOK);
},
/**
* FindItem
*
* Desc: Searches the list for the first item which matches the given options.
* Params: Options Associative array or object specifying the options used to perform the search.
* The following keys are supported:
* - "wrap" Boolean specifying whether to continue the search at the beginning if
* no match is found. Default is false.
* - "text" Searches the list for an item which item text matches this string.
* - "text-partial" Boolean specifying whether the text is partial. If this is set to true,
* an item beginning with "text" will match.
* - "lparam" Searches the list for an item which lParam matches this number.
* - "point" Searches the list for an item which is the nearest to this point.
* Can be a POINT memory structure or an [X,Y] array.
* - "point-dir" Specifies the direction to look for an item from the point coordinates.
* Can be one of the following value:
* - VK_LEFT
* - VK_RIGHT
* - VK_UP
* - VK_DOWN
* - VK_HOME
* - VK_END
* - VK_PRIOR
* - VK_NEXT
* Examples of this parameter:
* { text: "Romeo and ", text-partial: true }
* Will match an item like "Romeo and Juliette"
* { point:[50, 20], point-dir: VK_UP }
* Will match the item closest to the point (50, 20), searching upwards.
* StartIdx The index to start searching from. Set this to false to start from the beginning.
* Return value: The index of the found item when successful, otherwise -1.
*/
"FindItem" : function (Options, StartIdx) {
//Make sure the parameters are alright
if (typeof Options !== "object") return -1;
StartIdx = (typeof StartIdx === "number") ? StartIdx : -1;
//Create an LVFINDINFO structure
var LVFINDINFO = Interop.Allocate(24);
var Flags = 0;
if (typeof Options["text"] === "string") {
//psz
Flags |= LVFI_STRING;
if (typeof Options["text-partial"] !== "undefined" && Partial) {
Flags |= LVFI_PARTIAL;
}
var psz = Interop.Allocate( (Options["text"].length+1) *2);
psz.WriteString(0, Options["text"]);
LVFINDINFO.WriteDWORD(4, psz.DataPtr);
}
if (typeof Options["lparam"] === "number") {
//lParam
Flags |= LVFI_PARAM;
LVFINDINFO.WriteDWORD(8, Options["lparam"]);
}
if (typeof Options["point"] === "object") {
//pt and vkDirection
Flags |= LVFI_NEARESTXY;
Direction = (typeof Options["point-dir"] === "undefined") ? VK_DOWN : 1 * Options["point-dir"];
if (typeof Options["point"].Size === "number") {
LVFINDINFO.WriteDWORD(12, Options["point"].ReadDWORD(0));
LVFINDINFO.WriteDWORD(16, Options["point"].ReadDWORD(4));
} else if (typeof Options["point"].length === "number") {
LVFINDINFO.WriteDWORD(12, Options["point"][0]);
LVFINDINFO.WriteDWORD(16, Options["point"][1]);
}
}
if (typeof Options["wrap"] !== "undefined") {
//flags: wrap
Flags |= (Option["wrap"]) ? LVFI_WRAP : 0;
}
//Flags
LVFINDINFO.WriteDWORD(0, Flags);
//Do it!!!
var ItemIdx = this.Helpers.SendMessage(LVM_FINDITEMW, StartIdx, LVFINDINFO.DataPtr);
//Clean up
LVFINDINFO.Size = 0;
if (typeof psz === "object") psz.Size = 0;
return ItemIdx;
},
/**
* GetItemCount
*
* Desc: Counts the items in the list.
* Params: none
* Return value: The items count.
*/
"GetItemCount" : function () {
return this.Helpers.SendMessage(LVM_GETITEMCOUNT);
},
/**
* DeleteItem
*
* Desc: Removes an item from the list.
* Params: ItemIdx The index of the item to remove.
* Return value: True indicates success, false otherwise.
*/
"DeleteItem" : function (ItemIdx) {
//Make sure the parameters are alright
ItemIdx = (typeof ItemIdx === "number") ? ItemIdx : false;
if (ItemIdx == false) return false;
//Do it!!!
return this.Helpers.SendMessage(LVM_DELETEITEM, ItemIdx, 0);
},
/**
* DeleteAll
*
* Desc: Removes all items from the list.
* Params: none
* Return value: True indicates success, false otherwise.
*/
"DeleteAll" : function () {
return this.Helpers.SendMessage(LVM_DELETEALLITEMS);
},
/**
* AddImageToList
*
* Desc: Adds an image to the image list of the list-view control.
* Params: Image Valid GDI image handle for the image to add.
* IsSmall Boolean specifying whether to add the image to the large (false) or small (true) image list.
* Return value: The index of the new image in the image list.
*/
"AddImageToList" : function (Image, IsSmall) {
//Make sure the parameters are alright
Image = (typeof Image === "number") ? Image : 0;
IsSmall = (typeof IsSmall === "undefined") ? false : (IsSmall == true);
iImageList = IsSmall ? LVSIL_SMALL : LVSIL_NORMAL;
//Add the image to the image list
var iImage = Interop.Call("comctl32", "ImageList_Add", this.hImageList, Image, 0);
//Set the image list
var Result = this.Helpers.SendMessage(LVM_SETIMAGELIST, iImageList, this.hImageList);
return iImage;
},
/**
* RemoveImageFromList
*
* Desc: Removes an image from the image list of a list-view control.
* Params: Image Index of the image in the image list to remove.
* IsSmall Boolean specifying whether to add the image to the large (false) or small (true) image list.
* Return value: True indicates success, false otherwise.
*/
"RemoveImageFromList" : function (Image, IsSmall) {
//Make sure the parameters are alright
Image = (typeof Image === "undefined") ? 0 : 1*Image;
IsSmall = (typeof IsSmall === "undefined") ? false : (IsSmall == true);
ImageList = IsSmall ? LVSIL_SMALL : LVSIL_NORMAL;
//Get the image list
var hImageList = this.Helpers.SendMessage(LVM_GETIMAGELIST, ImageList, 0);
//Remove the image from the list
return (Interop.Call("comctl32", "ImageList_Remove", hImageList, Image) !== 0);
},
/**
* Destroy
*
* Desc: Removes this instance of the ListView class from the global array.
* Params: none
*/
"Destroy" : function () {
try { delete ListViews[this.Handle]; } catch(e) { }
},
/**
* Helper functions
*
* Desc: Functions used by the main functions to do their stuff. No need to look at these.
*/
"Helpers" : {
"Parent" : 0,
//Save the pointer of the parent ListView object
"AssignParent" : function (oParent) {
this.Parent = oParent;
},
//Checks if a given PlusWnd or Window ID is a valid window
"IsWindow" : function (PlusWnd) {
return(typeof PlusWnd === "object" && typeof PlusWnd.Handle === "number" && Interop.Call("user32", "IsWindow", PlusWnd.Handle) );
},
//Sends a control message
"SendMessage" : function (Message, wParam, lParam, hWnd) {
hWnd = (typeof hWnd === "undefined") ? this.Parent.Handle : 1*hWnd;
wParam = (typeof wParam === "undefined") ? 0 : wParam;
lParam = (typeof lParam === "undefined") ? 0 : lParam;
return Interop.Call("user32", "SendMessageW", hWnd, Message, wParam, lParam);
},
//ToArray - Converts any iterable object to an array. - based on $A from Prototype(www.prototypejs.org)
"ToArray" : function (iterable) {
if (!iterable) return[];
if (iterable.toArray) return iterable.toArray();
var length = iterable.length, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
},
//BindFunction - Binds a function to an object. - based on Function.bind from Prototype(www.prototypejs.org)
"BindFunction" : function () {
var $A = this.ToArray;
var args = $A(arguments);
var func = args.shift();
var obj = args.shift();
return function () {
return func.apply(obj, args.concat($A(arguments)));
}
},
//Creates an LVITEM structure
"LVITEM" : function (_LVITEM, ItemIdx, ItemText, ImageIdx, lParam, SubItemIdx) {
//Get a memory block for this!
var LVITEM;
var LVITEM_Size = 36;
if (typeof _LVITEM === "number" && _LVITEM > 0) {
//Move the memory block so we can access it
LVITEM = Interop.Allocate(LVITEM_Size);
var Result = Interop.Call("kernel32", "RtlMoveMemory", LVITEM.DataPtr, _LVITEM, LVITEM.Size);
} else if (typeof LVITEM === "object" && typeof LVITEM.Size === "number") {
//Modify the given LVITEM DataBloc
LVITEM = _LVITEM;
} else {
//Create a new block
LVITEM = Interop.Allocate(LVITEM_Size);
}
var Mask = LVITEM.ReadDWORD(0);
//iIndex
LVITEM.WriteDWORD(4, ItemIdx);
//pszText
if (typeof ItemText === "string") {
//Write the string in a memory block
var pszText = Interop.Allocate( (ItemText.length+1) *2);
pszText.WriteString(0, ItemText, true);
Mask |= LVIF_TEXT; //Set the mask
LVITEM.WriteDWORD(20, pszText.DataPtr);
}
//iImage
if (typeof ImageIdx === "number") {
Mask |= LVIF_IMAGE;
LVITEM.WriteDWORD(28, ImageIdx);
}
//lParam
if (typeof lParam === "number") {
Mask |= LVIF_PARAM;
LVITEM.WriteDWORD(32, lParam);
}
//iSubItem
if (typeof SubItemIdx === "number") {
LVITEM.WriteDWORD(8, SubItemIdx);
}
//mask
LVITEM.WriteDWORD(0, Mask);
return LVITEM;
},
//Creates an LVCOLUMN structure
"LVCOLUMN" : function (_LVCOLUMN, ColumnText, SubItemIdx, ImageIdx) {
//Get a memory block for this!
var LVCOLUMN;
var LVCOLUMN_Size = 32;
if (typeof _LVCOLUMN === "number" && _LVCOLUMN > 0) {
//Move the memory block so we can access it
LVCOLUMN = Interop.Allocate(LVCOLUMN_Size);
var Result = Interop.Call("kernel32", "RtlMoveMemory", LVCOLUMN.DataPtr, _LVCOLUMN, LVCOLUMN.Size);
} else if (typeof LVCOLUMN === "object" && typeof LVCOLUMN.Size === "number") {
//Modify the given LVITEM DataBloc
LVCOLUMN = _LVCOLUMN;
} else {
//Create a new block
LVCOLUMN = Interop.Allocate(LVCOLUMN_Size);
}
var Mask = LVCOLUMN.ReadDWORD(0);
var fmt = LVCOLUMN.ReadDWORD(4);
//pszText
if (typeof ColumnText === "string") {
//Write the string in a memory block
var pszText = Interop.Allocate( (ColumnText.length+1) *2);
pszText.WriteString(0, ColumnText, true);
Mask |= LVCF_TEXT; //Set the mask
LVCOLUMN.WriteDWORD(12, pszText.DataPtr);
}
//iSubItem
if (typeof SubItemIdx === "number") {
Mask |= LVCF_SUBITEM;
LVCOLUMN.WriteDWORD(20, SubItemIdx);
}
//iImage
if (typeof ImageIdx === "number") {
Mask |= LVCF_IMAGE;
fmt |= LVCFMT_IMAGE;
LVCOLUMN.WriteDWORD(24, ImageIdx);
}
//mask
LVCOLUMN.WriteDWORD(0, Mask);
//fmt
LVCOLUMN.WriteDWORD(4, fmt);
return LVCOLUMN;
}
}
}
/**
* ListViewCallback
*
* Desc: Callback function for sorting list-view controls. Used internally by the ListView class.
*/
function ListViewCallback_Sort(ItemIdx1, ItemIdx2, Handle) {
var Lst = ListViews[Handle], Result = 0;
if (typeof Lst !== "object") return 0;
switch (Lst.SortOptions.Flags) {
case 0x1: //As original index
Result = Lst.SortOptions.Callback(
Lst.FindItem({'lparam':ItemIdx1}),
Lst.FindItem({'lparam':ItemIdx2}),
Lst.SortOptions.Ascending
);
break;
case 0x2: //As index
Result = Lst.SortOptions.Callback(
ItemIdx1,
ItemIdx2,
Lst.SortOptions.Ascending
);
break;
default: //As subitem text
Result = Lst.SortOptions.Callback(
Lst.GetItemText(Lst.FindItem({'lparam':ItemIdx1}), Lst.SortOptions.Column),
Lst.GetItemText(Lst.FindItem({'lparam':ItemIdx2}), Lst.SortOptions.Column),
Lst.SortOptions.Ascending
);
}
return Result;
}