Skip to content

Commit b354fce

Browse files
egorzhdancompnerd
andcommitted
UI: add containing View for each Label
`WC_STATIC` control doesn't receive events like `WM_CONTEXTMENU`. To be able to handle those events, let's create containing views for `WC_STATIC` instances. Co-authored-by: Saleem Abdulrasool <[email protected]>
1 parent 3078755 commit b354fce

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

Sources/SwiftWin32/Views and Controls/Label.swift

+46-6
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,61 @@ private let SwiftLabelProc: SUBCLASSPROC = { (hWnd, uMsg, wParam, lParam, uIdSub
2121
}
2222

2323
public class Label: Control {
24-
private static let `class`: WindowClass = WindowClass(named: WC_STATIC)
25-
private static let style: WindowStyle = (base: WS_TABSTOP | DWORD(SS_NOTIFY), extended: 0)
24+
private static let `class`: WindowClass =
25+
WindowClass(hInst: GetModuleHandleW(nil), name: "Swift.Label")
26+
private static let style: WindowStyle = (base: WS_TABSTOP, extended: 0)
27+
28+
private var staticHWnd: HWND!
29+
30+
public var text: String? {
31+
get {
32+
let szLength: Int32 = GetWindowTextLengthW(self.staticHWnd)
33+
let buffer: [WCHAR] = Array<WCHAR>(unsafeUninitializedCapacity: Int(szLength) + 1) {
34+
$1 = Int(GetWindowTextW(self.staticHWnd, $0.baseAddress!, CInt($0.count)))
35+
}
36+
return String(decodingCString: buffer, as: UTF16.self)
37+
}
38+
set(value) { _ = SetWindowTextW(self.staticHWnd, value?.wide) }
39+
}
2640

2741
public override var font: Font! {
28-
get { return super.font }
29-
set(value) { super.font = value }
42+
didSet {
43+
SendMessageW(self.staticHWnd, UINT(WM_SETFONT),
44+
unsafeBitCast(self.font?.hFont.value, to: WPARAM.self),
45+
LPARAM(1))
46+
}
3047
}
3148

32-
@_Win32WindowText
33-
public var text: String?
49+
public override var frame: Rect {
50+
didSet {
51+
let rect = GetRect(hWnd: self.hWnd)
52+
_ = SetWindowPos(self.staticHWnd, nil,
53+
CInt(rect.origin.x), CInt(rect.origin.y),
54+
CInt(rect.size.width), CInt(rect.size.height),
55+
UINT(SWP_NOZORDER | SWP_FRAMECHANGED))
56+
}
57+
}
3458

3559
public init(frame: Rect) {
3660
super.init(frame: frame, class: Label.class, style: Label.style)
3761
_ = SetWindowSubclass(hWnd, SwiftLabelProc, UINT_PTR(1),
3862
unsafeBitCast(self as AnyObject, to: DWORD_PTR.self))
63+
64+
let rect = GetRect(hWnd: self.hWnd)
65+
self.staticHWnd = CreateWindowExW(0, WC_STATIC.wide, nil, 0,
66+
0, 0,
67+
Int32(rect.size.width),
68+
Int32(rect.size.height),
69+
nil, nil, GetModuleHandleW(nil), nil)!
70+
71+
_ = SetWindowLongW(self.staticHWnd, WinSDK.GWL_STYLE, WS_CHILD)
72+
_ = SetParent(self.staticHWnd, self.hWnd)
73+
74+
self.font = Font.systemFont(ofSize: Font.systemFontSize)
75+
}
76+
77+
deinit {
78+
DestroyWindow(self.staticHWnd)
3979
}
4080

4181
// ContentSizeCategoryAdjusting

Sources/SwiftWin32/Views and Controls/View.swift

+14-10
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ private func ScaleClient(rect: inout Rect, for dpi: UINT, _ style: WindowStyle)
7676
rect = Rect(from: r)
7777
}
7878

79+
internal func GetRect(hWnd: HWND) -> Rect {
80+
var r: RECT = RECT()
81+
if !GetClientRect(hWnd, &r) {
82+
log.warning("GetClientRect: \(Error(win32: GetLastError()))")
83+
}
84+
_ = withUnsafeMutablePointer(to: &r) { [hWnd] in
85+
$0.withMemoryRebound(to: POINT.self, capacity: 2) {
86+
MapWindowPoints(hWnd, nil, $0, 2)
87+
}
88+
}
89+
return Rect(from: r)
90+
}
91+
7992
extension View {
8093
/// Options to specify how a view adjusts its content when its size changes.
8194
public enum ContentMode: Int {
@@ -241,16 +254,7 @@ public class View: Responder {
241254
// If `CW_USEDEFAULT` was used, query the actual allocated rect
242255
if frame.origin.x == Double(CW_USEDEFAULT) ||
243256
frame.size.width == Double(CW_USEDEFAULT) {
244-
var r: RECT = RECT()
245-
if !GetClientRect(self.hWnd, &r) {
246-
log.warning("GetClientRect: \(Error(win32: GetLastError()))")
247-
}
248-
_ = withUnsafeMutablePointer(to: &r) { [hWnd = self.hWnd] in
249-
$0.withMemoryRebound(to: POINT.self, capacity: 2) {
250-
MapWindowPoints(hWnd, nil, $0, 2)
251-
}
252-
}
253-
client = Rect(from: r)
257+
client = GetRect(hWnd: self.hWnd)
254258
}
255259

256260
// Scale window for DPI

0 commit comments

Comments
 (0)