Last active
September 5, 2020 14:21
-
-
Save dixyes/c27c622aad2a722fb02520f3edb29f09 to your computer and use it in GitHub Desktop.
my mc mod updater
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AbyssalCraft-1.12.2-1.10.2.jar:AbyssalCraft* | |
astralsorcery-1.12.2-1.10.26.jar:astralsorcery* | |
BuildingGadgets-2.8.4.jar:BuildingGadgets* | |
gregtech-1.12.2-1.10.0.546.jar:gregtech* | |
industrialcraft-2-2.8.220-ex112.jar:industrialcraft* | |
Jade-0.1.0.jar:Jade* | |
jei_1.12.2-4.16.1.301.jar:jei_1.12.2* | |
just-enough-harvestcraft-1.12.2-1.7.2.jar:just-enough-harvestcraft-* | |
levelup2-1.5.6.jar:levelup2* | |
LittleMaidAppendPack-1.0.3.jar:LittleMaidAppendPack* | |
LittleMaidAvatar-1.0.4.jar:LittleMaidAvatar* | |
LittleMaidReengaged_FirisPatch-9.2.5.fp.049.jar:LittleMaidReengaged_FirisPatch* | |
LMLibrary-1.0.9.jar:LMLibrary* | |
MMLib-1.5.0.jar:MMLib* | |
phosphor-forge-mc1.12.2-0.2.7-universal.jar:phosphor* | |
SlashBlade-mc1.12-r33.jar:SlashBlade* | |
TLS-2.0.4-1.12.2.jar:TLS* | |
TofuCraftReload-0.1.0.8.jar:TofuCraftReload* | |
TravelersBackpack-1.12.2-1.0.33.jar:TravelersBackpack* | |
twilightforest-1.12.2-3.11.1020-universal[1].jar:twilightforest* | |
XaerosWorldMap_1.10.1_Forge_1.12.jar:XaerosWorldMap_* | |
Xaeros_Minimap_20.20.1_Forge_1.12.jar:Xaeros_Minimap_* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- my mod updater using pure lua and ffi with win32apis | |
-- MIT license | |
-- copyright 2020 dixyes | |
local ffi = require("ffi") | |
local newPath = "new" | |
local confPath = "config.list" | |
local defModsPath = "%APPDATA%\\.minecraft\\mods\\1.12.2" | |
local logf = io.open("log","a") | |
ffi.cdef[[ | |
uint32_t __stdcall FreeConsole(void); | |
uint32_t GetLastError(); | |
int MultiByteToWideChar(unsigned int,uint32_t,const char *,int,wchar_t *,int); | |
int WideCharToMultiByte(unsigned int,uint32_t,const wchar_t *,int,char *,int,const char *,uint32_t *); | |
uint32_t SetProcessDpiAwareness(uint32_t); | |
uint32_t ExpandEnvironmentStringsW(const wchar_t *, wchar_t *,uint32_t); | |
void* __stdcall ILCreateFromPathW(const wchar_t*); | |
void* LoadLibraryExW(wchar_t*, void*, int); | |
void* GetProcAddress(void*, const char*); | |
typedef uint64_t __stdcall (* WNDPROC)(void*, uint32_t, uint64_t, uint64_t); | |
typedef struct tagWNDCLASSEXW { | |
uint32_t cbSize; | |
uint32_t style; | |
WNDPROC lpfnWndProc; | |
int cbClsExtra; | |
int cbWndExtra; | |
void* hInstance; | |
void* hIcon; | |
void* hCursor; | |
void* hbrBackground; | |
wchar_t* lpszMenuName; | |
wchar_t* lpszClassName; | |
void* hIconSm; | |
} WNDCLASSEXW; | |
typedef struct tagPOINT | |
{ | |
int32_t x; | |
int32_t y; | |
} POINT; | |
typedef struct tagMSG { | |
void* hwnd; | |
uint32_t message; | |
void* wParam; | |
void* lParam; | |
uint32_t time; | |
POINT pt; | |
} MSG; | |
uint32_t __stdcall GetMessageW(MSG*,void*,uint32_t,uint32_t); | |
uint64_t __stdcall DefWindowProcW(void*, uint32_t, uint64_t, uint64_t); | |
void* GetModuleHandleW(wchar_t*); | |
void* __stdcall CreateWindowExW( | |
uint32_t,wchar_t*,wchar_t*,uint32_t, | |
int32_t,int32_t,int32_t,int32_t, | |
void*,void*,void*,void* | |
); | |
uint32_t __stdcall ShowWindow(void*,int); | |
uint32_t __stdcall UpdateWindow(void*); | |
uint32_t RegisterClassExW(const WNDCLASSEXW *); | |
void* GetStockObject(int); | |
void* LoadCursorW(void*, wchar_t*); | |
void* __stdcall LoadAcceleratorsW(void*,wchar_t*); | |
int32_t __stdcall TranslateAcceleratorW(void*, void*, MSG*); | |
uint32_t __stdcall TranslateMessage(MSG*); | |
uint32_t __stdcall DispatchMessageW(MSG*); | |
void __stdcall PostQuitMessage(int); | |
void* SendMessageW(void*,uint32_t,uint64_t,uint64_t); | |
typedef struct tagRECT | |
{ | |
int32_t left; | |
int32_t top; | |
int32_t right; | |
int32_t bottom; | |
} RECT; | |
typedef struct tagPAINTSTRUCT { | |
void* hdc; | |
uint32_t fErase; | |
RECT rcPaint; | |
uint32_t fRestore; | |
uint32_t fIncUpdate; | |
char rgbReserved[32]; | |
} PAINTSTRUCT; | |
void* BeginPaint(void*, PAINTSTRUCT*); | |
void* EndPaint(void*, PAINTSTRUCT*); | |
uint32_t TextOutW(void*,int,int,const wchar_t*,int); | |
uint32_t DrawTextExW(void*,const wchar_t*,int32_t,RECT*,uint32_t,void*); | |
uint32_t GetDpiForWindow(void*); | |
uint32_t GetDpiForSystem(); | |
uint32_t SystemParametersInfoW(uint32_t, uint32_t, void*, uint32_t); | |
uint32_t SetWindowPos(void*,void*,int,int,int,int,uint32_t); | |
uint32_t GetWindowRect(void*,RECT*); | |
uint32_t GetClientRect(void*,RECT*); | |
typedef struct tagMINMAXINFO { | |
POINT ptReserved; | |
POINT ptMaxSize; | |
POINT ptMaxPosition; | |
POINT ptMinTrackSize; | |
POINT ptMaxTrackSize; | |
} MINMAXINFO; | |
typedef struct tagTEXTMETRICW | |
{ | |
int32_t tmHeight; | |
int32_t tmAscent; | |
int32_t tmDescent; | |
int32_t tmInternalLeading; | |
int32_t tmExternalLeading; | |
int32_t tmAveCharWidth; | |
int32_t tmMaxCharWidth; | |
int32_t tmWeight; | |
int32_t tmOverhang; | |
int32_t tmDigitizedAspectX; | |
int32_t tmDigitizedAspectY; | |
wchar_t tmFirstChar; | |
wchar_t tmLastChar; | |
wchar_t tmDefaultChar; | |
wchar_t tmBreakChar; | |
int8_t tmItalic; | |
int8_t tmUnderlined; | |
int8_t tmStruckOut; | |
int8_t tmPitchAndFamily; | |
int8_t tmCharSet; | |
} TEXTMETRICW; | |
typedef struct tagLOGFONTW | |
{ | |
int32_t lfHeight; | |
int32_t lfWidth; | |
int32_t lfEscapement; | |
int32_t lfOrientation; | |
int32_t lfWeight; | |
int8_t lfItalic; | |
int8_t lfUnderline; | |
int8_t lfStrikeOut; | |
int8_t lfCharSet; | |
int8_t lfOutPrecision; | |
int8_t lfClipPrecision; | |
int8_t lfQuality; | |
int8_t lfPitchAndFamily; | |
wchar_t lfFaceName[32/* LF_FACESIZE */]; | |
} LOGFONTW; | |
typedef int (__stdcall * FONTENUMPROCW)(const LOGFONTW *, const TEXTMETRICW *, uint32_t, void*); | |
void* CreateFontIndirectW(const LOGFONTW *); | |
int EnumFontFamiliesW(void*,const wchar_t*,FONTENUMPROCW,void*); | |
void* SelectObject(void*, void*); | |
uint32_t SetConsoleOutputCP(uint32_t wCodePageID); | |
uint32_t GetConsoleOutputCP(void); | |
void* RtlCopyMemory(void*, void*, size_t); | |
void* GetDlgItem(void*, int); | |
int GetDlgCtrlID(void*); | |
typedef struct _browseinfoW { | |
void *hwndOwner; | |
void *pidlRoot; | |
wchar_t * pszDisplayName; | |
wchar_t * lpszTitle; | |
uint32_t ulFlags; | |
void * lpfn; | |
uint32_t lParam; | |
int iImage; | |
} BROWSEINFOW; | |
uint64_t SHBrowseForFolderW(BROWSEINFOW*); | |
uint32_t SHGetPathFromIDListW(const uint64_t,wchar_t *); | |
int __stdcall MessageBoxExW(void*, const wchar_t*,const wchar_t*,uint32_t,uint16_t); | |
int __stdcall lstrcpynW(wchar_t* ,const wchar_t*,int); | |
int GetWindowTextW(void*,wchar_t*,int); | |
uint32_t SetWindowTextW(void*, const wchar_t*); | |
uint32_t EnableWindow(void*,uint32_t); | |
uint32_t CopyFileW(wchar_t*,wchar_t*,uint32_t); | |
uint32_t DeleteFileW(wchar_t*); | |
void* CreateFileW(wchar_t*, uint32_t, uint32_t,void*,uint32_t,uint32_t,void*);\ | |
typedef struct _fakeFFD { | |
uint32_t dwFileAttributes; | |
wchar_t field1[20]; | |
wchar_t field2[260]; | |
wchar_t field3[14]; | |
} fakeFFD; | |
void* FindNextFileW(void* , fakeFFD*); | |
void* FindFirstFileExW(const wchar_t *,uint32_t,fakeFFD*,uint32_t,void*,uint32_t); | |
uint32_t CloseHandle(void*); | |
uint32_t GetFileAttributesW(const wchar_t*); | |
]] | |
local targetPathWCS = ffi.new("wchar_t[4096]") | |
local function printf(fmt, ...) | |
print(string.format(fmt, ...)) | |
logf:write(string.format(fmt, ...),"\n") | |
end | |
local function d(func) | |
local ok, excOrRet = xpcall(func, debug.traceback) | |
if not ok then | |
printf(excOrRet) | |
return | |
end | |
return excOrRet | |
end | |
local Shell32 = ffi.load("Shell32.dll", true) | |
local User32 = ffi.load("User32.dll", true) | |
--ffi.load("Gdi32.dll", true) | |
local function _mb2wc(s) | |
local szbuf = s:len() | |
local buf = ffi.new('wchar_t[?]', szbuf+1) | |
local ret = ffi.C.MultiByteToWideChar(65001--[[ utf8]], 0, s, -1, buf, szbuf) | |
if -1 == ret then | |
return nil | |
end | |
return ret, buf | |
end | |
local function mb2wc(s) | |
local ret, buf = _mb2wc(s) | |
return buf | |
end | |
local function _wc2mb(s, cp) | |
local dummybuf = ffi.new('char[?]', 1024) | |
local l = ffi.C.WideCharToMultiByte(cp, 0, s, -1, dummybuf, 0, nil, nil) | |
local buf = ffi.new('char[?]', l+1) | |
if ffi.C.WideCharToMultiByte(cp, 0, s, -1, buf, l, nil, nil) == -1 then | |
return nil | |
end | |
return ffi.string(buf) | |
end | |
local function wc2mb(s) | |
return _wc2mb(s, 65001) | |
end | |
local function pathJoin(a,b) | |
if string.sub(a, #a, #a) == "\\" then | |
return a .. b | |
end | |
return a .. "\\" .. b | |
end | |
local function rm(filename) | |
--print("do rm", filename) | |
local ret = ffi.C.DeleteFileW(mb2wc(filename)) | |
--local ret = 1 | |
if ret == 0 then | |
local le = ffi.C.GetLastError() | |
--print(le) | |
return string.format("DeleteFileW: %d", le) | |
end | |
end | |
local function cp(src, dst) | |
--print("do cp", src, dst) | |
local ret = ffi.C.CopyFileW(mb2wc(src), mb2wc(dst), 1) | |
--local ok = 1 | |
if 0 == ret then | |
local le = ffi.C.GetLastError() | |
--print(le) | |
if le == 5 --[[ERROR_ACCESS_DENIED]] then | |
return "eacces" | |
elseif le == 80 --[[ERROR_FILE_EXISTS]] then | |
return "eexist" | |
end | |
return string.format("CopyFileW: %d", le) | |
end | |
end | |
local function checkDirWritable(path) | |
local function touch(path) | |
--print("touch", path) | |
local handle = ffi.C.CreateFileW( | |
mb2wc(path), | |
0xc0000000,--[[GENERIC_READ | GENERIC_WRITE]] | |
3,--[[FILE_SHARE_READ|FILE_SHARE_WRITE]] | |
nil, | |
1,--[[CREATE_NEW]] | |
0x2, --[[FILE_ATTRIBUTE_HIDDEN]] | |
nil | |
) | |
local nhandle = ffi.cast("uint64_t", handle) | |
--print(nhandle, 18446744073709551615ULL == nhandle) | |
--os.exit() | |
if 0xffffffffffffffffULL == nhandle then | |
local le = ffi.C.GetLastError() | |
--print("touch", path,le) | |
if le == 5 --[[ERROR_ACCESS_DENIED]] then | |
return "eacces" | |
elseif le == 80 --[[ERROR_FILE_EXISTS]] then | |
return "eexist" | |
end | |
return string.format("CreateFileW: %d", le) | |
else | |
--print("touch", path, "ok") | |
ffi.C.CloseHandle(handle) | |
return nil | |
end | |
end | |
--print("testtouch is", touch(path.."\\CAN_I_CREATE_FILE_HERE")) | |
--print("testtouch is", touch(path.."\\新建文本文档.txt")) | |
local testPath = pathJoin(path,"CAN_I_CREATE_FILE_HERE") | |
--print("testtouch is", pathJoin(path,"CAN_I_CREATE_FILE_HERE")) | |
local err = touch(testPath) | |
--print("touch", err) | |
if nil == err then | |
err = rm(testPath) | |
if err then | |
--print("flag delete failed") | |
return false | |
end | |
elseif "eexist" == err then | |
--print("flag alreadey exist") | |
err = rm(testPath) | |
if err then | |
--print("flag delete failed with exist") | |
return false | |
end | |
err = touch(testPath) | |
if err then | |
--print("create flag failed") | |
return false | |
end | |
rm(testPath) | |
else | |
--print("create flag failed") | |
return false | |
end | |
return true | |
end | |
local arraylen = { | |
__index = function(self, k) | |
if k == "len" then | |
local l = 0 | |
for _,__ in pairs(self) do | |
l = l + 1 | |
end | |
return l | |
end | |
return rawget(k) | |
end | |
} | |
local files2Rm = {} | |
setmetatable(files2Rm,arraylen) | |
local files2Cp = {} | |
setmetatable(files2Cp,arraylen) | |
local hint = "baddir" | |
local readableHint = "" | |
local confList = {} | |
local targetPath = nil | |
local function checkTarget(target) | |
targetPath = nil | |
files2Rm = {} | |
setmetatable(files2Rm,arraylen) | |
files2Cp = {} | |
setmetatable(files2Cp,arraylen) | |
local fileAttr = ffi.C.GetFileAttributesW(mb2wc(target)) | |
--printf("target %s is 0x%08x", target, fileAttr) | |
if fileAttr == 0xffffffff--[[INVILID]] or bit.band(0x00000010--[[FILE_ATTRIBUTE_DIRECTORY]], fileAttr)~=0x00000010 then | |
--printf("target %s is not dir", target) | |
hint = "baddir" | |
return false | |
end | |
if not checkDirWritable(target) then | |
hint = "baddir" | |
return false | |
end | |
local ffd = ffi.new("fakeFFD",{ | |
--dwFileAttributes = 0x80 --[[FILE_ATTRIBUTE_NORMAL]] - not usable | |
}) | |
--print(ffi.sizeof(ffd)) | |
for newFn, oldPatterns in pairs(confList) do | |
--local fd = ffi.new('void*') | |
local skip = false | |
local removes = {} | |
--print() | |
--printf("oldpatterns is %s", oldPatterns) | |
for oldPattern in string.gmatch(oldPatterns, "[^,]+") do | |
local fullOp = pathJoin(target, oldPattern) | |
--printf("serch pattern is %s", oldPattern) | |
--printf("?? is %s", fullOp) | |
local firstFile = ffi.C.FindFirstFileExW( | |
mb2wc(fullOp), --path | |
1, -- basic info | |
ffd, -- find file data | |
0, --FindExSearchNameMatch | |
nil, | |
1 -- FIND_FIRST_EX_CASE_SENSITIVE | |
) | |
if 0xffffffffffffffffULL --[[INVALID_HANDLE_VALUE]] == ffi.cast("uint64_t", firstFile) then | |
--printf("FindFirstFileExW failed: %d", ffi.C.GetLastError()) | |
break | |
end | |
repeat | |
local fn = wc2mb(ffd.field2) | |
if fn:len()>0 then | |
--printf("determining %s should be delete", fn) | |
local attr = ffd.dwFileAttributes --ffi.C.GetFileAttributesW(mb2wc(pathJoin(target, fn))) | |
if fileAttr ~= 0xffffffff--[[INVILID]] and | |
tonumber(bit.band(0x00000050--[[FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE]], attr)) == 0 then | |
--printf("skip file %s with attr 0x%08x", fn, attr) | |
if fn ~= oldMatch and fn == newFn then | |
-- alreadey have | |
--print("already exist") | |
skip = true | |
break | |
end | |
--printf("toremove %s", fn) | |
table.insert(removes, fn) | |
end | |
end | |
until skip or nil == ffi.C.FindNextFileW(firstFile, ffd) | |
end | |
if not skip then | |
--print("add", newFn) | |
files2Cp[newFn] = true | |
for _,v in pairs(removes) do | |
--print("rm", v) | |
files2Rm[v] = true | |
end | |
end | |
end | |
if files2Cp.len == 0 and files2Rm.len == 0 then | |
--print("nothing to do") | |
hint = "nothing" | |
return true | |
end | |
hint = "ok" | |
targetPath = target | |
return true | |
end | |
local function doChange(target) | |
local rmSucc = 0 | |
for fn, ok in pairs(files2Rm) do | |
if ok then | |
--print("rm", ok, path, fn) | |
local err = rm(pathJoin(target, fn)) | |
if err then | |
printf("rm %s failed: %s", pathJoin(target, fn), err) | |
else | |
rmSucc = rmSucc + 1 | |
end | |
end | |
end | |
local cpSucc = 0 | |
for fn, ok in pairs(files2Cp) do | |
if ok then | |
--print("cp", ok, newPath, fn, pathJointarget, fn) | |
local err = cp(pathJoin(newPath, fn), pathJoin(target, fn)) | |
if err then | |
printf("cp %s to %s failed: %s", pathJoin(newPath, fn), pathJoin(target, fn), err) | |
else | |
cpSucc = cpSucc + 1 | |
end | |
end | |
end | |
return cpSucc, rmSucc | |
end | |
local function parseConf(path) | |
local data, err= io.open(path,"r") | |
if not data then | |
return string.format("can't open config file %s", path) | |
end | |
for line in data:lines() do | |
for newFn, oldMatch in string.gmatch(line, "(.+):(.+)") do | |
confList[newFn] = oldMatch | |
break | |
end | |
end | |
return nil | |
end | |
local function fuckdpi() | |
d(function() | |
local Shcore = ffi.load("Shcore.dll", true) | |
if nil == Shcore then | |
printf("fuckdpi: not supp0rt: no dll") | |
return | |
end | |
if nil ~= Shcore.SetProcessDpiAwareness then | |
local hr = Shcore.SetProcessDpiAwareness(2) | |
--printf("fuckdpi: SetProcessDpiAwareness ret 0x%08x", hr) | |
end | |
end) | |
end | |
local function registerWinClass(attributes) | |
local wincls = { | |
lpfnWndProc = attributes.winProc, | |
lpszClassName = mb2wc(attributes.className), | |
cbSize = ffi.sizeof("WNDCLASSEXW"), | |
style = 3, --[[CS_HREDRAW | CS_VREDRAW]] | |
hCursor = ffi.C.LoadCursorW(nil, ffi.cast("wchar_t*", 32512)--[[IDC_ARROW]]), | |
hbrBackground = ffi.cast("void *", 5), | |
--ffi.C.GetStockObject(0--[[WHITE_BRUSH]]), | |
} | |
local wcex = ffi.new("WNDCLASSEXW", wincls) | |
--print("pre RegisterClassExW") | |
if 0 == ffi.C.RegisterClassExW(wcex) then | |
local err = ffi.C.GetLastError() | |
return string.format("RegisterWinClassExW: %d", err) | |
end | |
--print("post RegisterClassExW") | |
return nil | |
end | |
local g_dpi = 96 | |
local metrics = {} | |
function initMetrics() | |
metrics.fontHeight = 18/96*g_dpi | |
metrics.selTextRight = 30 + 120/96*g_dpi | |
metrics.selTextBottom = 10 + 23/96*g_dpi | |
metrics.pathBrowseWinLeft = 642/96*g_dpi | |
metrics.bottomButtonTop = 457/96*g_dpi | |
metrics.stateTextTop = 407/96*g_dpi | |
metrics.cancelButtonLeft = 659/96*g_dpi | |
metrics.contentBoxVMargin = 10 | |
metrics.contentBoxHMargin = 30 | |
end | |
local function makeWinProc(win) | |
local defRoutines = { | |
[0x0002 --[[WM_DESTROY]]] = function() | |
ffi.C.PostQuitMessage(0) | |
end, | |
} | |
local routines = win.routines | |
setmetatable(routines, {__index = defRoutines}) | |
local cb = function(hwnd, message, wparam, lparam) | |
local ok, excOrRet = xpcall(function() | |
--print(win.specialCbs) | |
--if win.specialCbs and win.specialCbs.preRoutine then | |
-- win.specialCbs.preRoutine(hwnd, message, wparam, lparam) | |
--end | |
if routines[message] then | |
local ret = routines[message](win, hwnd, message, wparam, lparam) | |
if nil ~= ret then | |
return ret | |
end | |
end | |
--if win.specialCbs and win.specialCbs.postRoutine then | |
-- win.specialCbs.postRoutine(hwnd, message, wparam, lparam) | |
--end | |
end, debug.traceback) | |
if not ok then | |
printf("on message process:") | |
printf(excOrRet) | |
return ffi.C.DefWindowProcW(hwnd, message, wparam, lparam) | |
end | |
return excOrRet or ffi.C.DefWindowProcW(hwnd, message, wparam, lparam) | |
end | |
return ffi.cast("WNDPROC", cb) | |
end | |
local function createWin(win, options) | |
local wincls = win.winClass | |
if nil == wincls then | |
wincls = {} | |
end | |
if win.routines then | |
local err = registerWinClass(setmetatable(wincls, {__index = { | |
winProc = makeWinProc(win), | |
className = win.className | |
}})) | |
if nil ~= err then | |
return "registerWinClass: " .. err, nil | |
end | |
end | |
--print(1) | |
local defOptions = { | |
exStyle = 0, | |
--title = "Hello, Windows", | |
style = 0xcf0000, --[[WS_OVERLAPPEDWINDOW]] | |
x = 0x80000000, --[[CW_USEDEFAULT]] | |
y = 0x80000000, --[[CW_USEDEFAULT]] | |
w = 0x80000000, --[[CW_USEDEFAULT]] | |
h = 0x80000000, --[[CW_USEDEFAULT]] | |
parent = nil, | |
menu = nil, | |
inst = nil, | |
lparam = nil | |
} | |
if nil == options then | |
options = {} | |
end | |
setmetatable(options, {__index = defOptions}) | |
local title = type(options.title) == "string" and mb2wc(options.title) or options.title | |
--print("title is", title) | |
--print("pre CreateWindowExW", ffi.C.CreateWindowExW, User32.CreateWindowExW) | |
--print(string.format( | |
--[[ | |
CreateWindowExW(%p)( | |
exStyle=%08x, className=L"%s", title=L"%s", style=%08x, | |
x=%d, y=%d, w=%d, h=%d, | |
parent=%p, menu=%p, inst=%p, lparam=%p | |
)]] | |
-- ,ffi.C.CreateWindowExW, | |
-- options.exStyle, | |
-- win.className, | |
-- options.title, | |
-- options.style, | |
-- options.x, | |
-- options.y, | |
-- options.w, | |
-- options.h, | |
-- options.parent, | |
-- options.menu, | |
-- options.inst, | |
-- options.lparam)) | |
local hwnd = ffi.C.CreateWindowExW( | |
options.exStyle, | |
mb2wc(win.className), | |
title, | |
options.style, | |
options.x, | |
options.y, | |
options.w, | |
options.h, | |
options.parent, | |
options.menu, | |
options.inst, | |
options.lparam) | |
--print("post CreateWindowExW") | |
if nil == hwnd then | |
local err = ffi.C.GetLastError() | |
return string.format("failed CreateWindowExW: %d", err), nil | |
end | |
return nil, hwnd | |
end | |
local usableUIFont = nil | |
local function selUIFont(hdc) | |
if usableUIFont then | |
return usableUIFont | |
end | |
local prefer = { | |
"Microsoft YaHei UI", | |
"Microsoft JhengHei UI", | |
"思源黑体", | |
"思源黑體", | |
"Modern", | |
0 | |
} | |
local all = {} | |
local function enumproc (lf, tm, ft, lp) | |
d(function() | |
--print("font:",wc2mb(lf.lfFaceName)) | |
table.insert(all, wc2mb(lf.lfFaceName)) | |
end) | |
return 1 | |
end | |
local cb = ffi.cast("FONTENUMPROCW", enumproc) | |
if 1 ~= ffi.C.EnumFontFamiliesW(hdc, nil, cb, nil) then | |
print("selUIFont: my cb failed") | |
end | |
--print(1) | |
local found = #prefer + 1 | |
local foundName = "Modern" | |
for _, v in pairs(all) do | |
--print(v) | |
local newFound = #prefer + 1 | |
for i, a in pairs(prefer) do | |
--print(a,v) | |
if a == v then | |
newFound = i | |
--print(newFound) | |
break | |
end | |
end | |
if newFound < found then | |
found = newFound | |
foundName = v | |
--print("use", v) | |
end | |
if newFound == 0 then | |
break | |
end | |
end | |
--print(found) | |
usableUIFont = foundName | |
return usableUIFont | |
end | |
local fonts = {} | |
local function makeFont(name, numSize) | |
local size = math.floor(numSize + 0.5) | |
--printf("makeFont %s at %d", name, size) | |
if fonts[name] and fonts[name][size] then | |
--print("use already exist font") | |
return nil, fonts[name][size] | |
end | |
-- fuck ffi type converison | |
local fontWCS = ffi.new("wchar_t[32]") | |
ffi.C.MultiByteToWideChar(65001--[[ utf8]], 0, name, -1, fontWCS, 32) | |
local logfont = ffi.new("LOGFONTW",{ | |
lfHeight = size, | |
--lfCharSet = 1,--[[DEFAULT_CHARSET]] | |
--lfOutPrecision = 2 ,--[[OUT_CHARACTER_PRECIS]] | |
lfFaceName = fontWCS, | |
}) | |
local font = ffi.C.CreateFontIndirectW(logfont) | |
if nil == font then | |
return string.format("CreateFontIndirectW: %d",ffi.C.GetLastError()), nil | |
end | |
if nil == fonts[name] then | |
fonts[name] = {} | |
end | |
fonts[name][size] = font | |
return nil, font | |
end | |
local drawTextBuf = ffi.new("wchar_t[4096]") | |
local function drawText(hdc, text, inRect, size, attr) | |
local fontName = selUIFont(hdc) | |
--print(fontName) | |
--print("pre makeFont") | |
local err, font = makeFont(fontName, size) | |
--print("fontobj:", font) | |
if nil == font then | |
printf("makeFont failed: %s", err) | |
else | |
ffi.C.SelectObject(hdc, font) | |
end | |
--print(1) | |
ffi.fill(drawTextBuf, ffi.sizeof("wchar_t[4096]")) | |
--print(2) | |
local l = ffi.C.MultiByteToWideChar(65001--[[ utf8]], 0, text, -1, drawTextBuf, 4096) | |
--print(3) | |
local rect = ffi.new("RECT", inRect) | |
ffi.C.DrawTextExW(hdc, drawTextBuf, l-1, rect, attr or 0x25--[[DT_SINGLELINE | DT_CENTER | DT_VCENTER]], nil) | |
end | |
local defChildWin = { | |
recvParentRect = function(self, rect) | |
self.parentH = rect.bottom - rect.top | |
self.parentW = rect.right - rect.left | |
end, | |
fontUsed = nil, | |
postPaint = function(self, hwnd) | |
if usableUIFont then | |
--print("changing font for text") | |
local err, font = makeFont(usableUIFont, metrics.fontHeight) | |
if nil == err then | |
if self.fontUsed == font then | |
--print("not nessesery updat font") | |
return | |
end | |
--print('SendMessageW', hwnd, 0x0030--[[WM_SETFONT]], font, 0) | |
--d(function() | |
ffi.C.SendMessageW(hwnd, 0x0030--[[WM_SETFONT]], ffi.cast("uint64_t", font), 0) | |
--end) | |
--print('post SendMessageW') | |
self.fontNotSet = false | |
end | |
end | |
end, | |
} | |
local selTextWin = { | |
className = "Static", | |
style = 0x50000001, --[[WS_CHILD | WS_VISIBLE | SS_CENTER]] | |
getX = function(self) | |
metrics.selTextRight = metrics.contentBoxHMargin + self:getW() | |
--print("here metrics.selTextRight", metrics.selTextRight) | |
return metrics.contentBoxHMargin | |
end, | |
getW = function(self) | |
return 120/96*g_dpi | |
end, | |
getY = function(self) | |
metrics.selTextBottom = metrics.contentBoxVMargin + 23/96*g_dpi | |
return metrics.contentBoxVMargin | |
end, | |
getH = function(self) | |
return 23/96*g_dpi | |
end, | |
} | |
setmetatable(selTextWin, {__index = defChildWin}) | |
local stateTextWin = { | |
className = "Static", | |
style = 0x50000001, --[[WS_CHILD | WS_VISIBLE | SS_CENTER]] | |
getX = function(self) | |
return metrics.contentBoxHMargin | |
end, | |
getW = function(self) | |
return self.parentW - 2 * metrics.contentBoxHMargin | |
end, | |
getY = function(self) | |
local bottom = metrics.bottomButtonTop - 10 | |
metrics.stateTextTop = bottom - 40/96*g_dpi | |
return bottom - 40/96*g_dpi | |
end, | |
getH = function(self) | |
return metrics.bottomButtonTop - 10 - self:getY() | |
end, | |
} | |
setmetatable(stateTextWin, {__index = defChildWin}) | |
local pathEditWin = { | |
className = "EDIT", | |
--exStyle = 0x200,--[[WS_EX_CLIENTEDGE]] | |
style = 0x50810000, --[[WS_CHILD | WS_VISIBLE | WS_TABSTOP]] | |
getX = function(self) | |
--print(metrics.selTextRight) | |
return metrics.selTextRight + 10 | |
end, | |
getW = function(self) | |
return metrics.pathBrowseWinLeft - self:getX() - 10 | |
end, | |
getY = function(self) | |
return metrics.contentBoxVMargin | |
end, | |
getH = function(self) | |
return 23/96*g_dpi | |
end, | |
} | |
setmetatable(pathEditWin, {__index = defChildWin}) | |
local pathBrowseWin = { | |
className = "BUTTON", | |
title = "浏览...", | |
style = 0x50818f00, --[[WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON | BS_CENTER | BS_VCENTER | BS_FLAT | BS_TEXT | WS_TABSTOP]] | |
getX = function(self) | |
local left = self.parentW - metrics.contentBoxHMargin - self:getW() | |
metrics.pathBrowseWinLeft = left | |
--print("calced is",(metrics.pathBrowseWinLeft)) | |
return left | |
end, | |
getW = function(self) | |
return 50/96*g_dpi | |
end, | |
getY = function(self) | |
return metrics.contentBoxVMargin | |
end, | |
getH = function(self) | |
return 23/96*g_dpi | |
end, | |
} | |
setmetatable(pathBrowseWin, {__index = defChildWin}) | |
local cancelButtonWin = { | |
className = "BUTTON", | |
style = 0x50818f00, --[[WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON | BS_CENTER | BS_VCENTER | BS_FLAT | BS_TEXT|WS_TABSTOP]] | |
getX = function(self) | |
local left = self.parentW - metrics.contentBoxHMargin - self:getW() | |
metrics.cancelButtonLeft = left | |
--print("here cancelButtonLeft", metrics.cancelButtonLeft) | |
return left | |
end, | |
getW = function(self) | |
return 50/96*g_dpi | |
end, | |
getY = function(self) | |
local top = self.parentH - metrics.contentBoxVMargin - self:getH() | |
metrics.bottomButtonTop = top | |
--print("here bottomButtonTop", top) | |
return top | |
end, | |
getH = function(self) | |
return 23/96*g_dpi | |
end, | |
} | |
setmetatable(cancelButtonWin, {__index = defChildWin}) | |
local okButtonWin = { | |
className = "BUTTON", | |
style = 0x50818f00, --[[WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON | BS_CENTER | BS_VCENTER | BS_FLAT | BS_TEXT|WS_TABSTOP]] | |
getX = function(self) | |
return metrics.cancelButtonLeft - 10 - self:getW() | |
end, | |
getW = function(self) | |
return 50/96*g_dpi | |
end, | |
getY = function(self) | |
return metrics.bottomButtonTop | |
end, | |
getH = function(self) | |
return 23/96*g_dpi | |
end, | |
} | |
setmetatable(okButtonWin, {__index = defChildWin}) | |
local leftFrameWin = { | |
className = "LISTBOX", | |
--className = "leftFrameWin", | |
style = 0x50a0400a, --[[WS_CHILD |WS_VISIBLE | WS_VSCROLL | WS_BORDER | LBS_SORT | LBS_NOSEL | LBS_MULTIPLESEL]] | |
--exStyle = 0x00004000, --[[WS_EX_LEFTSCROLLBAR]] | |
getX = function(self) | |
return metrics.contentBoxHMargin | |
end, | |
getW = function(self) | |
return (self.parentW - (3*metrics.contentBoxHMargin))/2 | |
end, | |
getY = function(self) | |
return metrics.selTextBottom + 10 | |
end, | |
getH = function(self) | |
return metrics.stateTextTop - 10 - self:getY() | |
end, | |
} | |
setmetatable(leftFrameWin, {__index = defChildWin}) | |
local rightFrameWin = { | |
className = "LISTBOX", | |
--className = "leftFrameWin", | |
style = 0x50a0400a, --[[WS_CHILD |WS_VISIBLE | WS_VSCROLL | WS_BORDER | LBS_SORT | LBS_NOSEL | LBS_MULTIPLESEL]] | |
--exStyle = 0x00004000, --[[WS_EX_LEFTSCROLLBAR]] | |
getX = function(self) | |
return self.parentW - self:getW() - metrics.contentBoxHMargin | |
end, | |
getW = function(self) | |
return (self.parentW - (3*metrics.contentBoxHMargin))/2 | |
end, | |
getY = function(self) | |
return metrics.selTextBottom + 10 | |
end, | |
getH = function(self) | |
return metrics.stateTextTop - 10 - self:getY() | |
end, | |
} | |
setmetatable(rightFrameWin, {__index = defChildWin}) | |
local function lbWinUpdate(self, hint, targetDict) | |
--printf("%s:update",self.name) | |
if not self.hwnd then | |
return | |
end | |
ffi.C.SendMessageW(self.hwnd, 0x0184--[[LB_RESETCONTENT]], 0, 0) | |
for k,_ in pairs(targetDict) do | |
local ret = ffi.C.SendMessageW(self.hwnd, 0x0180--[[LB_ADDSTRING]], 0, ffi.cast("uint64_t", mb2wc(hint .. k))) | |
local idx = tonumber(ffi.cast("int64_t", ret)) | |
ffi.C.SendMessageW(self.hwnd, 0x019a--[[LB_SETITEMDATA]], idx, idx) | |
--print("add",k, "as", idx) | |
if idx < 0 then | |
printf("SendMessageW failed: %d", ffi.C.GetLastError()) | |
return | |
end | |
end | |
end | |
local mianWin = { | |
updateChildren = function (self, selfHwnd) | |
for _, child in pairs(self.children) do | |
if child.update then | |
child:update(selfHwnd) | |
end | |
end | |
end, | |
children = { | |
{ | |
name = "selTextWin", | |
win = selTextWin, | |
title = "选择jar所在的目录", | |
}, | |
{ | |
name = "pathBrowseWin", | |
win = pathBrowseWin, | |
title = "浏览...", | |
onClick = function(self, parent, parentHwnd) | |
--print("im clicked", parent, parentHwnd) | |
local targetPathIL = Shell32.ILCreateFromPathW(targetPathWCS) | |
local function initFolderCb(hwnd, message, wparam, lparam) | |
if message == 1 --[[BFFM_INITIALIZED]] then | |
--print("sending msg", hWnd) | |
ffi.C.SendMessageW(hwnd, 1126 --[[BFFM_SETSELECTION]], 0, ffi.cast("uint64_t", targetPathIL)) | |
return 1 | |
end | |
return 0 | |
end | |
local bi = ffi.new("BROWSEINFOW") | |
bi.lpfn=targetPathIL and ffi.cast("WNDPROC", initFolderCb) | |
bi.lpszTitle = mb2wc("选一下mod目录,jar在的那个目录\n例如.minecraft\\mods\\1.12.2") | |
bi.ulFlags= 624 --[[BIF_VALIDATE | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON]] | |
local ret = tonumber(Shell32.SHBrowseForFolderW(bi)) | |
--print(ret,Shell32.SHGetPathFromIDListW,targetPathWCS) | |
if 0 == ret then | |
--print("canceled BrowseForFolder") | |
return | |
end | |
if 0 == Shell32.SHGetPathFromIDListW(ret, targetPathWCS) then | |
printf("failed SHGetPathFromIDListW: %d", ffi.C.GetLastError()) | |
return | |
end | |
--print("selected",wc2mb(targetPathWCS)) | |
parent.children.pathEditWin:updateTitle() | |
checkTarget(wc2mb(targetPathWCS)) | |
parent:updateChildren(parentHwnd) | |
end, | |
}, | |
{ | |
name = "pathEditWin", | |
win = pathEditWin, | |
getTitle = function(self) return targetPathWCS end, | |
updateTitle = function(self) | |
if not self.hwnd then | |
return | |
end | |
ffi.C.SendMessageW(self.hwnd, 0x000c--[[WM_SETTEXT]], 0, ffi.cast("uint64_t", targetPathWCS)) | |
--self.hwnd | |
end, | |
onChange = function(self, parent, parentHwnd) | |
if not self.hwnd then | |
return | |
end | |
if 0 == ffi.C.GetWindowTextW(self.hwnd, targetPathWCS, 4096) then | |
printf("0 == GetWindowTextW, GetLastError() = %d", ffi.C.GetLastError()) | |
end | |
--print("updating targetPathWCS", wc2mb(targetPathWCS)) | |
checkTarget(wc2mb(targetPathWCS)) | |
parent:updateChildren(parentHwnd) | |
end, | |
}, | |
{ | |
name = "cancelButtonWin", | |
win = cancelButtonWin, | |
title = "算了", | |
onClick = function(self, parent, parentHwnd) | |
ffi.C.PostQuitMessage(0) | |
end | |
}, | |
{ | |
name = "okButtonWin", | |
win = okButtonWin, | |
title = "行吧", | |
onClick = function(self, parent, parentHwnd) | |
if hint ~= "ok" then | |
printf("wtf?") | |
ffi.C.MessageBoxExW(parentHwnd, mb2wc("我觉得不行"), mb2wc("???"), 0, 65001) | |
return | |
end | |
local ret = ffi.C.MessageBoxExW( | |
parentHwnd, | |
mb2wc(string.format("确认要这么做吗\r\n更新到 %s\r\n", targetPath) .. readableHint), | |
mb2wc("确认一下"), | |
0x2101--[[MB_OKCANCEL|MB_TASKMODAL|MB_DEFBUTTON2]], | |
65001 | |
) | |
if 1 --[[ID_OK]] == ret then | |
local ca = files2Cp.len | |
local ra = files2Rm.len | |
local c, r = doChange(targetPath) | |
if c == ca and r == ra then | |
ffi.C.MessageBoxExW(parentHwnd, mb2wc("成了"), mb2wc("OJBK"), 0, 65001) | |
else | |
ffi.C.MessageBoxExW( | |
parentHwnd, | |
mb2wc(string.format("%d 个要复制的文件中 %d 个复制失败了\r\n%d 个要删除的文件中 %d 个删除失败了",ca,ca-c,ra,ra-r)), | |
mb2wc("不太行"), | |
0, | |
65001 | |
) | |
end | |
checkTarget(targetPath) | |
parent:updateChildren(parentHwnd) | |
end | |
end, | |
update = function(self, parentHwnd) | |
if hint == "ok" then | |
--print("enabling") | |
ffi.C.SetWindowTextW(self.hwnd, mb2wc("行吧")) | |
ffi.C.EnableWindow(self.hwnd, 1) | |
return | |
end | |
ffi.C.SetWindowTextW(self.hwnd, mb2wc("不行")) | |
ffi.C.EnableWindow(self.hwnd, 0) | |
end | |
}, | |
{ | |
name = "stateTextWin", | |
win = stateTextWin, | |
title = "ceafbabeda", | |
update = function(self, parentHwnd) | |
readableHint = "??? You should never see this" | |
if "nothing" == hint then | |
readableHint = "“今日无事可做”" | |
elseif "ok" == hint then | |
local numCp = files2Cp.len | |
local numRm = files2Rm.len | |
readableHint = (0 ~= numCp and string.format("新增 %s 个文件", numCp) or "没有新增文件") .. | |
(0 ~= numRm and string.format(",删除 %s 个文件", numRm) or ",没有删除文件") | |
elseif "baddir" == hint then | |
readableHint = "选择的目录不对" | |
end | |
ffi.C.SetWindowTextW(self.hwnd, mb2wc(readableHint)) | |
end, | |
}, | |
{ | |
name = "leftFrameWin", | |
win = leftFrameWin, | |
update = function(self, parentHwnd) | |
lbWinUpdate(self, "添加 ", files2Cp) | |
end | |
}, | |
{ | |
name = "rightFrameWin", | |
win = rightFrameWin, | |
update = function(self, parentHwnd) | |
lbWinUpdate(self, "删除 ", files2Rm) | |
end | |
}, | |
}, | |
recvRect = function(self, hwnd) | |
if nil == self.clientRect then | |
self.clientRect = ffi.new("RECT") | |
end | |
--print("rect", rect) | |
if 0 == ffi.C.GetClientRect(hwnd, self.clientRect) then | |
printf("failed GetClientRect: %d", ffi.GetLastError()) | |
self.clientRect.left = 0 | |
self.clientRect.right = 1424 | |
self.clientRect.top = 0 | |
self.clientRect.bottom = 750 | |
end | |
--print(rect.left, rect.right, rect.top, rect.bottom) | |
end, | |
updateChildrenRect = function(self) | |
for k,v in pairs(self.children) do | |
if v.hwnd then | |
--print("updateChildrenRect", k) | |
v.win:recvParentRect(self.clientRect) | |
if 0 == ffi.C.SetWindowPos( | |
v.hwnd, | |
nil, | |
v.win:getX(), | |
v.win:getY(), | |
v.win:getW(), | |
v.win:getH(), | |
0x0014 --[[SWP_NOZORDER | SWP_NOACTIVATE]]) then | |
printf("updateChildrenRect: failed SetWindowPos: %d", ffi.C.GetLastError()) | |
end | |
end | |
end | |
end, | |
createChildren = function(self, hwnd) | |
for k,v in pairs(self.children) do | |
--print(string.format("createChildren %s, %p, %08x, %08x", v.name, v.win, v.win.style, v.win.exStyle or 0)) | |
v.win:recvParentRect(self.clientRect) | |
local err, childhwnd = createWin(v.win, { | |
parent = hwnd, | |
exStyle = v.win.exStyle, | |
style = v.win.style, | |
title = v.title or (v.getTitle and v.getTitle()), | |
menu = ffi.cast("void*", k), | |
x = v.win:getX(), | |
y = v.win:getY(), | |
w = v.win:getW(), | |
h = v.win:getH(), | |
}) | |
if nil ~= err then | |
printf("createWin failed err: %s", err) | |
end | |
v.hwnd = childhwnd | |
--if bit.band(v.win.style ) == nil then | |
local did = ffi.C.GetDlgCtrlID(childhwnd) | |
if k ~= did then | |
printf("did not match: k=%d, did=%d, err=0x%08x", k, did, ffi.C.GetLastError()) | |
else | |
v.did = did | |
end | |
--end | |
if v.update then | |
v:update(hwnd) | |
end | |
end | |
end, | |
className = "myWin", | |
routines = { | |
[0x0001 --[[WM_CREATE]]] = function(win, hwnd, message, wparam, lparam) | |
--print("mianWin: WM_CREATE") | |
--print(win, win.recvSize) | |
win:recvRect(hwnd) | |
win:createChildren(hwnd) | |
--print("oncreate:", err, child) | |
end, | |
[0x0005 --[[WM_SIZE]]] = function(win,hwnd,msg,wp,lp) | |
--print(hwnd,msg,wp,lp) | |
win:recvRect(hwnd) | |
win:updateChildrenRect() | |
end, | |
[0x0024 --[[WM_GETMINMAXINFO]]] = function(win,hwnd,msg,wp,lp) | |
--print("WM_GETMINMAXINFO",hwnd,msg,wp,lp) | |
local mmi = ffi.cast("MINMAXINFO*", lp) | |
if nil == win.defMinX then | |
win.defMinX = mmi.ptMinTrackSize.x | |
win.defMinY = mmi.ptMinTrackSize.y | |
end | |
if g_dpi < 300 then | |
mmi.ptMinTrackSize.x = (g_dpi * 7.87401575--[[20cm in inch]]) | |
mmi.ptMinTrackSize.y = (g_dpi * 5.51181102--[[14cm in inch]]) | |
end | |
end, | |
[0x0111 --[[WM_COMMAND]]] = function(win, hwnd, message, wparam, lparam) | |
--printf("WM_COMMAND:\n\twp:0x%016x\n\tlp:0x%016x", tonumber(ffi.cast("uint64_t", wparam)), tonumber(ffi.cast("uint64_t", lparam))) | |
--print(ffi.cast("void*", lparam), win.children[1].hwnd) | |
local notify = tonumber(bit.rshift(bit.band(wparam, 0xffff0000), 16)) | |
local did = tonumber(bit.band(wparam, 0xffff)) | |
--printf("notify=0x%04x, did=0x%04x", notify, did) | |
if notify == 0 --[[BN_CLICKED]] then | |
if win.children[did].onClick then | |
win.children[did]:onClick(win, hwnd) | |
end | |
elseif notify == 0x0300 --[[EN_CHANGE]] then | |
if win.children[did].onChange then | |
--printf("calling win.children.%s:onChange",win.children[did].name) | |
win.children[did]:onChange(win, hwnd) | |
end | |
end | |
end, | |
--[0x004E --[[WM_NOTIFY]]] = function(win, hwnd, message, wparam, lparam) | |
-- print("WM_NOTIFY", wparam, lparam) | |
--end, | |
[0x02E0 --[[WM_DPICHANGED]]] = function (win, hwnd, message, wparam, lparam) | |
g_dpi = tonumber(bit.rshift(bit.band(wparam,0xffff0000), 16)) | |
--print(g_dpi) | |
-- do things here | |
local prcNewWindow = ffi.cast("RECT*", lparam) | |
ffi.C.SetWindowPos( | |
hwnd, | |
nil, | |
prcNewWindow.left, | |
prcNewWindow.top, | |
prcNewWindow.right - prcNewWindow.left, | |
prcNewWindow.bottom - prcNewWindow.top, | |
0x14 --[[SWP_NOZORDER | SWP_NOACTIVATE]] | |
) | |
win:recvRect(hwnd) | |
--for k,v in pairs(win.texts) do | |
--v:setMetrics(win) | |
--end | |
win:updateChildrenRect() | |
metrics.fontHeight = 18/96*g_dpi | |
end, | |
[0x000F --[[WM_PAINT]]] = function(win, hwnd, message, wparam, lparam) | |
--print("WM_PAINT", wparam) | |
win:recvRect(hwnd) | |
local ps = ffi.new("PAINTSTRUCT") | |
local hdc = ffi.C.BeginPaint(hwnd, ps) | |
--print("hdc:", hdc) | |
if nil == hdc then | |
printf("failed BeginPaint: %d", ffi.C.GetLastError()) | |
return | |
else | |
selUIFont(hdc) | |
--print(-1) | |
--print(metrics.fontHeight) | |
--for k,v in pairs(win.texts) do | |
--print(v.size) | |
--drawText(hdc, v.text or v:getText(), v:getRect(win), v.size or v.getSize()) | |
--v:setMetrics(win,metrics) | |
--end | |
ffi.C.EndPaint(hwnd, ps) | |
end | |
for _, child in pairs(win.children) do | |
--print(child.win.postPaint) | |
if child.win.postPaint then | |
--printf("calling postPaint for %s",child.name) | |
child.win:postPaint(child.hwnd) | |
end | |
end | |
end | |
} | |
} | |
setmetatable(mianWin.children, {__index=function(mytable, index) | |
for _,v in pairs(mytable) do | |
if v.name == index then | |
return v | |
end | |
end | |
end}) | |
local function fuckAA() | |
ffi.C.SystemParametersInfoW( | |
75, --[[SPI_SETFONTSMOOTHING]] | |
1, | |
nil, | |
3 --[[SPIF_UPDATEINIFILE | SPIF_SENDCHANGE)]] | |
) | |
ffi.C.SystemParametersInfoW( | |
8203,--[[SPI_SETFONTSMOOTHINGTYPE]] | |
0, | |
ffi.cast("void*", 1600), | |
3 --[[SPIF_UPDATEINIFILE | SPIF_SENDCHANGE]] | |
) | |
end | |
local function mian() | |
ffi.C.ExpandEnvironmentStringsW(mb2wc("%APPDATA%\\.minecraft\\mods\\1.12.2"), targetPathWCS, 4096) | |
local targetPath = wc2mb(targetPathWCS) | |
local err = parseConf(confPath) | |
if err then | |
printf("parseConf: %s",err) | |
return 1 | |
end | |
local ret = checkTarget(targetPath) | |
--local ret = checkTarget("..\\mods") | |
--print(ret, hint) | |
--os.exit(0) | |
fuckdpi() | |
--fuckAA() | |
g_dpi = ffi.C.GetDpiForSystem() | |
initMetrics() | |
--print("pre create main win") | |
local err, hwnd = createWin(mianWin, { | |
title = "来更新一波mod吧", | |
w = g_dpi * 7.87401575,--[[20cm in inch]] | |
h = g_dpi * 5.51181102,--[[14cm in inch]] | |
}) | |
if nil ~= err then | |
printf("failed createWindow: %s", err) | |
return 1 | |
end | |
--print("post create main win") | |
ffi.C.FreeConsole() | |
ffi.C.ShowWindow(hwnd, 9--[[SW_RESTORE]]) | |
ffi.C.UpdateWindow(hwnd) | |
--local accel = ffi.C.LoadAcceleratorsW(nil, className) | |
local msg = ffi.new("MSG") | |
while 0 ~= ffi.C.GetMessageW(msg, nil, 0, 0) do | |
--if 0 == ffi.C.TranslateAcceleratorW(msg.hwnd, accel, msg) then | |
ffi.C.TranslateMessage(msg) | |
ffi.C.DispatchMessageW(msg) | |
--end | |
end | |
printf("done") | |
end | |
function entry() | |
--ffi.C.MessageBoxW(nil, mb2wc("你好测试测试"), mb2wc("Test"), 0) | |
--print(Shell32.ILCreateFromPathW(mb2wc("C:\\"))) | |
--os.exit(0) | |
local origcp = ffi.C.GetConsoleOutputCP() | |
ffi.C.SetConsoleOutputCP(65001) | |
local ret, exc = xpcall(function () | |
mian(arg) | |
end, debug.traceback) | |
if nil~=exc then | |
printf(exc) | |
end | |
ffi.C.SetConsoleOutputCP(origcp) | |
os.exit(ret) | |
end | |
entry() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment