quickwin 1.2.1 → 2.0.0

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 (137) hide show
  1. package/README.en.md +3 -3
  2. package/README.md +21 -24
  3. package/examples/PdfCanvas.js +8 -37
  4. package/examples/PdfCanvas.tsx +11 -41
  5. package/examples/exec_server.js +20054 -1423
  6. package/examples/exec_server.tsx +489 -0
  7. package/examples/exec_server_worker.js +383 -33
  8. package/examples/exec_server_worker.ts +408 -30
  9. package/examples/pdf_preview2.js +31 -73
  10. package/examples/pdf_preview2.ts +33 -76
  11. package/examples/pdf_viewer.js +1496 -616
  12. package/examples/pdf_viewer.tsx +23 -64
  13. package/examples/setres.js +22 -47
  14. package/examples/setres.ts +23 -57
  15. package/examples/test_gallery.js +1491 -525
  16. package/examples/test_react_lazy.js +1455 -500
  17. package/examples/test_react_listbox.js +1454 -499
  18. package/examples/test_root_window.js +1450 -495
  19. package/examples/test_tab.js +1455 -500
  20. package/lib/abort.js +70 -0
  21. package/lib/abort.ts +69 -0
  22. package/lib/certs.js +214 -0
  23. package/lib/certs.ts +224 -0
  24. package/lib/exec-log.js +15 -0
  25. package/lib/exec-log.ts +30 -0
  26. package/lib/fetch.js +37 -4
  27. package/lib/fetch.ts +35 -4
  28. package/lib/ffi/bind.js +352 -0
  29. package/lib/ffi/bind.ts +442 -0
  30. package/lib/ffi/ctype.js +168 -0
  31. package/lib/ffi/ctype.ts +331 -0
  32. package/lib/ffi/index.js +6 -0
  33. package/lib/ffi/index.ts +6 -0
  34. package/lib/ffi/struct.js +412 -0
  35. package/lib/ffi/struct.ts +664 -0
  36. package/lib/http-common.js +43 -5
  37. package/lib/http-common.ts +48 -6
  38. package/lib/http-server.js +187 -29
  39. package/lib/http-server.ts +177 -26
  40. package/lib/react-qw/components/DateTimePicker.js +20 -33
  41. package/lib/react-qw/components/Input.js +3 -10
  42. package/lib/react-qw/components/Link.js +7 -22
  43. package/lib/react-qw/components/ListView.js +80 -141
  44. package/lib/react-qw/components/PathPicker.js +36 -80
  45. package/lib/react-qw/components/ScrollView.js +15 -8
  46. package/lib/react-qw/components/Slider.js +2 -1
  47. package/lib/react-qw/components/Tab.js +15 -20
  48. package/lib/react-qw/components/Tooltip.js +21 -20
  49. package/lib/react-qw/components/TreeView.js +14 -47
  50. package/lib/react-qw/index.js +4 -2
  51. package/lib/react-qw/index.ts +4 -2
  52. package/lib/react-qw/nmhdr.js +5 -0
  53. package/lib/react-qw/nmhdr.ts +7 -0
  54. package/lib/react-qw/props.js +7 -2
  55. package/lib/react-qw/props.ts +7 -3
  56. package/lib/react-qw/reconciler.js +23 -13
  57. package/lib/react-qw/reconciler.ts +22 -13
  58. package/lib/text-measure.js +18 -35
  59. package/lib/text-measure.ts +20 -37
  60. package/lib/websocket.js +12 -2
  61. package/lib/websocket.ts +15 -2
  62. package/lib/windows/comctl32.js +18 -0
  63. package/lib/windows/comctl32.ts +20 -0
  64. package/lib/windows/comdlg32.js +7 -0
  65. package/lib/windows/comdlg32.ts +9 -0
  66. package/lib/windows/gdi32.js +90 -0
  67. package/lib/windows/gdi32.ts +97 -0
  68. package/lib/windows/kernel32.js +66 -0
  69. package/lib/windows/kernel32.ts +76 -0
  70. package/lib/windows/ntdll.js +8 -0
  71. package/lib/windows/ntdll.ts +10 -0
  72. package/lib/windows/ole32.js +7 -0
  73. package/lib/windows/ole32.ts +9 -0
  74. package/lib/windows/shell32.js +11 -0
  75. package/lib/windows/shell32.ts +14 -0
  76. package/lib/windows/structs.js +384 -0
  77. package/lib/windows/structs.ts +422 -0
  78. package/lib/windows/user32.js +469 -0
  79. package/lib/windows/user32.ts +502 -0
  80. package/package.json +1 -1
  81. package/quickwin.d.ts +22 -33
  82. package/quickwin_const.d.ts +1 -0
  83. package/qwin-nowasm-x86.exe +0 -0
  84. package/qwin-nowasm.exe +0 -0
  85. package/qwin-x86.exe +0 -0
  86. package/qwin.exe +0 -0
  87. package/test/bench_ffi_callraw.js +236 -0
  88. package/test/bench_ffi_callraw.ts +236 -0
  89. package/test/bench_ffi_overhead.js +139 -0
  90. package/test/bench_ffi_overhead.ts +141 -0
  91. package/test/bench_sendmessage.js +104 -0
  92. package/test/bench_sendmessage.ts +100 -0
  93. package/test/bench_sendmessage_nonnull.js +187 -0
  94. package/test/bench_sendmessage_nonnull.ts +188 -0
  95. package/test/run.js +14 -4
  96. package/test/run.ts +15 -5
  97. package/test/test_basic_fetch.js +8 -0
  98. package/test/test_basic_fetch.ts +9 -0
  99. package/test/test_ffi.js +33 -47
  100. package/test/test_ffi.ts +41 -60
  101. package/test/test_ffi_abi.js +235 -0
  102. package/test/test_ffi_abi.ts +218 -0
  103. package/test/test_ffi_bind.js +572 -0
  104. package/test/test_ffi_bind.ts +597 -0
  105. package/test/test_ffi_struct.js +745 -0
  106. package/test/test_ffi_struct.ts +798 -0
  107. package/test/test_ffi_struct_layout.js +495 -0
  108. package/test/test_ffi_struct_layout.ts +543 -0
  109. package/test/test_ffi_user32.js +103 -0
  110. package/test/test_ffi_user32.ts +113 -0
  111. package/test/test_ffi_windows.js +101 -0
  112. package/test/test_ffi_windows.ts +113 -0
  113. package/test/test_helper.js +8 -1
  114. package/test/test_helper.ts +9 -1
  115. package/test/test_http_import.js +18 -0
  116. package/test/test_http_import.ts +19 -0
  117. package/test/test_http_server.js +73 -1
  118. package/test/test_http_server.ts +75 -1
  119. package/test/test_ipv6.js +2 -2
  120. package/test/test_ipv6.ts +2 -2
  121. package/test/test_net_fetch.js +70 -8
  122. package/test/test_net_fetch.ts +69 -7
  123. package/test/test_net_websocket.js +1 -1
  124. package/test/test_net_websocket.ts +1 -1
  125. package/test/test_react_complex.js +1465 -510
  126. package/test/test_react_counter.js +1455 -500
  127. package/test/test_react_flex.js +1475 -513
  128. package/test/test_react_hidden.js +1458 -503
  129. package/test/test_react_listview_link.js +1455 -500
  130. package/test/test_react_notify.js +18534 -0
  131. package/test/test_react_render.js +1455 -500
  132. package/test/test_wolfssl_read.js +3 -2
  133. package/test/test_wolfssl_read.ts +3 -1
  134. package/test/test_worker_net.js +35 -17
  135. package/test/test_worker_net.ts +27 -15
  136. package/tsconfig.json +1 -1
  137. package/examples/exec_server.ts +0 -80
