Read_StringTable(DllFile, StringNum) { hModule := DllCall("LoadLibrary", "str", DllFile, "Ptr") VarSetCapacity(string, 1024) DllCall("LoadString", "uint", hModule, "uint", StringNum, "uint", &string, "int", 1024) DllCall("FreeLibrary", "Ptr", hModule) Return string }举例：result:=Read_StringTable("CBDHSvc.dll", "101")
#SingleInstance force #Persistent SendMode Input SetBatchLines -1 return $!F4:: ;$作用等同于钩子 wid2:=WinExist("A") winget, wida,id,ahk_class Shell_TrayWnd winget,widb,ID, % "Program Manager" IF (wid2 = wida) or (wid2=widb) { msgbox,64,提醒,桌面和任务栏上禁用ALT+F4,2 return } SendInput !{F4} return
对run命令后面的变量，不建议用表达式，而建议用%变量，如hosts命令用表达式反而不起作用gui命令获得的尺寸为真实尺寸，而win命令获得的尺寸均为A_screenDPI/96的倍数后的，尤其是winset，region这样的w和h一定要记得进行dpi缩放，否则窗口尺寸显示会小。gui, font 命令在其他线程中会对后面的gui一些控件（特别是销毁后再生成）的外观会有影响通过FrameShadow（GUIID）来实现窗体阴影的尺寸，似乎比A_GUIWIDTH要大一点点，哪怕是无边框无标题栏的情况scite4对某些脚本中存在emoji字符的时候，不采用% "★" 而是直接采用 ★ 这样的会出现卡死的情况。gui的+owner是指该窗口隶属于 owner后面的ID变量窗口，如 +owner%mainguiid%，当mainguiid窗口关闭时，这个gui也会自动被关闭。如果需要顶层，那么可以在该gui之前将owner窗口disable，到该gui窗口销毁的时候在enable这个owner窗口。而+parent 则将该gui嵌入到 parent后面的id变量窗口中，如嵌入到桌面，任务栏等等。sendinput {Enter} 这样的发送方式更可靠有效一个有效的判断窗体移除窗体的代码;************************************************** ;另一种窗口拖动的方案 ;************************************************** WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) { static init := OnMessage(0x0201, "WM_LBUTTONDOWN") PostMessage, 0xA1, 2,,, A } ;************************************************** ;另一种窗口拖动的方案 ,成功实现鼠标离开窗口的操作，应该是通过loop操作的时间与移动速度的时间打了一个时间差 ;************************************************** WM_MOUSEMOVE(wParam, lParam, msg, hwnd) { static init := OnMessage(0x0200, "WM_MOUSEMOVE") MouseGetPos,,,cwid winset, transcolor, OFF, ahk_id %testid% loop { MouseGetPos,,,cwid if !(cwid=testid) { winset, transcolor, EAEAEA 255, ahk_id %testid% BREAK } } }暗黑主题（win10~11窗体），这条命令结合frameshadow可以避免frameshadow在guimove的时候闪动。darkme(hWnd) { if 1 DWMWA_USE_IMMERSIVE_DARK_MODE := 19 ;23h2是这个数字。貌似在10.0.17763以后都是 else DWMWA_USE_IMMERSIVE_DARK_MODE := 20 DllCall("dwmapi\DwmSetWindowAttribute", "Ptr", hWnd, "Int", DWMWA_USE_IMMERSIVE_DARK_MODE, "Int*", true, "Int", 4) ;~ uxtheme := DllCall("GetModuleHandle", "Str", "uxtheme", "Ptr") ;~ DllCall(DllCall("GetProcAddress", "Ptr", uxtheme, "Ptr", 135, "Ptr"), "Int", 2) ;~ DllCall(DllCall("GetProcAddress", "Ptr", uxtheme, "Ptr", 136, "Ptr")) }彩色按钮button，详情参阅：https://github.com/AHK-just-megui, abt: add, button, xP y+15 w60 gbuyacoffee h25 vcfe1 hwndbtncoffee, % "buy" Opt1 := [0, 0xFF1296DB, , "White", 5, , ,2] ; "Red" ; normal flat background & text color；常规背景+字体颜色，5为圆角 Opt2 := [ , 0xFFFC0000] ; hot flat background color 移到上面背景颜色 Opt5 := [ , , ,"WHITE"] ; defaulted text color -> animation 默认字体颜色 If !ImageButton.Create(btncoffee, Opt1, Opt2, , , Opt5) MsgBox, 0, ImageButton Error btnclose, % ImageButton.LastError新建ahk自动添加内容：修改ahk目录下的template.ahk文件注册表 [HKEY_CLASSES_ROOT.ahk\ShellNew] 右侧的FileName输入该 template的全路径名称即可。关于关键词颜色高亮不全的解决办法检查 ahk.properties 中的下面段落# Keywords import ahk.keywords ;比如这个文件就因为没有包含，或者不存在ahk1.keyword.properties文件。 import ahk1.keywords import ahk2.keywords import ahk.keys如何将 ah2 关联为v2版本主要是通过ahk.properties中的 ahk.file.extension=`*.ah2 设置为你要的后缀，这样用scite4打开ah2的文件就会自动进行高亮等。这样可以分别设置v1和v2版本了。GUI的细边框 +border 如果在无标题 -caption 模式下，必须要放在 -caption后面，否则不起作用win11窗体外框效果;************************************************** ;【函数】无边框窗口显示阴影 ;************************************************** FrameShadow(HGui, _ISENABLED:="1") { DllCall("dwmapi\DwmIsCompositionEnabled","IntP",_ISENABLED) ; Get if DWM Manager is Enabled if !_ISENABLED ; if DWM is not enabled, Make Basic Shadow DllCall("SetClassLong","UInt",HGui,"Int",-26,"Int",DllCall("GetClassLong","UInt",HGui,"Int",-26)|0x20000) else { VarSetCapacity(_MARGINS,16) NumPut(1,&_MARGINS,0,"UInt") NumPut(1,&_MARGINS,4,"UInt") NumPut(1,&_MARGINS,8,"UInt") NumPut(1,&_MARGINS,12,"UInt") DllCall("dwmapi\DwmSetWindowAttribute", "Ptr", HGui, "UInt", 2, "Int*", 2, "UInt", 4) DllCall("dwmapi\DwmExtendFrameIntoClientArea", "Ptr", HGui, "Ptr", &_MARGINS) } }数组变量在if中似乎对大小写有区别，名称最好全部对上，如 Array._MaxIndex() 这样的。遇到一次全小写结果总是无法读取的情况。api动画，动画参数详见：aminatewindow动画参数动画设置几个注意地方：1）gui,show, hide x y w h 这样的设置建议全部确定好，并且处于hide状态，然后就直接设置dllcall动画语句，然后就是再gui,show这样，最后的一句show不要再调整窗口的位置及大小，否则动画失效。2）对于采用frameshow的外框效果的gui，在动画dllcall后面紧跟frameshadow处理，不要把frameshadow放在dllcall之前，否则会影响动画时会有一个一个浅色外框（gui外框尺寸大小）DllCall("AnimateWindow", "Ptr", topmainGUIid, "UINT", 500, "UINT", "0x00000004") ;动画函数 DllCall("ShowWindow", "Ptr", topmainGUIid, "INT", "8") ;显示窗口 DllCall("ShowWindow", "Ptr", topmainGUIid, "INT", "0") ;隐藏窗口读取RC资源中的png文件举例：ret := getpicture(hPicCtrl, "logo1.PNG") ;使用方法，hPicCtrl为pic控件的hwnd，LOGO1.PNG为文件RCDATA中的PNG名称 GETPicture(hwnd,RCPng){ hRSrc := DllCall("FindResource", "ptr", 0, "str", RCPng, "ptr", 10, "ptr") sData := DllCall("SizeofResource", "ptr", 0, "ptr", hRSrc, "uint") hRes := DllCall("LoadResource", "ptr", 0, "ptr", hRSrc, "ptr") pData := DllCall("LockResource", "ptr", hRes, "ptr") hGlob := DllCall("GlobalAlloc", "uint", 2, "uint", sData, "ptr") pGlob := DllCall("GlobalLock", "ptr", hGlob, "ptr") DllCall("msvcrt\memcpy", "ptr", pGlob, "ptr", pData, "uint", sData, "CDecl") DllCall("GlobalUnlock", "ptr", hGlob) DllCall("ole32\CreateStreamOnHGlobal", "ptr", hGlob, "int", 1, "ptr*", pStream) hGdip := DllCall("LoadLibrary", "str", "gdiplus", "Ptr") VarSetCapacity(si, 16, 0), NumPut(1, si, "UChar") DllCall("gdiplus\GdiplusStartup", "ptr*", gdipToken, "ptr", &si, "ptr", 0) DllCall("gdiplus\GdipCreateBitmapFromStream", "ptr", pStream, "ptr*", pBitmap) DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pBitmap, "ptr*", hBitmap, "uint", 0) SendMessage, 0x172, 0, hBitmap,, ahk_id %hwnd% ;~ GuiControl, Move, %hwnd%, w240 h78 DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap) DllCall("gdiplus\GdiplusShutdown", "ptr", gdipToken) DllCall("FreeLibrary", "ptr", hGdip) ObjRelease(pStream) return }
前言快速启动软件简直多如牛毛，有侧重图标类操作的，有侧重命令行模式操作的，CLaunch,Lily,Lucy,nrLaunch,nTrun,Rolan,TrayLauncher,TrueLaunchBar,TurboLaunch,音速启动（VStart）,ALMRun,ALTRun,Keypirinha,Launchy,Listary,PowerToysRun,uTools,Wox,RunZ,RunAny，这里面大部分我基本都用过一次或多次，然而总觉得并没有完美契合我的需求点，所以我觉得自己来写一个，这个软件我是从2020年开始写的，也是我人生中写的第一个软件。软件在写的过程中也不断的改名，最初的版本叫PD（我家小狗的名字），后来叫过aGo，现在我给它取了一个比较俗气的名字，叫xRun。一边用一边写，从开始到至今大小版本大约迭代了40多个版本。对于快速启动类型的软件，我的观点是：轻，快，简单快速完成文件夹跳转快速启动程序xRun能干什么？它只是一个纯粹的快速启动，用最少的步骤实现操作结果的呈现。它可以在任意位置一步打开文件夹，在任意位置一步启动想要启动的程序，它可以用最少的字符输入大段常用的文字内容（如快件地址信息，如常用的短语）。它可以用命令行的模式启动，也可以用菜单模式启动。xrun文件组成：一个主程序xrun .exe，一个配置文件config.ini，xrun不需要安装，也没有设置窗口，所有的设置都是通过config.ini完成。怎么用？命令窗口模式：xrun的命令行窗口模式是通过双击热键呼出命令窗口，输入命令回车完成。热键可以定义为双击Ctrl键，或者双击 shift键盘，设置可以设置为Lctrl指定左ctrl键），关于按键名称，参见：http://doc.ilaoyao.cn/index.php/168.html菜单模式：xrun的菜单模式是通过单击鼠标中键跳出菜单，菜单分三部分组成，上段为文件夹，常用快速打开或者快速跳转，中部为CLSID特殊文件夹（如控制面板，打印机，回收站等），下段为常用程序。其中CLSID文件夹和常用程序可以设置在菜单中显示与否。如何自定义命令：xrun的自定义命令分为两种，一种是单命令，写在config.ini中的[s_cmdstr]段落中，如定义wd来启动word，ffp来启动firefox的隐私模式。写法为：wd=C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE|Word其中wd表示自定义短命令，等号后面的全路径exe表示要执行的程序，结尾的|分隔符后面的word表示该程序将会显示在菜单中，并且显示菜单名称为word，这种情况下，你可以双击热键呼出命令窗口，输入wd，回车启动word，或者你可以单击鼠标中键，在菜单中选择word启动word。如果|后面留空，则该exe将不会显示在菜单中，但是依然可以在命令窗口中输入执行。单命令主要是启动一个单独的程序用。支持带参数模式，如ffp=D:\firefox_113\core\firefox.exe -private-window，则表示输入ffp，会启动firefox的隐私模式。在windows系统中win+R中能运行的命令，都不需要单独定义，可以直接输入运行，当然，你也可以自定义，比如：ip=cmd.exe /k ipconfig，输入ip就会打开cmd窗口并且执行ipconfig的命令。单命令还支持文件夹模式，举例说比如在d:\soft\study\action\usa\pureteen\hot\2023这个隐藏的文件夹，该文件夹下面存放了一些不希望别人看到的资料，那么桌面上放个快捷方式也不妥当，资源管理器一路点下去也是非常耗时，这时候可以自定义一行：3v1=d:\soft\study\action\usa\pureteen\hot\2023，这样你可以输入3v1的时候就会一步打开该文件夹，但是菜单中并不显示，这对于一些隐私操作来说是非常方便的。第二种是双命令，写在config.ini中的[m_cmdstr]段落中双命令最常用的作为网络查询，比如你可以这样定义：jd=https://search.jd.com/Search?keyword={query}，其中jd为自定义命令，后面的表示到京东上搜索{query}这个关键词。那么在命令窗口中输入 jd 小米14，回车后就会自动打开浏览器进入京东搜索小米14，凡是支持搜索的网络站点都可以在这里写入，如豆瓣，bilibili，微博，github等等。其中{query} 表示关键词，上面例子中的小米14这就是要搜索的关键词。双命令还有一个隐藏的功能，就是快速用管理员模式运行程序（包括上面自定义的单命令程序），比如你可以输入 admin wd，回车后就会以管理员模式启动word，输入 admin cmd 就会以管理员模式启动cmd命令行。管理员模式命令为admin开始。如何自定义菜单菜单中顶部的常用文件夹在config.ini中的[quick_folder]段落中这个文件夹始终在菜单中显示，并不支持命令行模式，如果需要命令行中启动文件夹，请采用上面单命令的文件夹模式。比如你可以这样定义：软件=D:\soft|C:\Windows\System32\imageres.dll,153，其中软件就表示显示菜单上的名称，等号后面表示对应的文件夹全路径地址，|分隔号后面表示自定义该文件夹的图标（如果留空则采用默认的常规文件夹图标）这时候你可以鼠标中键呼出菜单，点击菜单中的软件，那么就会在资源管理器中打开D:\soft文件夹，这里有几种场景：当前有资源管理器窗口打开，则会在最近的资源管理器中快速切换到D:\soft文件夹，如果当前没有资源管理器，则会自动打开一个新的资源管理窗口并进入D:\soft文件夹。弹出菜单后按住shift再点击菜单，这样就会打开一个新的资源管理器窗口而不是直接在原来的窗口中切换到D:\soft。这就是文件夹跳转功能。文件夹跳转还有一个实用场景就是比如打开保存这类的对话框，在该对话框顶部中键唤出菜单，选择文件夹，则会自动跳转到该文件夹内，这个对快速保存和快速打开文件时可以节省很大的时间的。菜单的中部有一个CLSID菜单，这个菜单主要是存放一些特殊文件夹作为二级菜单显示，比如快速打开回收站，控制面板，打印机，桌面，用户文档等等。这个CLSID可以设置显示或者不显示；菜单的下部就是常用程序的菜单，这个菜单的数据来源于你自定义的单命令中的内容，并且指定了该命令显示在菜单中，如果自定义但命令中明确不在菜单中显示，那么该命令将不会出现在菜单该区域内。补充操作：左键双击资源管理器空白处，比如左侧树形列表的空白处，会自动跳转上一层目录左键双击任务栏空白处，同样可以唤出命令窗口使用5键鼠标的，单击鼠标的xbutton1同样也可以唤出快速菜单。命令窗口在失去焦点后则会自动隐藏。在打开保存之类的对话框中，点击鼠标中键仅显示文件夹部分，clsid和快速程序的菜单部分不会显示。单命令和文件夹段落中如果一行只输入X，则表示菜单在此位置生成一个分隔线。（双命令中无效）热字符串操作xrun有一个高级操作，叫热字符串操作，它可以更快速的启动程序，和输入大段常用的文字内容。假如你在单命令中自定义了这样的一行：wd=C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE|Word，这时候你可以呼出命令窗口，输入wd回车来启动word，也可以中键菜单选择word菜单启动word，但是你可以在任何界面直接输入 wd+ 来更快的启动word。这就是热字符串，其中wd时你定义的简化命令，+是热字符串启动的标识符。所有单命令中的自定义命都支持这种方式。热字符串还有一个操作就是简化常用短语的输入，比如在交换快递地址信息的时候。你可以在config.ini中的[autoreplacetext]段定义这样的一行dz=江苏省常州市钟楼区XX街道88号\`r\`n收件人：XXX\`r\`n电话：17712345678，然后你可以在任何接收输入的窗口（比如微信，qq，淘宝等等），输入dz+，这样就会自动将等号后面的内容瞬间呈现。其中\`r\`n表示换行（由于markdown语法，实际\这个字符不需要）。热字符串操作可以在任何界面任何位置进行无显示的操作。补充config.ini中有一个[excludeapp]段落，是表示该段中的程序处于活动状态的时候，中键是不会被激活的。因为类似浏览器或者autocad程序中，中键是由固定操作意义的。所以在这些程序处于当前活动窗口的时候，中键被禁止激活。属于排除列表。排除列表只针对固定的exe进程名称，如firefox.exe，并不需要带路径。下载地址：https://ilaoyao.lanzouo.com/b019wbeyh 密码: JP25
设置text控件字符有时候不显示的原因
在text控件生成后，其宽度不会自动扩展，这时候如果在后面添加了字符，超过此宽度的字符内容则无法显示。特别是对于settimer子程序中增添text控件内容长度的时候。所以在初始设置text这类控件的文本长度很重要，确保在后期能容纳修改后的文字长度内容。
/* ************************************************************************************** listview单元格颜色设置class ************************************************************************************** */ ; ====================================================================================================================== ; Namespace: LV_Colors ; Function: Individual row and cell coloring for AHK ListView controls. ; Tested with: AHK 1.1.23.05 (A32/U32/U64) ; Tested on: Win 10 (x64) ; Changelog: ; 1.1.04.01/2016-05-03/just me - added change to remove the focus rectangle from focused rows ; 1.1.04.00/2016-05-03/just me - added SelectionColors method ; 1.1.03.00/2015-04-11/just me - bugfix for StaticMode ; 1.1.02.00/2015-04-07/just me - bugfixes for StaticMode, NoSort, and NoSizing ; 1.1.01.00/2015-03-31/just me - removed option OnMessage from __New(), restructured code ; 1.1.00.00/2015-03-27/just me - added AlternateRows and AlternateCols, revised code. ; 1.0.00.00/2015-03-23/just me - new version using new AHK 1.1.20+ features ; 0.5.00.00/2014-08-13/just me - changed 'static mode' handling ; 0.4.01.00/2013-12-30/just me - minor bug fix ; 0.4.00.00/2013-12-30/just me - added static mode ; 0.3.00.00/2013-06-15/just me - added "Critical, 100" to avoid drawing issues ; 0.2.00.00/2013-01-12/just me - bugfixes and minor changes ; 0.1.00.00/2012-10-27/just me - initial release ; ====================================================================================================================== ; CLASS LV_Colors ; ; The class provides six public methods to set individual colors for rows and/or cells, to clear all colors, to ; prevent/allow sorting and rezising of columns dynamically, and to deactivate/activate the message handler for ; WM_NOTIFY messages (see below). ; ; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is ; created. If you want to temporarily disable coloring call MyInstance.OnMessage(False). This must be done also before ; you try to destroy the instance. To enable it again, call MyInstance.OnMessage(). ; ; To avoid the loss of Gui events and messages the message handler might need to be set 'critical'. This can be ; achieved by setting the instance property 'Critical' ti the required value (e.g. MyInstance.Critical := 100). ; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become ; unresponsive under certain circumstances if Critical is set and the ListView has a g-label. ; ====================================================================================================================== Class LV_Colors { ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; META FUNCTIONS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; =================================================================================================================== ; __New() Create a new LV_Colors instance for the given ListView ; Parameters: HWND - ListView's HWND. ; Optional ------------------------------------------------------------------------------------------ ; StaticMode - Static color assignment, i.e. the colors will be assigned permanently to the row ; contents rather than to the row number. ; Values: True/False ; Default: False ; NoSort - Prevent sorting by click on a header item. ; Values: True/False ; Default: True ; NoSizing - Prevent resizing of columns. ; Values: True/False ; Default: True ; =================================================================================================================== __New(HWND, StaticMode := False, NoSort := True, NoSizing := True) { If (This.Base.Base.__Class) ; do not instantiate instances Return False If This.Attached[HWND] ; HWND is already attached Return False If !DllCall("IsWindow", "Ptr", HWND) ; invalid HWND Return False VarSetCapacity(Class, 512, 0) DllCall("GetClassName", "Ptr", HWND, "Str", Class, "Int", 256) If (Class <> "SysListView32") ; HWND doesn't belong to a ListView Return False ; ---------------------------------------------------------------------------------------------------------------- ; Set LVS_EX_DOUBLEBUFFER (0x010000) style to avoid drawing issues. SendMessage, 0x1036, 0x010000, 0x010000, , % "ahk_id " . HWND ; LVM_SETEXTENDEDLISTVIEWSTYLE ; Get the default colors SendMessage, 0x1025, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTBKCOLOR This.BkClr := ErrorLevel SendMessage, 0x1023, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTCOLOR This.TxClr := ErrorLevel ; Get the header control SendMessage, 0x101F, 0, 0, , % "ahk_id " . HWND ; LVM_GETHEADER This.Header := ErrorLevel ; Set other properties This.HWND := HWND This.IsStatic := !!StaticMode This.AltCols := False This.AltRows := False This.NoSort(!!NoSort) This.NoSizing(!!NoSizing) This.OnMessage() This.Critical := "Off" This.Attached[HWND] := True } ; =================================================================================================================== __Delete() { This.Attached.Remove(HWND, "") This.OnMessage(False) WinSet, Redraw, , % "ahk_id " . This.HWND } ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PUBLIC METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; =================================================================================================================== ; Clear() Clears all row and cell colors. ; Parameters: AltRows - Reset alternate row coloring (True / False) ; Default: False ; AltCols - Reset alternate column coloring (True / False) ; Default: False ; Return Value: Always True. ; =================================================================================================================== Clear(AltRows := False, AltCols := False) { If (AltCols) This.AltCols := False If (AltRows) This.AltRows := False This.Remove("Rows") This.Remove("Cells") Return True } ; =================================================================================================================== ; AlternateRows() Sets background and/or text color for even row numbers. ; Parameters: BkColor - Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default background color ; TxColor - Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default text color ; Return Value: True on success, otherwise false. ; =================================================================================================================== AlternateRows(BkColor := "", TxColor := "") { If !(This.HWND) Return False This.AltRows := False If (BkColor = "") && (TxColor = "") Return True BkBGR := This.BGR(BkColor) TxBGR := This.BGR(TxColor) If (BkBGR = "") && (TxBGR = "") Return False This["ARB"] := (BkBGR <> "") ? BkBGR : This.BkClr This["ART"] := (TxBGR <> "") ? TxBGR : This.TxClr This.AltRows := True Return True } ; =================================================================================================================== ; AlternateCols() Sets background and/or text color for even column numbers. ; Parameters: BkColor - Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default background color ; TxColor - Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default text color ; Return Value: True on success, otherwise false. ; =================================================================================================================== AlternateCols(BkColor := "", TxColor := "") { If !(This.HWND) Return False This.AltCols := False If (BkColor = "") && (TxColor = "") Return True BkBGR := This.BGR(BkColor) TxBGR := This.BGR(TxColor) If (BkBGR = "") && (TxBGR = "") Return False This["ACB"] := (BkBGR <> "") ? BkBGR : This.BkClr This["ACT"] := (TxBGR <> "") ? TxBGR : This.TxClr This.AltCols := True Return True } ; =================================================================================================================== ; SelectionColors() Sets background and/or text color for selected rows. ; Parameters: BkColor - Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default selected background color ; TxColor - Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default selected text color ; Return Value: True on success, otherwise false. ; =================================================================================================================== SelectionColors(BkColor := "", TxColor := "") { If !(This.HWND) Return False This.SelColors := False If (BkColor = "") && (TxColor = "") Return True BkBGR := This.BGR(BkColor) TxBGR := This.BGR(TxColor) If (BkBGR = "") && (TxBGR = "") Return False This["SELB"] := BkBGR This["SELT"] := TxBGR This.SelColors := True Return True } ; =================================================================================================================== ; Row() Sets background and/or text color for the specified row. ; Parameters: Row - Row number ; Optional ------------------------------------------------------------------------------------------ ; BkColor - Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default background color ; TxColor - Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> default text color ; Return Value: True on success, otherwise false. ; =================================================================================================================== Row(Row, BkColor := "", TxColor := "") { If !(This.HWND) Return False If This.IsStatic Row := This.MapIndexToID(Row) This["Rows"].Remove(Row, "") If (BkColor = "") && (TxColor = "") Return True BkBGR := This.BGR(BkColor) TxBGR := This.BGR(TxColor) If (BkBGR = "") && (TxBGR = "") Return False This["Rows", Row, "B"] := (BkBGR <> "") ? BkBGR : This.BkClr This["Rows", Row, "T"] := (TxBGR <> "") ? TxBGR : This.TxClr Return True } ; =================================================================================================================== ; Cell() Sets background and/or text color for the specified cell. ; Parameters: Row - Row number ; Col - Column number ; Optional ------------------------------------------------------------------------------------------ ; BkColor - Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> row's background color ; TxColor - Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name. ; Default: Empty -> row's text color ; Return Value: True on success, otherwise false. ; =================================================================================================================== Cell(Row, Col, BkColor := "", TxColor := "") { If !(This.HWND) Return False If This.IsStatic Row := This.MapIndexToID(Row) This["Cells", Row].Remove(Col, "") If (BkColor = "") && (TxColor = "") Return True BkBGR := This.BGR(BkColor) TxBGR := This.BGR(TxColor) If (BkBGR = "") && (TxBGR = "") Return False If (BkBGR <> "") This["Cells", Row, Col, "B"] := BkBGR If (TxBGR <> "") This["Cells", Row, Col, "T"] := TxBGR Return True } ; =================================================================================================================== ; NoSort() Prevents/allows sorting by click on a header item for this ListView. ; Parameters: Apply - True/False ; Default: True ; Return Value: True on success, otherwise false. ; =================================================================================================================== NoSort(Apply := True) { If !(This.HWND) Return False If (Apply) This.SortColumns := False Else This.SortColumns := True Return True } ; =================================================================================================================== ; NoSizing() Prevents/allows resizing of columns for this ListView. ; Parameters: Apply - True/False ; Default: True ; Return Value: True on success, otherwise false. ; =================================================================================================================== NoSizing(Apply := True) { Static OSVersion := DllCall("GetVersion", "UChar") If !(This.Header) Return False If (Apply) { If (OSVersion > 5) Control, Style, +0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING = 0x0800 This.ResizeColumns := False } Else { If (OSVersion > 5) Control, Style, -0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING This.ResizeColumns := True } Return True } ; =================================================================================================================== ; OnMessage() Adds/removes a message handler for WM_NOTIFY messages for this ListView. ; Parameters: Apply - True/False ; Default: True ; Return Value: Always True ; =================================================================================================================== OnMessage(Apply := True) { If (Apply) && !This.HasKey("OnMessageFunc") { This.OnMessageFunc := ObjBindMethod(This, "On_WM_Notify") OnMessage(0x004E, This.OnMessageFunc) ; add the WM_NOTIFY message handler } Else If !(Apply) && This.HasKey("OnMessageFunc") { OnMessage(0x004E, This.OnMessageFunc, 0) ; remove the WM_NOTIFY message handler This.OnMessageFunc := "" This.Remove("OnMessageFunc") } WinSet, Redraw, , % "ahk_id " . This.HWND Return True } ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PRIVATE PROPERTIES +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Static Attached := {} ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PRIVATE METHODS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ On_WM_NOTIFY(W, L, M, H) { ; Notifications: NM_CUSTOMDRAW = -12, LVN_COLUMNCLICK = -108, HDN_BEGINTRACKA = -306, HDN_BEGINTRACKW = -326 Critical, % This.Critical If ((HCTL := NumGet(L + 0, 0, "UPtr")) = This.HWND) || (HCTL = This.Header) { Code := NumGet(L + (A_PtrSize * 2), 0, "Int") If (Code = -12) Return This.NM_CUSTOMDRAW(This.HWND, L) If !This.SortColumns && (Code = -108) Return 0 If !This.ResizeColumns && ((Code = -306) || (Code = -326)) Return True } } ; ------------------------------------------------------------------------------------------------------------------- NM_CUSTOMDRAW(H, L) { ; Return values: 0x00 (CDRF_DODEFAULT), 0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW) Static SizeNMHDR := A_PtrSize * 3 ; Size of NMHDR structure Static SizeNCD := SizeNMHDR + 16 + (A_PtrSize * 5) ; Size of NMCUSTOMDRAW structure Static OffItem := SizeNMHDR + 16 + (A_PtrSize * 2) ; Offset of dwItemSpec (NMCUSTOMDRAW) Static OffItemState := OffItem + A_PtrSize ; Offset of uItemState (NMCUSTOMDRAW) Static OffCT := SizeNCD ; Offset of clrText (NMLVCUSTOMDRAW) Static OffCB := OffCT + 4 ; Offset of clrTextBk (NMLVCUSTOMDRAW) Static OffSubItem := OffCB + 4 ; Offset of iSubItem (NMLVCUSTOMDRAW) ; ---------------------------------------------------------------------------------------------------------------- DrawStage := NumGet(L + SizeNMHDR, 0, "UInt") , Row := NumGet(L + OffItem, "UPtr") + 1 , Col := NumGet(L + OffSubItem, "Int") + 1 , Item := Row - 1 If This.IsStatic Row := This.MapIndexToID(Row) ; CDDS_SUBITEMPREPAINT = 0x030001 -------------------------------------------------------------------------------- If (DrawStage = 0x030001) { UseAltCol := !(Col & 1) && (This.AltCols) , ColColors := This["Cells", Row, Col] , ColB := (ColColors.B <> "") ? ColColors.B : UseAltCol ? This.ACB : This.RowB , ColT := (ColColors.T <> "") ? ColColors.T : UseAltCol ? This.ACT : This.RowT , NumPut(ColT, L + OffCT, "UInt"), NumPut(ColB, L + OffCB, "UInt") Return (!This.AltCols && !This.HasKey(Row) && (Col > This["Cells", Row].MaxIndex())) ? 0x00 : 0x20 } ; CDDS_ITEMPREPAINT = 0x010001 ----------------------------------------------------------------------------------- If (DrawStage = 0x010001) { ; LVM_GETITEMSTATE = 0x102C, LVIS_SELECTED = 0x0002 If (This.SelColors) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") { ; Remove the CDIS_SELECTED (0x0001) and CDIS_FOCUS (0x0010) states from uItemState and set the colors. NumPut(NumGet(L + OffItemState, "UInt") & ~0x0011, L + OffItemState, "UInt") If (This.SELB <> "") NumPut(This.SELB, L + OffCB, "UInt") If (This.SELT <> "") NumPut(This.SELT, L + OffCT, "UInt") Return 0x02 ; CDRF_NEWFONT } UseAltRow := (Item & 1) && (This.AltRows) , RowColors := This["Rows", Row] , This.RowB := RowColors ? RowColors.B : UseAltRow ? This.ARB : This.BkClr , This.RowT := RowColors ? RowColors.T : UseAltRow ? This.ART : This.TxClr If (This.AltCols || This["Cells"].HasKey(Row)) Return 0x20 NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt") Return 0x00 } ; CDDS_PREPAINT = 0x000001 --------------------------------------------------------------------------------------- Return (DrawStage = 0x000001) ? 0x20 : 0x00 } ; ------------------------------------------------------------------------------------------------------------------- MapIndexToID(Row) { ; provides the unique internal ID of the given row number SendMessage, 0x10B4, % (Row - 1), 0, , % "ahk_id " . This.HWND ; LVM_MAPINDEXTOID Return ErrorLevel } ; ------------------------------------------------------------------------------------------------------------------- BGR(Color, Default := "") { ; converts colors to BGR Static Integer := "Integer" ; v2 ; HTML Colors (BGR) Static HTML := {AQUA: 0xFFFF00, BLACK: 0x000000, BLUE: 0xFF0000, FUCHSIA: 0xFF00FF, GRAY: 0x808080, GREEN: 0x008000 , LIME: 0x00FF00, MAROON: 0x000080, NAVY: 0x800000, OLIVE: 0x008080, PURPLE: 0x800080, RED: 0x0000FF , SILVER: 0xC0C0C0, TEAL: 0x808000, WHITE: 0xFFFFFF, YELLOW: 0x00FFFF} If Color Is Integer Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16) Return (HTML.HasKey(Color) ? HTML[Color] : Default) } }使用范例：1、首先设置一个实例，如 MyListColor:= New LV_Colors(stocklistviewID)? ;注，这里填写的listview的hwnd。2、然后可以在其他位置设置，如：MyListColor.Cell("1","8", "0xff0000","0x00ffff") ;1为行，8为列，第一个颜色为背景颜色，第二个颜色为文字颜色。3、还可以用：MyListColor.Row("1", "0xff0000","0x00ffff") ;1为行，第一个颜色为背景颜色，第二个颜色为文字颜色。??
/* ********************************** 以下为LISTVIEW编辑类控件 ********************************** */ ; ================================================================================================================================== ; Namespace: LV_InCellEdit ; Function: Support for in-cell ListView editing. ; Tested with: AHK 1.1.24.00 (1.1.20+ required) ; Tested on: Win 10 Pro (x64) ; Change History: 1.3.00.00/2016-07-21/just me - Code revision + new options. ; 1.2.02.00/2015-12-14/just me - Bug fix and support for centered columns. ; 1.2.01.00/2015-09-08/just me - Added EditUserFunc option. ; 1.2.00.00/2015-03-29/just me - New version based on AHK 1.1.20+ features. ; 1.1.04.00/2014-03-22/just me - Added method EditCell ; 1.1.03.00/2012-05-05/just me - Added back option BlankSubItem for method Attach ; 1.1.02.00/2012-05-01/just me - Added method SetColumns ; 1.1.01.00/2012-03-18/just me ; ================================================================================================================================== ; CLASS LV_InCellEdit ; ; Unlike other in-cell editing scripts, this class is using the ListViews built-in edit control. ; Advantage: ; You don't have to care about the font and the GUI, and most of the job can be done by handling common ListView ; notifications. ; Disadvantage: ; I've still found no way to prevent the ListView from blanking out the first subitem of the row while editing another ; subitem. The only known workaround is to add a hidden first column. ; ; The class provides methods to restrict editing to certain columns, to directly start editing of a specified cell, and to ; deactivate/activate the built-in message handler for WM_NOTIFY messages (see below). ; ; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is created. ; As long as the message handler is activated a double-click on any cell will show an Edit control within this cell allowing to ; edit the current content. The default behavior for editing the first column by two subsequent single clicks is disabled. ; You have to press "Esc" to cancel editing, otherwise the content of the Edit will be stored in the current cell. ; ListViews must have the -ReadOnly option to be editable. ; ; While editing, "Esc", "Tab", "Shift+Tab", "Down", and "Up" keys are registered as hotkeys. "Esc" will cancel editing without ; changing the value of the current cell. All other hotkeys will store the content of the edit in the current cell and continue ; editing for the next (Tab), previous (Shift+Tab), upper (Up), or lower (Down) cell. You cannot use the keys for other purposes ; while editing. ; ; All changes are stored in MyInstance.Changed. You may track the changes by triggering (A_GuiEvent == "F") in the ListView's ; g-Label and checking MyInstance["Changed"] as shown in the sample scipt. If "True", MyInstance.Changed contains an array of ; objects with keys "Row" (row number), "Col" (column number), and "Txt" (new content). ; Changed may be deleted by the script whenever it is needed. ; ; If you want to temporarily disable in-cell editing call MyInstance.OnMessage(False). To enable it again, call ; MyInstance.OnMessage(). ; ; To avoid the loss of Gui events and messages the message handler might need to be 'critical'. This can be achieved by setting ; the instance property 'Critical' to the required value (e.g. MyInstance.Critical := 100). ; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become unresponsive under ; certain circumstances if Critical is set and the ListView has a g-label. ;类LV_InCellEdit ;与其他单元内编辑脚本不同，这个类使用的是ListViews内置的编辑控件。 ;优势: ;你不需要关心字体和GUI，大部分工作可以通过处理common ListView来完成 ;通知。 ;劣势: ;我仍然发现没有办法防止ListView从空白的第一个子项的行，而编辑另一个 ;子项。 ;已知的唯一解决方案是添加一个隐藏的第一列。 ;类提供了一些方法，以限制对某些列的编辑，直接开始编辑指定的单元格，以及 ;取消激活/激活WM_NOTIFY消息的内置消息处理程序(见下文)。 ;;WM_NOTIFY消息的消息处理程序将在创建新实例时为指定的ListView激活。 ;只要消息处理程序被激活，双击任何单元格都会显示该单元格内的编辑控件 ;编辑当前内容。禁用后续两次单击编辑第一列的默认行为。 ;您必须按“Esc”来取消编辑，否则编辑的内容将存储在当前单元格中。 ;ListViews必须具有-ReadOnly选项才能编辑。 ;;编辑时，“Esc”、“Tab”、“Shift+Tab”、“Down”和“Up”键注册为热键。“Esc”将取消编辑 ;更改当前单元格的值。所有其他热键将在当前单元格中存储编辑的内容并继续 ;编辑下一个(标签)，上一个(Shift+标签)，上(上)，或下(下)单元格。您不能将密钥用于其他目的;当编辑。 ;;所有更改都存储在MyInstance.Changed中。你可以通过在ListView中触发(A_GuiEvent == "F")来跟踪变化 ;g-Label并检查MyInstance["Changed"]，如示例脚本所示。如果“True”,MyInstance。changes包含一个数组 ;对象的键“Row”(行号)、“Col”(列号)和“Txt”(新内容)。;更改后的可以在需要时被脚本删除。 ;;如果您想临时禁用单元内编辑，请调用MyInstance.OnMessage(False)。要再次启用它，请调用 ;MyInstance.OnMessage()。 ;;为了避免Gui事件和消息的丢失，消息处理程序可能需要是“关键的”。这可以通过设置来实现 ;实例属性“Critical”到所需的值(例如MyInstance。关键:= 100)。 ;新实例默认为'Critical, Off'。虽然有时需要，ListViews或整个Gui可能会变得无响应;在某些情况下，如果设置了Critical并且ListView有g-label。 ; ================================================================================================================================== Class LV_InCellEdit { ; =============================================================================================================================== ; Constructor Creates a new LV_InCellEdit instance for the specified ListView. ; Parameters: HWND - The ListView's HWND. ; Optional ------------------------------------------------------------------------------------------------------ ; BlankSubItem - Blank out subitems text while editing. ; Values: True / False ; Default: False ; ScrollToLeft - Per default, edited columns are scrolled only until they are fully visible. ; Set this parameter to True to scroll the columns to the left edge of the ListView. ; Values: True / False ; Default: False (use default scrolling). ; UseColumnWidth - Per default, the width of the edit control is determined by the width of its text. ; Set this parameter to true to let the edit fill the whole column. ; Values: True / False ; Default: False (use default scrolling). ; EditUserFunc - The name of a user-defined funtion to be called from ; LVN_BEGINEDITLABEL and LVN_ENDEDITLABEL. ; The function must accept at least 6 Parameters: ; State - The state of the edit operation: BEGIN / END ; HLV - The handle to the ListView. ; HED - The handle to the edit control. ; Row - The row number of the edited item. ; Col - The column number of the edited item. ; Text - The edited item's text before / after editing. ; To avoid the loss of messages the function should return as soon as possible. ; Note: The BlankSubItem, ScrollToLeft, and UseColumnWidth properties may be changed dynamically after the instance ; has been created. ; =============================================================================================================================== __New(HWND, BlankSubItem := False, ScrollToLeft := False, UseColumnWidth := False, EditUserFunc := "") { If (This.Base.Base.__Class) ; do not instantiate instances Return False If LV_InCellEdit.Attached[HWND] ; HWND is already attached Return False If !DllCall("IsWindow", "Ptr", HWND) ; invalid HWND Return False VarSetCapacity(Class, 512, 0) DllCall("GetClassName", "Ptr", HWND, "Str", Class, "Int", 256) If (Class <> "SysListView32") ; HWND doesn't belong to a ListView Return False If (EditUserFunc <> "") && (Func(EditUserFunc).MaxParams < 6) Return False ; ---------------------------------------------------------------------------------------------------------------------------- ControlGet, Styles, Style, , , ahk_id %HWND% If !(Styles & 0x0200) ; LVS_EDITLABELS GuiControl, +0x0200, %HWND% This.Styles := Styles ; Set LVS_EX_DOUBLEBUFFER (0x010000) style to avoid drawing issues. DllCall("SendMessage", "Ptr", HWND, "UInt", 0x1036, "Ptr", 0x010000, "Ptr", 0x010000) ; LVM_SETEXTENDEDLISTVIEWSTYLE This.HWND := HWND This.HEDT := 0 This.HHDR := DllCall("SendMessage", "Ptr", HWND, "UInt", 0x101F, "Ptr", 0, "Ptr", 0, "UPtr") ; LVM_GETHEADER This.Item := -1 This.Subitem := -1 This.ItemText := "" This.MaxItem := 0 This.MaxSubitem := 0 This.Cancelled := False This.Next := False This.BlankSubitem := !!BlankSubItem This.ScrollToLeft := !!ScrollToLeft This.UseColumnWidth := !!UseColumnWidth This.Critical := "Off" This.Col1W := 0 This.MinW := 0 This.ExtW := 0 If (EditUserFunc <> "") This.EditUserFunc := Func(EditUserFunc) This.OnMessage() LV_InCellEdit.Attached[HWND] := True } ; =============================================================================================================================== ; Destructor ; =============================================================================================================================== __Delete() { LV_InCellEdit.Attached.Delete(This.HWND) If !(This.Styles & 0x0200) GuiControl, -0x0200, % This.HWND This.OnMessage(False) } ; =============================================================================================================================== ; EditCell Edit the specified cell, if possible. ; Parameters: Row - 1-based row number ; Col - 1-based column number ; Default: 0 - edit the first editable column ; Return values: True on success; otherwise False ; =============================================================================================================================== EditCell(Row, Col := 0) { If !(H := This.HWND) Return False Rows := DllCall("SendMessage", "Ptr", H, "UInt", 0x1004, "Ptr", 0, "Ptr", 0, "Int") ; LVM_GETITEMCOUNT If (Row < 1) || (Row > Rows) Return False This.MaxItem := Rows - 1 Cols := DllCall("SendMessage", "Ptr", This.HHDR, "UInt", 0x1200, "Ptr", 0, "Ptr", 0, "Int") ; HDM_GETITEMCOUNT This.MaxSubitem := Cols - 1 If (Col = 0) If This["Columns"] Col := This.Columns.MinIndex() + 1 Else Loop, %Cols% Col := A_Index Until (DllCall("SendMessage", "Ptr", H, "UInt", 0x101D, "Ptr", Col - 1, "Ptr", 0, "Int") > 0) ; LVM_GETCOLUMNWIDTH If (Col < 1) || (Col > Cols) Return False If (This["Columns"]) && (!This.Columns[Col - 1]) Return False If !(DllCall("SendMessage", "Ptr", H, "UInt", 0x101D, "Ptr", Col - 1, "Ptr", 0, "Int") > 0) Return False This.DoubleClick(--Row, --Col) Return True } ; =============================================================================================================================== ; SetColumns Sets the columns you want to edit ; Parameters: ColNumbers* - zero or more numbers of columns which shall be editable. If entirely omitted, ; the ListView will be reset to enable editing of all columns. ; Return values: True on success; otherwise False ; Note: All passed editable columns must be visible! ; =============================================================================================================================== SetColumns(ColNumbers*) { If !(H := This.HWND) Return False This.Delete("Columns") If (ColNumbers.MinIndex() = "") Return True ColCount := DllCall("SendMessage", "Ptr", This.HHDR, "UInt", 0x1200, "Ptr", 0, "Ptr", 0, "Int") ; HDM_GETITEMCOUNT Cols := [] For Each, Col In ColNumbers { If Col Is Not Integer Return False If (Col < 1) || (Col > ColCount) Return False If !(DllCall("SendMessage", "Ptr", H, "UInt", 0x101D, "Ptr", Col - 1, "Ptr", 0, "Int") > 0) ; LVM_GETCOLUMNWIDTH Return False Cols[Col - 1] := True } This["Columns"] := Cols Return True } ; =============================================================================================================================== ; OnMessage Activate / deactivate the message handler for WM_NOTIFY messages for this ListView ; Parameters: Apply - True / False ; Default: True ; Return Value: Always True ; =============================================================================================================================== OnMessage(Apply := True) { If !This.HWND Return False If (Apply) && !This["NotifyFunc"] { This.NotifyFunc := ObjBindMethod(This, "On_WM_NOTIFY") OnMessage(0x004E, This.NotifyFunc, -1) ; add the WM_NOTIFY message handler } Else If !(Apply) && This["NotifyFunc"] { OnMessage(0x004E, This.NotifyFunc, 0) ; remove the WM_NOTIFY message handler This.NotifyFunc := "" } WinSet, Redraw, , % "ahk_id " . This.HWND Return True } ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; PRIVATE PROPERTIES AND METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Static Attached := {} Static OSVersion := DllCall("GetVersion", "UChar") ; ------------------------------------------------------------------------------------------------------------------------------- ; WM_COMMAND message handler for edit notifications ; ------------------------------------------------------------------------------------------------------------------------------- On_WM_COMMAND(W, L, M, H) { ; LVM_GETSTRINGWIDTHW = 0x1057, LVM_GETSTRINGWIDTHA = 0x1011 Critical, % This.Critical If (L = This.HEDT) { N := (W >> 16) If (N = 0x0400) || (N = 0x0300) || (N = 0x0100) { ; EN_UPDATE | EN_CHANGE | EN_SETFOCUS If (N = 0x0400) && !This.UseColumnWidth { ControlGetText, EditText, , % "ahk_id " . L EW := DllCall("SendMessage", "Ptr", This.HWND, "UInt", A_IsUnicode ? 0x1057 : 0x1011, "Ptr", 0, "Ptr", &EditText, "Int") ; LVM_GETSTRINGWIDTH , EW += This.ExtW If (EW < This.MinW) EW := This.MinW If (This.EX + EW) > This.ClientW EW := This.ClientW - This.EX This.EW := EW } DllCall("SetWindowPos", "Ptr", L, "Ptr", 0, "Int", This.EX, "Int", This.EY, "Int", This.EW, "Int", This.EH, "UInt", 0x04) } } } ; ------------------------------------------------------------------------------------------------------------------------------- ; WM_HOTKEY message handler ; ------------------------------------------------------------------------------------------------------------------------------- On_WM_HOTKEY(W, L, M, H) { ; LVM_CANCELEDITLABEL = 0x10B3, Hotkeys: 0x801B (Esc -> cancel) Critical, % This.Critical If (H = This.HWND) { If (W = 0x801B) { ; Esc This.Cancelled := True , DllCall("PostMessage", "Ptr", H, "UInt", 0x10B3, "Ptr", 0, "Ptr", 0) } Else { This.Next := True , DllCall("SendMessage", "Ptr", H, "UInt", 0x10B3, "Ptr", 0, "Ptr", 0) , This.Next := True , This.NextSubitem(W) } Return False } } ; ------------------------------------------------------------------------------------------------------------------------------- ; WM_NOTIFY message handler for ListView notifications ; ------------------------------------------------------------------------------------------------------------------------------- On_WM_NOTIFY(W, L) { Critical, % This.Critical If (H := NumGet(L + 0, 0, "UPtr") = This.HWND) { M := NumGet(L + (A_PtrSize * 2), 0, "Int") ; BeginLabelEdit ------------------------------------------------------- If (M = -175) || (M = -105) ; LVN_BEGINLABELEDITW || LVN_BEGINLABELEDITA Return This.LVN_BEGINLABELEDIT(L) ; EndLabelEdit --------------------------------------------------------- If (M = -176) || (M = -106) ; LVN_ENDLABELEDITW || LVN_ENDLABELEDITA Return This.LVN_ENDLABELEDIT(L) ; Double click --------------------------------------------------------- If (M = -3) ; NM_DBLCLICK This.NM_DBLCLICK(L) } } ; ------------------------------------------------------------------------------------------------------------------------------- ; LVN_BEGINLABELEDIT notification ; ------------------------------------------------------------------------------------------------------------------------------- LVN_BEGINLABELEDIT(L) { If (This.Item = -1) || (This.Subitem = -1) Return True SetControlDelay, -1 H := This.HWND, Item := This.Item, SubItem := This.Subitem This.HEDT := HEDT := DllCall("SendMessage", "Ptr", H, "UInt", 0x1018, "Ptr", 0, "Ptr", 0, "UPtr") , DllCall("SendMessage", "Ptr", HEDT, "UInt", 0x00D3, "Ptr", 0x01, "Ptr", 0) ; EM_SETMARGINS, EC_LEFTMARGIN , VarSetCapacity(ItemText, 2048, 0) ; text buffer , VarSetCapacity(LVITEM, 40 + (A_PtrSize * 5), 0) ; LVITEM structure , NumPut(Item, LVITEM, 4, "Int"), NumPut(Subitem, LVITEM, 8, "Int") , NumPut(&ItemText, LVITEM, 16 + A_PtrSize, "Ptr") , NumPut(1024 + 1, LVITEM, 16 + (A_PtrSize * 2), "Int") ; pszText, cchTextMax , DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1073 : 0x102D, "Ptr", Item, "Ptr", &LVITEM) ; LVM_GETITEMTEXT , This.ItemText := StrGet(&ItemText) ; Call the user function, if any If (This.EditUserFunc) This.EditUserFunc.Call("BEGIN", H, HEDT, Item + 1, Subitem + 1, This.ItemText) DllCall("SendMessage", "Ptr", This.HEDT, "UInt", 0x000C, "Ptr", 0, "Ptr", &ItemText) ; WM_SETTEXT If (Subitem > 0) && (This.BlankSubitem) { Empty := "" , NumPut(&Empty, LVITEM, 16 + A_PtrSize, "Ptr") ; pszText in LVITEM , NumPut(0, LVITEM, 16 + (A_PtrSize * 2), "Int") ; cchTextMax in LVITEM , DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1074 : 0x102E, "Ptr", Item, "Ptr", &LVITEM) ; LVM_SETITEMTEXT } ; Set the edit's position and size EX := This.CX + This.Indent , EY := This.CY - (This.OSVersion < 6 ? 1 : 0) ; subtract 1 for WinXP If (This.UseColumnWidth) EW := This.CR - EX Else EW := DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1057 : 0x1011, "Ptr", 0, "Ptr", &ItemText, "Int") ; LVM_GETSTRINGWIDTH , EW += This.ExtW , EW := EW < This.MinW ? This.MinW : EW EH := This.CH + (This.OSVersion < 6 ? 3 : 0) ; add 3 for WinXP ; Check the column alignment If (Subitem > 0) { VarSetCapacity(LVCOL, 56, 0) , NumPut(1, LVCOL, "UInt") ; LVCF_FMT , DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x105F : 0x1019, "Ptr", Subitem, "Ptr", &LVCOL) ; LVM_GETCOLUMN If (This.Center := NumGet(LVCOL, 4, "UInt") & 0x0002) ; LVCFMT_CENTER If (This.UseColumnWidth) Control, Style, +0x0001, , % "ahk_id " . This.HEDT Else If (ER := EX + EW) < (CR := This.CX + This.CW) EX += ((CR - ER) // 2) + This.Indent } EW := (EX + EW) > This.ClientW ? This.ClientW - EX : EW This.EX := EX, This.EY := EY, This.EW := EW, This.EH := EH ; Register WM_COMMAND handler This.CommandFunc := ObjBindMethod(This, "On_WM_COMMAND") , OnMessage(0x0111, This.CommandFunc) ; Register hotkeys If !(This.Next) This.RegisterHotkeys() This.Cancelled := False This.Next := False Return False } ; ------------------------------------------------------------------------------------------------------------------------------- ; LVN_ENDLABELEDIT notification ; ------------------------------------------------------------------------------------------------------------------------------- LVN_ENDLABELEDIT(L) { H := This.HWND, Item := This.Item, Subitem := This.Subitem, ItemText := This.ItemText ; Unregister WM_COMMAND handler OnMessage(0x0111, This.CommandFunc, 0) This.CommandFunc := "" ; Unregister hotkeys If !(This.Next) This.RegisterHotkeys(False) If !(This.Cancelled) ControlGetText, ItemText, , % "ahk_id " . This.HEDT If (ItemText <> This.ItemText) { If !(This["Changed"]) This.Changed := [] This.Changed.Push({Row: Item + 1, Col: Subitem + 1, Txt: ItemText}) } ; Restore subitem's text if changed or blanked out If (ItemText <> This.ItemText) || ((Subitem > 0) && (This.BlankSubitem)) { VarSetCapacity(LVITEM, 40 + (A_PtrSize * 5), 0) ; LVITEM structure , NumPut(Item, LVITEM, 4, "Int") , NumPut(Subitem, LVITEM, 8, "Int") , NumPut(&ItemText, LVITEM, 16 + A_PtrSize, "Ptr") ; pszText in LVITEM , DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1074 : 0x102E, "Ptr", Item, "Ptr", &LVITEM) ; LVM_SETITEMTEXT } If !(This.Next) This.Item := This.Subitem := -1 This.Cancelled := False This.Next := False ; Call the user function, if any If (This.EditUserFunc) This.EditUserFunc.Call("END", H, This.HEDT, Item + 1, Subitem + 1, ItemText) Return False } ; ------------------------------------------------------------------------------------------------------------------------------- ; NM_DBLCLICK notification ; ------------------------------------------------------------------------------------------------------------------------------- NM_DBLCLICK(L) { Static CBW := DllCall("GetSystemMetrics", "Int", 49, "Int") H := This.HWND , This.Item := This.Subitem := -1 , Item := NumGet(L + (A_PtrSize * 3), 0, "Int") , Subitem := NumGet(L + (A_PtrSize * 3), 4, "Int") If (This["Columns"]) && (!This["Columns", Subitem]) Return False VarSetCapacity(RC, 16, 0) If (Item >= 0) && (Subitem >= 0) { This.Item := Item, This.Subitem := Subitem If !(This.Next) { Rows := DllCall("SendMessage", "Ptr", H, "UInt", 0x1004, "Ptr", 0, "Ptr", 0, "Int") ; LVM_GETITEMCOUNT , This.MaxItem := Rows - 1 , Cols := DllCall("SendMessage", "Ptr", This.HHDR, "UInt", 0x1200, "Ptr", 0, "Ptr", 0, "Int") ; HDM_GETITEMCOUNT , This.MaxSubitem := Cols - 1 , DllCall("GetClientRect", "Ptr", H, "Ptr", &RC) , This.ClientW := NumGet(RC, 8, "Int") , This.MinW := DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1057 : 0x1011, "Ptr", 0, "Str", "WWW", "Int") ; LVM_GETSTRINGWIDTH , This.ExtW := DllCall("SendMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1057 : 0x1011, "Ptr", 0, "Str", "III", "Int") ; LVM_GETSTRINGWIDTH , This.Col1W := DllCall("SendMessage", "Ptr", H, "UInt", 0x101D, "Ptr", 0, "Ptr", 0, "Int") ; LVM_GETCOLUMNWIDTH , This.Checked := DllCall("SendMessage", "Ptr", H, "UInt", 0x1037, "Ptr", 0, "Ptr", 0, "UInt") & 0x00000004 ; LVM_GETEXTENDEDLISTVIEWSTYLE } Numput(0, RC, "Int") , DllCall("SendMessage", "Ptr", H, "UInt", 0x100E, "Ptr", 0, "Ptr", &RC) ; LVM_GETITEMRECT , CX := NumGet(RC, "Int") , NumPut(Subitem = 0 ? 2 : 1, RC, "Int") , DllCall("SendMessage", "Ptr", H, "UInt", 0x100E, "Ptr", 0, "Ptr", &RC) ; LVM_GETITEMRECT , This.Indent := NumGet(RC, "Int") - CX - ((Subitem > 0) && This.Checked ? CBW : 0) , NumPut(0, RC, "Int") , NumPut(Subitem, RC, 4, "Int") , DllCall("SendMessage", "Ptr", H, "UInt", 0x1038, "Ptr", Item, "Ptr", &RC) ; LVM_GETSUBITEMRECT , CX := NumGet(RC, 0, "Int"), CY := NumGet(RC, 4, "Int") , CR := (Subitem = 0 ? CX + This.Col1W : NumGet(RC, 8, "Int")) , CW := (Subitem = 0 ? This.Col1W : CR - CX), CH := NumGet(RC, 12, "Int") - CY ScrollH := 0 If (CX < 0) || This.ScrollToLeft ScrollH := CX Else If ((CX + CW) > This.ClientW) { ScrollH := CX + CW - This.ClientW If (ScrollH > CX) ScrollH := CX } If (ScrollH) DllCall("SendMessage", "Ptr", H, "UInt", 0x1014, "Ptr", ScrollH, "Ptr", 0) ; LVM_SCROLL This.CX := CX - ScrollH, This.CY := CY, This.CW := CW, This.CH := CH, This.CR := CR - ScrollH DllCall("PostMessage", "Ptr", H, "UInt", A_IsUnicode ? 0x1076 : 0x1017, "Ptr", Item, "Ptr", 0) ; LVM_EDITLABEL } Return False } ; ------------------------------------------------------------------------------------------------------------------------------- ; Next subitem ; ------------------------------------------------------------------------------------------------------------------------------- NextSubitem(K) { ; Hotkeys: 0x8009 (Tab -> right), 0x8409 (Shift+Tab -> left), 0x8028 (Down -> down), 0x8026 (Up -> up) ; Find the next subitem H := This.HWND Item := This.Item Subitem := This.Subitem If (K = 0x8028) || (K = 0x8026) ; down || up Item += (K = 0x8028) ? 1 : -1 Else { ; left || right Next := (K = 0x8409) ? -1 : 1 Loop { Subitem += Next If (This["Columns"]) { If (Subitem < This.Columns.MinIndex()) Subitem := This.Columns.MaxIndex(), Item-- Else If (Subitem > This.Columns.MaxIndex()) Subitem := This.Columns.MinIndex(), Item++ Else While (This["Columns", Subitem] = "") Subitem += Next } Else If (Subitem < 0) SubItem := This.MaxSubitem, Item-- Else If (Subitem > This.MaxSubitem) Subitem := 0, Item++ If (DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x101D, "Ptr", SubItem, "Ptr", 0, "Int") > 0) ; LVM_GETCOLUMNWIDTH Break } } Item := (Item > This.MaxItem) ? 0 : (Item < 0) ? This.MaxItem : Item If (Item <> This.Item) DllCall("SendMessage", "Ptr", H, "UInt", 0x1013, "Ptr", Item, "Ptr", 0) ; LVM_ENSUREVISIBLE This.DoubleClick(Item, Subitem) } ; ------------------------------------------------------------------------------------------------------------------------------- ; Double Click ; ------------------------------------------------------------------------------------------------------------------------------- DoubleClick(Item, Subitem) { If (H := This.HWND) { VarSetCapacity(RC, 16, 0), NumPut(Subitem, RC, 4, "Int") , DllCall("SendMessage", "Ptr", H, "UInt", 0x1038, "Ptr", Item, "Ptr", &RC) ; LVM_GETSUBITEMRECT , Point := NumGet(RC, 0, "UShort") | (NumGet(RC, 4, "UShort") << 16) , DllCall("SendMessage", "Ptr", H, "UInt", 0x0201, "Ptr", 0, "Ptr", POINT) ; WM_LBUTTONDOWN , DllCall("SendMessage", "Ptr", H, "UInt", 0x0202, "Ptr", 0, "Ptr", POINT) ; WM_LBUTTONUP , DllCall("SendMessage", "Ptr", H, "UInt", 0x0203, "Ptr", 0, "Ptr", POINT) ; WM_LBUTTONDBLCLK , DllCall("SendMessage", "Ptr", H, "UInt", 0x0202, "Ptr", 0, "Ptr", POINT) ; WM_LBUTTONUP } } ; ------------------------------------------------------------------------------------------------------------------------------- ; Register/UnRegister hotkeys ; ------------------------------------------------------------------------------------------------------------------------------- RegisterHotkeys(Register = True) { ; WM_HOTKEY := 0x0312, MOD_SHIFT := 0x0004 ; Hotkeys: 0x801B (Esc -> cancel, 0x8009 (Tab -> right), 0x8409 (Shift+Tab -> left) ; 0x8028 (Down -> down), 0x8026 (Up -> up) H := This.HWND If (Register) { ; Register DllCall("RegisterHotKey", "Ptr", H, "Int", 0x801B, "UInt", 0, "UInt", 0x1B) , DllCall("RegisterHotKey", "Ptr", H, "Int", 0x8009, "UInt", 0, "UInt", 0x09) , DllCall("RegisterHotKey", "Ptr", H, "Int", 0x8409, "UInt", 4, "UInt", 0x09) , DllCall("RegisterHotKey", "Ptr", H, "Int", 0x8028, "UInt", 0, "UInt", 0x28) , DllCall("RegisterHotKey", "Ptr", H, "Int", 0x8026, "UInt", 0, "UInt", 0x26) , This.HotkeyFunc := ObjBindMethod(This, "On_WM_HOTKEY") , OnMessage(0x0312, This.HotkeyFunc) ; WM_HOTKEY } Else { ; Unregister DllCall("UnregisterHotKey", "Ptr", H, "Int", 0x801B) , DllCall("UnregisterHotKey", "Ptr", H, "Int", 0x8009) , DllCall("UnregisterHotKey", "Ptr", H, "Int", 0x8409) , DllCall("UnregisterHotKey", "Ptr", H, "Int", 0x8028) , DllCall("UnregisterHotKey", "Ptr", H, "Int", 0x8026) , OnMessage(0x0312, This.HotkeyFunc, 0) ; WM_HOTKEY , This.HotkeyFunc := "" } } } 代码使用就是：ICELV2 := New LV_InCellEdit(listviewID, True)
1、在使用listview内置函数之前，最好用一句： gui, listview, listviewname （listviewname表示v变量名称），否则可能出现内置函数无效。2、LV_ModifyCol(列号, “width center”) 表示调节列号的列宽并且数字居中3、ICELV2 := New LV_InCellEdit(listviewID, True) 这行代码主要是针对class函数的操作编辑时需要4、gui, GUI1:default ;如果在listview上右键出现菜单的时候，最好前面添加这句。否则可能会出现菜单无法弹出的情况。
改代码对于不调整x的时候还是很有用，对于调整x的会出现bug。; ================================================================================= ; Function: AutoXYWH ; Move and resize control automatically when GUI resizes. ; Parameters: ; DimSize - Can be one or more of x/y/w/h optional followed by a fraction ; add a '*' to DimSize to 'MoveDraw' the controls rather then just 'Move', this is recommended for Groupboxes ; cList - variadic list of ControlIDs ; ControlID can be a control HWND, associated variable name, ClassNN or displayed text. ; The later (displayed text) is possible but not recommend since not very reliable ; Examples: ; AutoXYWH("xy", "Btn1", "Btn2") ; AutoXYWH("w0.5 h 0.75", hEdit, "displayed text", "vLabel", "Button1") ; AutoXYWH("*w0.5 h 0.75", hGroupbox1, "GrbChoices") ; --------------------------------------------------------------------------------- ; Version: 2015-5-29 / Added 'reset' option (by tmplinshi) ; 2014-7-03 / toralf ; 2014-1-2 / tmplinshi ; requires AHK version : 1.1.13.01+ ; ================================================================================= AutoXYWH(DimSize, cList*){ ; http://ahkscript.org/boards/viewtopic.php?t=1079 static cInfo := {} If (DimSize = "reset") Return cInfo := {} For i, ctrl in cList { ctrlID := A_Gui ":" ctrl If ( cInfo[ctrlID].x = "" ){ GuiControlGet, i, %A_Gui%:Pos, %ctrl% MMD := InStr(DimSize, "*") ? "MoveDraw" : "Move" fx := fy := fw := fh := 0 For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]"))) If !RegExMatch(DimSize, "i)" dim "\s*\K[\d.-]+", f%dim%) f%dim% := 1 cInfo[ctrlID] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:a , m:MMD} }Else If ( cInfo[ctrlID].a.1) { dgx := dgw := A_GuiWidth - cInfo[ctrlID].gw , dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh For i, dim in cInfo[ctrlID]["a"] Options .= dim (dg%dim% * cInfo[ctrlID]["f" dim] + cInfo[ctrlID][dim]) A_Space GuiControl, % A_Gui ":" cInfo[ctrlID].m , % ctrl, % Options } } }?在guisize中引用的时候：;其中 e1 或者 b1表示GUI控件的v变量名称；"wh"表示wh随着gui自动变化，xy不动。"y"表示仅y随着guisize变化而变化，其他的不变化。 AutoXYWH("wh", "e1") AutoXYWH("y", "b1")
ZigZag 是用在图像压缩中的一个算法，对于任意二维数组 ar[x_max][y_max] 按照下面的顺序遍历?直接放代码，思路就是凑一个最大范围的三角形，代码可以更精简。/*ZigZag遍历任意二维数组 */ global ar:=object() a=5 ;行 b=7 ;列 c :=a+b-1 ;对角线数量 d:=a>b ? a : b make_array(a,b) loop, % c { sn2:=a_index loop, % sn2 { if (mod(sn2,2)=0) { tmp.=ar[a_index, sn2+1-a_index] ? ar[a_index, sn2+1-a_index] . "|" : "" } else { tmp.=ar[sn2+1-a_index, a_index] ? ar[sn2+1-a_index, a_index] . "|" : "" } } } msgbox, % tmp return /*生成一个二维数组 */ make_array(x,y) { loop, % x { aa:=A_Index loop, % y { ar[aa,A_index]:=a_index+(aa-1)*y } } return, % ar }