quickwin 2026.5.2-3.145209

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +6 -0
  2. package/examples/pdf_preview.js +440 -0
  3. package/examples/pdf_preview.ts +470 -0
  4. package/examples/preact_demo.js +35 -0
  5. package/examples/preact_demo.tsx +49 -0
  6. package/examples/tray_demo.js +75 -0
  7. package/examples/tray_demo.tsx +79 -0
  8. package/lib/fetch.js +746 -0
  9. package/lib/fetch.ts +811 -0
  10. package/lib/polyfill.js +500 -0
  11. package/lib/polyfill.ts +454 -0
  12. package/lib/preact/hooks.js +287 -0
  13. package/lib/preact/hooks.ts +330 -0
  14. package/lib/preact/jsx-runtime.js +1 -0
  15. package/lib/preact/jsx-runtime.ts +2 -0
  16. package/lib/preact/jsx.d.ts +36 -0
  17. package/lib/preact/layout.js +153 -0
  18. package/lib/preact/layout.ts +183 -0
  19. package/lib/preact/preact.js +54 -0
  20. package/lib/preact/preact.ts +133 -0
  21. package/lib/preact/props.js +99 -0
  22. package/lib/preact/props.ts +119 -0
  23. package/lib/preact/render.js +320 -0
  24. package/lib/preact/render.ts +353 -0
  25. package/lib/websocket.js +540 -0
  26. package/lib/websocket.ts +574 -0
  27. package/package.json +32 -0
  28. package/quickwin.d.ts +657 -0
  29. package/test/add.wasm +0 -0
  30. package/test/complex.wasm +0 -0
  31. package/test/complex_imports.wasm +0 -0
  32. package/test/global_imports.wasm +0 -0
  33. package/test/import_func.wasm +0 -0
  34. package/test/imports.wasm +0 -0
  35. package/test/run.js +86 -0
  36. package/test/run.ts +90 -0
  37. package/test/sjlj.wasm +0 -0
  38. package/test/test_basic.js +7 -0
  39. package/test/test_basic.ts +9 -0
  40. package/test/test_brotli.js +48 -0
  41. package/test/test_brotli.ts +52 -0
  42. package/test/test_fetch_cache.js +131 -0
  43. package/test/test_fetch_cache.ts +141 -0
  44. package/test/test_ffi.js +157 -0
  45. package/test/test_ffi.ts +174 -0
  46. package/test/test_frame_encoding.js +128 -0
  47. package/test/test_frame_encoding.ts +132 -0
  48. package/test/test_helper.js +84 -0
  49. package/test/test_helper.ts +80 -0
  50. package/test/test_http_import.js +78 -0
  51. package/test/test_http_import.ts +74 -0
  52. package/test/test_mupdf_render.js +69 -0
  53. package/test/test_mupdf_render.ts +74 -0
  54. package/test/test_mupdf_twice.js +77 -0
  55. package/test/test_mupdf_twice.ts +81 -0
  56. package/test/test_mupdf_wasm.js +33 -0
  57. package/test/test_mupdf_wasm.ts +30 -0
  58. package/test/test_net_event.js +63 -0
  59. package/test/test_net_event.ts +59 -0
  60. package/test/test_net_fetch.js +153 -0
  61. package/test/test_net_fetch.ts +131 -0
  62. package/test/test_net_websocket.js +158 -0
  63. package/test/test_net_websocket.ts +144 -0
  64. package/test/test_polyfill.js +58 -0
  65. package/test/test_polyfill.ts +60 -0
  66. package/test/test_url.js +173 -0
  67. package/test/test_url.ts +183 -0
  68. package/test/test_wasm_basic.js +82 -0
  69. package/test/test_wasm_basic.ts +70 -0
  70. package/test/test_wasm_import_global.js +41 -0
  71. package/test/test_wasm_import_global.ts +39 -0
  72. package/test/test_wasm_sjlj.js +153 -0
  73. package/test/test_wasm_sjlj.ts +134 -0
  74. package/test/test_wasm_types.js +96 -0
  75. package/test/test_wasm_types.ts +108 -0
  76. package/test/types.wasm +0 -0
  77. package/tsconfig.json +18 -0
  78. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +571 -0
  79. package/vendor/mupdf-wasm/mupdf-wasm.js +2749 -0
  80. package/vendor/mupdf-wasm/mupdf-wasm.wasm +0 -0
  81. package/vendor/mupdf-wasm/mupdf.d.ts +939 -0
  82. package/vendor/mupdf-wasm/mupdf.js +3317 -0
  83. package/win-mingw64.exe +0 -0
