quickwin 2.2.0 → 2.3.1

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 (111) hide show
  1. package/README.en.md +7 -7
  2. package/README.md +7 -7
  3. package/constants.ts +1070 -0
  4. package/enum_map.d.ts +130 -0
  5. package/examples/PdfCanvas.js +2 -2
  6. package/examples/PdfCanvas.tsx +3 -2
  7. package/examples/{execd.js → execd/main.js} +717 -148
  8. package/examples/execd/tray.js +192 -0
  9. package/examples/{execd_worker.js → execd/worker.js} +7 -7
  10. package/examples/pdf_preview2.js +46 -46
  11. package/examples/pdf_preview2.ts +55 -54
  12. package/examples/pdf_viewer.js +34 -19
  13. package/examples/pdf_viewer.tsx +6 -5
  14. package/examples/test_gallery.js +35 -20
  15. package/examples/test_gallery.tsx +9 -8
  16. package/examples/test_react_lazy.js +34 -19
  17. package/examples/test_react_lazy.tsx +7 -6
  18. package/examples/test_react_listbox.js +34 -19
  19. package/examples/test_react_listbox.tsx +8 -7
  20. package/examples/test_root_window.js +34 -19
  21. package/examples/test_root_window.tsx +5 -5
  22. package/examples/test_tab.js +34 -19
  23. package/examples/test_tab.tsx +7 -6
  24. package/examples/tray_demo.js +8 -8
  25. package/examples/tray_demo.tsx +9 -8
  26. package/lib/dumpRects.js +2 -2
  27. package/lib/dumpRects.ts +3 -2
  28. package/lib/fetch.js +15 -15
  29. package/lib/fetch.ts +16 -15
  30. package/lib/ffi/bind.js +3 -3
  31. package/lib/ffi/bind.ts +3 -3
  32. package/lib/http-server.js +54 -29
  33. package/lib/http-server.ts +56 -27
  34. package/lib/react-qw/components/Button.js +2 -2
  35. package/lib/react-qw/components/CheckBox.js +4 -4
  36. package/lib/react-qw/components/ComboBox.js +10 -10
  37. package/lib/react-qw/components/DateTimePicker.js +12 -12
  38. package/lib/react-qw/components/Input.js +7 -7
  39. package/lib/react-qw/components/Link.js +4 -4
  40. package/lib/react-qw/components/ListBox.js +12 -12
  41. package/lib/react-qw/components/ListView.js +35 -35
  42. package/lib/react-qw/components/PathPicker.js +3 -3
  43. package/lib/react-qw/components/ProgressBar.js +4 -4
  44. package/lib/react-qw/components/RadioButton.js +4 -4
  45. package/lib/react-qw/components/ScrollView.js +28 -28
  46. package/lib/react-qw/components/Slider.js +11 -11
  47. package/lib/react-qw/components/Tab.js +10 -10
  48. package/lib/react-qw/components/Tooltip.js +8 -8
  49. package/lib/react-qw/components/TreeView.js +20 -20
  50. package/lib/react-qw/index.js +5 -5
  51. package/lib/react-qw/index.ts +6 -5
  52. package/lib/react-qw/props.js +4 -4
  53. package/lib/react-qw/props.ts +5 -4
  54. package/lib/react-qw/reconciler.js +10 -10
  55. package/lib/react-qw/reconciler.ts +11 -10
  56. package/lib/text-measure.js +3 -3
  57. package/lib/text-measure.ts +4 -3
  58. package/lib/websocket.js +17 -17
  59. package/lib/websocket.ts +18 -17
  60. package/lib/windows/advapi32.js +7 -7
  61. package/lib/windows/advapi32.ts +7 -7
  62. package/lib/windows/gdi32.js +16 -16
  63. package/lib/windows/gdi32.ts +16 -16
  64. package/lib/windows/kernel32.js +41 -2
  65. package/lib/windows/kernel32.ts +45 -2
  66. package/lib/windows/shell32.js +24 -3
  67. package/lib/windows/shell32.ts +27 -4
  68. package/lib/windows/structs.js +54 -0
  69. package/lib/windows/structs.ts +63 -1
  70. package/lib/windows/user32.js +18 -6
  71. package/lib/windows/user32.ts +18 -6
  72. package/lib/windows/winspool.js +3 -3
  73. package/lib/windows/winspool.ts +3 -3
  74. package/package.json +4 -3
  75. package/quickwin.d.ts +32 -10
  76. package/qwin-nowasm-x86.exe +0 -0
  77. package/qwin-nowasm.exe +0 -0
  78. package/qwin-x86.exe +0 -0
  79. package/qwin.exe +0 -0
  80. package/test/test_ffi_bind.js +7 -7
  81. package/test/test_ffi_bind.ts +8 -8
  82. package/test/test_ffi_struct.js +2 -2
  83. package/test/test_ffi_struct.ts +3 -3
  84. package/test/test_ffi_windows.js +1 -1
  85. package/test/test_ffi_windows.ts +1 -1
  86. package/test/test_files.js +7 -7
  87. package/test/test_files.ts +8 -8
  88. package/test/test_gdi_draw.js +51 -51
  89. package/test/test_gdi_draw.ts +57 -57
  90. package/test/test_http_server.js +3 -3
  91. package/test/test_http_server.ts +4 -3
  92. package/test/test_ipv6.js +3 -3
  93. package/test/test_ipv6.ts +4 -3
  94. package/test/test_net_event.js +3 -3
  95. package/test/test_net_event.ts +4 -3
  96. package/test/test_printer.js +4 -4
  97. package/test/test_printer.ts +5 -5
  98. package/test/test_react_complex.js +36 -21
  99. package/test/test_react_counter.js +34 -19
  100. package/test/test_react_flex.js +36 -21
  101. package/test/test_react_hidden.js +34 -19
  102. package/test/test_react_listview_link.js +35 -20
  103. package/test/test_react_notify.js +52 -37
  104. package/test/test_react_render.js +34 -19
  105. package/test/test_registry.js +6 -6
  106. package/test/test_registry.ts +8 -8
  107. package/test/test_wolfssl_read.js +8 -8
  108. package/test/test_wolfssl_read.ts +9 -8
  109. package/examples/execd.tsx +0 -798
  110. package/examples/execd_worker.ts +0 -127
  111. package/quickwin_const.d.ts +0 -1063
