function Control_Class() {
    MsgBox = function (lpText, wType, lpCaption) {
        Api.ECall("User32.dll", "MessageBoxW", 0, (lpText || "").toString(), (lpCaption || "").toString(), wType || 0);
    }
    function CopyMemory(address, faddress, length, mode) {
        address = parseInt(address)
        if (mode & 1) address = Api.VarPtr(address) + 8
        if (typeof faddress == "string") {
            var Str = Api.Malloc()
            Str.FromString = faddress
            Api.ECall("kernel32.dll", "RtlMoveMemory", address, Str.GetPtr(0), length || Str.GetCount + 1)
            // Str = null
            // CollectGarbage() '立刻GC
            return
        }
        faddress = parseInt(faddress)
        if (mode & 2) faddress = Api.VarPtr(faddress) + 8
        Api.ECall("kernel32.dll", "RtlMoveMemory", address, faddress, length || 4)
        // var Malloc = Api.Malloc()
        // Malloc.FromBytes = Api.LongToBytes(123456789)
    }
    this.Exist = function (key, Obj, mode) {
        return mode ? Obj.hasOwnProperty(key) : key in Obj
    }
    this.Keys = function (Obj, mode) {
        var keys = new Array()
        for (var key in Obj) {
            switch (true) {
                case Boolean(mode & 1):
                    if (!Obj.hasOwnProperty(key))
                        break;
                case Boolean(mode & 6): //2 返回属性  4返回函数
                    if (typeof Obj[key] == 'function' ? mode & 2 : mode & 4)
                        break;
                default:
                    keys.push(key)
            }
        }
        if (mode & 8) keys = keys.sort()
        return keys.join("|")
    }
    this.XPStyle = function () {
        // Private Type ACTCTX
        //     cbSize As Long                          0
        //     dwFlags As Long                         4
        //     lpSource As String                      8
        //     wProcessorArchitecture As Integer       12
        //     wLangId As Integer                      14
        //     lpAssemblyDirectory As String           16
        //     lpResourceName As String                20
        //     lpApplicationName As String             24
        //     hModule As Long                         28
        // End Type
        // for (key in this){
        //     MsgBox(key)
        // }

        length = Api.ECall("kernel32", "GetWindowsDirectoryW", 0, 0)
        var Path = Api.Malloc((length - 1) * 2 - 1)
        if (Api.ECall("kernel32", "GetWindowsDirectoryW", Path.GetPtr(0), length)) {
            Path.FromString = Path.ToString + "\\WindowsShell.manifest" + String.fromCharCode(0)
            var ACTCTX = Api.Malloc(31)
            ACTCTX.SetVal(32, 0, 4)
            ACTCTX.SetVal(Path.GetPtr(0), 8, 4)
            var hActCtx = Api.ECall("kernel32", "CreateActCtxW", ACTCTX.GetPtr(0))
            if (hActCtx != -1) return Api.ECall("kernel32", "ActivateActCtx", hActCtx, Api.VarPtr(length) + 8) != 0
        }
    }
    this.SetComboBox = function (Control, List, Index) {
        var GWL_STYLE = -16
        var GW_CHILD = 5
        var v = List.split("|")
        for (var i = 0; i < v.length; i++) {
            Control.AddItem(v[i])
        }
        var ChildHwnd = Api.ECall("user32.dll", "GetWindow", Control.hwnd, GW_CHILD)
        Api.ECall("user32.dll", "DestroyWindow", ChildHwnd)
        Api.ECall("user32.dll", "SetWindowLongA", Control.hwnd, GWL_STYLE, Api.ECall("user32.dll", "GetWindowLongA", Control.hwnd, GWL_STYLE) + 1)
        Control.ListIndex = Index
    }
    this.Drag = function (hwnd) {   //管理员权限开启拖放文件
        var WM_DROPFILES = 0x233
        var MSGFLT_ALLOW = 1
        var MSGFLT_ADD = 1
        var WM_COPYDATA = 0x4A
        var WM_COPYGLOBALDATA = 0x49
        var hModule = Api.ProcAddress("user32");
        var i = Api.ProcAddress(hModule, "ChangeWindowMessageFilter");
        if (i) {
            if (hwnd) {
                Api.ECall("user32", "ChangeWindowMessageFilterEx", hwnd, WM_DROPFILES, MSGFLT_ALLOW, 0)
                Api.ECall("user32", "ChangeWindowMessageFilterEx", hwnd, WM_COPYGLOBALDATA, MSGFLT_ALLOW, 0)
                Api.ECall("shell32", "DragAcceptFiles", hwnd, true)
            } else {
                Api.ECall("user32", "ChangeWindowMessageFilter", WM_COPYGLOBALDATA, MSGFLT_ADD)
                Api.ECall("user32", "ChangeWindowMessageFilter", WM_DROPFILES, MSGFLT_ADD)
                Api.ECall("user32", "ChangeWindowMessageFilter", WM_COPYDATA, MSGFLT_ADD)
            }
        }
        Api.ProcAddress(-hModule);
    }
    this.Menu = function () {
        this.Create = function (hwnd, vMenus) {
            var MF_STRING = 0x0
            var MF_POPUP = 0x10
            var MF_BYPOSITION = 0x400
            var MF_SEPARATOR = 0x800
            var hMenu = Api.ECall("user32.dll", "GetMenu", hwnd)
            if (!hMenu) hMenu = Api.ECall("user32.dll", "CreateMenu")
            hSubMenu = Api.ECall("user32.dll", "CreatePopupMenu")
            var Menus = vMenus.split(String.fromCharCode(0));
            Api.ECall("user32.dll", "AppendMenuW", hMenu, MF_STRING | MF_BYPOSITION | MF_POPUP, hSubMenu, Menus[0].toString())
            for (var i = 0; i < Menus.length; i++) {
                Api.ECall("user32.dll", "AppendMenuW", hSubMenu, MF_STRING | MF_BYPOSITION | (Menus[i] == "-" ? MF_SEPARATOR : 0), i + 1, Menus[i].toString())
            }
            Api.ECall("user32.dll", "SetMenu", hwnd, hMenu)
            return hSubMenu
        }
        this.Pop = function (hwnd, Menu, x, y) {
            var TPM_RETURNCMD = 0x100
            var Point = Api.Malloc(7)
            Point.SetVal(x / Globals("Screen").TwipsPerPixelX, 0, 4)
            Point.SetVal(y / Globals("Screen").TwipsPerPixelY, 4, 8)
            Api.ECall("user32.dll", "ClientToScreen", hwnd, Point.GetPtr(0))
            return Api.ECall("user32.dll", "TrackPopupMenu", Menu, TPM_RETURNCMD, Point.ReadVal(0, 4), Point.ReadVal(4, 4), 0, hwnd, 0)
        }
        //     Private Type MENUITEMINFO
        //       cbSize As Long          0
        //       fMask As Long           4
        //       fType As Long           8
        //       fState As Long          12
        //       wID As Long             16
        //       hSubMenu As Long        20
        //       hbmpChecked As Long     24
        //       hbmpUnchecked As Long   28
        //       dwItemData As Long      32
        //       dwTypeData As String    36
        //       cch As Long             40
        //   End Type
        this.Set = function (Menu, Index, Mode, Val) {
            var MIIM_TYPE = 0x10
            var MIIM_STATE = 0x1
            var MIIM_CHECKMARKS = 0x8

            var MFT_STRING = 0x0

            var MF_CHECKED = 0x8
            var MFS_GRAYED = 0x3
            pszText = Api.Malloc(255)
            var MENUITEMINFO = Api.Malloc(43)
            MENUITEMINFO.SetVal(44, 0, 4)
            MENUITEMINFO.SetVal(MIIM_TYPE | MIIM_STATE, 4, 4)
            MENUITEMINFO.SetVal(pszText.GetPtr(0), 36, 4)
            MENUITEMINFO.SetVal(pszText.GetCount + 1, 40, 4)
            if (Api.ECall("user32", "GetMenuItemInfoW", Menu, Index, true, MENUITEMINFO.GetPtr(0))) {
                if (Mode & 1) {
                    pszText.FromString = Val + String.fromCharCode(0)
                    MENUITEMINFO.SetVal(pszText.GetPtr(0), 36, 4)
                    MENUITEMINFO.SetVal(pszText.GetCount + 1, 40, 4)
                }
                fState = MENUITEMINFO.ReadVal(12, 4)
                if (Mode & 2)
                    fState = fState & ~MF_CHECKED
                else if (Mode & 4)
                    fState = fState | MF_CHECKED
                if (Mode & 8)
                    fState = fState & ~MFS_GRAYED
                else if (Mode & 16)
                    fState = fState | MFS_GRAYED
                MENUITEMINFO.SetVal(fState, 12, 4)
                return Api.ECall("user32", "SetMenuItemInfoW", Menu, Index, true, MENUITEMINFO.GetPtr(0))
            }
        }
        return this
    }

    this.Tray = function (handle) {
        // Private Type NOTIFYICONDATA
        //     cbSize As Long               0
        //     hwnd As Long                 4
        //     uID As Long                  8
        //     uFlags As Long               12
        //     uCallbackMessage As Long     16
        //     hIcon As Long                20
        //     szTip As String * 128        24
        //     dwState As Long              152
        //     dwStateMask As Long          156
        //     szInfo As String * 256       160
        //     uTimeout As Integer          416
        //     uVersion As Integer          418
        //     szInfoTitle As String * 64   420
        //     dwInfoFlags As Long          484
        // End Type
        var NIF_ICON = 0x2
        var NIF_TIP = 0x4
        var NIF_MESSAGE = 0x1
        var NIM_MODIFY = 0x1
        this.handle = handle || 0;
        this.Add = function (hwnd, ToolTip, ICO) {
            var LMEM_ZEROINIT = 0x40
            handle = Api.ECall("kernel32.dll", "LocalAlloc", LMEM_ZEROINIT, 488)
            // Api.ECall("kernel32.dll", "RtlZeroMemory", handle, 484)
            CopyMemory(handle, 488, 4, 2)
            CopyMemory(handle + 4, hwnd, 4, 2)
            var WM_MOUSEMOVE = 0x200
            CopyMemory(handle + 16, WM_MOUSEMOVE, 4, 2)
            Up(ToolTip, ICO || Api.ECall("user32.dll", "SendMessageA", hwnd, 0x7F, 1, 0), NIF_ICON | NIF_TIP | NIF_MESSAGE);
            var NIM_ADD = 0x0
            Api.ECall("shell32.dll", "Shell_NotifyIconA", NIM_ADD, handle);
            return handle
        }
        this.UpData = function (ToolTip, ICO) {
            Up(ToolTip, ICO, NIF_TIP | NIF_MESSAGE);
            Api.ECall("shell32.dll", "Shell_NotifyIconA", NIM_MODIFY, handle);
        }
        function Up(ToolTip, ICO, Flag) {
            if (ICO) {
                Flag = Flag | NIF_ICON
                CopyMemory(handle + 20, ICO, 4, 2)
            }
            CopyMemory(handle + 12, Flag, 4, 2)
            CopyMemory(handle + 24, Api.StrConv(ToolTip + String.fromCharCode(0), 0x80))
        }
        this.Tips = function (Text, Title, bFlag) {
            var NIF_INFO = 0x10;
            CopyMemory(handle + 12, NIF_INFO, 4, 2);
            CopyMemory(handle + 420, Api.StrConv(Title || String.fromCharCode(0) + String.fromCharCode(0), 0x80));
            CopyMemory(handle + 160, Api.StrConv(Text + String.fromCharCode(0), 0x80));
            CopyMemory(handle + 484, bFlag || 0, 4, 2);
            Api.ECall("shell32.dll", "Shell_NotifyIconA", NIM_MODIFY, handle);
        }
        this.Remove = function () {
            var NIM_DELETE = 0x2
            Api.ECall("shell32.dll", "Shell_NotifyIconA", NIM_DELETE, handle);
            Api.ECall("kernel32.dll", "LocalFree", handle)
        }
        return this
    }
    this.ToopTip = function () {
        var WM_USER = 0x400
        this.Create = function (hwnd) {
            var TTS_BALLOON = 0x40
            var CW_USEDEFAULT = -2147483648 //0x80000000
            return Api.ECall("user32.dll", "CreateWindowExW", 0, "tooltips_class32", "", TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwnd || 0, 0, 0, 0)
        }
        // Private Type TOOLINFO
        //     lSize As Long     0
        //     lFlags As Long    4
        //     lHwnd As Long     8
        //     lId As Long       12
        //     RectL As Long     16
        //     RectT As Long     20
        //     RectR As Long     24
        //     RectB As Long     28
        //     hInstance As Long 32
        //     lpStr As String   36
        //     lParam As Long    40
        // End Type
        this.Tips = function (hwnd, Title, Text, x1, y1, x2, y2) {
            var TTF_SUBCLASS = 0x10
            var TTM_ADDTOOLA = WM_USER + 4
            var TTM_DELTOOLA = WM_USER + 5
            var TTM_UPDATETIPTEXTA = WM_USER + 12
            var TOOLINFO = Api.Malloc(43)
            TOOLINFO.SetVal(TTF_SUBCLASS, 4, 4)
            TOOLINFO.SetVal(hwnd, 8, 4)
            TOOLINFO.SetVal(x1, 16, 4)
            TOOLINFO.SetVal(y1, 20, 4)
            TOOLINFO.SetVal(x2, 24, 4)
            TOOLINFO.SetVal(y2, 28, 4)

            pszText = Api.Malloc()
            pszText.FromString = Api.StrConv(Text + String.fromCharCode(0), 128)
            TOOLINFO.SetVal(pszText.GetPtr(0), 36, 4)
            Api.ECall("user32.dll", "SendMessageA", TooptipHwnd, TTM_DELTOOLA, 0, TOOLINFO.GetPtr(0))
            Api.ECall("user32.dll", "SendMessageA", TooptipHwnd, TTM_ADDTOOLA, 0, TOOLINFO.GetPtr(0))
            Api.ECall("user32.dll", "SendMessageA", TooptipHwnd, TTM_UPDATETIPTEXTA, 0, TOOLINFO.GetPtr(0))

            var TTM_SETTITLEW = WM_USER + 33
            Api.ECall("user32.dll", "SendMessageA", TooptipHwnd, TTM_SETTITLEW, 0, Title)
        }
        this.Remove = function () {
            var NIM_DELETE = 0x2
            Api.ECall("shell32.dll", "Shell_NotifyIconA", NIM_DELETE, handle);
            Api.ECall("kernel32.dll", "LocalFree", handle)
        }
        return this
    }
    this.TimeDialog = function (Index) {
        var FormD, Tag
        var me = this
        var VBScript = Api.NewScript();
        var Show = function (Index) {
            Index = Index || "12:00:00:1"
            Index = Index.replace(/\|/g, ":")
            FormD = Api.NewFrom()

            FormD.Caption = "填写时间:"
            var i = Api.ECall("user32.dll", "GetWindowLongA", FormD.hwnd, -16)
            Api.ECall("user32.dll", "SetWindowLongA", FormD.hwnd, -16, i & ~(0x10000 | 0x20000 | 0x40000))
            FormD.Move(0, 0, 0, 0)
            FormD.Width = (260 - FormD.ScaleWidth) * Globals("Screen").TwipsPerPixelX + FormD.Width
            FormD.Height = (60 - FormD.ScaleHeight) * Globals("Screen").TwipsPerPixelY + FormD.Height

            var obj = FormD.Controls.Add("VB.Label", "Label")
            obj.Move(10, 10, 200, 20)
            obj.Caption = "24小时制:时 分 秒"
            obj.Visible = true
            var arr = Index.split(":")

            obj = FormD.Controls.Add("VB.ComboBox", "ComboBox")
            obj.Move(10, 30, 73)
            obj.Visible = true
            if (arr[3] < 0) {
                obj.Enabled = false
                arr[3] = Math.abs(arr[3])
            }

            me.SetComboBox(FormD.Controls("ComboBox"), "每天|一次|每隔", arr[3] - 1)
            for (i = 0; i < arr.length - 1; i++) {
                obj = FormD.Controls.Add("VB.TextBox", "t" + i)
                obj.Move(100 + 25 * i, 30, 20, 20)
                obj.Visible = true
                obj.Text = arr[i]
            }
            arr = new Array("确定", "取消")
            for (i = 0; i < arr.length; i++) {
                obj = FormD.Controls.Add("VB.CommandButton", arr[i])
                obj.Caption = arr[i]
                obj.Move(180 + 35 * i, 30, 35, 21)
                obj.Visible = true
            }
            var wMsgs = VBScript.Eval('Array(&H111,&H18)')
            VBScript.AddCode('Function JTypeName(Obj)\nJTypeName=TypeName(Obj)\nEnd Function')
            FormD.SetEventLong(FormD.hwnd, wMsgs, me, "Form")

            FormD.Show(1)
            VBScript.Reset()
            VBScript = null
            FormD = null
            me = null
            return Tag
        }
        this.Form_GetMessage = function (cHwnd, Message, wParam, lParam) {
            switch (Message) {
                case 0x18:
                    FormD.Move((Globals("Screen").Width - FormD.Width) / 2, (Globals("Screen").Height - FormD.Height) / 2)
                case 0x111:
                    var fenum = new Enumerator(FormD.Controls);
                    for (; !fenum.atEnd(); fenum.moveNext()) {
                        var Obj = fenum.item()
                        var TypeName = VBScript.Run("JTypeName", Obj)
                        if ("CommandButton|CheckBox|TextBox|ComboBox".indexOf(TypeName) >= 0) {
                            if (Obj.hwnd == lParam) {
                                switch (TypeName) {
                                    case "CommandButton":
                                        if (Obj.Name == "确定") {
                                            Tag = FormD.Controls("t0") + ":" + FormD.Controls("t1") + ":" + FormD.Controls("t2") + "|" + (FormD.Controls("ComboBox").ListIndex + 1)
                                        }

                                        Api.UnloadFrom(FormD)
                                        break
                                    case "TextBox":
                                        switch (parseInt(wParam / 0x100)) {
                                            case 0x30000:
                                                // MsgBox(Api.ECall("user32.dll", "GetWindowLongA", FormD.hwnd, -8), 0, Api.ECall("user32.dll", "GetWindow", FormD.hwnd, 4))
                                                var iText = Api.Val(Obj.Text)
                                                if (iText >= (Obj.Name == "t0" ? 24 : 60) | iText < 0) iText = 0
                                                var Text = iText.toString()
                                                if (Text.length == 1) Text = "0" + Text
                                                Obj.Text = Text
                                                Obj.SelStart = Text.length
                                            // Obj.SelLength = Text.length
                                        }
                                        break
                                }
                                return
                            }
                        }
                    }
                    break
            }
        }
        return Show(Index);
    }
}