quickwin 2.3.1 → 3.0.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.
- package/README.en.md +1 -2
- package/README.md +1 -2
- package/constants.ts +15 -0
- package/enum_map.d.ts +3 -0
- package/examples/PdfCanvas.js +1 -1
- package/examples/PdfCanvas.tsx +2 -2
- package/examples/execd/main.js +334 -188
- package/examples/pdf_preview2.js +76 -67
- package/examples/pdf_preview2.ts +84 -64
- package/examples/pdf_viewer.js +4932 -1029
- package/examples/pdf_viewer.tsx +11 -22
- package/examples/test_gallery.js +308 -143
- package/examples/test_gallery.tsx +12 -7
- package/examples/test_react_lazy.js +295 -133
- package/examples/test_react_lazy.tsx +4 -3
- package/examples/test_react_listbox.js +293 -132
- package/examples/test_react_listbox.tsx +3 -2
- package/examples/test_root_window.js +283 -126
- package/examples/test_tab.js +295 -133
- package/examples/test_tab.tsx +4 -3
- package/examples/tray_demo.js +37 -30
- package/examples/tray_demo.tsx +39 -32
- package/lib/abort.d.ts +21 -0
- package/lib/assert.d.ts +2 -0
- package/lib/bitmap.d.ts +7 -0
- package/lib/bitmap.js +40 -0
- package/lib/cache-utils.d.ts +6 -0
- package/lib/certs.d.ts +1 -0
- package/lib/certs.js +31 -3
- package/lib/dpi.d.ts +9 -0
- package/lib/dpi.js +30 -0
- package/lib/dumpRects.d.ts +2 -0
- package/lib/dumpRects.js +14 -7
- package/lib/exec-log.d.ts +23 -0
- package/lib/fetch.d.ts +4 -0
- package/lib/ffi/bind.d.ts +70 -0
- package/lib/ffi/bind.js +5 -4
- package/lib/ffi/ctype.d.ts +117 -0
- package/lib/ffi/index.d.ts +2 -0
- package/lib/ffi/struct.d.ts +174 -0
- package/lib/http-common.d.ts +143 -0
- package/lib/http-server.d.ts +59 -0
- package/lib/polyfill.d.ts +22 -0
- package/lib/react-qw/components/Button.d.ts +9 -0
- package/lib/react-qw/components/CheckBox.d.ts +11 -0
- package/lib/react-qw/components/ComboBox.d.ts +11 -0
- package/lib/react-qw/components/DateTimePicker.d.ts +15 -0
- package/lib/react-qw/components/DateTimePicker.js +6 -7
- package/lib/react-qw/components/Input.d.ts +15 -0
- package/lib/react-qw/components/Input.js +5 -1
- package/lib/react-qw/components/Link.d.ts +12 -0
- package/lib/react-qw/components/ListBox.d.ts +13 -0
- package/lib/react-qw/components/ListView.d.ts +37 -0
- package/lib/react-qw/components/ListView.js +8 -6
- package/lib/react-qw/components/PathPicker.d.ts +23 -0
- package/lib/react-qw/components/ProgressBar.d.ts +9 -0
- package/lib/react-qw/components/RadioButton.d.ts +11 -0
- package/lib/react-qw/components/ScrollView.d.ts +9 -0
- package/lib/react-qw/components/ScrollView.js +28 -22
- package/lib/react-qw/components/Slider.d.ts +12 -0
- package/lib/react-qw/components/Tab.d.ts +14 -0
- package/lib/react-qw/components/Tooltip.d.ts +7 -0
- package/lib/react-qw/components/TreeView.d.ts +18 -0
- package/lib/react-qw/components/index.d.ts +16 -0
- package/lib/react-qw/index.d.ts +24 -0
- package/lib/react-qw/index.js +7 -5
- package/lib/react-qw/layout.d.ts +29 -0
- package/lib/react-qw/nmhdr.d.ts +1 -0
- package/lib/react-qw/props.d.ts +2 -0
- package/lib/react-qw/props.js +3 -3
- package/lib/react-qw/reconciler.d.ts +21 -0
- package/lib/react-qw/reconciler.js +12 -17
- package/lib/stream.d.ts +20 -0
- package/lib/text-codec.d.ts +39 -0
- package/lib/text-measure.d.ts +14 -0
- package/lib/text-measure.js +9 -6
- package/lib/url.d.ts +54 -0
- package/lib/websocket.d.ts +73 -0
- package/lib/windows/{advapi32.ts → advapi32.d.ts} +6 -21
- package/lib/windows/comctl32.d.ts +14 -0
- package/lib/windows/comctl32.js +3 -2
- package/lib/windows/comdlg32.d.ts +4 -0
- package/lib/windows/{gdi32.ts → gdi32.d.ts} +184 -97
- package/lib/windows/gdi32.js +28 -6
- package/lib/windows/{kernel32.ts → kernel32.d.ts} +145 -113
- package/lib/windows/kernel32.js +9 -0
- package/lib/windows/{msimg32.ts → msimg32.d.ts} +11 -14
- package/lib/windows/ntdll.d.ts +5 -0
- package/lib/windows/ole32.d.ts +3 -0
- package/lib/windows/{psapi.ts → psapi.d.ts} +9 -18
- package/lib/windows/shell32.d.ts +51 -0
- package/lib/windows/shell32.js +11 -2
- package/lib/windows/structs.d.ts +3141 -0
- package/lib/windows/structs.js +51 -0
- package/lib/windows/user32.d.ts +623 -0
- package/lib/windows/user32.js +6 -5
- package/lib/windows/version.d.ts +27 -0
- package/lib/windows/{winspool.ts → winspool.d.ts} +18 -32
- package/main.js +13 -5
- package/package.json +16 -7
- package/quickwin.d.ts +13 -115
- 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 +3 -4
- package/test/bench_ffi_callraw.ts +3 -4
- package/test/debug/mupdf_debug.js +4 -22
- package/test/debug/wasm_export_debug.js +2 -12
- package/test/debug/wasm_names.js +3 -13
- package/test/example.pdf +0 -0
- package/test/mupdf-cdn.js +40 -0
- package/test/mupdf-cdn.ts +43 -0
- package/test/test_ffi.js +8 -9
- package/test/test_ffi.ts +8 -9
- package/test/test_ffi_abi.js +6 -6
- package/test/test_ffi_abi.ts +8 -8
- package/test/test_ffi_windows.js +82 -11
- package/test/test_ffi_windows.ts +85 -11
- package/test/test_gdi_draw.js +3 -3
- package/test/test_gdi_draw.ts +4 -4
- package/test/test_mupdf_render.js +4 -22
- package/test/test_mupdf_render.ts +4 -23
- package/test/test_mupdf_twice.js +4 -19
- package/test/test_mupdf_twice.ts +4 -20
- package/test/test_mupdf_wasm.js +10 -4
- package/test/test_mupdf_wasm.ts +6 -4
- package/test/test_react_complex.js +316 -140
- package/test/test_react_counter.js +295 -133
- package/test/test_react_flex.js +297 -138
- package/test/test_react_hidden.js +296 -134
- package/test/test_react_listview_link.js +288 -131
- package/test/test_react_notify.js +290 -133
- package/test/test_react_render.js +295 -133
- package/lib/abort.ts +0 -69
- package/lib/assert.ts +0 -7
- package/lib/cache-utils.ts +0 -40
- package/lib/certs.ts +0 -229
- package/lib/dumpRects.ts +0 -26
- package/lib/exec-log.ts +0 -30
- package/lib/fetch.ts +0 -589
- package/lib/ffi/bind.ts +0 -539
- package/lib/ffi/ctype.ts +0 -371
- package/lib/ffi/index.ts +0 -6
- package/lib/ffi/struct.ts +0 -780
- package/lib/http-common.ts +0 -441
- package/lib/http-server.ts +0 -604
- package/lib/polyfill.ts +0 -171
- package/lib/react-qw/components/index.ts +0 -17
- package/lib/react-qw/index.ts +0 -96
- package/lib/react-qw/layout.ts +0 -111
- package/lib/react-qw/nmhdr.ts +0 -7
- package/lib/react-qw/props.ts +0 -41
- package/lib/react-qw/reconciler.ts +0 -383
- package/lib/stream.ts +0 -22
- package/lib/text-codec.ts +0 -171
- package/lib/text-measure.ts +0 -41
- package/lib/url.ts +0 -201
- package/lib/websocket.ts +0 -600
- package/lib/windows/comctl32.ts +0 -19
- package/lib/windows/comdlg32.ts +0 -10
- package/lib/windows/ntdll.ts +0 -11
- package/lib/windows/ole32.ts +0 -9
- package/lib/windows/shell32.ts +0 -39
- package/lib/windows/structs.ts +0 -752
- package/lib/windows/user32.ts +0 -619
- package/lib/windows/version.ts +0 -35
- package/vendor/mupdf-wasm/mupdf-wasm.d.ts +0 -571
- package/vendor/mupdf-wasm/mupdf-wasm.js +0 -2749
- package/vendor/mupdf-wasm/mupdf-wasm.wasm +0 -0
- package/vendor/mupdf-wasm/mupdf.d.ts +0 -939
- package/vendor/mupdf-wasm/mupdf.js +0 -3317
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface ListBoxProps {
|
|
4
|
+
items: string[];
|
|
5
|
+
selectedIndex?: number;
|
|
6
|
+
defaultSelectedIndex?: number;
|
|
7
|
+
onChange?: (index: number) => void;
|
|
8
|
+
style?: WStyle;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
sort?: boolean;
|
|
11
|
+
scrollToBottom?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const ListBox: import("react").ForwardRefExoticComponent<ListBoxProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
import { StandardCursor } from '../../../constants';
|
|
4
|
+
export declare function makeColorBlock(size: number, bgra: number): ArrayBuffer;
|
|
5
|
+
export type Align = 'left' | 'center' | 'right';
|
|
6
|
+
export interface CellStyle {
|
|
7
|
+
color?: number;
|
|
8
|
+
background?: number;
|
|
9
|
+
bold?: boolean;
|
|
10
|
+
underline?: boolean;
|
|
11
|
+
italic?: boolean;
|
|
12
|
+
cursor?: StandardCursor;
|
|
13
|
+
}
|
|
14
|
+
export interface Column<D> {
|
|
15
|
+
name: string;
|
|
16
|
+
dataIndex?: keyof D;
|
|
17
|
+
width?: number;
|
|
18
|
+
align?: Align;
|
|
19
|
+
render?: (record: D, index: number) => string;
|
|
20
|
+
cellStyle?: CellStyle | ((record: D, index: number) => CellStyle);
|
|
21
|
+
onCellClick?: (record: D, index: number) => void;
|
|
22
|
+
}
|
|
23
|
+
export interface ListViewProps<D extends object> {
|
|
24
|
+
columns: Column<D>[];
|
|
25
|
+
data: D[];
|
|
26
|
+
style?: WStyle;
|
|
27
|
+
/** 图标像素数据数组,每个元素为 iconSize*iconSize*4 的 BGRA 像素 ArrayBuffer(色块/程序生成) */
|
|
28
|
+
icons?: ArrayBuffer[];
|
|
29
|
+
/** 图标尺寸,默认 32 */
|
|
30
|
+
iconSize?: number;
|
|
31
|
+
/** 返回记录使用的图标在 icons 中的下标 */
|
|
32
|
+
getIcon?: (record: D, index: number) => number;
|
|
33
|
+
}
|
|
34
|
+
declare const ListView: <D extends object>(props: ListViewProps<D> & {
|
|
35
|
+
ref?: React.Ref<gui.HWND>;
|
|
36
|
+
}) => React.ReactElement;
|
|
37
|
+
export { ListView };
|
|
@@ -7,6 +7,8 @@ import { WCHAR } from '../../ffi/bind.js';
|
|
|
7
7
|
import { nmCode } from '../nmhdr.js';
|
|
8
8
|
import { LoadCursor, SetCursor, ScreenToClient, GetCursorPos } from '../../windows/user32.js';
|
|
9
9
|
import { CreateFontIndirect, DeleteObject, GetObject, SelectObject } from '../../windows/gdi32.js';
|
|
10
|
+
import { createBitmapFromPixels } from '../../bitmap.js';
|
|
11
|
+
import { ImageListCreate, ImageListAdd, ImageListDestroy } from '../../windows/comctl32.js';
|
|
10
12
|
import { LOGFONTW, POINT, NMCUSTOMDRAW, NMLVCUSTOMDRAW, NMLISTVIEW, LVHITTESTINFO, LVITEMW, LVCOLUMNW, } from '../../windows/structs.js';
|
|
11
13
|
export function makeColorBlock(size, bgra) {
|
|
12
14
|
const n = size * size;
|
|
@@ -134,27 +136,27 @@ function makeLVItem(i, sub, text, image) {
|
|
|
134
136
|
}
|
|
135
137
|
const ListView = forwardRef(function ListViewInner({ columns, data, style, icons, iconSize, getIcon }, ref) {
|
|
136
138
|
const lvRef = useRef(null);
|
|
137
|
-
const iconListRef = useRef(
|
|
139
|
+
const iconListRef = useRef(NULL);
|
|
138
140
|
useEffect(() => {
|
|
139
141
|
const h = lvRef.current;
|
|
140
142
|
if (!h)
|
|
141
143
|
return;
|
|
142
144
|
const il = iconListRef.current;
|
|
143
|
-
iconListRef.current =
|
|
145
|
+
iconListRef.current = NULL;
|
|
144
146
|
if (il) {
|
|
145
147
|
gui.SendMessage(h, 4099 /* LvMsg.SETIMAGELIST */, 1 /* LvImageList.SMALL */, 0);
|
|
146
|
-
|
|
148
|
+
ImageListDestroy(il);
|
|
147
149
|
}
|
|
148
150
|
if (!icons || icons.length === 0)
|
|
149
151
|
return;
|
|
150
152
|
const size = iconSize ?? 32;
|
|
151
|
-
const img =
|
|
153
|
+
const img = ImageListCreate(size, size, 32 /* ImageListFlag.COLOR32 */, icons.length, 1);
|
|
152
154
|
if (!img)
|
|
153
155
|
return;
|
|
154
156
|
for (const p of icons) {
|
|
155
|
-
const hbm =
|
|
157
|
+
const hbm = createBitmapFromPixels(size, size, p);
|
|
156
158
|
if (hbm) {
|
|
157
|
-
|
|
159
|
+
ImageListAdd(img, hbm, NULL);
|
|
158
160
|
DeleteObject(hbm);
|
|
159
161
|
}
|
|
160
162
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
interface PathPickerBase {
|
|
4
|
+
type?: 'file' | 'folder';
|
|
5
|
+
filter?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
style?: WStyle;
|
|
10
|
+
}
|
|
11
|
+
export type PathPickerProps = PathPickerBase & ({
|
|
12
|
+
multiple: true;
|
|
13
|
+
value?: string[];
|
|
14
|
+
defaultValue?: string[];
|
|
15
|
+
onChange?: (v: string[]) => void;
|
|
16
|
+
} | {
|
|
17
|
+
multiple?: false;
|
|
18
|
+
value?: string;
|
|
19
|
+
defaultValue?: string;
|
|
20
|
+
onChange?: (v: string) => void;
|
|
21
|
+
});
|
|
22
|
+
export declare const PathPicker: import("react").ForwardRefExoticComponent<PathPickerProps & import("react").RefAttributes<gui.HWND>>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface ProgressBarProps {
|
|
4
|
+
value?: number;
|
|
5
|
+
max?: number;
|
|
6
|
+
style?: WStyle;
|
|
7
|
+
smooth?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const ProgressBar: import("react").ForwardRefExoticComponent<ProgressBarProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface RadioButtonProps {
|
|
4
|
+
checked?: boolean;
|
|
5
|
+
defaultChecked?: boolean;
|
|
6
|
+
onChange?: (checked: boolean) => void;
|
|
7
|
+
label?: string;
|
|
8
|
+
style?: WStyle;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const RadioButton: import("react").ForwardRefExoticComponent<RadioButtonProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface ScrollViewProps {
|
|
4
|
+
children?: React.ReactNode;
|
|
5
|
+
style?: WStyle;
|
|
6
|
+
contentWidth?: number;
|
|
7
|
+
contentHeight?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const ScrollView: import("react").ForwardRefExoticComponent<ScrollViewProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useLayoutEffect, useRef } from 'react';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import { NULL } from '../../ffi/ctype.js';
|
|
6
|
-
import { GetDeviceCaps } from '../../windows/gdi32.js';
|
|
3
|
+
import { DefWindowProc, GetClientRect, GetScrollInfo, SetScrollInfo, SetWindowPos, ShowScrollBar } from '../../windows/user32.js';
|
|
4
|
+
import { RECT, SCROLLINFO } from '../../windows/structs.js';
|
|
7
5
|
import { forceFlexLayout } from '../reconciler.js';
|
|
6
|
+
import { getScaleFactor } from '../../dpi.js';
|
|
8
7
|
export const ScrollView = forwardRef(({ children, style, contentWidth, contentHeight }, ref) => {
|
|
9
8
|
const svRef = useRef(null);
|
|
10
9
|
const contentRef = useRef(null);
|
|
@@ -16,16 +15,13 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
16
15
|
// page = viewportSize(可见行数)
|
|
17
16
|
// nPos = 0 … max - page + 1(即 0 … contentSize - viewportSize)
|
|
18
17
|
function updateScroll(sv, content) {
|
|
19
|
-
const
|
|
20
|
-
if (!
|
|
18
|
+
const svBuf = RECT.alloc();
|
|
19
|
+
if (!GetClientRect(sv, svBuf.ptr))
|
|
21
20
|
return;
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const scale = hdc ? GetDeviceCaps(hdc, 88) / 96 : 1;
|
|
27
|
-
if (hdc)
|
|
28
|
-
ReleaseDC(NULL, hdc);
|
|
21
|
+
const { left, top, right, bottom } = RECT.decode(svBuf);
|
|
22
|
+
const svW = right - left;
|
|
23
|
+
const svH = bottom - top;
|
|
24
|
+
const scale = getScaleFactor();
|
|
29
25
|
const natW = Math.round((contentWidth ?? (svW / scale)) * scale);
|
|
30
26
|
const natH = Math.round((contentHeight ?? (svH / scale)) * scale);
|
|
31
27
|
scrollXRef.current = Math.max(0, Math.min(scrollXRef.current, natW - svW));
|
|
@@ -33,7 +29,10 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
33
29
|
SetWindowPos(content, 0 /* SetWindowPosHwnd.TOP */, -scrollXRef.current, -scrollYRef.current, natW, natH, 4 /* SetWindowPosFlag.SWP_NOZORDER */);
|
|
34
30
|
forceFlexLayout(content);
|
|
35
31
|
if (natW > svW) {
|
|
36
|
-
|
|
32
|
+
SetScrollInfo(sv, 0 /* ScrollBar.HORZ */, {
|
|
33
|
+
cbSize: SCROLLINFO.size, fMask: 1 /* ScrollInfoFlag.RANGE */ | 2 /* ScrollInfoFlag.PAGE */ | 4 /* ScrollInfoFlag.POS */,
|
|
34
|
+
nMin: 0, nMax: natW - 1, nPage: svW, nPos: scrollXRef.current,
|
|
35
|
+
}, 1);
|
|
37
36
|
ShowScrollBar(sv, 0 /* ScrollBar.HORZ */, 1);
|
|
38
37
|
}
|
|
39
38
|
else {
|
|
@@ -41,7 +40,10 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
41
40
|
ShowScrollBar(sv, 0 /* ScrollBar.HORZ */, 0);
|
|
42
41
|
}
|
|
43
42
|
if (natH > svH) {
|
|
44
|
-
|
|
43
|
+
SetScrollInfo(sv, 1 /* ScrollBar.VERT */, {
|
|
44
|
+
cbSize: SCROLLINFO.size, fMask: 1 /* ScrollInfoFlag.RANGE */ | 2 /* ScrollInfoFlag.PAGE */ | 4 /* ScrollInfoFlag.POS */,
|
|
45
|
+
nMin: 0, nMax: natH - 1, nPage: svH, nPos: scrollYRef.current,
|
|
46
|
+
}, 1);
|
|
45
47
|
ShowScrollBar(sv, 1 /* ScrollBar.VERT */, 1);
|
|
46
48
|
}
|
|
47
49
|
else {
|
|
@@ -64,15 +66,17 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
64
66
|
scrollXRef.current = newPos;
|
|
65
67
|
}
|
|
66
68
|
SetWindowPos(content, 0 /* SetWindowPosHwnd.TOP */, -scrollXRef.current, -scrollYRef.current, 0, 0, 1 /* SetWindowPosFlag.SWP_NOSIZE */ | 4 /* SetWindowPosFlag.SWP_NOZORDER */);
|
|
67
|
-
|
|
69
|
+
SetScrollInfo(sv, bar, { cbSize: SCROLLINFO.size, fMask: 4 /* ScrollInfoFlag.POS */, nPos: newPos }, 1);
|
|
68
70
|
}
|
|
69
71
|
function handleScroll(e, bar) {
|
|
70
72
|
const sv = svRef.current;
|
|
71
73
|
const content = contentRef.current;
|
|
72
74
|
if (!sv || !content)
|
|
73
75
|
return;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
+
const si = SCROLLINFO.encode({ cbSize: SCROLLINFO.size, fMask: 23 /* ScrollInfoFlag.ALL */ });
|
|
77
|
+
GetScrollInfo(sv, bar, si.ptr);
|
|
78
|
+
const info = SCROLLINFO.decode(si);
|
|
79
|
+
const maxPos = info.nMax - info.nPage + 1;
|
|
76
80
|
const code = e.wParam & 0xFFFF;
|
|
77
81
|
const ref_ = bar === 1 /* ScrollBar.VERT */ ? scrollYRef : scrollXRef;
|
|
78
82
|
let newPos = ref_.current;
|
|
@@ -84,9 +88,9 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
84
88
|
else if (code === 1 /* ScrollCmd.LINEDOWN */)
|
|
85
89
|
newPos += 20;
|
|
86
90
|
else if (code === 2 /* ScrollCmd.PAGEUP */)
|
|
87
|
-
newPos -= info.
|
|
91
|
+
newPos -= info.nPage;
|
|
88
92
|
else if (code === 3 /* ScrollCmd.PAGEDOWN */)
|
|
89
|
-
newPos += info.
|
|
93
|
+
newPos += info.nPage;
|
|
90
94
|
else
|
|
91
95
|
return;
|
|
92
96
|
newPos = Math.max(0, Math.min(maxPos, newPos));
|
|
@@ -106,8 +110,10 @@ export const ScrollView = forwardRef(({ children, style, contentWidth, contentHe
|
|
|
106
110
|
if (!isHorz && contentHeight === undefined)
|
|
107
111
|
return;
|
|
108
112
|
const bar = isHorz ? 0 /* ScrollBar.HORZ */ : 1 /* ScrollBar.VERT */;
|
|
109
|
-
const
|
|
110
|
-
|
|
113
|
+
const si = SCROLLINFO.encode({ cbSize: SCROLLINFO.size, fMask: 23 /* ScrollInfoFlag.ALL */ });
|
|
114
|
+
GetScrollInfo(sv, bar, si.ptr);
|
|
115
|
+
const info = SCROLLINFO.decode(si);
|
|
116
|
+
const maxPos = info.nMax - info.nPage + 1;
|
|
111
117
|
const ref_ = isHorz ? scrollXRef : scrollYRef;
|
|
112
118
|
let newPos = ref_.current + dy;
|
|
113
119
|
newPos = Math.max(0, Math.min(maxPos, newPos));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface SliderProps {
|
|
4
|
+
value: number;
|
|
5
|
+
onChange?: (value: number) => void;
|
|
6
|
+
min?: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
vertical?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
style?: WStyle;
|
|
11
|
+
}
|
|
12
|
+
export declare const Slider: import("react").ForwardRefExoticComponent<SliderProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import * as gui from 'gui';
|
|
3
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
4
|
+
export interface TabProps {
|
|
5
|
+
tabs: {
|
|
6
|
+
title: string;
|
|
7
|
+
content: ReactNode;
|
|
8
|
+
}[];
|
|
9
|
+
selectedIndex?: number;
|
|
10
|
+
defaultSelectedIndex?: number;
|
|
11
|
+
onChange?: (index: number) => void;
|
|
12
|
+
style?: WStyle;
|
|
13
|
+
}
|
|
14
|
+
export declare const Tab: import("react").ForwardRefExoticComponent<TabProps & import("react").RefAttributes<gui.HWND>>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface TooltipProps {
|
|
2
|
+
text: string;
|
|
3
|
+
children: React.ReactElement;
|
|
4
|
+
balloon?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare function Tooltip({ text, children, balloon }: TooltipProps): import("react").ReactElement<Record<string, unknown>, string | import("react").JSXElementConstructor<any>>;
|
|
7
|
+
export { Tooltip };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import type { WStyle } from '../jsx.d.ts';
|
|
3
|
+
export interface TreeNode<D = unknown> {
|
|
4
|
+
key?: string;
|
|
5
|
+
label: string;
|
|
6
|
+
children?: TreeNode<D>[];
|
|
7
|
+
}
|
|
8
|
+
export interface TreeViewProps<D> {
|
|
9
|
+
data: TreeNode<D>[];
|
|
10
|
+
onSelect?: (node: TreeNode<D> | null) => void;
|
|
11
|
+
defaultSelectedKey?: string;
|
|
12
|
+
selectedKey?: string;
|
|
13
|
+
style?: WStyle;
|
|
14
|
+
}
|
|
15
|
+
declare const TreeView: <D = unknown>(props: TreeViewProps<D> & {
|
|
16
|
+
ref?: React.Ref<gui.HWND>;
|
|
17
|
+
}) => React.ReactElement;
|
|
18
|
+
export { TreeView };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { Button, type ButtonProps } from './Button.js';
|
|
2
|
+
export { CheckBox, type CheckBoxProps } from './CheckBox.js';
|
|
3
|
+
export { ComboBox, type ComboBoxProps } from './ComboBox.js';
|
|
4
|
+
export { DateTimePicker, type DateTimePickerProps } from './DateTimePicker.js';
|
|
5
|
+
export { Input, type InputProps } from './Input.js';
|
|
6
|
+
export { Link, type LinkProps } from './Link.js';
|
|
7
|
+
export { ListBox, type ListBoxProps } from './ListBox.js';
|
|
8
|
+
export { ListView, makeColorBlock, type ListViewProps, type Column, type CellStyle, type Align } from './ListView.js';
|
|
9
|
+
export { ProgressBar, type ProgressBarProps } from './ProgressBar.js';
|
|
10
|
+
export { RadioButton, type RadioButtonProps } from './RadioButton.js';
|
|
11
|
+
export { ScrollView, type ScrollViewProps } from './ScrollView.js';
|
|
12
|
+
export { Slider, type SliderProps } from './Slider.js';
|
|
13
|
+
export { Tab, type TabProps } from './Tab.js';
|
|
14
|
+
export { Tooltip, type TooltipProps } from './Tooltip.js';
|
|
15
|
+
export { TreeView, type TreeViewProps, type TreeNode } from './TreeView.js';
|
|
16
|
+
export { PathPicker, type PathPickerProps } from './PathPicker.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as gui from 'gui';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface RootWindowConfig {
|
|
4
|
+
text?: string;
|
|
5
|
+
ws?: number;
|
|
6
|
+
x?: number;
|
|
7
|
+
y?: number;
|
|
8
|
+
width?: number;
|
|
9
|
+
height?: number;
|
|
10
|
+
noShowWindow?: boolean;
|
|
11
|
+
onEvent?: (e: {
|
|
12
|
+
hwnd: gui.HWND;
|
|
13
|
+
msg: number;
|
|
14
|
+
wParam: number;
|
|
15
|
+
lParam: number;
|
|
16
|
+
}) => number | void;
|
|
17
|
+
}
|
|
18
|
+
export declare function createRoot(container: gui.HWND | RootWindowConfig): {
|
|
19
|
+
hwnd: gui.HWND;
|
|
20
|
+
render(element: React.ReactNode): void;
|
|
21
|
+
unmount(): void;
|
|
22
|
+
};
|
|
23
|
+
export * from './components/index.js';
|
|
24
|
+
export declare function render(element: React.ReactNode, containerOrConfig?: gui.HWND | RootWindowConfig | null, _callback?: () => void): void;
|
package/lib/react-qw/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as gui from 'gui';
|
|
2
|
-
import { DefWindowProc, GetSystemMetrics } from '../windows/user32.js';
|
|
2
|
+
import { DefWindowProc, GetSystemMetrics, ShowWindow, UpdateWindow } from '../windows/user32.js';
|
|
3
3
|
import reconciler, { scaleFactor, instancesByHwnd, forceFlexLayout } from './reconciler.js';
|
|
4
4
|
const noop = () => { };
|
|
5
5
|
let defaultClassRegistered = false;
|
|
@@ -34,8 +34,7 @@ export function createRoot(container) {
|
|
|
34
34
|
const ws = (cfg.ws ?? 0) | 13565952 /* WindowStyle.OVERLAPPEDWINDOW */;
|
|
35
35
|
const w = (cfg.width ?? 800) * scaleFactor;
|
|
36
36
|
const h = (cfg.height ?? 600) * scaleFactor;
|
|
37
|
-
|
|
38
|
-
const [sw, sh] = [GetSystemMetrics(0), GetSystemMetrics(1)];
|
|
37
|
+
const [sw, sh] = [GetSystemMetrics(0 /* SysMetrics.CXSCREEN */), GetSystemMetrics(1 /* SysMetrics.CYSCREEN */)];
|
|
39
38
|
const x = cfg.x === undefined ? ((sw - w) / 2) | 0
|
|
40
39
|
: cfg.x === -2147483648 /* CreatePos.USEDEFAULT */ ? -2147483648 /* CreatePos.USEDEFAULT */ : cfg.x * scaleFactor;
|
|
41
40
|
const y = cfg.y === undefined ? ((sh - h) / 2) | 0
|
|
@@ -44,8 +43,11 @@ export function createRoot(container) {
|
|
|
44
43
|
if (!hwin)
|
|
45
44
|
throw new Error('CreateWindow failed');
|
|
46
45
|
hwnd = hwin;
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// 启动首帧:ShowWindow 后立即 WM_PAINT,不留白(原 gui.ShowWindow 复合语义)
|
|
47
|
+
if (!cfg.noShowWindow) {
|
|
48
|
+
ShowWindow(hwnd, 1 /* ShowWindowCmd.SHOWNORMAL */);
|
|
49
|
+
UpdateWindow(hwnd);
|
|
50
|
+
}
|
|
49
51
|
}
|
|
50
52
|
else {
|
|
51
53
|
hwnd = container;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly';
|
|
2
|
+
export interface FlexStyle {
|
|
3
|
+
flexDirection?: 'row' | 'column';
|
|
4
|
+
justifyContent?: JustifyContent;
|
|
5
|
+
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch';
|
|
6
|
+
gap?: number;
|
|
7
|
+
padding?: number;
|
|
8
|
+
paddingTop?: number;
|
|
9
|
+
paddingRight?: number;
|
|
10
|
+
paddingBottom?: number;
|
|
11
|
+
paddingLeft?: number;
|
|
12
|
+
}
|
|
13
|
+
interface ChildStyle {
|
|
14
|
+
width?: number | 'auto';
|
|
15
|
+
height?: number | 'auto';
|
|
16
|
+
flexGrow?: number;
|
|
17
|
+
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch';
|
|
18
|
+
}
|
|
19
|
+
interface ChildInfo {
|
|
20
|
+
style: ChildStyle;
|
|
21
|
+
}
|
|
22
|
+
export interface LayoutResult {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function calculateFlexLayout(flex: FlexStyle, parentW: number, parentH: number, children: ChildInfo[]): LayoutResult[];
|
|
29
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function nmCode(lParam: number): number;
|
package/lib/react-qw/props.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as gui from 'gui';
|
|
2
|
-
import { SetWindowText, EnableWindow } from '../windows/user32.js';
|
|
2
|
+
import { SetWindowText, EnableWindow, ShowWindow } from '../windows/user32.js';
|
|
3
3
|
export function applyProps(instance, newProps, _oldProps) {
|
|
4
4
|
const hwnd = instance.hwnd;
|
|
5
5
|
instance.props = newProps;
|
|
@@ -24,9 +24,9 @@ export function applyProps(instance, newProps, _oldProps) {
|
|
|
24
24
|
EnableWindow(hwnd, !newProps.disabled ? 1 : 0);
|
|
25
25
|
}
|
|
26
26
|
if ('hidden' in newProps) {
|
|
27
|
-
|
|
27
|
+
ShowWindow(hwnd, newProps.hidden ? 0 /* ShowWindowCmd.HIDE */ : 5 /* ShowWindowCmd.SHOW */);
|
|
28
28
|
}
|
|
29
29
|
if ('visible' in newProps) {
|
|
30
|
-
|
|
30
|
+
ShowWindow(hwnd, newProps.visible ? 5 /* ShowWindowCmd.SHOW */ : 0 /* ShowWindowCmd.HIDE */);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import ReactReconciler from 'react-reconciler';
|
|
2
|
+
import * as gui from 'gui';
|
|
3
|
+
import type { WIntrinsicProps } from './jsx.js';
|
|
4
|
+
export declare const scaleFactor: number;
|
|
5
|
+
export type Props = WIntrinsicProps;
|
|
6
|
+
export interface Instance {
|
|
7
|
+
hwnd: gui.HWND | null;
|
|
8
|
+
type: string;
|
|
9
|
+
props: Props;
|
|
10
|
+
children: Instance[];
|
|
11
|
+
lastRect?: {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
w: number;
|
|
15
|
+
h: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare const instancesByHwnd: Map<gui.HWND, Instance>;
|
|
19
|
+
export declare function forceFlexLayout(hwnd: gui.HWND): void;
|
|
20
|
+
declare const reconciler: ReactReconciler.Reconciler<gui.HWND, Instance, Instance, never, never, gui.HWND>;
|
|
21
|
+
export default reconciler;
|
|
@@ -3,21 +3,15 @@ import { createContext } from 'react';
|
|
|
3
3
|
import { DefaultEventPriority, NoEventPriority } from 'react-reconciler/constants';
|
|
4
4
|
import * as gui from 'gui';
|
|
5
5
|
import * as os from 'os';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { GetClientRect, GetWindowLongPtr, CallWindowProc, SetWindowPos, ShowWindow, InvalidateRect, SetParent, SetWindowText } from '../windows/user32.js';
|
|
7
|
+
import { createSystemDpiFont, getScaleFactor } from '../dpi.js';
|
|
8
|
+
import { RECT } from '../windows/structs.js';
|
|
8
9
|
import { NULL } from '../ffi/ctype.js';
|
|
9
10
|
import { applyProps } from './props.js';
|
|
10
11
|
import { calculateFlexLayout } from './layout.js';
|
|
11
12
|
import { getButtonIdealSize, measureTextForHwnd } from '../text-measure.js';
|
|
12
|
-
const dpiFont =
|
|
13
|
-
|
|
14
|
-
export const scaleFactor = (() => {
|
|
15
|
-
const hdc = GetDC(NULL);
|
|
16
|
-
const dpi = hdc ? GetDeviceCaps(hdc, 88) : 96;
|
|
17
|
-
if (hdc)
|
|
18
|
-
ReleaseDC(NULL, hdc);
|
|
19
|
-
return dpi / 96;
|
|
20
|
-
})();
|
|
13
|
+
const dpiFont = createSystemDpiFont();
|
|
14
|
+
export const scaleFactor = getScaleFactor();
|
|
21
15
|
const DELAYED_CONTROLS = new Set(['SysListView32', 'SysTreeView32', 'LISTBOX', 'COMBOBOX', 'msctls_trackbar32', 'SysDateTimePick32', 'SysLink']);
|
|
22
16
|
function isDelayedControl(winClass) {
|
|
23
17
|
return DELAYED_CONTROLS.has(winClass);
|
|
@@ -59,11 +53,12 @@ function runFlexLayout(inst) {
|
|
|
59
53
|
const visible = children.filter(c => !c.props.hidden);
|
|
60
54
|
if (visible.length === 0)
|
|
61
55
|
return;
|
|
62
|
-
const
|
|
63
|
-
if (!
|
|
56
|
+
const rcBuf = RECT.alloc();
|
|
57
|
+
if (!GetClientRect(inst.hwnd, rcBuf.ptr)) {
|
|
64
58
|
console.log('flex: no rect for', inst.hwnd, inst.type);
|
|
65
59
|
return;
|
|
66
60
|
}
|
|
61
|
+
const rect = RECT.decode(rcBuf);
|
|
67
62
|
const pw = (rect.right - rect.left) / scaleFactor;
|
|
68
63
|
const ph = (rect.bottom - rect.top) / scaleFactor;
|
|
69
64
|
if (pw <= 0 || ph <= 0) {
|
|
@@ -260,19 +255,19 @@ const hostConfig = {
|
|
|
260
255
|
},
|
|
261
256
|
hideInstance(instance) {
|
|
262
257
|
if (instance.hwnd !== null)
|
|
263
|
-
|
|
258
|
+
ShowWindow(instance.hwnd, 0 /* ShowWindowCmd.HIDE */);
|
|
264
259
|
},
|
|
265
260
|
hideTextInstance(instance) {
|
|
266
261
|
if (instance.hwnd !== null)
|
|
267
|
-
|
|
262
|
+
ShowWindow(instance.hwnd, 0 /* ShowWindowCmd.HIDE */);
|
|
268
263
|
},
|
|
269
264
|
unhideInstance(instance, _props) {
|
|
270
265
|
if (instance.hwnd !== null)
|
|
271
|
-
|
|
266
|
+
ShowWindow(instance.hwnd, 5 /* ShowWindowCmd.SHOW */);
|
|
272
267
|
},
|
|
273
268
|
unhideTextInstance(instance, _text) {
|
|
274
269
|
if (instance.hwnd !== null)
|
|
275
|
-
|
|
270
|
+
ShowWindow(instance.hwnd, 5 /* ShowWindowCmd.SHOW */);
|
|
276
271
|
},
|
|
277
272
|
shouldSetTextContent(_type, props) {
|
|
278
273
|
return typeof props.children === 'string' || typeof props.children === 'number';
|
package/lib/stream.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
import { ReadableStream as ReadableStreamImpl, ReadableStreamDefaultController as ReadableStreamDefaultControllerImpl, ReadableStreamDefaultReader as ReadableStreamDefaultReaderImpl } from './vendor/web-streams/ponyfill.mjs';
|
|
3
|
+
declare global {
|
|
4
|
+
type ReadableStreamReadResult<R = any> = {
|
|
5
|
+
done: false;
|
|
6
|
+
value: R;
|
|
7
|
+
} | {
|
|
8
|
+
done: true;
|
|
9
|
+
value?: undefined;
|
|
10
|
+
};
|
|
11
|
+
interface ReadableStreamReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {
|
|
12
|
+
}
|
|
13
|
+
interface ReadableStreamDefaultReader<R = any> extends ReadableStreamDefaultReaderImpl<R> {
|
|
14
|
+
}
|
|
15
|
+
interface ReadableStream<R = any> extends ReadableStreamImpl<R> {
|
|
16
|
+
}
|
|
17
|
+
interface ReadableStreamDefaultController<R = any> extends ReadableStreamDefaultControllerImpl<R> {
|
|
18
|
+
}
|
|
19
|
+
var ReadableStream: typeof ReadableStreamImpl;
|
|
20
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
declare global {
|
|
3
|
+
interface TextDecoder<T extends _Label | undefined = _Label | undefined> extends TextDecoderImpl<T> {
|
|
4
|
+
}
|
|
5
|
+
var TextDecoder: typeof TextDecoderImpl;
|
|
6
|
+
interface TextEncoder<T extends _Label | undefined = _Label | undefined> extends TextEncoderImpl<T> {
|
|
7
|
+
}
|
|
8
|
+
var TextEncoder: typeof TextEncoderImpl;
|
|
9
|
+
}
|
|
10
|
+
declare const _labelMap: {
|
|
11
|
+
readonly 'utf-8': 'utf-8';
|
|
12
|
+
readonly utf8: 'utf-8';
|
|
13
|
+
readonly 'unicode-1-1-utf-8': 'utf-8';
|
|
14
|
+
readonly 'utf-16': 'utf-16le';
|
|
15
|
+
readonly 'utf-16le': 'utf-16le';
|
|
16
|
+
readonly 'utf-16be': 'utf-16be';
|
|
17
|
+
};
|
|
18
|
+
type _Label = keyof typeof _labelMap;
|
|
19
|
+
type _Encoding = typeof _labelMap[_Label];
|
|
20
|
+
type _Result<T> = T extends _Label ? typeof _labelMap[T] : 'utf-8';
|
|
21
|
+
declare class TextDecoderImpl<T extends _Label | undefined = _Label | undefined> {
|
|
22
|
+
_encoding: _Encoding;
|
|
23
|
+
_fatal: boolean;
|
|
24
|
+
_ignoreBOM: boolean;
|
|
25
|
+
constructor(label?: T, options?: {
|
|
26
|
+
fatal?: boolean;
|
|
27
|
+
ignoreBOM?: boolean;
|
|
28
|
+
});
|
|
29
|
+
get encoding(): _Result<T>;
|
|
30
|
+
get fatal(): boolean;
|
|
31
|
+
get ignoreBOM(): boolean;
|
|
32
|
+
decode(buffer?: ArrayBufferView | ArrayBuffer | null): string;
|
|
33
|
+
}
|
|
34
|
+
declare class TextEncoderImpl<T extends _Label | undefined = _Label | undefined> {
|
|
35
|
+
_encoding: _Encoding;
|
|
36
|
+
constructor(label?: T);
|
|
37
|
+
get encoding(): _Result<T>;
|
|
38
|
+
encode(input?: string): Uint8Array<ArrayBuffer>;
|
|
39
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Ptr } from './ffi/ctype.js';
|
|
2
|
+
import * as gui from 'gui';
|
|
3
|
+
export declare function measureText(hdc: Ptr<'HDC'>, text: string, maxWidth: number): {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function getButtonIdealSize(hwnd: gui.HWND): {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
11
|
+
export declare function measureTextForHwnd(hwnd: gui.HWND, text: string): {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
package/lib/text-measure.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NULL } from './ffi/ctype.js';
|
|
2
2
|
import * as gui from 'gui';
|
|
3
|
-
import { DrawText, GetDC, ReleaseDC } from './windows/user32.js';
|
|
3
|
+
import { DrawText, GetDC, GetClientRect, GetWindowRect, ReleaseDC } from './windows/user32.js';
|
|
4
4
|
import { SelectObject } from './windows/gdi32.js';
|
|
5
5
|
import { RECT, SIZE } from './windows/structs.js';
|
|
6
6
|
export function measureText(hdc, text, maxWidth) {
|
|
@@ -29,11 +29,14 @@ export function measureTextForHwnd(hwnd, text) {
|
|
|
29
29
|
if (hFont)
|
|
30
30
|
SelectObject(hdc, oldFont);
|
|
31
31
|
ReleaseDC(hwnd, hdc);
|
|
32
|
-
const wr =
|
|
33
|
-
const cr =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const wr = RECT.alloc();
|
|
33
|
+
const cr = RECT.alloc();
|
|
34
|
+
const okWr = GetWindowRect(hwnd, wr.ptr);
|
|
35
|
+
const okCr = GetClientRect(hwnd, cr.ptr);
|
|
36
|
+
if (okWr && okCr) {
|
|
37
|
+
const w = RECT.decode(wr), c = RECT.decode(cr);
|
|
38
|
+
result.width += (w.right - w.left) - (c.right - c.left);
|
|
39
|
+
result.height += (w.bottom - w.top) - (c.bottom - c.top);
|
|
37
40
|
}
|
|
38
41
|
return result;
|
|
39
42
|
}
|