@@ -14,7 +14,7 @@ const H = 240;
14
14
  export const suite = {
15
15
  name: 'gdi-draw',
16
16
  run: (t) => {
17
- // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 execd_worker 截屏同型)——
17
+ // —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 execd/worker 截屏同型)——
18
18
  t.section('setup: memory DC + 32bpp bitmap');
19
19
  const screen = GetDC(NULL);
20
20
  const mem = CreateCompatibleDC(screen);
@@ -47,16 +47,16 @@ export const suite = {
47
47
  return (pxU8[i] << 16) | (pxU8[i + 1] << 8) | pxU8[i + 2]; // B,G,R → COLORREF
48
48
  };
49
49
  const clearWhite = () => {
50
- PatBlt(mem, 0, 0, W, H, 16711778 /* gui.RasterOp.WHITENESS */); // 与画刷无关的整白
50
+ PatBlt(mem, 0, 0, W, H, 16711778 /* RasterOp.WHITENESS */); // 与画刷无关的整白
51
51
  readPx();
52
52
  };
53
53
  clearWhite();
54
54
  t.check('baseline = white', WHITE, px(5, 5));
55
55
  t.checkTrue('GetDIBits full read', pxOk);
56
56
  t.section('state: return-previous semantics');
57
- t.check('fresh DC default bkMode = OPAQUE', 2 /* gui.BackgroundMode.OPAQUE */, SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */));
58
- t.check('SetBkMode returns previous', 2 /* gui.BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* gui.BackgroundMode.TRANSPARENT */));
59
- SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */);
57
+ t.check('fresh DC default bkMode = OPAQUE', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */));
58
+ t.check('SetBkMode returns previous', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */));
59
+ SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
60
60
  SetTextColor(mem, RED); // 返回默认色(不假设)
61
61
  t.check('SetTextColor returns previous', RED, SetTextColor(mem, BLUE));
62
62
  SetTextColor(mem, 0);