package/README.md ADDED
@@ -0,0 +1,6 @@
1
+ TODO
2
+ 修复:
3
+ PS C:\Users\Docker\quickwin> .\run.ps1 "make js" ; .\win.exe .\test\mupdf.js
4
+ Compiling TypeScript files to JavaScript using tsgo...
5
+ TypeScript compilation complete
6
+ FIlE:0000027CA3BDD2A0base_name: .\test\mupdf.js name: ../lib/mupdf_init.jsmodule_name:'../lib/mupdf_init.js'FIlE:0000000000000000JS Error: ReferenceError: could not load module filename '../lib/mupdf_init.js'
@@ -0,0 +1,440 @@
1
+ import '../lib/polyfill.js';
2
+ import * as std from 'std';
3
+ import * as gui from 'gui';
4
+ import * as win from 'win';
5
+ import * as ffi from 'ffi';
6
+ const FFI_PTR = ffi.FFI_TYPE_POINTER;
7
+ const FFI_U32 = ffi.FFI_TYPE_UINT32;
8
+ const FFI_S32 = ffi.FFI_TYPE_SINT32;
9
+ const _user32 = win.LoadLibrary('user32.dll');
10
+ const _gdi32 = win.LoadLibrary('gdi32.dll');
11
+ const _comdlg32 = win.LoadLibrary('comdlg32.dll');
12
+ if (!(_user32 && _gdi32 && _comdlg32)) {
13
+ std.exit(0);
14
+ }
15
+ function loadProc(lib, name) {
16
+ const ptr = win.GetProcAddress(lib, name);
17
+ if (!ptr) {
18
+ std.printf('Error: cannot load %s\n', name);
19
+ std.exit(1);
20
+ }
21
+ return ptr;
22
+ }
23
+ const GetDC = loadProc(_user32, 'GetDC');
24
+ const ReleaseDC = loadProc(_user32, 'ReleaseDC');
25
+ const GetOpenFileNameW = loadProc(_comdlg32, 'GetOpenFileNameW');
26
+ const SetDIBitsToDevice = loadProc(_gdi32, 'SetDIBitsToDevice');
27
+ const PatBlt = loadProc(_gdi32, 'PatBlt');
28
+ const InvalidateRect = loadProc(_user32, 'InvalidateRect');
29
+ const GetSystemMetrics = loadProc(_user32, 'GetSystemMetrics');
30
+ const SetScrollInfo = loadProc(_user32, 'SetScrollInfo');
31
+ const GetClientRect = loadProc(_user32, 'GetClientRect');
32
+ const TOP_OFFSET = 50;
33
+ // FFI 类型签名快捷常量
34
+ const T_U64 = [ffi.FFI_TYPE_UINT64];
35
+ const T_U64_PTR = [ffi.FFI_TYPE_UINT64, FFI_PTR];
36
+ const T_U64_S32_PTR_U32 = [ffi.FFI_TYPE_UINT64, FFI_S32, FFI_PTR, FFI_U32];
37
+ const T_U64_U64_U32 = [ffi.FFI_TYPE_UINT64, ffi.FFI_TYPE_UINT64, FFI_U32];
38
+ function clamp(v, max) {
39
+ return Math.max(0, Math.min(v, max));
40
+ }
41
+ function makeBitmapInfo(w, h) {
42
+ const bmi = new ArrayBuffer(40);
43
+ const bv = new DataView(bmi);
44
+ bv.setUint32(0, 40, true);
45
+ bv.setInt32(4, w, true);
46
+ bv.setInt32(8, -h, true);
47
+ bv.setUint16(12, 1, true);
48
+ bv.setUint16(14, 24, true);
49
+ return bmi;
50
+ }
51
+ function strToWide(str) {
52
+ const buf = new ArrayBuffer((str.length + 1) * 2);
53
+ const dv = new DataView(buf);
54
+ for (let i = 0; i < str.length; i++)
55
+ dv.setUint16(i * 2, str.charCodeAt(i), true);
56
+ return buf;
57
+ }
58
+ function wideToStr(buf) {
59
+ const dv = new DataView(buf);
60
+ const chars = [];
61
+ for (let i = 0; i < buf.byteLength; i += 2) {
62
+ const c = dv.getUint16(i, true);
63
+ if (c === 0)
64
+ break;
65
+ chars.push(c);
66
+ }
67
+ return String.fromCharCode(...chars);
68
+ }
69
+ function setPtr(dv, off, ptr) {
70
+ dv.setUint32(off, ptr & 0xFFFFFFFF, true);
71
+ dv.setUint32(off + 4, Math.floor(ptr / 0x100000000), true);
72
+ }
73
+ let hwndMain = null;
74
+ let hwndEdit = null;
75
+ let hwndBtnOpen = null;
76
+ let hwndBtnPrev = null;
77
+ let hwndBtnNext = null;
78
+ let currentPixmap = null;
79
+ let currentPage = 0;
80
+ let totalPages = 0;
81
+ let scrollX = 0;
82
+ let scrollY = 0;
83
+ // PDF 文档缓存 — 翻页时不重复解析
84
+ let cachedPath = '';
85
+ let cachedDoc = null;
86
+ let cachedTotalPages = 0;
87
+ function clearCachedDoc() {
88
+ if (cachedDoc) {
89
+ try {
90
+ cachedDoc.destroy();
91
+ }
92
+ catch { }
93
+ }
94
+ cachedDoc = null;
95
+ cachedPath = '';
96
+ cachedTotalPages = 0;
97
+ }
98
+ async function loadMupdf() {
99
+ const wasmPath = './vendor/mupdf-wasm/mupdf-wasm.wasm';
100
+ const fp = std.open(wasmPath, 'rb');
101
+ if (!fp) {
102
+ std.printf('Error: cannot open %s\n', wasmPath);
103
+ return null;
104
+ }
105
+ fp.seek(0, 2);
106
+ const size = fp.tell();
107
+ fp.seek(0, 0);
108
+ const buf = new ArrayBuffer(size);
109
+ fp.read(buf, 0, size);
110
+ fp.close();
111
+ console.log(buf.byteLength);
112
+ (globalThis).$libmupdf_wasm_Module = {
113
+ wasmBinary: buf,
114
+ locateFile: (p) => p
115
+ };
116
+ try {
117
+ return await import('../vendor/mupdf-wasm/mupdf.js');
118
+ }
119
+ catch (e) {
120
+ std.printf('Error: mupdf load failed: %s\n', String(e));
121
+ return null;
122
+ }
123
+ }
124
+ function openPdfFileDialog() {
125
+ const structBuf = new ArrayBuffer(152);
126
+ const sv = new DataView(structBuf);
127
+ const fileBuf = new ArrayBuffer(260 * 2);
128
+ const filterWide = strToWide('PDF Files\0*.pdf\0All Files\0*.*\0\0');
129
+ sv.setUint32(0, 152, true);
130
+ const ownerPtr = hwndMain;
131
+ if (!ownerPtr)
132
+ return null;
133
+ sv.setUint32(8, ownerPtr & 0xFFFFFFFF, true);
134
+ sv.setUint32(12, Math.floor(ownerPtr / 0x100000000), true);
135
+ setPtr(sv, 24, ffi.bufferPtr(filterWide));
136
+ setPtr(sv, 48, ffi.bufferPtr(fileBuf));
137
+ sv.setUint32(56, 260, true);
138
+ sv.setUint32(96, 0x1000 | 0x0800 | 0x0004, true);
139
+ const ret = ffi.ffiCall(GetOpenFileNameW, [FFI_PTR], [structBuf], FFI_U32);
140
+ if (!ret)
141
+ return null;
142
+ const path = wideToStr(fileBuf);
143
+ return path.length > 0 ? path : null;
144
+ }
145
+ function renderPdfPage(mupdf, filePath, pageIndex) {
146
+ if (filePath !== cachedPath) {
147
+ clearCachedDoc();
148
+ const fp = std.open(filePath, 'rb');
149
+ if (!fp) {
150
+ std.printf('Error: cannot open %s\n', filePath);
151
+ return null;
152
+ }
153
+ let buf = null;
154
+ try {
155
+ fp.seek(0, 2);
156
+ const size = fp.tell();
157
+ fp.seek(0, 0);
158
+ buf = new ArrayBuffer(size);
159
+ fp.read(buf, 0, size);
160
+ }
161
+ finally {
162
+ fp.close();
163
+ }
164
+ if (!buf)
165
+ return null;
166
+ try {
167
+ cachedDoc = mupdf.Document.openDocument(new Uint8Array(buf), 'application/pdf');
168
+ cachedTotalPages = cachedDoc.countPages();
169
+ std.printf('Pages: %d\n', cachedTotalPages);
170
+ cachedPath = filePath;
171
+ }
172
+ catch (e) {
173
+ std.printf('Error opening document: %s\n', String(e));
174
+ return null;
175
+ }
176
+ }
177
+ if (!cachedDoc)
178
+ return null;
179
+ if (pageIndex >= cachedTotalPages)
180
+ return null;
181
+ let page = null;
182
+ let pixmap = null;
183
+ try {
184
+ page = cachedDoc.loadPage(pageIndex);
185
+ const scale = 1.5;
186
+ pixmap = page.toPixmap(mupdf.Matrix.scale(scale, scale), mupdf.ColorSpace.DeviceRGB, false);
187
+ if (!pixmap)
188
+ return null;
189
+ const srcPixels = pixmap.getPixels();
190
+ const srcStride = pixmap.getStride();
191
+ const w = pixmap.getWidth();
192
+ const h = pixmap.getHeight();
193
+ const dibStride = Math.floor((w * 3 + 3) / 4) * 4;
194
+ const dibSize = h * dibStride;
195
+ const dibBuffer = new ArrayBuffer(dibSize);
196
+ const dib = new Uint8Array(dibBuffer);
197
+ for (let y = 0; y < h; y++) {
198
+ const srcOff = y * srcStride;
199
+ const dstOff = y * dibStride;
200
+ for (let x = 0; x < w; x++) {
201
+ const sx = srcOff + x * 3;
202
+ const dx = dstOff + x * 3;
203
+ dib[dx] = srcPixels[sx + 2];
204
+ dib[dx + 1] = srcPixels[sx + 1];
205
+ dib[dx + 2] = srcPixels[sx];
206
+ }
207
+ }
208
+ return { data: dibBuffer, w, h, totalPages: cachedTotalPages };
209
+ }
210
+ catch (e) {
211
+ std.printf('Error rendering: %s\n', String(e));
212
+ clearCachedDoc();
213
+ return null;
214
+ }
215
+ finally {
216
+ if (pixmap) {
217
+ try {
218
+ pixmap.destroy();
219
+ }
220
+ catch { }
221
+ }
222
+ if (page) {
223
+ try {
224
+ page.destroy();
225
+ }
226
+ catch { }
227
+ }
228
+ }
229
+ }
230
+ function getClientSize(h) {
231
+ const rect = new ArrayBuffer(16);
232
+ ffi.ffiCall(GetClientRect, T_U64_PTR, [h, rect], FFI_U32);
233
+ const dv = new DataView(rect);
234
+ return { w: dv.getInt32(8, true), h: dv.getInt32(12, true) };
235
+ }
236
+ function setScrollPos(h, bar, pos) {
237
+ const si = new ArrayBuffer(28);
238
+ const dv = new DataView(si);
239
+ dv.setUint32(0, 28, true);
240
+ dv.setUint32(4, 4 /* gui.ScrollInfoFlag.POS */, true);
241
+ dv.setInt32(20, pos, true);
242
+ ffi.ffiCall(SetScrollInfo, T_U64_S32_PTR_U32, [h, bar, si, 1], FFI_U32);
243
+ }
244
+ function updateScrollRange(h) {
245
+ if (!currentPixmap)
246
+ return;
247
+ const client = getClientSize(h);
248
+ const viewH = client.h - TOP_OFFSET;
249
+ const maxX = Math.max(0, currentPixmap.w - client.w);
250
+ const maxY = Math.max(0, currentPixmap.h - viewH);
251
+ scrollX = Math.min(scrollX, maxX);
252
+ scrollY = Math.min(scrollY, maxY);
253
+ const si = new ArrayBuffer(28);
254
+ const dv = new DataView(si);
255
+ dv.setUint32(0, 28, true);
256
+ dv.setUint32(4, 1 /* gui.ScrollInfoFlag.RANGE */ | 2 /* gui.ScrollInfoFlag.PAGE */, true);
257
+ dv.setInt32(8, 0, true);
258
+ dv.setInt32(12, currentPixmap.w - 1, true);
259
+ dv.setUint32(16, client.w, true);
260
+ ffi.ffiCall(SetScrollInfo, T_U64_S32_PTR_U32, [h, 0 /* gui.ScrollBar.HORZ */, si, 1], FFI_U32);
261
+ dv.setInt32(8, 0, true);
262
+ dv.setInt32(12, currentPixmap.h - 1, true);
263
+ dv.setUint32(16, viewH, true);
264
+ ffi.ffiCall(SetScrollInfo, T_U64_S32_PTR_U32, [h, 1 /* gui.ScrollBar.VERT */, si, 1], FFI_U32);
265
+ setScrollPos(h, 0 /* gui.ScrollBar.HORZ */, scrollX);
266
+ setScrollPos(h, 1 /* gui.ScrollBar.VERT */, scrollY);
267
+ }
268
+ function doScroll(h, dx, dy) {
269
+ const client = getClientSize(h);
270
+ scrollX = clamp(scrollX + dx, currentPixmap ? Math.max(0, currentPixmap.w - client.w) : 0);
271
+ scrollY = clamp(scrollY + dy, currentPixmap ? Math.max(0, currentPixmap.h - (client.h - TOP_OFFSET)) : 0);
272
+ setScrollPos(h, 0 /* gui.ScrollBar.HORZ */, scrollX);
273
+ setScrollPos(h, 1 /* gui.ScrollBar.VERT */, scrollY);
274
+ ffi.ffiCall(InvalidateRect, T_U64_U64_U32, [h, 0, 1], FFI_U32);
275
+ }
276
+ function renderAndDisplay(mupdf, path, pageIndex) {
277
+ const edit = hwndEdit;
278
+ const hMain = hwndMain;
279
+ if (!edit || !hMain)
280
+ return;
281
+ gui.SetWindowText(edit, path);
282
+ const pix = renderPdfPage(mupdf, path, pageIndex);
283
+ if (pix) {
284
+ currentPixmap = pix;
285
+ currentPage = pageIndex;
286
+ totalPages = pix.totalPages;
287
+ gui.SetWindowText(hMain, 'PDF 预览 - 第 ' + (pageIndex + 1) + '/' + totalPages + ' 页');
288
+ scrollX = 0;
289
+ scrollY = 0;
290
+ updateScrollRange(hMain);
291
+ ffi.ffiCall(InvalidateRect, T_U64_U64_U32, [hMain, 0, 1], FFI_U32);
292
+ }
293
+ else {
294
+ gui.MessageBox('渲染 PDF 失败');
295
+ }
296
+ }
297
+ async function main() {
298
+ const mupdf = await loadMupdf();
299
+ if (!mupdf) {
300
+ gui.MessageBox('加载 mupdf WASM 失败。\n请确保 vendor/mupdf-wasm/ 在构建目录中。');
301
+ return;
302
+ }
303
+ gui.RegisterClass('PdfPreview', (hwnd, msg, wParam, lParam) => {
304
+ if (!hwnd)
305
+ return gui.DefWindowProc(hwnd, msg, wParam, lParam);
306
+ const h = hwnd;
307
+ switch (msg) {
308
+ case 2 /* gui.WmMsg.DESTROY */:
309
+ gui.PostQuitMessage(0);
310
+ return 0;
311
+ case 273 /* gui.WmMsg.COMMAND */: {
312
+ const hCtrl = lParam;
313
+ const btnOpen = hwndBtnOpen;
314
+ const btnPrev = hwndBtnPrev;
315
+ const btnNext = hwndBtnNext;
316
+ if (hCtrl === btnOpen) {
317
+ const path = openPdfFileDialog();
318
+ if (path)
319
+ renderAndDisplay(mupdf, path, 0);
320
+ }
321
+ else if (hCtrl === btnPrev && currentPage > 0) {
322
+ const path = gui.GetWindowText(hwndEdit);
323
+ if (path)
324
+ renderAndDisplay(mupdf, path, currentPage - 1);
325
+ }
326
+ else if (hCtrl === btnNext && currentPage < totalPages - 1) {
327
+ const path = gui.GetWindowText(hwndEdit);
328
+ if (path)
329
+ renderAndDisplay(mupdf, path, currentPage + 1);
330
+ }
331
+ return 0;
332
+ }
333
+ case 15 /* gui.WmMsg.PAINT */: {
334
+ const hdc = ffi.ffiCall(GetDC, [ffi.FFI_TYPE_UINT64], [h], ffi.FFI_TYPE_UINT64);
335
+ if (hdc) {
336
+ ffi.ffiCall(PatBlt, [ffi.FFI_TYPE_UINT64, FFI_S32, FFI_S32, FFI_S32, FFI_S32, FFI_U32], [hdc, 0, 0, 32767, TOP_OFFSET, 0x00FF0062], FFI_U32);
337
+ if (currentPixmap) {
338
+ const bmi = makeBitmapInfo(currentPixmap.w, currentPixmap.h);
339
+ ffi.ffiCall(SetDIBitsToDevice, [
340
+ ffi.FFI_TYPE_UINT64, FFI_S32, FFI_S32, FFI_U32, FFI_U32,
341
+ FFI_S32, FFI_S32, FFI_U32, FFI_U32,
342
+ FFI_PTR, FFI_PTR, FFI_U32
343
+ ], [
344
+ hdc, -scrollX, TOP_OFFSET - scrollY,
345
+ currentPixmap.w, currentPixmap.h,
346
+ 0, 0, 0, currentPixmap.h,
347
+ currentPixmap.data, bmi, 0
348
+ ], FFI_S32);
349
+ }
350
+ ffi.ffiCall(ReleaseDC, [ffi.FFI_TYPE_UINT64, ffi.FFI_TYPE_UINT64], [h, hdc], FFI_S32);
351
+ }
352
+ return gui.DefWindowProc(hwnd, msg, wParam, lParam);
353
+ }
354
+ case 276 /* gui.WmMsg.HSCROLL */: {
355
+ if (wParam === 0)
356
+ return 0;
357
+ const code = wParam & 0xFFFF;
358
+ const thumb = (wParam >> 16) & 0xFFFF;
359
+ let dx = 0;
360
+ if (code === 0 /* gui.ScrollCmd.LINEUP */)
361
+ dx = -20;
362
+ else if (code === 1 /* gui.ScrollCmd.LINEDOWN */)
363
+ dx = 20;
364
+ else if (code === 2 /* gui.ScrollCmd.PAGEUP */)
365
+ dx = -60;
366
+ else if (code === 3 /* gui.ScrollCmd.PAGEDOWN */)
367
+ dx = 60;
368
+ else if (code === 5 /* gui.ScrollCmd.THUMBTRACK */)
369
+ dx = thumb - scrollX;
370
+ if (dx)
371
+ doScroll(h, dx, 0);
372
+ return 0;
373
+ }
374
+ case 277 /* gui.WmMsg.VSCROLL */:
375
+ case 522 /* gui.WmMsg.MOUSEWHEEL */: {
376
+ let dy = 0;
377
+ if (msg === 277 /* gui.WmMsg.VSCROLL */) {
378
+ if (wParam === 0)
379
+ return 0;
380
+ const code = wParam & 0xFFFF;
381
+ const thumb = (wParam >> 16) & 0xFFFF;
382
+ if (code === 0 /* gui.ScrollCmd.LINEUP */)
383
+ dy = -20;
384
+ else if (code === 1 /* gui.ScrollCmd.LINEDOWN */)
385
+ dy = 20;
386
+ else if (code === 2 /* gui.ScrollCmd.PAGEUP */)
387
+ dy = -60;
388
+ else if (code === 3 /* gui.ScrollCmd.PAGEDOWN */)
389
+ dy = 60;
390
+ else if (code === 5 /* gui.ScrollCmd.THUMBTRACK */)
391
+ dy = thumb - scrollY;
392
+ }
393
+ else {
394
+ const raw = (wParam >>> 16) & 0xFFFF;
395
+ const wheel = raw >= 0x8000 ? raw - 0x10000 : raw;
396
+ dy = -Math.round(wheel * 40 / 120);
397
+ }
398
+ if (dy)
399
+ doScroll(h, 0, dy);
400
+ return 0;
401
+ }
402
+ case 3 /* gui.WmMsg.SIZE */: {
403
+ if (currentPixmap)
404
+ updateScrollRange(h);
405
+ ffi.ffiCall(InvalidateRect, T_U64_U64_U32, [h, 0, 1], FFI_U32);
406
+ return 0;
407
+ }
408
+ default:
409
+ return gui.DefWindowProc(hwnd, msg, wParam, lParam);
410
+ }
411
+ });
412
+ const winW = 960, winH = 720;
413
+ const screenW = ffi.ffiCall(GetSystemMetrics, [FFI_S32], [0 /* gui.SysMetrics.CXSCREEN */], FFI_S32);
414
+ const screenH = ffi.ffiCall(GetSystemMetrics, [FFI_S32], [1 /* gui.SysMetrics.CYSCREEN */], FFI_S32);
415
+ const winX = Math.max(0, (screenW - winW) >> 1);
416
+ const winY = Math.max(0, (screenH - winH) >> 1);
417
+ const ctrlY = 12;
418
+ const ctrlH = 26;
419
+ const gap = 4;
420
+ const btnOpenW = 80;
421
+ hwndMain = gui.CreateWindow('PdfPreview', 'PDF 预览', 13565952 /* gui.WindowStyle.OVERLAPPEDWINDOW */ | 1048576 /* gui.WindowStyle.HSCROLL */ | 2097152 /* gui.WindowStyle.VSCROLL */ | 33554432 /* gui.WindowStyle.CLIPCHILDREN */, winX, winY, winW, winH, null, null);
422
+ if (!hwndMain) {
423
+ gui.MessageBox('创建主窗口失败');
424
+ return;
425
+ }
426
+ hwndBtnOpen = gui.CreateWindow('BUTTON', '打开 PDF', 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */ | 273 /* gui.WmMsg.COMMAND */, ctrlY, ctrlY, btnOpenW, ctrlH, hwndMain, null);
427
+ const editW = 480;
428
+ const btnPageW = 72;
429
+ const editX = ctrlY + btnOpenW + gap;
430
+ hwndEdit = gui.CreateWindow('EDIT', '', 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */ | 8388608 /* gui.WindowStyle.BORDER */, editX, ctrlY, editW, ctrlH, hwndMain, null);
431
+ hwndBtnPrev = gui.CreateWindow('BUTTON', '上一页', 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */ | 273 /* gui.WmMsg.COMMAND */, editX + editW + gap, ctrlY, btnPageW, ctrlH, hwndMain, null);
432
+ hwndBtnNext = gui.CreateWindow('BUTTON', '下一页', 1073741824 /* gui.WindowStyle.CHILD */ | 268435456 /* gui.WindowStyle.VISIBLE */ | 273 /* gui.WmMsg.COMMAND */, editX + editW + gap + btnPageW + gap, ctrlY, btnPageW, ctrlH, hwndMain, null);
433
+ gui.ShowWindow(hwndMain);
434
+ const test = std.open('example.pdf', 'rb');
435
+ if (test) {
436
+ test.close();
437
+ renderAndDisplay(mupdf, 'example.pdf', 0);
438
+ }
439
+ }
440
+ main();