@@ -1,76 +1,35 @@
1
+ import { MaybePtr, PtrArrayBuffer } from '../lib/ffi/ctype.js'
1
2
  import '../lib/polyfill.js'
2
3
  import * as std from 'std'
3
4
  import * as gui from 'gui'
4
- import * as win from 'win'
5
- import * as ffi from 'ffi'
6
5
  import type { Document, Page, Pixmap } from '../vendor/mupdf-wasm/mupdf.js'
7
6
  import { useState } from 'react'
8
7
  import { render, Button, Input, ScrollView } from '../lib/react-qw/index.js'
8
+ import { WCHAR } from '../lib/ffi/bind.js'
9
9
  import { PdfCanvas } from './PdfCanvas.js'
10
+ import { OPENFILENAMEW } from '../lib/windows/structs.js'
11
+ import { GetOpenFileName } from '../lib/windows/comdlg32.js'
10
12
 
11
13
  type MuPdf = typeof import('../vendor/mupdf-wasm/mupdf.js')
12
14
 
13
- const _user32 = win.LoadLibrary('user32.dll')
14
- const _gdi32 = win.LoadLibrary('gdi32.dll')
15
- const _comdlg32 = win.LoadLibrary('comdlg32.dll')
16
- if (!_user32 || !_gdi32 || !_comdlg32) {
17
- gui.MessageBox('Failed to load system libraries')
18
- std.exit(0)
19
- }
20
-
21
- function loadProc(lib: win.HMODULE, name: string): number {
22
- const ptr = win.GetProcAddress(lib, name)
23
- if (!ptr) throw new Error('Failed to load ' + name)
24
- return ptr
25
- }
26
-
27
- const GetOpenFileNameW_ = loadProc(_comdlg32, 'GetOpenFileNameW')
28
- const FFI_PTR = ffi.FFI_TYPE_POINTER
29
- const FFI_U32 = ffi.FFI_TYPE_UINT32
30
-
31
- function strToWide(str: string): ArrayBuffer {
32
- const buf = new ArrayBuffer((str.length + 1) * 2)
33
- const dv = new DataView(buf)
34
- for (let i = 0; i < str.length; i++) dv.setUint16(i * 2, str.charCodeAt(i), true)
35
- return buf
36
- }
37
-
38
- function wideToStr(buf: ArrayBuffer): string {
39
- const dv = new DataView(buf)
40
- const chars: number[] = []
41
- for (let i = 0; i < buf.byteLength; i += 2) {
42
- const c = dv.getUint16(i, true)
43
- if (c === 0) break
44
- chars.push(c)
45
- }
46
- return String.fromCharCode(...chars)
47
- }
48
-
49
- function setPtr(dv: DataView, off: number, ptr: number): void {
50
- dv.setUint32(off, ptr & 0xFFFFFFFF, true)
51
- dv.setUint32(off + 4, Math.floor(ptr / 0x100000000), true)
52
- }
53
-
54
- function openPdfFileDialog(owner: number): string | null {
55
- const structBuf = new ArrayBuffer(152)
56
- const sv = new DataView(structBuf)
57
- const fileBuf = new ArrayBuffer(260 * 2)
58
- const filterWide = strToWide('PDF Files\0*.pdf\0All Files\0*.*\0\0')
59
-
60
- sv.setUint32(0, 152, true)
61
- sv.setUint32(8, owner & 0xFFFFFFFF, true)
62
- sv.setUint32(12, Math.floor(owner / 0x100000000), true)
63
-
64
- setPtr(sv, 24, ffi.bufferPtr(filterWide))
65
- setPtr(sv, 48, ffi.bufferPtr(fileBuf))
66
- sv.setUint32(56, 260, true)
67
-
68
- sv.setUint32(96, 0x1000 | 0x0800 | 0x0004, true)
69
-
70
- const ret = ffi.ffiCall(GetOpenFileNameW_, [FFI_PTR], [structBuf], FFI_U32)
15
+ function openPdfFileDialog(owner: MaybePtr<'HWND'>): string | null {
16
+ const fileBuf = WCHAR.alloc(260)
17
+ const filterWide = WCHAR.encode('PDF Files\0*.pdf\0All Files\0*.*\0\0')
18
+ // 缺省字段跳过 = fresh buffer 上留 0
19
+ const ofn: PtrArrayBuffer<'OPENFILENAMEW'> & { __keep?: ArrayBuffer[] } = OPENFILENAMEW.encode({
20
+ lStructSize: OPENFILENAMEW.size,
21
+ hwndOwner: owner,
22
+ lpstrFilter: filterWide.ptr,
23
+ lpstrFile: fileBuf.ptr,
24
+ nMaxFile: 260,
25
+ Flags: 0x1000 | 0x0800 | 0x0004,
26
+ })
27
+ ofn.__keep = [fileBuf, filterWide]
28
+
29
+ const ret = GetOpenFileName(ofn)
71
30
  if (!ret) return null
72
31
 
73
- const path = wideToStr(fileBuf)
32
+ const path = WCHAR.decode(fileBuf)
74
33
  return path.length > 0 ? path : null
75
34
  }
76
35
 
@@ -98,7 +57,7 @@ async function loadMupdf(): Promise<MuPdf | null> {
98
57
  }
99
58
 
100
59
  interface PixmapInfo {
101
- data: ArrayBuffer
60
+ data: PtrArrayBuffer<string>
102
61
  w: number
103
62
  h: number
104
63
  }
@@ -159,7 +118,7 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
159
118
  const dibStride = Math.floor((w * 3 + 3) / 4) * 4
160
119
 
161
120
  const dibSize = h * dibStride
162
- const dibBuffer = new ArrayBuffer(dibSize)
121
+ const dibBuffer = new PtrArrayBuffer(dibSize)
163
122
  const dib = new Uint8Array(dibBuffer)
164
123
 
165
124
  for (let y = 0; y < h; y++) {
@@ -186,7 +145,7 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
186
145
  }
187
146
  }