@@ -66,7 +66,7 @@ export const suite = {
66
66
  // 类型专用块(只过 tsc、不执行)
67
67
  const typeOnly = () => {
68
68
  // @ts-expect-error 跨枚举 nominal:BackgroundMode 成员进不了 PenStyle 位
69
- CreatePen(1 /* gui.BackgroundMode.TRANSPARENT */, 1, 0);
69
+ CreatePen(1 /* BackgroundMode.TRANSPARENT */, 1, 0);
70
70
  // @ts-expect-error '<HDC>ptr!' 禁空位不收 NULL
71
71
  Rectangle(NULL, 0, 0, 1, 1);
72
72
  // @ts-expect-error encoder 数组位不收裸对象(单对象对 C 是越界基址)
@@ -76,37 +76,37 @@ export const suite = {
76
76
  // @ts-expect-error <WCHAR>ptr 文本位收 string / NULL,不收裸数字
77
77
  TextOut(0, 0, 0, 123, 1);
78
78
  // @ts-expect-error 跨枚举 nominal:PenStyle 成员进不了 StockObject 位
79
- GetStockObject(0 /* gui.PenStyle.SOLID */);
79
+ GetStockObject(0 /* PenStyle.SOLID */);
80
80
  // @ts-expect-error 跨枚举 nominal:HatchStyle 成员进不了 PolyFillMode 位
81
- SetPolyFillMode(0, 4 /* gui.HatchStyle.CROSS */);
81
+ SetPolyFillMode(0, 4 /* HatchStyle.CROSS */);
82
82
  // @ts-expect-error u32@RasterOp 标注拦枚举外光栅码(字面量不匹配成员值)
83
83
  PatBlt(0, 0, 0, 1, 1, 0x123456);
84
84
  // @ts-expect-error '<SIZE>ptr!' 出参位不收 NULL
85
85
  GetTextExtentPoint32(0, 'x', 1, NULL);
86
86
  // @ts-expect-error 跨枚举 nominal:StretchBltMode 成员进不了 ArcDirection 位
87
- SetArcDirection(0, 4 /* gui.StretchBltMode.HALFTONE */);
87
+ SetArcDirection(0, 4 /* StretchBltMode.HALFTONE */);
88
88
  };
89
89
  t.checkTrue('type-only block wired', typeof typeOnly === 'function');
90
90
  t.section('SaveDC/RestoreDC: state stack rollback');
91
91
  // 先定基态(断言不依赖前面 section 的收尾值)
92
92
  SetTextColor(mem, 0);
93
- SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */);
93
+ SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
94
94
  SetBkColor(mem, WHITE);
95
95
  const saved = SaveDC(mem);
96
96
  t.checkTrue(`SaveDC state id ≠ 0 (${saved})`, saved !== 0);
97
97
  // 打乱:三项绘图状态 + 换一支笔
98
98
  SetTextColor(mem, RED);
99
- SetBkMode(mem, 1 /* gui.BackgroundMode.TRANSPARENT */);
99
+ SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */);
100
100
  SetBkColor(mem, BLUE);
101
- const junkPen = CreatePen(1 /* gui.PenStyle.DASH */, 1, GREEN);
101
+ const junkPen = CreatePen(1 /* PenStyle.DASH */, 1, GREEN);
102
102
  SelectObject(mem, junkPen);
103
103
  t.checkTrue('RestoreDC ok', RestoreDC(mem, saved) !== 0);
104
104
  DeleteObject(junkPen); // 恢复后已卸下,可安全删
105
105
  // 逐项回滚断言:各 Set 返回的就是回滚后的当前值
106
106
  t.check('text color rolled back', 0, SetTextColor(mem, RED));
107
107
  SetTextColor(mem, 0);
108
- t.check('bkMode rolled back', 2 /* gui.BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* gui.BackgroundMode.TRANSPARENT */));
109
- SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */);
108
+ t.check('bkMode rolled back', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */));
109
+ SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
110
110
  t.check('bkColor rolled back', WHITE, SetBkColor(mem, RED));
111
111
  SetBkColor(mem, WHITE);
112
112
  t.section('Rectangle: brush fill (inside/outside pixels)');
