summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stdwndclass_windows.go47
-rw-r--r--sysdata_windows.go8
-rw-r--r--tools/windowsconstgen.go4
-rw-r--r--zconstants_windows_386.go6
-rw-r--r--zconstants_windows_amd64.go6
5 files changed, 63 insertions, 8 deletions
diff --git a/stdwndclass_windows.go b/stdwndclass_windows.go
index d57cc20..44af126 100644
--- a/stdwndclass_windows.go
+++ b/stdwndclass_windows.go
@@ -31,8 +31,53 @@ func defWindowProc(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRE
return _LRESULT(r1)
}
-func stdWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
+// don't worry about error returns from GetWindowLongPtr()/SetWindowLongPtr()
+// see comments of http://blogs.msdn.com/b/oldnewthing/archive/2014/02/03/10496248.aspx
+
+func getWindowLongPtr(hwnd _HWND, what uintptr) uintptr {
+ r1, _, _ := _getWindowLongPtr.Call(
+ uintptr(hwnd),
+ what)
+ return r1
+}
+
+func setWindowLongPtr(hwnd _HWND, what uintptr, value uintptr) {
+ _setWindowLongPtr.Call(
+ uintptr(hwnd),
+ what,
+ value)
+}
+
+// we can store a pointer in extra space provided by Windows
+// we'll store sysData there
+// see http://blogs.msdn.com/b/oldnewthing/archive/2005/03/03/384285.aspx
+func getSysData(hwnd _HWND) *sysData {
+ return (*sysData)(unsafe.Pointer(getWindowLongPtr(hwnd, negConst(_GWLP_USERDATA))))
+}
+
+func storeSysData(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
+ // we can get the lpParam from CreateWindowEx() in WM_NCCREATE and WM_CREATE
+ // we can freely skip any messages that come prior
+ // see http://blogs.msdn.com/b/oldnewthing/archive/2005/04/22/410773.aspx and http://blogs.msdn.com/b/oldnewthing/archive/2014/02/03/10496248.aspx (note the date on the latter one!)
+ if uMsg == _WM_NCCREATE {
+ // the lpParam to CreateWindowEx() is the first uintptr of the CREATESTRUCT
+ // so rather than create that whole structure, we'll just grab the uintptr at the address pointed to by lParam
+ cs := (*uintptr)(unsafe.Pointer(lParam))
+ saddr := *cs
+ setWindowLongPtr(hwnd, negConst(_GWLP_USERDATA), saddr)
+ // don't set s; we return here
+ }
+ // TODO is this correct for WM_NCCREATE? I think the above link does it but I'm not entirely sure...
+ return defWindowProc(hwnd, uMsg, wParam, lParam)
+}
+
+func stdWndProc(unused *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
return func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) _LRESULT {
+ s := getSysData(hwnd)
+ if s == nil { // not yet saved
+ return storeSysData(hwnd, uMsg, wParam, lParam)
+ }
+
switch uMsg {
case _WM_COMMAND:
id := _HMENU(wParam.LOWORD())
diff --git a/sysdata_windows.go b/sysdata_windows.go
index b9df277..f813de3 100644
--- a/sysdata_windows.go
+++ b/sysdata_windows.go
@@ -30,6 +30,7 @@ type classData struct {
xstyle uint32
mkid bool
altStyle uint32
+ storeSysData bool
doNotLoadFont bool
appendMsg uintptr
insertBeforeMsg uintptr
@@ -48,6 +49,7 @@ var classTypes = [nctypes]*classData{
register: registerStdWndClass,
style: _WS_OVERLAPPEDWINDOW,
xstyle: 0,
+ storeSysData: true,
doNotLoadFont: true,
},
c_button: &classData{
@@ -157,6 +159,10 @@ func (s *sysData) make(window *sysData) (err error) {
if s.alternate {
style = uintptr(ct.altStyle)
}
+ lpParam := uintptr(_NULL)
+ if ct.storeSysData {
+ lpParam = uintptr(unsafe.Pointer(s))
+ }
uitask <- &uimsg{
call: _createWindowEx,
p: []uintptr{
@@ -171,7 +177,7 @@ func (s *sysData) make(window *sysData) (err error) {
pwin,
uintptr(cid),
uintptr(hInstance),
- uintptr(_NULL),
+ lpParam,
},
ret: ret,
}
diff --git a/tools/windowsconstgen.go b/tools/windowsconstgen.go
index 6be1b59..777324d 100644
--- a/tools/windowsconstgen.go
+++ b/tools/windowsconstgen.go
@@ -110,8 +110,8 @@ func preamble(pkg string) string {
// for backwards compatibiilty reasons, Windows defines GetWindowLongPtr()/SetWindowLongPtr() as a macro which expands to GetWindowLong()/SetWindowLong() on 32-bit systems
// we'll just simulate that here
var gwlpNames = map[string]string{
- "386": "etWindowLong",
- "amd64": "etWindowLongPtr",
+ "386": "etWindowLongW",
+ "amd64": "etWindowLongPtrW",
}
func printConst(f *os.File, goconst string, winconst string) {
diff --git a/zconstants_windows_386.go b/zconstants_windows_386.go
index c1d88c2..fa0ab76 100644
--- a/zconstants_windows_386.go
+++ b/zconstants_windows_386.go
@@ -28,6 +28,7 @@ const _ERROR = 0
const _ES_AUTOHSCROLL = 128
const _ES_PASSWORD = 32
const _FALSE = 0
+const _GWLP_USERDATA = -21
const _GWL_STYLE = -16
const _ICC_PROGRESS_CLASS = 32
const _LBS_EXTENDEDSEL = 2048
@@ -140,6 +141,7 @@ const _WM_MBUTTONDOWN = 519
const _WM_MBUTTONUP = 520
const _WM_MOUSEACTIVATE = 33
const _WM_MOUSEMOVE = 512
+const _WM_NCCREATE = 129
const _WM_PAINT = 15
const _WM_RBUTTONDOWN = 516
const _WM_RBUTTONUP = 517
@@ -162,5 +164,5 @@ const _IDC_ARROW = 32512
const _IDI_APPLICATION = 32512
const _INVALID_HANDLE_VALUE = 4294967295
const _NULL = 0
-var _getWindowLongPtr = user32.NewProc("GetWindowLong")
-var _setWindowLongPtr = user32.NewProc("SetWindowLong")
+var _getWindowLongPtr = user32.NewProc("GetWindowLongW")
+var _setWindowLongPtr = user32.NewProc("SetWindowLongW")
diff --git a/zconstants_windows_amd64.go b/zconstants_windows_amd64.go
index 4d3c1c3..54bbae8 100644
--- a/zconstants_windows_amd64.go
+++ b/zconstants_windows_amd64.go
@@ -28,6 +28,7 @@ const _ERROR = 0
const _ES_AUTOHSCROLL = 128
const _ES_PASSWORD = 32
const _FALSE = 0
+const _GWLP_USERDATA = -21
const _GWL_STYLE = -16
const _ICC_PROGRESS_CLASS = 32
const _LBS_EXTENDEDSEL = 2048
@@ -140,6 +141,7 @@ const _WM_MBUTTONDOWN = 519
const _WM_MBUTTONUP = 520
const _WM_MOUSEACTIVATE = 33
const _WM_MOUSEMOVE = 512
+const _WM_NCCREATE = 129
const _WM_PAINT = 15
const _WM_RBUTTONDOWN = 516
const _WM_RBUTTONUP = 517
@@ -162,5 +164,5 @@ const _IDC_ARROW = 32512
const _IDI_APPLICATION = 32512
const _INVALID_HANDLE_VALUE = 18446744073709551615
const _NULL = 0
-var _getWindowLongPtr = user32.NewProc("GetWindowLongPtr")
-var _setWindowLongPtr = user32.NewProc("SetWindowLongPtr")
+var _getWindowLongPtr = user32.NewProc("GetWindowLongPtrW")
+var _setWindowLongPtr = user32.NewProc("SetWindowLongPtrW")