--proc/controls/button: button and button-like controls --Written by Cosmin Apreutesei. Public Domain. setfenv(1, require'winapi') require'winapi.window' require'winapi.comctl' --creation WC_BUTTON = 'Button' BS_PUSHBUTTON = 0x00000000 BS_DEFPUSHBUTTON = 0x00000001 BS_CHECKBOX = 0x00000002 BS_AUTOCHECKBOX = 0x00000003 BS_RADIOBUTTON = 0x00000004 BS_3STATE = 0x00000005 BS_AUTO3STATE = 0x00000006 BS_GROUPBOX = 0x00000007 BS_AUTORADIOBUTTON = 0x00000009 BS_PUSHBOX = 0x0000000A --does not display a button face or frame; only the text appears BS_OWNERDRAW = 0x0000000B BS_LEFTTEXT = 0x00000020 BS_TEXT = 0x00000000 BS_ICON = 0x00000040 BS_BITMAP = 0x00000080 BS_LEFT = 0x00000100 BS_RIGHT = 0x00000200 BS_CENTER = 0x00000300 BS_TOP = 0x00000400 BS_BOTTOM = 0x00000800 BS_VCENTER = 0x00000C00 BS_PUSHLIKE = 0x00001000 BS_MULTILINE = 0x00002000 BS_NOTIFY = 0x00004000 BS_FLAT = 0x00008000 BS_SPLITBUTTON = 0x0000000C --vista+ BS_DEFSPLITBUTTON = 0x0000000D --vista+ BS_COMMANDLINK = 0x0000000E --vista+ BS_DEFCOMMANDLINK = 0x0000000F --vista+ --commands BM_GETCHECK = 0x00F0 BM_SETCHECK = 0x00F1 BM_GETSTATE = 0x00F2 BM_SETSTATE = 0x00F3 BM_SETSTYLE = 0x00F4 BM_CLICK = 0x00F5 BM_GETIMAGE = 0x00F6 BM_SETIMAGE = 0x00F7 BM_SETDONTCLICK = 0x00F8 --vista+ Button_Enable = EnableWindow Button_GetText = GetWindowText Button_SetText = SetWindowText BST_UNCHECKED = 0x0000 BST_CHECKED = 0x0001 BST_INDETERMINATE = 0x0002 BST_PUSHED = 0x0004 BST_FOCUS = 0x0008 function Button_GetCheck(hwndCtl) return SNDMSG(hwndCtl, BM_GETCHECK) end function Button_SetCheck(hwndCtl, check) return SNDMSG(hwndCtl, BM_SETCHECK, flags(check)) end function Button_GetState(hwndCtl) --pushed state return SNDMSG(hwndCtl, BM_GETSTATE) ~= 0 end function Button_SetState(hwndCtl, state) --pushed state checkz(SNDMSG(hwndCtl, BM_SETSTATE, state)) end function Button_SetStyle(hwndCtl, style, fRedraw) checknz(SNDMSG(hwndCtl, BM_SETSTYLE, flags(style), MAKELPARAM(fRedraw and 1 or 0, 0))) end function Button_Click(hwndCtl) SNDMSG(hwndCtl, BM_CLICK) end function Button_GetBitmap(hwndCtl) return ptr(ffi.cast('HBITMAP', SNDMSG(hwndCtl, BM_GETIMAGE, IMAGE_BITMAP))) end function Button_GetIcon(hwndCtl) return ptr(ffi.cast('HICON', SNDMSG(hwndCtl, BM_GETIMAGE, IMAGE_ICON))) end function Button_SetBitmap(hwndCtl, bitmap) --must set BS_BITMAP return ptr(ffi.cast('HBITMAP', SNDMSG(hwndCtl, BM_SETIMAGE, IMAGE_BITMAP, bitmap))) end function Button_SetIcon(hwndCtl, icon) --must set BS_ICON return ptr(ffi.cast('HICON', SNDMSG(hwndCtl, BM_SETIMAGE, IMAGE_ICON, icon))) end function Button_SetDontClick(hwndCtl, dontclick) SNDMSG(hwndCtl, BM_SETDONTCLICK, dontclick) end BCM_FIRST = 0x1600 BCM_GETIDEALSIZE = (BCM_FIRST + 0x0001) BCM_SETIMAGELIST = (BCM_FIRST + 0x0002) BCM_GETIMAGELIST = (BCM_FIRST + 0x0003) BCM_SETTEXTMARGIN = (BCM_FIRST + 0x0004) BCM_GETTEXTMARGIN = (BCM_FIRST + 0x0005) BCM_SETDROPDOWNSTATE = (BCM_FIRST + 0x0006) BCM_SETSPLITINFO = (BCM_FIRST + 0x0007) BCM_GETSPLITINFO = (BCM_FIRST + 0x0008) BCM_SETNOTE = (BCM_FIRST + 0x0009) BCM_GETNOTE = (BCM_FIRST + 0x000A) BCM_GETNOTELENGTH = (BCM_FIRST + 0x000B) BCM_SETSHIELD = (BCM_FIRST + 0x000C) function Button_GetIdealSize(hwnd, size) size = SIZE(size) --checknz(SNDMSG(hwnd, BCM_GETIDEALSIZE, 0, ffi.cast('PSIZE', size))) return size end BUTTON_IMAGELIST_ALIGN_LEFT = 0 BUTTON_IMAGELIST_ALIGN_RIGHT = 1 BUTTON_IMAGELIST_ALIGN_TOP = 2 BUTTON_IMAGELIST_ALIGN_BOTTOM = 3 BUTTON_IMAGELIST_ALIGN_CENTER = 4 ffi.cdef[[ enum PUSHBUTTONSTATES { PBS_NORMAL = 1, PBS_HOT = 2, PBS_PRESSED = 3, PBS_DISABLED = 4, PBS_DEFAULTED = 5, PBS_DEFAULTED_ANIMATING = 6, }; typedef struct { HIMAGELIST imagelist; RECT margin; UINT uAlign; } BUTTON_IMAGELIST, *PBUTTON_IMAGELIST; ]] BUTTON_IMAGELIST = struct{ ctype = 'BUTTON_IMAGELIST', fields = sfields{ 'align', 'uAlign', flags, } } BCCL_NOGLYPH = ffi.cast('HIMAGELIST', -1) --flag to indicate no glyph to SetImageList function Button_SetImageList(hwnd, bimlist) bimlist = BUTTON_IMAGELIST(bimlist) checknz(SNDMSG(hwnd, BCM_SETIMAGELIST, 0, ffi.cast('PBUTTON_IMAGELIST', bimlist))) end function Button_GetImageList(hwnd, bimlist) bimlist = BUTTON_IMAGELIST(bimlist) checknz(SNDMSG(hwnd, BCM_GETIMAGELIST, 0, ffi.cast('PBUTTON_IMAGELIST', bimlist))) return bimlist end function Button_SetTextMargin(hwnd, margin) margin = RECT(margin) checknz(SNDMSG(hwnd, BCM_SETTEXTMARGIN, 0, ffi.cast('RECT*', margin))) end function Button_GetTextMargin(hwnd, margin) margin = RECT(margin) checknz(SNDMSG(hwnd, BCM_GETTEXTMARGIN, 0, ffi.cast('RECT*', margin))) return margin end function Button_SetDropDownState(hwnd, fDropDown) checknz(SNDMSG(hwnd, BCM_SETDROPDOWNSTATE, fDropDown)) end function Button_SetSplitInfo(hwnd, pInfo) checknz(SNDMSG(hwnd, BCM_SETSPLITINFO, 0, pInfo)) end function Button_GetSplitInfo(hwnd, pInfo) checknz(SNDMSG(hwnd, BCM_GETSPLITINFO, 0, pInfo)) end function Button_SetNote(hwnd, psz) checknz(SNDMSG(hwnd, BCM_SETNOTE, 0, ffi.cast('LPCWSTR', wcs(psz)))) end function Button_GetNote(hwnd, buf) local ws, sz = WCS(buf or checkpoz(SNDMSG(hwnd, BCM_GETNOTELENGTH))) checknz(SNDMSG(hwnd, BCM_GETNOTE, ws, ffi.cast('LPCWSTR', sz))) return buf or mbs(ws) end -- Macro to use on a button or command link to display an elevated icon function Button_SetElevationRequiredState(hwnd, fRequired) return checkpoz(SNDMSG(hwnd, BCM_SETSHIELD, 0, fRequired)) end --notifications BN_CLICKED = 0 BN_DOUBLECLICKED = 5 --only if BS_NOTIFY BN_SETFOCUS = 6 --only if BS_NOTIFY damn it BN_KILLFOCUS = 7 --only if BS_NOTIFY damn it ffi.cdef[[ typedef struct tagNMBCDROPDOWN { NMHDR hdr; RECT rcButton; } NMBCDROPDOWN, *LPNMBCDROPDOWN; ]] BCN_FIRST = ffi.cast('UINT', -1250) BCN_HOTITEMCHANGE = (BCN_FIRST + 0x0001) BCN_DROPDOWN = (BCN_FIRST + 0x0002) --[[ -- SPLIT BUTTON INFO mask flags BCSIF_GLYPH = 0x0001 BCSIF_IMAGE = 0x0002 BCSIF_STYLE = 0x0004 BCSIF_SIZE = 0x0008 -- SPLIT BUTTON STYLE flags BCSS_NOSPLIT = 0x0001 BCSS_STRETCH = 0x0002 BCSS_ALIGNLEFT = 0x0004 BCSS_IMAGE = 0x0008 -- Hot item change flags #define HICF_OTHER 0x00000000 #define HICF_MOUSE 0x00000001 -- Triggered by mouse #define HICF_ARROWKEYS 0x00000002 -- Triggered by arrow keys #define HICF_ACCELERATOR 0x00000004 -- Triggered by accelerator #define HICF_DUPACCEL 0x00000008 -- This accelerator is not unique #define HICF_ENTERING 0x00000010 -- idOld is invalid #define HICF_LEAVING 0x00000020 -- idNew is invalid #define HICF_RESELECT 0x00000040 -- hot item reselected #define HICF_LMOUSE 0x00000080 -- left mouse button selected #define HICF_TOGGLEDROPDOWN 0x00000100 -- Toggle button's dropdown state typedef struct tagNMBCHOTITEM { NMHDR hdr; DWORD dwFlags; -- HICF_* } NMBCHOTITEM, *LPNMBCHOTITEM; #define BST_HOT 0x0200 -- BUTTON STATE FLAGS #define BST_DROPDOWNPUSHED 0x0400 -- BUTTON STRUCTURES typedef struct tagBUTTON_SPLITINFO { UINT mask; HIMAGELIST himlGlyph; -- interpreted as WCHAR if BCSIF_GLYPH is set UINT uSplitStyle; SIZE size; } BUTTON_SPLITINFO, *PBUTTON_SPLITINFO; ]]