@@ -123,7 +123,7 @@ export const suite = {
123
123
  DeleteObject(brush);
124
124
  t.section('Polyline: encoder array position + NULL passthrough');
125
125
  clearWhite();
126
- const pen = CreatePen(0 /* gui.PenStyle.SOLID */, 1, GREEN);
126
+ const pen = CreatePen(0 /* PenStyle.SOLID */, 1, GREEN);
127
127
  t.checkTrue('pen created', !!pen);
128
128
  const oldPen = SelectObject(mem, pen);
129
129
  t.checkTrue('Polyline success', Polyline(mem, [{ x: 0, y: 100 }, { x: 100, y: 100 }], 2) !== 0);
@@ -161,9 +161,9 @@ export const suite = {
161
161
  SelectObject(mem, oldPen);
162
162
  DeleteObject(pen);
163
163
  t.section('SetROP2: R2_XORPEN reversible');
164
- PatBlt(mem, 0, 0, W, H, 66 /* gui.RasterOp.BLACKNESS */); // 黑底:黑^绿=绿,绿^绿=黑
165
- t.check('default raster mode = R2_COPYPEN', 13 /* gui.RasterMode.R2_COPYPEN */, SetROP2(mem, 7 /* gui.RasterMode.R2_XORPEN */)); // 返回旧值 = 默认,同时设为 XOR
166
- const xorPen = CreatePen(0 /* gui.PenStyle.SOLID */, 1, GREEN);
164
+ PatBlt(mem, 0, 0, W, H, 66 /* RasterOp.BLACKNESS */); // 黑底:黑^绿=绿,绿^绿=黑
165
+ t.check('default raster mode = R2_COPYPEN', 13 /* RasterMode.R2_COPYPEN */, SetROP2(mem, 7 /* RasterMode.R2_XORPEN */)); // 返回旧值 = 默认,同时设为 XOR
166
+ const xorPen = CreatePen(0 /* PenStyle.SOLID */, 1, GREEN);
167
167
  const xorOld = SelectObject(mem, xorPen);
168
168
  MoveToEx(mem, 10, 200, NULL);
169
169
  LineTo(mem, 100, 200);
@@ -175,7 +175,7 @@ export const suite = {
175
175
  t.check('second pass cancels back to black', BLACK, px(50, 200));
176
176
  SelectObject(mem, xorOld);
177
177
  DeleteObject(xorPen);
178
- SetROP2(mem, 13 /* gui.RasterMode.R2_COPYPEN */); // 恢复
178
+ SetROP2(mem, 13 /* RasterMode.R2_COPYPEN */); // 恢复
179
179
  t.section('Polygon: fill + outline (auto-close)');
180
180
  clearWhite();
181
181
  const pBrush = CreateSolidBrush(BLUE);
@@ -205,7 +205,7 @@ export const suite = {
205
205
  // 圆 (100,100)-(200,200) 心 (150,150) r=50;起 12 点 (150,100) → 终 9 点 (100,150):
206
206
  // GDI 默认逆时针 12→11→10→9 = 左上 90° 弧(SetArcDirection 可改,见 MSDN Arc)
207
207
  clearWhite();
208
- const arcPen = CreatePen(0 /* gui.PenStyle.SOLID */, 1, RED);
208
+ const arcPen = CreatePen(0 /* PenStyle.SOLID */, 1, RED);
209
209
  const arcOldPen = SelectObject(mem, arcPen);
210
210
  Arc(mem, 100, 100, 200, 200, 150, 100, 100, 150);
211
211
  readPx();
@@ -247,13 +247,13 @@ export const suite = {
247
247
  clearWhite();
248
248
  const dirBrush = CreateSolidBrush(RED);
249
249
  const dirOldB = SelectObject(mem, dirBrush);
250
- t.check('default arc direction = counterclockwise', 1 /* gui.ArcDirection.COUNTERCLOCKWISE */, GetArcDirection(mem));
251
- t.check('SetArcDirection returns previous', 1 /* gui.ArcDirection.COUNTERCLOCKWISE */, SetArcDirection(mem, 2 /* gui.ArcDirection.CLOCKWISE */));
250
+ t.check('default arc direction = counterclockwise', 1 /* ArcDirection.COUNTERCLOCKWISE */, GetArcDirection(mem));
251
+ t.check('SetArcDirection returns previous', 1 /* ArcDirection.COUNTERCLOCKWISE */, SetArcDirection(mem, 2 /* ArcDirection.CLOCKWISE */));
252
252
  Pie(mem, 100, 100, 200, 200, 150, 100, 100, 150); // 起 12 点终 9 点:顺时针 → 右下 270°
253
253
  readPx();
254
254
  t.check('clockwise sweep fills opposite side', RED, px(180, 180));
255
255
  t.check('clockwise sweep skips upper-left', WHITE, px(118, 128));
256
- SetArcDirection(mem, 1 /* gui.ArcDirection.COUNTERCLOCKWISE */); // 恢复默认
256
+ SetArcDirection(mem, 1 /* ArcDirection.COUNTERCLOCKWISE */); // 恢复默认
257
257
  SelectObject(mem, dirOldB);
258
258
  DeleteObject(dirBrush);
259
259
  t.section('SetPolyFillMode: ALTERNATE vs WINDING (pentagram)');
@@ -265,7 +265,7 @@ export const suite = {
265
265
  V.push({ x: Math.round(150 + 55 * Math.cos(a)), y: Math.round(150 + 55 * Math.sin(a)) });
266
266
  }
267
267
  const star = [V[0], V[2], V[4], V[1], V[3]];
268
- t.check('default fill mode = ALTERNATE', 1 /* gui.PolyFillMode.ALTERNATE */, SetPolyFillMode(mem, 1 /* gui.PolyFillMode.ALTERNATE */));
268
+ t.check('default fill mode = ALTERNATE', 1 /* PolyFillMode.ALTERNATE */, SetPolyFillMode(mem, 1 /* PolyFillMode.ALTERNATE */));
269
269
  const starBrush = CreateSolidBrush(RED);
270
270
  const starOldB = SelectObject(mem, starBrush);
271
271
  Polygon(mem, star, 5);
@@ -279,18 +279,18 @@ export const suite = {
279
279
  }
280
280
  t.checkTrue(`ALTERNATE: star drawn (${starRed}px)`, starRed > 200);
281
281
  t.check('ALTERNATE: center hollow (even-odd)', WHITE, px(150, 150));
282
- SetPolyFillMode(mem, 2 /* gui.PolyFillMode.WINDING */);
282
+ SetPolyFillMode(mem, 2 /* PolyFillMode.WINDING */);
283
283
  clearWhite();
284
284
  Polygon(mem, star, 5);
285
285
  readPx();
286
286
  t.check('WINDING: center filled (nonzero)', RED, px(150, 150));
287
287
  SelectObject(mem, starOldB);
288
288
  DeleteObject(starBrush);
289
- SetPolyFillMode(mem, 1 /* gui.PolyFillMode.ALTERNATE */); // 恢复默认
289
+ SetPolyFillMode(mem, 1 /* PolyFillMode.ALTERNATE */); // 恢复默认
290
290
  t.section('GetStockObject: stock objects, outline-only shape');
291
291
  clearWhite();
292
- const hollow = GetStockObject(5 /* gui.StockObject.NULL_BRUSH */);
293
- const stkPen = GetStockObject(7 /* gui.StockObject.BLACK_PEN */);
292
+ const hollow = GetStockObject(5 /* StockObject.NULL_BRUSH */);
293
+ const stkPen = GetStockObject(7 /* StockObject.BLACK_PEN */);
294
294
  t.checkTrue(`stock handles non-zero (0x${hollow.toString(16)}, 0x${stkPen.toString(16)})`, hollow !== 0 && stkPen !== 0);
295
295
  const stockOldBrush = SelectObject(mem, hollow);
296
296
  const stockOldPen = SelectObject(mem, stkPen);
@@ -318,8 +318,8 @@ export const suite = {
318
318
  // stock 对象是系统共享的,不 DeleteObject
319
319
  t.section('CreateHatchBrush: textured fill');
320
320
  clearWhite();
321
- SetBkMode(mem, 1 /* gui.BackgroundMode.TRANSPARENT */); // 间隙透底 = 白
322
- const hatch = CreateHatchBrush(0 /* gui.HatchStyle.HORIZONTAL */, RED);
321
+ SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */); // 间隙透底 = 白
322
+ const hatch = CreateHatchBrush(0 /* HatchStyle.HORIZONTAL */, RED);
323
323
  t.checkTrue('hatch brush created', hatch !== 0);
324
324
  const hatchOldB = SelectObject(mem, hatch);
325
325
  Rectangle(mem, 20, 20, 120, 60);
@@ -343,7 +343,7 @@ export const suite = {
343
343
  t.check('no other colors in hatch', 0, hOther);
344
344
  SelectObject(mem, hatchOldB);
345
345
  DeleteObject(hatch);
346
- SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */);
346
+ SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
347
347
  t.section('FrameRect/InvertRect: border and invert (user32)');
348
348
  clearWhite();
349
349
  const frBrush = CreateSolidBrush(RED);
@@ -372,15 +372,15 @@ export const suite = {
372
372
  const stOldBmp = SelectObject(stTmp, stBmp);
373
373
  const stFill = CreateSolidBrush(RED);
374
374
  SelectObject(stTmp, stFill);
375
- PatBlt(stTmp, 0, 0, 4, 4, 15728673 /* gui.RasterOp.PATCOPY */); // 源 4×4 全红
376
- t.checkTrue('StretchBlt ok', StretchBlt(mem, 10, 10, 40, 40, stTmp, 0, 0, 4, 4, 13369376 /* gui.RasterOp.SRCCOPY */) !== 0);
375
+ PatBlt(stTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 源 4×4 全红
376
+ t.checkTrue('StretchBlt ok', StretchBlt(mem, 10, 10, 40, 40, stTmp, 0, 0, 4, 4, 13369376 /* RasterOp.SRCCOPY */) !== 0);
377
377
  readPx();
378
378
  t.check('scaled center red', RED, px(30, 30));
379
379
  t.check('scaled near-origin red', RED, px(11, 11));
380
380
  t.check('outside target untouched', WHITE, px(60, 30));
381
381
  const stMode0 = GetStretchBltMode(mem);
382
- t.check('SetStretchBltMode returns current', stMode0, SetStretchBltMode(mem, 4 /* gui.StretchBltMode.HALFTONE */));
383
- t.check('GetStretchBltMode = HALFTONE', 4 /* gui.StretchBltMode.HALFTONE */, GetStretchBltMode(mem));
382
+ t.check('SetStretchBltMode returns current', stMode0, SetStretchBltMode(mem, 4 /* StretchBltMode.HALFTONE */));
383
+ t.check('GetStretchBltMode = HALFTONE', 4 /* StretchBltMode.HALFTONE */, GetStretchBltMode(mem));
384
384
  SelectObject(stTmp, stOldBmp);
385
385
  DeleteObject(stFill);
386
386
  DeleteObject(stBmp);
@@ -396,11 +396,11 @@ export const suite = {
396
396
  const pkOldBmp = SelectObject(pkTmp, pkBmp);
397
397
  const pkRed = CreateSolidBrush(RED);
398
398
  SelectObject(pkTmp, pkRed);
399
- PatBlt(pkTmp, 0, 0, 4, 4, 15728673 /* gui.RasterOp.PATCOPY */); // 红底
399
+ PatBlt(pkTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 红底
400
400
  const pkWhite = CreateSolidBrush(WHITE);
401
401
  SelectObject(pkTmp, pkWhite);
402
- PatBlt(pkTmp, 2, 0, 2, 2, 15728673 /* gui.RasterOp.PATCOPY */); // 挖两白角 = 2×2 棋盘
403
- PatBlt(pkTmp, 0, 2, 2, 2, 15728673 /* gui.RasterOp.PATCOPY */);
402
+ PatBlt(pkTmp, 2, 0, 2, 2, 15728673 /* RasterOp.PATCOPY */); // 挖两白角 = 2×2 棋盘
403
+ PatBlt(pkTmp, 0, 2, 2, 2, 15728673 /* RasterOp.PATCOPY */);
404
404
  SelectObject(pkTmp, pkOldBmp); // 位图退出选入状态
405
405
  const pkPat = CreatePatternBrush(pkBmp);
406
406
  t.checkTrue('pattern brush created', pkPat !== 0);
@@ -441,7 +441,7 @@ export const suite = {
441
441
  t.check('dib bottom rows blue', BLUE, px(21, 23));
442
442
  t.check('dib outside untouched', WHITE, px(30, 21));
443
443
  clearWhite();
444
- t.checkTrue('StretchDIBits ok', StretchDIBits(mem, 20, 20, 40, 40, 0, 0, 4, 4, dibBits, dibBmi, 0, 13369376 /* gui.RasterOp.SRCCOPY */) === 4);
444
+ t.checkTrue('StretchDIBits ok', StretchDIBits(mem, 20, 20, 40, 40, 0, 0, 4, 4, dibBits, dibBmi, 0, 13369376 /* RasterOp.SRCCOPY */) === 4);
445
445
  readPx();
446
446
  t.check('stretched top half red', RED, px(40, 30));
447
447
  t.check('stretched bottom half blue', BLUE, px(40, 50));
@@ -457,7 +457,7 @@ export const suite = {
457
457
  const plgOldB = SelectObject(plgTmp, plgBmp);
458
458
  const plgRed = CreateSolidBrush(RED);
459
459
  SelectObject(plgTmp, plgRed);
460
- PatBlt(plgTmp, 0, 0, 40, 40, 15728673 /* gui.RasterOp.PATCOPY */); // 源 40×40 全红
460
+ PatBlt(plgTmp, 0, 0, 40, 40, 15728673 /* RasterOp.PATCOPY */); // 源 40×40 全红
461
461
  // 三点 TL(40,60) TR(160,60) BL(70,160) → 方向 s(120,0)+t(30,100),中心 (115,110)
462
462
  t.checkTrue('PlgBlt ok', PlgBlt(mem, [{ x: 40, y: 60 }, { x: 160, y: 60 }, { x: 70, y: 160 }], plgTmp, 0, 0, 40, 40, NULL, 0, 0) !== 0);
463
463
  readPx();
@@ -478,7 +478,7 @@ export const suite = {
478
478
  const mkOldB = SelectObject(mkTmp, mkBmp);
479
479
  const mkRed = CreateSolidBrush(RED);
480
480
  SelectObject(mkTmp, mkRed);
481
- PatBlt(mkTmp, 0, 0, 4, 4, 15728673 /* gui.RasterOp.PATCOPY */); // 源 4×4 全红
481
+ PatBlt(mkTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 源 4×4 全红
482
482
  // 1bpp 掩码 4×4:行按 word(2B) 对齐(CreateBitmap 惯例,非 DIB 的 4B)——
483
483
  // 行 0/2 = 0xFF(白)、行 1/3 = 0x00(黑)
484
484
  const mkBits = new PtrArrayBuffer(8);
@@ -487,9 +487,9 @@ export const suite = {
487
487
  mkU8[4] = 0xFF;
488
488
  const mask = CreateBitmap(4, 4, 1, 1, mkBits);
489
489
  t.checkTrue('CreateBitmap(1bpp) ok', mask !== 0);
490
- PatBlt(mem, 30, 30, 4, 4, 66 /* gui.RasterOp.BLACKNESS */); // 目标底黑 → back 白可辨
490
+ PatBlt(mem, 30, 30, 4, 4, 66 /* RasterOp.BLACKNESS */); // 目标底黑 → back 白可辨
491
491
  // MAKEROP4(fore=SRCCOPY 取源, back=WHITENESS 画白):back 码在 bit31..24、fore 在 bit23..16
492
- const rop4 = (((16711778 /* gui.RasterOp.WHITENESS */ << 8) & 0xFF000000) | 13369376 /* gui.RasterOp.SRCCOPY */) >>> 0;
492
+ const rop4 = (((16711778 /* RasterOp.WHITENESS */ << 8) & 0xFF000000) | 13369376 /* RasterOp.SRCCOPY */) >>> 0;
493
493
  t.checkTrue('MaskBlt ok', MaskBlt(mem, 30, 30, 4, 4, mkTmp, 0, 0, mask, 0, 0, rop4) !== 0);
494
494
  readPx();
495
495
  t.check('mask row0 = fore (red)', RED, px(31, 30));
@@ -512,10 +512,10 @@ export const suite = {
512
512
  const trOldB = SelectObject(trTmp, trBmp);
513
513
  const trRed = CreateSolidBrush(RED);
514
514
  SelectObject(trTmp, trRed);
515
- PatBlt(trTmp, 0, 0, 20, 16, 15728673 /* gui.RasterOp.PATCOPY */); // 左半红
515
+ PatBlt(trTmp, 0, 0, 20, 16, 15728673 /* RasterOp.PATCOPY */); // 左半红
516
516
  const trBlue = CreateSolidBrush(BLUE);
517
517
  SelectObject(trTmp, trBlue);
518
- PatBlt(trTmp, 20, 0, 20, 16, 15728673 /* gui.RasterOp.PATCOPY */); // 右半蓝 = 键色
518
+ PatBlt(trTmp, 20, 0, 20, 16, 15728673 /* RasterOp.PATCOPY */); // 右半蓝 = 键色
519
519
  t.checkTrue('TransparentBlt ok', TransparentBlt(mem, 20, 20, 40, 16, trTmp, 0, 0, 40, 16, BLUE) !== 0);
520
520
  readPx();
521
521
  t.check('non-key pixels copied (red)', RED, px(25, 25));
@@ -538,7 +538,7 @@ export const suite = {
538
538
  const abOldB = SelectObject(abTmp, abBmp);
539
539
  const abGreen = CreateSolidBrush(GREEN);
540
540
  SelectObject(abTmp, abGreen);
541
- PatBlt(abTmp, 0, 0, 40, 16, 15728673 /* gui.RasterOp.PATCOPY */); // 源 = 纯绿(不透明)
541
+ PatBlt(abTmp, 0, 0, 40, 16, 15728673 /* RasterOp.PATCOPY */); // 源 = 纯绿(不透明)
542
542
  // 完全覆盖:SourceConstantAlpha=255、无调制(BlendFlags=0)、BlendOp=AC_SRC_OVER(0)
543
543
  t.checkTrue('AlphaBlend full alpha ok', AlphaBlend(mem, 20, 20, 40, 16, abTmp, 0, 0, 40, 16, { BlendOp: 0, BlendFlags: 0, SourceConstantAlpha: 255, AlphaFormat: 0 }) !== 0);
544
544
  readPx();
@@ -565,7 +565,7 @@ export const suite = {
565
565
  t.section('TextOut: transparent background + text color');
566
566
  clearWhite();
567
567
  SetBkColor(mem, BLUE); // 衬底设蓝:若 TRANSPARENT 未生效,字底必现蓝块
568
- SetBkMode(mem, 1 /* gui.BackgroundMode.TRANSPARENT */);
568
+ SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */);
569
569
  SetTextColor(mem, RED);
570
570
  t.checkTrue('TextOut success', TextOut(mem, 20, 100, 'Hello GDI', 9) !== 0);
571
571
  readPx();
@@ -583,7 +583,7 @@ export const suite = {
583
583
  }
584
584
  t.checkTrue(`glyph pixels rendered (red=${redPx})`, redPx > 20);
585
585
  t.checkTrue(`transparent bg: zero blue backdrop (blue=${bluePx})`, bluePx === 0);
586
- SetBkMode(mem, 2 /* gui.BackgroundMode.OPAQUE */);
586
+ SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
587
587
  SetBkColor(mem, WHITE);
588
588
  SetTextColor(mem, 0);
589
589
  t.section('text metrics/align: extent + SetTextAlign + ExtTextOut');
@@ -603,7 +603,7 @@ export const suite = {
603
603
  t.checkTrue(`tmAveCharWidth sane (${tmv.tmAveCharWidth})`, (tmv.tmAveCharWidth ?? 0) >= 4 && (tmv.tmAveCharWidth ?? 0) <= 48);
604
604
  // (c) SetTextAlign 右对齐:字形全部落在锚点左侧
605
605
  SetTextColor(mem, RED);
606
- t.check('default align = 0 (LEFT|TOP|NOUPDATECP)', 0, SetTextAlign(mem, 2 /* gui.TextAlign.TA_RIGHT */));
606
+ t.check('default align = 0 (LEFT|TOP|NOUPDATECP)', 0, SetTextAlign(mem, 2 /* TextAlign.TA_RIGHT */));
607
607
  TextOut(mem, 200, 100, 'Right', 5);
608
608
  readPx();
609
609
  let rRight = 0;
@@ -621,12 +621,12 @@ export const suite = {
621
621
  }
622
622
  t.checkTrue(`right-aligned glyphs left of anchor (red=${rRight})`, rRight > 10);
623
623
  t.check('no glyphs right of anchor', 0, rWrong);
624
- SetTextAlign(mem, 0 /* gui.TextAlign.TA_LEFT */); // 恢复 0
624
+ SetTextAlign(mem, 0 /* TextAlign.TA_LEFT */); // 恢复 0
625
625
  SetTextColor(mem, 0);
626
626
  // (d) ExtTextOut ETO_OPAQUE 衬底(lprc 对象形直传 = encoder 入参位)
627
627
  SetTextColor(mem, RED);
628
628
  SetBkColor(mem, BLUE);
629
- t.checkTrue('ExtTextOut ETO_OPAQUE ok', ExtTextOut(mem, 20, 100, 2 /* gui.TextOutOptions.ETO_OPAQUE */, { left: 18, top: 98, right: 100, bottom: 118 }, 'Opaque', 6, NULL) !== 0);
629
+ t.checkTrue('ExtTextOut ETO_OPAQUE ok', ExtTextOut(mem, 20, 100, 2 /* TextOutOptions.ETO_OPAQUE */, { left: 18, top: 98, right: 100, bottom: 118 }, 'Opaque', 6, NULL) !== 0);
630
630
  readPx();
631
631
  let oBlue = 0;
632
632
  let oRed = 0;