├── LICENSE ├── README.md └── src ├── default.aproj ├── lib └── config.aardio ├── main.aardio └── res └── setodo_logo.ico /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 bituplink 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # setodo 2 | 这是一个简单的每日待办事项管理软件,轻巧绿色,满足基本的操作需求,基于aardio开发 3 | 4 | ##### 更新记录: 5 | 1. 201900725 setodo v0.99版本发布 关机自动保存数据,窗口置顶和开机启动功能移到功能栏,点击勾选,支持用户自定义拖动窗口大小并保存记录 6 | 2. 20190709 setodo v0.98版本发布 增加右键设置待办事项优先级三色显示,增加右键转移单个待办和批量转移所有待办功能 7 | 3. 20190516 setodo v0.9版本发布 增加窗口置顶功能,增加日历控件,可以灵活选择时间记录待办事项 8 | 9 | ![snapshot](https://imgsrc.io/images/2019/07/25/Snipaste_2019-07-25_10-43-34.jpg) 10 | 11 | ##### 程序优点: 12 | 1. win平台全支持,无需其他额外的组件支持 13 | 2. 小巧,单文件,绿色,解压即用,只有500K,拥有UI界面,交互简单便捷 14 | 3. 支持打开历史待办记录 15 | 4. 每日一个记录文件保存待办事项和已完成事项 16 | 5. 支持右键删除待办和已完成事项 17 | 6. 支持windows窗口上左右三个方向贴边停靠吸附 18 | 7. 支持托盘图标,最小化到托盘,双击托盘显示 19 | 8. 支持回车输入待办事项内容 20 | 9. 待办事项内容支持鼠标双击修改 21 | 10. 支持窗口置顶,支持日历控件 22 | 11. 支持设置待办事项优先级颜色显示 23 | 12. 支持单个待办事项和全部待办的转移操作 24 | 13. 支持开机启动,窗口置顶在功能栏勾选设置 25 | 14. 用户自定义拖动设置窗体的大小尺寸并保存配置 26 | 15. 直接关机依然会保存数据,不会丢失 27 | 28 | ##### 获得exe执行程序 29 | * github releases下载: [releases](https://github.com/bituplink/setodo/releases) 30 | * 访问官网下载: [官网](http://www.bituplink.com/windows_setodo.html) 31 | * 访问百度云盘下载: [百度网盘](https://pan.baidu.com/s/1Wb83kIg-KziE_1eKxP5WCg) 密码: fu7t 32 | * 下载源码,并使用[aardio IDE](http://ide.update.aardio.com/releases/aardio.7z)加载项目文件(src目录下),运行并发布后,在publish目录下获得 33 | 34 | ### 运行说明 35 | * 下载exe文件,放在任意目录下,双击exe打开并执行程序 36 | * 在输入框输入待办事项内容,点击添加,或者键盘回车输入 37 | * 待办列表项勾选可以将内容标记为已完成事项,并将内容转移到下方的列表显示 38 | * 已完成列表项勾选可以将内容重新标记为待办事项,并将内容转移到上方的列表显示 39 | * 对于需要删除的内容,右键删除 40 | * 点击菜单栏文件->打开文件选择历史记录文件,可以加载显示,历史记录文件按照时间命名,不需要的可以手动删除文件 41 | * 点击日历控件可以选择时间,来回点击窗口置顶,可以切换窗口置顶状态 42 | * 右键单个待办选择优先级或转移操作 43 | * 点击日历控件可以选择时间,执行批量全部转移待办到指定日期 44 | 45 | 46 | ### 建议和改进 47 | 1. github提issue 48 | 2. 发送邮件到 bituplink@foxmail.com 49 | 50 | 51 | ### 捐助 52 | 如果觉得程序对你有帮助或者想要支持我(毕竟写程序和调试代码也是很费时费力的,哎呦,我的酸脖子和鼠标手呀 ┬_┬),可以小额赞助下 53 | 54 | 方式一: 支付宝捐助 55 | * ![alipay](http://www.bituplink.com/assets/img/alipay.png) 56 | 57 | 方式二: 微信捐助 58 | * ![wxpay](http://www.bituplink.com/assets/img/wxpay.png) 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/default.aproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/lib/config.aardio: -------------------------------------------------------------------------------- 1 | //config 配置文件 2 | import fsys.config; 3 | config = ..fsys.config("/config/"); 4 | 5 | /** 6 | config = ..fsys.config( 7 | ..fsys.joinpath( ..fsys.getSpecial( 0x1c /*_CSIDL_LOCAL_APPDATA*/ ),"setodo" ) 8 | ); 9 | **/ 10 | 11 | //不需要序列化的配置名字前请添加下划线 12 | namespace config { 13 | __appName = "setodo"; 14 | __appVersion = "0.99"; 15 | __appDescription = "setodo程序"; 16 | __website = "http://www.bituplink.com/"; 17 | } 18 | 19 | /**intellisense(config) 20 | __appName = 应用程序名 21 | __appVersion = 应用程序内部版本号 22 | __appDescription = 程序说明 23 | __website = 官方网站 24 | 25 | saveAll() = 写入所有配置到文件 26 | mainForm.load() = 从配置文件(文件名"default")载入\n加载成功返回对象,加载失败返回null空值\n!fsys_table. 27 | mainForm.save() = 存储到配置文件(文件名"default") 28 | mainForm.mixin = @.mixin(\n 键名 = 值__;\n 键名 = 值;\n);//该数会自动调用save函数保存配置到文件 29 | mainForm.控件名称 = 控件默认值\n调用save()函数同步控件当前值 30 | mainForm.属性名 = 自配置文件(文件名"default")读写属性\n属性值可以是支持序列化的普通变量,支持table对象.\n配置文件在首次使用时自动加载,退出程序时自动保存. 31 | ? = 配置文件名,\n读写配置并序列化为一个表对象,\n表的成员值可以是支持序列化的普通变量,支持table对象\n配置文件在首次使用时自动加载,退出程序时自动保存\n!fsys_table. 32 | end intellisense**/ 33 | -------------------------------------------------------------------------------- /src/main.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import win.ui.menu; 3 | import win.ui.atom; 4 | import win.util.tray; 5 | import winex; 6 | import mouse; 7 | import fsys.table; 8 | import fsys.ini; 9 | import win.ui.tooltip; 10 | import fsys.dlg; 11 | import process; 12 | import console; 13 | import util; 14 | import fsys.lnk; 15 | import win.ui.minmax; 16 | /*DSG{{*/ 17 | mainForm = win.form(text="日常轻单 v0.99 by bituplink.com";right=404;bottom=522;composited=1;max=false) 18 | mainForm.add( 19 | btnAddTodo={cls="button";text="添加";left=344;top=16;right=396;bottom=42;dr=1;dt=1;z=1}; 20 | btnTodoTrans={cls="button";text="待办转移至";left=163;top=48;right=243;bottom=74;dl=1;dt=1;z=9}; 21 | checklistDone={cls="checklist";left=10;top=324;right=394;bottom=507;ah=1;aw=1;dl=1;edge=1;font=LOGFONT(strike=1;h=-14);items={};z=4}; 22 | checklistTodo={cls="checklist";left=10;top=83;right=394;bottom=278;ah=1;aw=1;dl=1;dt=1;edge=1;font=LOGFONT(h=-14);items={};z=3}; 23 | datetimepick={cls="datetimepick";left=71;top=48;right=157;bottom=74;dl=1;dt=1;edge=1;font=LOGFONT(h=-13);z=7}; 24 | datetimepickTrans={cls="datetimepick";left=248;top=48;right=336;bottom=74;dl=1;dt=1;edge=1;font=LOGFONT(h=-13);z=8}; 25 | editAddTodo={cls="edit";left=10;top=16;right=336;bottom=42;aw=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(h=-14);z=2}; 26 | static1={cls="static";text="待办列表";left=10;top=56;right=72;bottom=69;dl=1;dt=1;notify=1;transparent=1;z=6}; 27 | static2={cls="static";text="完成列表";left=10;top=298;right=64;bottom=319;dl=1;transparent=1;z=5} 28 | ) 29 | /*}}*/ 30 | 31 | // debug 32 | // console.varDump() 33 | 34 | 35 | // 设置框体最小和最大的宽度和高度 36 | 37 | win.ui.minmax(mainForm,420,560) 38 | 39 | 40 | // 单实例运行功能 41 | var atom,hwndConflict = mainForm.atom("21FD3719-8C39-4D33-8DC2-9B0103A4DE69"); 42 | if(!atom){ 43 | /*为窗口设置原子值可以避免一个程序重复运行多个实例*/ 44 | win.quitMessage();//程序退出 45 | return; 46 | }; 47 | 48 | 49 | // 在窗口上创建tooltip对象, mainForm是界面主窗口的名称,可以改变,但是需要保持一致 50 | var toolTipObj = win.ui.tooltip(mainForm); 51 | 52 | // 给控件添加悬停提示, btnAddFile是之前创建的按键控件的名称, 0x10/*_TTF_SUBCLASS*/参数表示默认提示 53 | toolTipObj.addTool(mainForm.btnTodoTrans, "默认转移当前所有待办项,也可以鼠标右键转移每一个待办项", 0x10/*_TTF_SUBCLASS*/ ); 54 | toolTipObj.addTool(mainForm.datetimepickTrans, "默认转移到明天,也可以自选任意日期", 0x10/*_TTF_SUBCLASS*/ ); 55 | 56 | 57 | // 增加双击修改内容的样式能力 58 | mainForm.checklistTodo.modifyStyle(,0x200/*_LVS_EDITLABELS*/) 59 | 60 | 61 | // 设置全局文件所在路径 62 | exe_path = io._exepath 63 | 64 | 65 | function loadIniFile(){ 66 | 67 | setting = fsys.table("/config/setting.table") 68 | setting.load(); //从文件载入表 69 | 70 | // 加载设置文件,更新界面的设置状态 71 | if(setting.isTopWindow == true){ 72 | win.setTopmost(mainForm.hwnd,true) 73 | mainForm.cfgmenu.check(2) 74 | } 75 | 76 | if(setting.isStartup == true){ 77 | mainForm.cfgmenu.check(1) 78 | } 79 | 80 | mainForm.width = setting.mf_width 81 | mainForm.height = setting.mf_height 82 | 83 | // 加载数据前清空旧数据 84 | mainForm.checklistTodo.clear(); 85 | mainForm.checklistDone.clear(); 86 | todoLevelTable = {}; 87 | 88 | var dayTime = mainForm.datetimepick.time; 89 | 90 | // 默认设置转移的日期为下一天 91 | var dayOriginTime = mainForm.datetimepick.time 92 | var defaultNextDayTime = dayOriginTime.addday(1); 93 | mainForm.datetimepickTrans.time = defaultNextDayTime; 94 | 95 | dayTime.format="%Y%m%d"; 96 | var dayString = tostring(dayTime) 97 | 98 | // 当前日期对应的存储文件路径 99 | iniData = fsys.ini("\data\setodo_" + dayString + ".ini"); 100 | 101 | var iniDataList = iniData.readSectionNames(); 102 | 103 | mainForm.checklistTodo.clrText=0x000000 104 | mainForm.checklistTodo.redraw() 105 | 106 | // 有数据则加载到应用 107 | if(iniDataList!=null){ 108 | 109 | sectionTodo = iniData.getSection("ToDoList"); 110 | for( k,v in sectionTodo){ 111 | mainForm.checklistTodo.addItem(v, tonumber(k)); 112 | changeTodoLevel(tonumber(k), 0) 113 | } 114 | 115 | sectionDone = iniData.getSection("DoneList"); 116 | for( k,v in sectionDone){ 117 | mainForm.checklistDone.addItem(v, tonumber(k)); 118 | mainForm.checklistDone.setChecked(k); 119 | } 120 | 121 | sectionToDoLevel = iniData.getSection("ToDoLevelList"); 122 | for(k,v in sectionToDoLevel){ 123 | changeTodoLevel(tonumber(k), v) 124 | } 125 | } 126 | } 127 | 128 | 129 | /*主要逻辑代码{{*/ 130 | // 添加待办记录内容到列表的功能 131 | function addCntToList(){ 132 | // 字符串长度为零,没有输入,不处理 133 | if(!(#mainForm.editAddTodo.text)){ 134 | return ; 135 | } 136 | 137 | // 将文本框内容增加到待办列表 138 | addItemIndex = mainForm.checklistTodo.addItem(mainForm.editAddTodo.text); 139 | changeTodoLevel(addItemIndex, 0) 140 | 141 | // 输入文本框清空,方便用户下次重新输入 142 | mainForm.editAddTodo.text = ""; 143 | } 144 | 145 | 146 | // 将输入文本框的内容放置到待办事项列表中,增加待办事项 147 | mainForm.btnAddTodo.oncommand = function(id,event){ 148 | addCntToList(); 149 | } 150 | 151 | 152 | // 消息回调不起作用,是因为回车键是对话框的快捷键之一,可以重写mainForm.isDialogMessage函数 153 | mainForm.isDialogMessage = function(hwnd,msg){ 154 | if ( (msg.message >= 0x100/*_WM_KEYFIRST*/) && (msg.message <= 0x108/*_WM_KEYLAST*/) ) { 155 | if(msg.wParam==0xD/*_VK_ENTER*/){ 156 | return false //使回车键不是对话框快捷键 157 | } 158 | } 159 | return win.isDialogMessage(hwnd,msg); 160 | } 161 | 162 | 163 | // 回车事件处理,调用增加输入内容到待办列表中 164 | mainForm.editAddTodo.wndproc = function(hwnd,message,wparam,lparam){ 165 | select(message) {//判断消息类型 166 | case 0x100/*_WM_KEYDOWN*/ { 167 | if(wparam == 0xD/*_VK_RETURN*/){ 168 | addCntToList(); 169 | } 170 | } 171 | } 172 | } 173 | 174 | 175 | // 单个待办事项转移函数 176 | function transTodo(itemIndex, cntStr){ 177 | 178 | var selectDayTime = mainForm.datetimepickTrans.time; 179 | 180 | selectDayTime.format="%Y%m%d"; 181 | var selectDayString = tostring(selectDayTime) 182 | 183 | // 当前日期对应的存储文件路径 184 | var selectIniData = fsys.ini("\data\setodo_" + selectDayString + ".ini"); 185 | 186 | var todoList = selectIniData.readKeys("ToDoList"); 187 | 188 | var transSeq = #todoList + 1 189 | 190 | keyString = "" + transSeq; 191 | selectIniData.write("ToDoList", keyString, cntStr); 192 | 193 | // 把优先级也要写过去 194 | transColor = todoLevelTable[tostring(itemIndex)]; 195 | selectIniData.write("ToDoLevelList", keyString, transColor); 196 | } 197 | 198 | 199 | // 在全局变量中设置待办事项的优先级 200 | function changeTodoLevel(checkListItemIndex, levelNum){ 201 | 202 | var keyName = "" + checkListItemIndex 203 | 204 | // 将待办事项的优先级信息存储到全局变量 205 | todoLevelTable[keyName] = levelNum 206 | 207 | int_levelNum = tonumber(levelNum) 208 | 209 | // 按照不同的级别设置颜色 switch case , 其中1 2 3分别为高 中 低优先级, 对应 0x0045FF 0x20A5DA 0x32CD32 210 | // 0是默认的级别,就是字体的颜色,此处是黑色 211 | select (int_levelNum){ 212 | case 0{ 213 | mainForm.checklistTodo._clrText[checkListItemIndex]=0x000000 214 | mainForm.checklistTodo.redraw() 215 | } 216 | case 1{ 217 | mainForm.checklistTodo._clrText[checkListItemIndex]=0x0045FF 218 | mainForm.checklistTodo.redraw() 219 | } 220 | case 2{ 221 | mainForm.checklistTodo._clrText[checkListItemIndex]=0xD00614 222 | mainForm.checklistTodo.redraw() 223 | } 224 | case 3{ 225 | mainForm.checklistTodo._clrText[checkListItemIndex]=0x32CD32 226 | mainForm.checklistTodo.redraw() 227 | } 228 | 229 | } 230 | } 231 | 232 | // 批量 233 | function autoBatchChangeColor(seqNum){ 234 | var todoList = mainForm.checklistTodo.items; 235 | for(i=seqNum; #todoList; 1){ 236 | 237 | var nextIndex = i+1 238 | changeLevelColor = todoLevelTable[tostring(nextIndex)] 239 | changeTodoLevel(i, changeLevelColor) 240 | } 241 | } 242 | 243 | 244 | // 勾选待办事项实现转移到已完成的功能 245 | mainForm.checklistTodo.onnotify = function(id,code,ptr){ 246 | 247 | if( code == 0xFFFFFFF4/*_NM_CUSTOMDRAW*/ ){ 248 | owner._clrText:=..table.array(owner.count,owner.columnCount,0); 249 | 250 | var lvcd = owner.getNotifyCustomDraw(code,ptr); 251 | 252 | if( lvcd.nmcd.dwDrawStage == 0x10001/*_CDDS_ITEMPREPAINT*/) 253 | return 0x20/*_CDRF_NOTIFYSUBITEMDRAW*/ 254 | elseif( lvcd.nmcd.dwDrawStage == 1/*_CDDS_PREPAINT*/ ){ 255 | return 0x20/*_CDRF_NOTIFYITEMDRAW*/; 256 | } 257 | elseif( lvcd.nmcd.dwDrawStage == ( 0x10001/*_CDDS_ITEMPREPAINT*/ | 0x20000/*_CDDS_SUBITEM*/) ){ 258 | lvcd.clrText=owner._clrText[lvcd.nmcd.dwItemSpec+1]; 259 | 260 | lvcd.update() 261 | return 0/*_CDRF_DODEFAULT*/ 262 | } 263 | } 264 | elseif( code == 0xFFFFFF9B/*_LVN_ITEMCHANGED*/ ){ 265 | var nmChecklist = mainForm.checklistTodo.getNotifyMessage(code,ptr); 266 | if( !nmChecklist ) 267 | return; 268 | 269 | if( nmChecklist.uNewState & 0xF000/*_LVIS_STATEIMAGEMASK*/){ 270 | var selIndex = nmChecklist.iItem; 271 | if( mainForm.checklistTodo.getChecked( selIndex ) ){ 272 | 273 | // 实现待办事项的转移并获取移动后的索引值,用于下面状态的修改 274 | checkListAddIndex = mainForm.checklistDone.addItem(mainForm.checklistTodo.getItemText(selIndex,1)); 275 | 276 | // 将已完成的事项状态改为勾选 277 | mainForm.checklistDone.setChecked(checkListAddIndex); 278 | 279 | // 将待办事项转移后,删除待办列表中的记录 280 | mainForm.checklistTodo.delItem(selIndex); 281 | 282 | //changeTodoLevel(selIndex, 0) 283 | autoBatchChangeColor(selIndex) 284 | } 285 | } 286 | } 287 | elseif( code = 0xFFFFFFFB/*_NM_RCLICK*/ ){ 288 | 289 | var nmListView = mainForm.checklistTodo.getNotifyMessage(code,ptr); 290 | 291 | // 创建弹出菜单 292 | var popmenu = win.ui.popmenu(mainForm); 293 | 294 | popmenu.add('删除',function(id){ 295 | mainForm.checklistTodo.delItem( nmListView.iItem ) 296 | 297 | autoBatchChangeColor(nmListView.iItem) 298 | 299 | } ) 300 | 301 | popmenu.add('转移待办',function(id){ 302 | var transTodoCnt = mainForm.checklistTodo.getItemText(nmListView.iItem,1) 303 | transTodo(nmListView.iItem, transTodoCnt) 304 | 305 | mainForm.checklistTodo.delItem( nmListView.iItem ) 306 | 307 | // 这块也要写优先级的处理逻辑,优先级重回需要网上刷 308 | autoBatchChangeColor(nmListView.iItem) 309 | 310 | } ) 311 | 312 | popmenu.add('设置高优先级',function(id){ 313 | changeTodoLevel( nmListView.iItem, 1) 314 | } ) 315 | 316 | popmenu.add('设置中优先级',function(id){ 317 | changeTodoLevel( nmListView.iItem, 2) 318 | } ) 319 | 320 | popmenu.add('设置低优先级',function(id){ 321 | changeTodoLevel( nmListView.iItem, 3) 322 | } ) 323 | 324 | popmenu.add('清除优先级',function(id){ 325 | changeTodoLevel( nmListView.iItem, 0) 326 | } ) 327 | 328 | // 在最后一次鼠标事件的位置弹出,采用默认方式 329 | popmenu.popup(); 330 | 331 | popmenu.close(); 332 | 333 | } 334 | elseif(code = 0xFFFFFF51/*_LVN_BEGINLABELEDITW*/ ){ 335 | return false; //允许编辑项 336 | } 337 | elseif( code == 0xFFFFFF50/*_LVN_ENDLABELEDITW*/ ){ 338 | var dispInfo = mainForm.checklistTodo.getNotifyDispInfo(code,ptr); 339 | if( dispInfo ? dispInfo.item.text ) { 340 | mainForm.checklistTodo.setItemText(dispInfo.item.text, dispInfo.item.iItem); 341 | } 342 | } 343 | elseif(code = 0xFFFFFFFD/*_NM_DBLCLK*/) { 344 | mainForm.checklistTodo.editLable() 345 | } 346 | 347 | } 348 | 349 | // 去勾选已完成事项实现状态变为到待办的功能 350 | mainForm.checklistDone.onnotify = function(id,code,ptr){ 351 | 352 | if( code == 0xFFFFFF9B/*_LVN_ITEMCHANGED*/ ){ 353 | var nmChecklist = mainForm.checklistDone.getNotifyMessage(code,ptr); 354 | if( !nmChecklist ) 355 | return; 356 | 357 | if( nmChecklist.uOldState & 0xF000/*_LVIS_STATEIMAGEMASK*/){ 358 | var selIndex = nmChecklist.iItem; 359 | if(! mainForm.checklistDone.getChecked( selIndex ) ){ 360 | 361 | checkListAddIndex = mainForm.checklistTodo.addItem(mainForm.checklistDone.getItemText(selIndex,1)); 362 | 363 | mainForm.checklistTodo.setChecked(checkListAddIndex,false); 364 | 365 | changeTodoLevel(checkListAddIndex, 0) 366 | 367 | mainForm.checklistDone.delItem(selIndex); 368 | } 369 | } 370 | } 371 | elseif( code = 0xFFFFFFFB/*_NM_RCLICK*/ ){ 372 | 373 | var x,y = win.getMessagePos(); 374 | var nmListView = mainForm.checklistDone.getNotifyMessage(code,ptr); 375 | 376 | // 创建弹出菜单 377 | var popmenu = win.ui.popmenu(mainForm); 378 | popmenu.add('删除',function(id){ 379 | mainForm.checklistDone.delItem( nmListView.iItem ) 380 | } ) 381 | popmenu.popup(x,y,true); 382 | 383 | popmenu.close(); 384 | } 385 | } 386 | 387 | // 程序退出处理代码 388 | function saveIniFile(){ 389 | iniData.write("ToDoList",null) 390 | iniData.write("DoneList",null) 391 | iniData.write("ToDoLevelList",null) 392 | 393 | var todoList = mainForm.checklistTodo.items; 394 | for(i=1;#todoList;1){ 395 | keyString = "" + i; 396 | iniData.write("ToDoList",keyString,mainForm.checklistTodo.getItemText(i,1)); 397 | } 398 | 399 | var doneList = mainForm.checklistDone.items; 400 | for(i=1;#doneList;1){ 401 | keyString = "" + i; 402 | iniData.write("DoneList",keyString,mainForm.checklistDone.getItemText(i,1)); 403 | } 404 | 405 | for k, v in todoLevelTable{ 406 | iniData.write("ToDoLevelList", tostring(k) , tostring(v)); 407 | } 408 | 409 | // 保存记忆窗体的大小 410 | setting.mf_height = mainForm.height 411 | setting.mf_width = mainForm.width 412 | setting.save(); 413 | } 414 | 415 | // 软件退出前保存数据 416 | mainForm.wndproc = function(hwnd,message,wparam,lparam){ 417 | select(message) { //判断消息类型 418 | case 0x10/*_WM_CLOSE*/ //窗口关闭消息 419 | { 420 | saveIniFile(); 421 | } 422 | } 423 | } 424 | /*}}*/ 425 | 426 | /*软件功能区菜单代码{{*/ 427 | // 创建主菜单 428 | var menu = win.ui.menu(mainForm); 429 | 430 | // 创建第一个弹出菜单 431 | mainForm.filemenu = win.ui.popmenu(mainForm); 432 | mainForm.filemenu.add('&打开文件',function(id){ 433 | 434 | // 打开之前保存的记录 435 | var fileLoaded = fsys.dlg.open("指定文件|setodo_*.ini|","选择打开历史记录文件","/data"); 436 | 437 | // 用户取消加载新文件的处理 438 | if(fileLoaded!=null){ 439 | // 未关闭窗口情况下切换记录文件也需要保存一次数据 440 | saveIniFile(); 441 | 442 | var fileLoadedName = io.splitpath(fileLoaded).file; 443 | 444 | // 获取并刷新日期变量 445 | dayString = string.sub(fileLoadedName, 8, 15); 446 | 447 | iniData = fsys.ini("\data\" + fileLoadedName); 448 | 449 | mainForm.checklistTodo.clear(); 450 | mainForm.checklistDone.clear(); 451 | 452 | // 软件重新加载选定文件的记录信息 453 | loadIniFile(); 454 | } 455 | }); 456 | 457 | menu.add('文件',mainForm.filemenu) 458 | 459 | 460 | // ----分隔处 461 | 462 | 463 | mainForm.cfgmenu = win.ui.popmenu(mainForm);//创建设置菜单 464 | 465 | mainForm.cfgmenu.add('&开机启动',function(id){ 466 | if (mainForm.cfgmenu.checked(1)) { 467 | // 已经设置开启启动,再次点击取消开机启动 468 | mainForm.cfgmenu.check(1,false); 469 | 470 | enableStartup(exe_path,false); 471 | 472 | setting.isStartup = false; 473 | setting.save(); 474 | 475 | } else { 476 | mainForm.cfgmenu.check(1); 477 | 478 | enableStartup(exe_path,true); 479 | 480 | setting.isStartup = true; 481 | setting.save(); 482 | } 483 | }); 484 | 485 | mainForm.cfgmenu.add('&窗口置顶',function(id){ 486 | if (mainForm.cfgmenu.checked(2)) { 487 | 488 | mainForm.cfgmenu.check(2,false); 489 | 490 | win.setTopmost(mainForm.hwnd,false); 491 | 492 | setting.isTopWindow = false; 493 | setting.save(); 494 | 495 | } else { 496 | mainForm.cfgmenu.check(2); 497 | 498 | win.setTopmost(mainForm.hwnd,true) 499 | 500 | setting.isTopWindow = true; 501 | setting.save(); 502 | } 503 | }); 504 | 505 | menu.add('设置', mainForm.cfgmenu) 506 | 507 | 508 | // ----分隔处 509 | 510 | 511 | mainForm.infomenu = win.ui.popmenu(mainForm);//创建信息菜单 512 | 513 | mainForm.infomenu.add('&使用说明',function(id){ 514 | process.execute("http://www.bituplink.com/windows_setodo.html"); 515 | }); 516 | 517 | mainForm.infomenu.add('&捐助',function(id){ 518 | process.execute("http://www.bituplink.com/donate"); 519 | }); 520 | 521 | menu.add('帮助', mainForm.infomenu) 522 | /*}}*/ 523 | 524 | /*托盘支持功能代码{{*/ 525 | // 增加托盘功能支持,包括托盘图标,右键托盘功能列表,托盘鼠标时间等 526 | exeTray = win.util.tray(mainForm.hwnd); 527 | exeTray.message = 0xACCF/*_WM_TRAYMESSAGE*/; 528 | 529 | mainForm.popmenuTray = win.ui.popmenu(mainForm); 530 | mainForm.popmenuTray.add('打开窗口',function(id){ 531 | mainForm.show(true)//打开窗口 532 | }); 533 | mainForm.popmenuTray.add('最小化',function(id){ 534 | mainForm.hitmin() 535 | }) 536 | mainForm.popmenuTray.add('退出',function(id){ 537 | mainForm.close() 538 | }) 539 | 540 | mainForm.wndproc = function(hwnd,message,wparam,lparam){ 541 | 542 | if( message == 0xACCF/*_WM_TRAYMESSAGE*/ ) { //托盘回调信息 543 | 544 | select(lparam){ 545 | case 0x203/*_WM_LBUTTONDBLCLK*/{ //双击托盘图标打开窗口 546 | if( win.isVisible(mainForm.hwnd) ){ 547 | mainForm.hitmin() //最小化窗口 548 | } 549 | else { 550 | mainForm.show(0x9/*_SW_RESTORE*/); 551 | win.setForeground(mainForm.hwnd) 552 | } 553 | } 554 | case 0x205/*_WM_RBUTTONUP*/ {//单击鼠标右键弹出菜单 555 | x,y = mouse.getPos(); 556 | mainForm.popmenuTray.popup( x,y,true ) 557 | } 558 | case 0x201/*_WM_LBUTTONDOWN*/ {//单击鼠标左键前置窗口 559 | win.setForeground(mainForm.hwnd) 560 | } 561 | } 562 | } 563 | elseif( message == 0x112/*_WM_SYSCOMMAND*/ ){ //系统命令消息 564 | if( wparam == 0xF020/*_SC_MINIMIZE*/ ){ //用户点击了最小化按钮 565 | mainForm.show(false); //隐藏窗口 566 | return true;//阻击默认消息传递,取消最小化过程 567 | } 568 | } 569 | 570 | } 571 | 572 | mainForm.onClose = function(hwnd,message,wParam,lParam){ 573 | exeTray.delete(); 574 | } 575 | /*}}*/ 576 | 577 | // 修改时间要尝试加载文件 578 | mainForm.datetimepick.onnotify = function(id,code,ptr){ 579 | 580 | if(code == 0xFFFFFD09/*_DTN_DATETIMECHANGE*/ ){ 581 | saveIniFile(); 582 | loadIniFile(); 583 | } 584 | } 585 | 586 | // 修改转移时间要判断禁止修改至当天 587 | mainForm.datetimepickTrans.onnotify = function(id,code,ptr){ 588 | 589 | if(code == 0xFFFFFD09/*_DTN_DATETIMECHANGE*/ ){ 590 | var dayTime = mainForm.datetimepick.time; 591 | 592 | // 默认设置转移的日期为下一天 593 | var dayTransTime = mainForm.datetimepickTrans.time 594 | 595 | if(dayTime.diffday(dayTransTime) == 0){ 596 | mainForm.msgbox("不能设置转移时间为当天!") 597 | 598 | // 把时间设置回明天 599 | var defaultNextDayTime = dayTransTime.addday(1); 600 | mainForm.datetimepickTrans.time = defaultNextDayTime; 601 | } 602 | } 603 | } 604 | 605 | 606 | // 开启/关闭开机启动 607 | enableStartup = function(app, enable){ 608 | if ( enable ) { 609 | var lnk = fsys.lnk(); 610 | lnk.path = app; //设置目标路径 611 | lnk.setIcon(app, 0); //设置图标 612 | 613 | return lnk.save( 614 | fsys.joinpath( 615 | fsys.getSpecial( 0x0007 /*_CSIDL_STARTUP*/ ) 616 | , ..io.splitpath(app).name + ".lnk" 617 | ) 618 | ) 619 | } 620 | else { 621 | var lnkpath = fsys.joinpath( fsys.getSpecial( 0x0007 /*_CSIDL_STARTUP*/ ), ..io.splitpath(app).name + ".lnk"); 622 | if( ..io.exist(lnkpath) ){ 623 | fsys.delete(lnkpath); 624 | } 625 | 626 | return true; 627 | } 628 | } 629 | 630 | 631 | mainForm.btnTodoTrans.oncommand = function(id,event){ 632 | // 批量转移所有的待办事项到指定的日期 633 | var todoList = mainForm.checklistTodo.items; 634 | for(i=1;#todoList;1){ 635 | transTodo(i, mainForm.checklistTodo.getItemText(i,1)) 636 | } 637 | 638 | mainForm.checklistTodo.clear(); 639 | } 640 | 641 | mainForm.enableDpiScaling(); 642 | mainForm.show(); 643 | 644 | loadIniFile(); 645 | 646 | return win.loopMessage(); 647 | -------------------------------------------------------------------------------- /src/res/setodo_logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bituplink/setodo/1a06355a0a95dfd3e42fd18e9c7cef78df06085b/src/res/setodo_logo.ico --------------------------------------------------------------------------------