quickwin 1.3.0 → 2.1.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.
- package/README.en.md +18 -24
- package/README.md +17 -23
- package/examples/PdfCanvas.js +8 -37
- package/examples/PdfCanvas.tsx +11 -41
- package/examples/exec_server.js +20155 -1420
- package/examples/exec_server.tsx +489 -0
- package/examples/exec_server_worker.js +383 -33
- package/examples/exec_server_worker.ts +408 -30
- package/examples/pdf_preview2.js +25 -82
- package/examples/pdf_preview2.ts +27 -84
- package/examples/pdf_viewer.js +1424 -1180
- package/examples/pdf_viewer.tsx +16 -67
- package/examples/setres.js +22 -47
- package/examples/setres.ts +23 -57
- package/examples/test_gallery.js +1418 -1075
- package/examples/test_react_lazy.js +1391 -1059
- package/examples/test_react_listbox.js +1390 -1058
- package/examples/test_root_window.js +1384 -1052
- package/examples/test_tab.js +1391 -1059
- package/lib/abort.js +70 -0
- package/lib/abort.ts +69 -0
- package/lib/certs.js +219 -0
- package/lib/certs.ts +229 -0
- package/lib/exec-log.js +15 -0
- package/lib/exec-log.ts +30 -0
- package/lib/fetch.js +88 -7
- package/lib/fetch.ts +73 -7
- package/lib/ffi/bind.js +441 -0
- package/lib/ffi/bind.ts +539 -0
- package/lib/ffi/ctype.js +194 -0
- package/lib/ffi/ctype.ts +369 -0
- package/lib/ffi/index.js +6 -0
- package/lib/ffi/index.ts +6 -0
- package/lib/ffi/struct.js +490 -0
- package/lib/ffi/struct.ts +753 -0
- package/lib/http-common.js +43 -5
- package/lib/http-common.ts +48 -6
- package/lib/http-server.js +187 -29
- package/lib/http-server.ts +177 -26
- package/lib/react-qw/components/DateTimePicker.js +18 -37
- package/lib/react-qw/components/Input.js +3 -10
- package/lib/react-qw/components/Link.js +6 -19
- package/lib/react-qw/components/ListView.js +50 -154
- package/lib/react-qw/components/PathPicker.js +28 -88
- package/lib/react-qw/components/ScrollView.js +15 -8
- package/lib/react-qw/components/Slider.js +2 -1
- package/lib/react-qw/components/Tab.js +6 -22
- package/lib/react-qw/components/Tooltip.js +10 -21
- package/lib/react-qw/components/TreeView.js +8 -31
- package/lib/react-qw/index.js +5 -3
- package/lib/react-qw/index.ts +8 -3
- package/lib/react-qw/nmhdr.js +3 -24
- package/lib/react-qw/nmhdr.ts +5 -30
- package/lib/react-qw/props.js +7 -2
- package/lib/react-qw/props.ts +7 -3
- package/lib/react-qw/reconciler.js +23 -13
- package/lib/react-qw/reconciler.ts +22 -13
- package/lib/text-measure.js +20 -23
- package/lib/text-measure.ts +22 -26
- package/lib/websocket.js +44 -4
- package/lib/websocket.ts +40 -4
- package/lib/windows/advapi32.js +53 -0
- package/lib/windows/advapi32.ts +64 -0
- package/lib/windows/comctl32.js +18 -0
- package/lib/windows/comctl32.ts +19 -0
- package/lib/windows/comdlg32.js +8 -0
- package/lib/windows/comdlg32.ts +10 -0
- package/lib/windows/gdi32.js +392 -0
- package/lib/windows/gdi32.ts +420 -0
- package/lib/windows/kernel32.js +262 -0
- package/lib/windows/kernel32.ts +291 -0
- package/lib/windows/msimg32.js +38 -0
- package/lib/windows/msimg32.ts +45 -0
- package/lib/windows/ntdll.js +9 -0
- package/lib/windows/ntdll.ts +11 -0
- package/lib/windows/ole32.js +7 -0
- package/lib/windows/ole32.ts +9 -0
- package/lib/windows/psapi.js +32 -0
- package/lib/windows/psapi.ts +37 -0
- package/lib/windows/shell32.js +13 -0
- package/lib/windows/shell32.ts +16 -0
- package/lib/windows/structs.js +519 -0
- package/lib/windows/structs.ts +566 -0
- package/lib/windows/user32.js +572 -0
- package/lib/windows/user32.ts +607 -0
- package/lib/windows/version.js +29 -0
- package/lib/windows/version.ts +35 -0
- package/lib/windows/winspool.js +71 -0
- package/lib/windows/winspool.ts +80 -0
- package/package.json +1 -1
- package/quickwin.d.ts +31 -40
- package/quickwin_const.d.ts +137 -0
- package/qwin-nowasm-x86.exe +0 -0
- package/qwin-nowasm.exe +0 -0
- package/qwin-x86.exe +0 -0
- package/qwin.exe +0 -0
- package/test/bench_ffi_callraw.js +236 -0
- package/test/bench_ffi_callraw.ts +236 -0
- package/test/bench_ffi_overhead.js +139 -0
- package/test/bench_ffi_overhead.ts +141 -0
- package/test/bench_sendmessage.js +104 -0
- package/test/bench_sendmessage.ts +100 -0
- package/test/bench_sendmessage_nonnull.js +187 -0
- package/test/bench_sendmessage_nonnull.ts +188 -0
- package/test/run.js +19 -4
- package/test/run.ts +20 -5
- package/test/test_basic_fetch.js +29 -0
- package/test/test_basic_fetch.ts +26 -0
- package/test/test_ffi.js +27 -45
- package/test/test_ffi.ts +35 -54
- package/test/test_ffi_abi.js +290 -0
- package/test/test_ffi_abi.ts +274 -0
- package/test/test_ffi_array.js +116 -0
- package/test/test_ffi_array.ts +141 -0
- package/test/test_ffi_bind.js +620 -8
- package/test/test_ffi_bind.ts +630 -8
- package/test/test_ffi_struct.js +632 -88
- package/test/test_ffi_struct.ts +666 -91
- package/test/test_ffi_struct_layout.js +495 -0
- package/test/test_ffi_struct_layout.ts +543 -0
- package/test/test_ffi_user32.js +103 -0
- package/test/test_ffi_user32.ts +113 -0
- package/test/test_ffi_windows.js +101 -0
- package/test/test_ffi_windows.ts +113 -0
- package/test/test_files.js +102 -0
- package/test/test_files.ts +121 -0
- package/test/test_gdi_draw.js +681 -0
- package/test/test_gdi_draw.ts +725 -0
- package/test/test_helper.js +8 -1
- package/test/test_helper.ts +9 -1
- package/test/test_http_import.js +18 -0
- package/test/test_http_import.ts +19 -0
- package/test/test_http_server.js +73 -1
- package/test/test_http_server.ts +75 -1
- package/test/test_ipv6.js +2 -2
- package/test/test_ipv6.ts +2 -2
- package/test/test_net_fetch.js +74 -11
- package/test/test_net_fetch.ts +73 -10
- package/test/test_net_websocket.js +1 -1
- package/test/test_net_websocket.ts +1 -1
- package/test/test_printer.js +137 -0
- package/test/test_printer.ts +148 -0
- package/test/test_proc.js +141 -0
- package/test/test_proc.ts +163 -0
- package/test/test_react_complex.js +1401 -1069
- package/test/test_react_counter.js +1391 -1059
- package/test/test_react_flex.js +1411 -1072
- package/test/test_react_hidden.js +1394 -1062
- package/test/test_react_listview_link.js +1391 -1059
- package/test/test_react_notify.js +18638 -0
- package/test/test_react_render.js +1391 -1059
- package/test/test_registry.js +74 -0
- package/test/test_registry.ts +95 -0
- package/test/test_sysinfo.js +122 -0
- package/test/test_sysinfo.ts +141 -0
- package/test/test_wolfssl_read.js +45 -43
- package/test/test_wolfssl_read.ts +42 -40
- package/test/test_worker_net.js +35 -17
- package/test/test_worker_net.ts +27 -15
- package/tsconfig.json +1 -1
- package/examples/exec_server.ts +0 -80
- package/lib/ffi-bind.js +0 -85
- package/lib/ffi-bind.ts +0 -170
- package/lib/ffi-struct.js +0 -224
- package/lib/ffi-struct.ts +0 -239
- package/lib/win-common-structs.js +0 -39
- package/lib/win-common-structs.ts +0 -41
package/examples/pdf_viewer.tsx
CHANGED
|
@@ -1,86 +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/
|
|
10
|
+
import { OPENFILENAMEW } from '../lib/windows/structs.js'
|
|
11
|
+
import { GetOpenFileName } from '../lib/windows/comdlg32.js'
|
|
11
12
|
|
|
12
13
|
type MuPdf = typeof import('../vendor/mupdf-wasm/mupdf.js')
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
std.exit(0)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function loadProc(lib: win.HMODULE, name: string): number {
|
|
23
|
-
const ptr = win.GetProcAddress(lib, name)
|
|
24
|
-
if (!ptr) throw new Error('Failed to load ' + name)
|
|
25
|
-
return ptr
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const GetOpenFileNameW_ = loadProc(_comdlg32, 'GetOpenFileNameW')
|
|
29
|
-
const FFI_PTR = ffi.FFI_TYPE_POINTER
|
|
30
|
-
const FFI_U32 = ffi.FFI_TYPE_UINT32
|
|
31
|
-
|
|
32
|
-
function strToWide(str: string): ArrayBuffer {
|
|
33
|
-
const buf = new ArrayBuffer((str.length + 1) * 2)
|
|
34
|
-
const dv = new DataView(buf)
|
|
35
|
-
for (let i = 0; i < str.length; i++) dv.setUint16(i * 2, str.charCodeAt(i), true)
|
|
36
|
-
return buf
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function wideToStr(buf: ArrayBuffer): string {
|
|
40
|
-
const dv = new DataView(buf)
|
|
41
|
-
const chars: number[] = []
|
|
42
|
-
for (let i = 0; i < buf.byteLength; i += 2) {
|
|
43
|
-
const c = dv.getUint16(i, true)
|
|
44
|
-
if (c === 0) break
|
|
45
|
-
chars.push(c)
|
|
46
|
-
}
|
|
47
|
-
return String.fromCharCode(...chars)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function openPdfFileDialog(owner: number): string | null {
|
|
51
|
-
const fileBuf = new ArrayBuffer(260 * 2)
|
|
52
|
-
const filterWide = strToWide('PDF Files\0*.pdf\0All Files\0*.*\0\0')
|
|
53
|
-
const ofn: ArrayBuffer & { __keep?: ArrayBuffer[] } = OPENFILENAMEW.write({
|
|
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({
|
|
54
20
|
lStructSize: OPENFILENAMEW.size,
|
|
55
21
|
hwndOwner: owner,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
lpstrCustomFilter: 0,
|
|
59
|
-
nMaxCustFilter: 0,
|
|
60
|
-
nFilterIndex: 0,
|
|
61
|
-
lpstrFile: ffi.bufferPtr(fileBuf),
|
|
22
|
+
lpstrFilter: filterWide.ptr,
|
|
23
|
+
lpstrFile: fileBuf.ptr,
|
|
62
24
|
nMaxFile: 260,
|
|
63
|
-
lpstrFileTitle: 0,
|
|
64
|
-
nMaxFileTitle: 0,
|
|
65
|
-
lpstrInitialDir: 0,
|
|
66
|
-
lpstrTitle: 0,
|
|
67
25
|
Flags: 0x1000 | 0x0800 | 0x0004,
|
|
68
|
-
nFileOffset: 0,
|
|
69
|
-
nFileExtension: 0,
|
|
70
|
-
lpstrDefExt: 0,
|
|
71
|
-
lCustData: 0,
|
|
72
|
-
lpfnHook: 0,
|
|
73
|
-
lpTemplateName: 0,
|
|
74
|
-
pvReserved: 0,
|
|
75
|
-
dwReserved: 0,
|
|
76
|
-
FlagsEx: 0,
|
|
77
26
|
})
|
|
78
27
|
ofn.__keep = [fileBuf, filterWide]
|
|
79
28
|
|
|
80
|
-
const ret =
|
|
29
|
+
const ret = GetOpenFileName(ofn.ptr)
|
|
81
30
|
if (!ret) return null
|
|
82
31
|
|
|
83
|
-
const path =
|
|
32
|
+
const path = WCHAR.decode(fileBuf)
|
|
84
33
|
return path.length > 0 ? path : null
|
|
85
34
|
}
|
|
86
35
|
|
|
@@ -108,7 +57,7 @@ async function loadMupdf(): Promise<MuPdf | null> {
|
|
|
108
57
|
}
|
|
109
58
|
|
|
110
59
|
interface PixmapInfo {
|
|
111
|
-
data:
|
|
60
|
+
data: PtrArrayBuffer<string>
|
|
112
61
|
w: number
|
|
113
62
|
h: number
|
|
114
63
|
}
|
|
@@ -169,7 +118,7 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
|
|
|
169
118
|
const dibStride = Math.floor((w * 3 + 3) / 4) * 4
|
|
170
119
|
|
|
171
120
|
const dibSize = h * dibStride
|
|
172
|
-
const dibBuffer = new
|
|
121
|
+
const dibBuffer = new PtrArrayBuffer(dibSize)
|
|
173
122
|
const dib = new Uint8Array(dibBuffer)
|
|
174
123
|
|
|
175
124
|
for (let y = 0; y < h; y++) {
|
|
@@ -196,7 +145,7 @@ function renderPdfPage(mupdf: MuPdf, filePath: string, pageIndex: number): Pixma
|
|
|
196
145
|
}
|
|
197
146
|
}
|
|
198
147
|
|
|
199
|
-
function App({ mupdf, mainHwnd: hwnd }: { mupdf: MuPdf; mainHwnd:
|
|
148
|
+
function App({ mupdf, mainHwnd: hwnd }: { mupdf: MuPdf; mainHwnd: gui.HWND }) {
|
|
200
149
|
const [filePath, setFilePath] = useState('')
|
|
201
150
|
const [currentPage, setCurrentPage] = useState(0)
|
|
202
151
|
const [pixmap, setPixmap] = useState<PixmapInfo | undefined>(undefined)
|
package/examples/setres.js
CHANGED
|
@@ -1,24 +1,8 @@
|
|
|
1
1
|
import * as std from 'std';
|
|
2
2
|
import * as gui from 'gui';
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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 (!
|
|
27
|
+
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, dm.ptr)) {
|
|
51
28
|
print(label + ': EnumDisplaySettings CURRENT failed');
|
|
52
29
|
return null;
|
|
53
30
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 (!
|
|
57
|
+
if (!EnumDisplaySettings(NULL, i, probe.ptr))
|
|
82
58
|
break;
|
|
83
|
-
const
|
|
84
|
-
if (
|
|
59
|
+
const dm = DEVMODEW.decode(probe);
|
|
60
|
+
if (dm.dmBitsPerPel !== 32)
|
|
85
61
|
continue;
|
|
86
|
-
|
|
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');
|
package/examples/setres.ts
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import * as std from 'std'
|
|
2
2
|
import * as gui from 'gui'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
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()
|
|
38
|
-
|
|
39
|
-
|
|
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 (!
|
|
31
|
+
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, dm.ptr)) {
|
|
59
32
|
print(label + ': EnumDisplaySettings CURRENT failed')
|
|
60
33
|
return null
|
|
61
34
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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 =
|
|
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 (!
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
|
|
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
|
|