188
147
 
189
- function App({ mupdf, mainHwnd: hwnd }: { mupdf: MuPdf; mainHwnd: number }) {
148
+ function App({ mupdf, mainHwnd: hwnd }: { mupdf: MuPdf; mainHwnd: gui.HWND }) {
190
149
  const [filePath, setFilePath] = useState('')
191
150
  const [currentPage, setCurrentPage] = useState(0)
192
151
  const [pixmap, setPixmap] = useState<PixmapInfo | undefined>(undefined)
@@ -1,24 +1,8 @@
1
1
  import * as std from 'std';
2
2
  import * as gui from 'gui';
3
- import * as win from 'win';
4
- import * as ffi from 'ffi';
5
- const user32 = win.LoadLibrary('user32.dll');
6
- if (!user32) {
7
- print('LoadLibrary user32 failed');
8
- std.exit(1);
9
- }
10
- function loadProc(lib, name) {
11
- const ptr = win.GetProcAddress(lib, name);
12
- if (!ptr) {
13
- print('GetProcAddress ' + name + ' failed');
14
- std.exit(1);
15
- }
16
- return ptr;
17
- }
18
- const EnumDisplaySettingsA = loadProc(user32, 'EnumDisplaySettingsA');
19
- const ChangeDisplaySettingsA = loadProc(user32, 'ChangeDisplaySettingsA');
20
- /** DEVMODEA used by EnumDisplaySettings; driver reports actual dmSize (often 124). */
21
- const DEVMODE_SIZE = 220;
3
+ import { NULL } from '../lib/ffi/ctype.js';
4
+ import { ChangeDisplaySettings, EnumDisplaySettings } from '../lib/windows/user32.js';
5
+ import { DEVMODEW } from '../lib/windows/structs.js';
22
6
  const DM_PELSWIDTH = 0x00800000;
23
7
  const DM_PELSHEIGHT = 0x01000000;
24
8
  const ENUM_CURRENT_SETTINGS = -1;
@@ -35,35 +19,27 @@ const DISP_CHANGE = {
35
19
  [-6]: 'BADDUALVIEW',
36
20
  };
37
21
  function newDevMode() {
38
- const buf = new ArrayBuffer(DEVMODE_SIZE);
39
- new DataView(buf).setUint16(36, DEVMODE_SIZE, true);
40
- return buf;
41
- }
42
- function enumMode(modeNum, buf) {
43
- return ffi.ffiCall(EnumDisplaySettingsA, [ffi.FFI_TYPE_POINTER, ffi.FFI_TYPE_SINT32, ffi.FFI_TYPE_POINTER], [null, modeNum, buf], ffi.FFI_TYPE_SINT32);
44
- }
45
- function getPels(dv) {
46
- return [dv.getUint32(108, true), dv.getUint32(112, true), dv.getUint32(120, true)];
22
+ // dmSize = 结构自身大小是 Win32 要求(否则 API 拒绝);其余字段由 Enum 就地填充
23
+ return DEVMODEW.encode({ dmSize: DEVMODEW.size });
47
24
  }
48
25
  function applyFromCurrent(w, h, flags, label) {
49
26
  const dm = newDevMode();
50
- if (!enumMode(ENUM_CURRENT_SETTINGS, dm)) {
27
+ if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, dm.ptr)) {
51
28
  print(label + ': EnumDisplaySettings CURRENT failed');
52
29
  return null;
53
30
  }
54
- const dv = new DataView(dm);
55
- const before = getPels(dv);
56
- const size = dv.getUint16(36, true);
57
- const extra = dv.getUint16(38, true);
58
- const fields = dv.getUint32(40, true);
59
- const bpp = dv.getUint32(104, true);
60
- const freq = dv.getUint32(120, true);
61
- print(label + ': base size=' + size + ' extra=' + extra + ' fields=0x' + fields.toString(16) +
62
- ' ' + before[0] + 'x' + before[1] + '@' + freq + ' bpp=' + bpp);
63
- dv.setUint32(40, fields | DM_PELSWIDTH | DM_PELSHEIGHT, true);
64
- dv.setUint32(108, w, true);
65
- dv.setUint32(112, h, true);
66
- const ret = ffi.ffiCall(ChangeDisplaySettingsA, [ffi.FFI_TYPE_POINTER, ffi.FFI_TYPE_UINT32], [dm, flags], ffi.FFI_TYPE_SINT32);
31
+ const cur = DEVMODEW.decode(dm);
32
+ print(label + ': base size=' + cur.dmSize + ' extra=' + cur.dmDriverExtra +
33
+ ' fields=0x' + cur.dmFields.toString(16) +
34
+ ' ' + cur.dmPelsWidth + 'x' + cur.dmPelsHeight +
35
+ '@' + cur.dmDisplayFrequency + ' bpp=' + cur.dmBitsPerPel);
36
+ // 复用同一 buffer 原地改三项(encode 缺省字段跳过 = 保留 Enum 填的其余项)
37
+ DEVMODEW.encode({
38
+ dmFields: cur.dmFields | DM_PELSWIDTH | DM_PELSHEIGHT,
39
+ dmPelsWidth: w,
40
+ dmPelsHeight: h,
41
+ }, dm);
42
+ const ret = ChangeDisplaySettings(dm.ptr, flags);
67
43
  print(label + ': ChangeDisplaySettings ' + w + 'x' + h +
68
44
  ' flags=0x' + flags.toString(16) + ' ret=' + ret + ' (' + (DISP_CHANGE[ret] ?? '?') + ')');
69
45
  return ret;
@@ -78,13 +54,12 @@ print('before GetScreenSize: ' + JSON.stringify(gui.GetScreenSize()));
78
54
  const probe = newDevMode();
79
55
  const modes32 = [];
80
56
  for (let i = 0; i < 200; i++) {
81
- if (!enumMode(i, probe))
57
+ if (!EnumDisplaySettings(NULL, i, probe.ptr))
82
58
  break;
83
- const dv = new DataView(probe);
84
- if (dv.getUint32(104, true) !== 32)
59
+ const dm = DEVMODEW.decode(probe);
60
+ if (dm.dmBitsPerPel !== 32)
85
61
  continue;
86
- const p = getPels(dv);
87
- modes32.push(p[0] + 'x' + p[1] + '@' + p[2]);
62
+ modes32.push(dm.dmPelsWidth + 'x' + dm.dmPelsHeight + '@' + dm.dmDisplayFrequency);
88
63
  }
89
64
  print('32bpp modes sample: ' + modes32.slice(0, 25).join(', ') + (modes32.length > 25 ? ' ...' : ''));
90
65
  const testRet = applyFromCurrent(targetW, targetH, CDS_TEST, 'TEST');
@@ -1,22 +1,9 @@
1
1
  import * as std from 'std'
2
2
  import * as gui from 'gui'
3
- import * as win from 'win'
4
- import * as ffi from 'ffi'
3
+ import { NULL } from '../lib/ffi/ctype.js'
4
+ import { ChangeDisplaySettings, EnumDisplaySettings } from '../lib/windows/user32.js'
5
+ import { DEVMODEW } from '../lib/windows/structs.js'
5
6
 
6
- const user32 = win.LoadLibrary('user32.dll')
7
- if (!user32) { print('LoadLibrary user32 failed'); std.exit(1) }
8
-
9
- function loadProc(lib: win.HMODULE, name: string): number {
10
- const ptr = win.GetProcAddress(lib, name)
11
- if (!ptr) { print('GetProcAddress ' + name + ' failed'); std.exit(1) }
12
- return ptr
13
- }
14
-
15
- const EnumDisplaySettingsA = loadProc(user32, 'EnumDisplaySettingsA')
16
- const ChangeDisplaySettingsA = loadProc(user32, 'ChangeDisplaySettingsA')
17
-
18
- /** DEVMODEA used by EnumDisplaySettings; driver reports actual dmSize (often 124). */
19
- const DEVMODE_SIZE = 220
20
7
  const DM_PELSWIDTH = 0x00800000
21
8
  const DM_PELSHEIGHT = 0x01000000
22
9
  const ENUM_CURRENT_SETTINGS = -1
@@ -34,51 +21,31 @@ const DISP_CHANGE: Record<number, string> = {
34
21
  [-6]: 'BADDUALVIEW',
35
22
  }
36
23
 
37
- function newDevMode(): ArrayBuffer {
38
- const buf = new ArrayBuffer(DEVMODE_SIZE)
39
- new DataView(buf).setUint16(36, DEVMODE_SIZE, true)
40
- return buf
41
- }
42
-
43
- function enumMode(modeNum: number, buf: ArrayBuffer): number {
44
- return ffi.ffiCall(
45
- EnumDisplaySettingsA,
46
- [ffi.FFI_TYPE_POINTER, ffi.FFI_TYPE_SINT32, ffi.FFI_TYPE_POINTER],
47
- [null, modeNum, buf],
48
- ffi.FFI_TYPE_SINT32,
49
- )
50
- }
51
-
52
- function getPels(dv: DataView): [number, number, number] {
53
- return [dv.getUint32(108, true), dv.getUint32(112, true), dv.getUint32(120, true)]
24
+ function newDevMode() {
25
+ // dmSize = 结构自身大小是 Win32 要求(否则 API 拒绝);其余字段由 Enum 就地填充
26
+ return DEVMODEW.encode({ dmSize: DEVMODEW.size })
54
27
  }
55
28
 
56
29
  function applyFromCurrent(w: number, h: number, flags: number, label: string): number | null {
57
30
  const dm = newDevMode()
58
- if (!enumMode(ENUM_CURRENT_SETTINGS, dm)) {
31
+ if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, dm.ptr)) {
59
32
  print(label + ': EnumDisplaySettings CURRENT failed')
60
33
  return null
61
34
  }
62
- const dv = new DataView(dm)
63
- const before = getPels(dv)
64
- const size = dv.getUint16(36, true)
65
- const extra = dv.getUint16(38, true)
66
- const fields = dv.getUint32(40, true)
67
- const bpp = dv.getUint32(104, true)
68
- const freq = dv.getUint32(120, true)
69
- print(label + ': base size=' + size + ' extra=' + extra + ' fields=0x' + fields.toString(16) +
70
- ' ' + before[0] + 'x' + before[1] + '@' + freq + ' bpp=' + bpp)
35
+ const cur = DEVMODEW.decode(dm)
36
+ print(label + ': base size=' + cur.dmSize + ' extra=' + cur.dmDriverExtra +
37
+ ' fields=0x' + cur.dmFields.toString(16) +
38
+ ' ' + cur.dmPelsWidth + 'x' + cur.dmPelsHeight +
39
+ '@' + cur.dmDisplayFrequency + ' bpp=' + cur.dmBitsPerPel)
71
40
 
72
- dv.setUint32(40, fields | DM_PELSWIDTH | DM_PELSHEIGHT, true)
73
- dv.setUint32(108, w, true)
74
- dv.setUint32(112, h, true)
41
+ // 复用同一 buffer 原地改三项(encode 缺省字段跳过 = 保留 Enum 填的其余项)
42
+ DEVMODEW.encode({
43
+ dmFields: cur.dmFields | DM_PELSWIDTH | DM_PELSHEIGHT,
44
+ dmPelsWidth: w,
45
+ dmPelsHeight: h,
46
+ }, dm)
75
47
 
76
- const ret = ffi.ffiCall(
77
- ChangeDisplaySettingsA,
78
- [ffi.FFI_TYPE_POINTER, ffi.FFI_TYPE_UINT32],
79
- [dm, flags],
80
- ffi.FFI_TYPE_SINT32,
81
- )
48
+ const ret = ChangeDisplaySettings(dm.ptr, flags)
82
49
  print(label + ': ChangeDisplaySettings ' + w + 'x' + h +
83
50
  ' flags=0x' + flags.toString(16) + ' ret=' + ret + ' (' + (DISP_CHANGE[ret] ?? '?') + ')')
84
51
  return ret
@@ -96,11 +63,10 @@ print('before GetScreenSize: ' + JSON.stringify(gui.GetScreenSize()))
96
63
  const probe = newDevMode()
97
64
  const modes32: string[] = []
98
65
  for (let i = 0; i < 200; i++) {
99
- if (!enumMode(i, probe)) break
100
- const dv = new DataView(probe)
101
- if (dv.getUint32(104, true) !== 32) continue
102
- const p = getPels(dv)
103
- modes32.push(p[0] + 'x' + p[1] + '@' + p[2])
66
+ if (!EnumDisplaySettings(NULL, i, probe.ptr)) break
67
+ const dm = DEVMODEW.decode(probe)
68
+ if (dm.dmBitsPerPel !== 32) continue
69
+ modes32.push(dm.dmPelsWidth + 'x' + dm.dmPelsHeight + '@' + dm.dmDisplayFrequency)
104
70
  }
105
71
  print('32bpp modes sample: ' + modes32.slice(0, 25).join(', ') + (modes32.length > 25 ? ' ...' : ''))
106
72