summaryrefslogtreecommitdiff
path: root/stdwndclass_windows.go
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-05-30 17:59:29 -0400
committerPietro Gagliardi <[email protected]>2014-05-30 17:59:29 -0400
commit4a66f1467bf0ee9a69c0758a53ab6f1425da166d (patch)
treef11a897c449cc7634c229e00db0d41a37ba8808d /stdwndclass_windows.go
parentc543f5639b121bcdae11f681466c030394902f65 (diff)
Moved the standard window class (for Window) on Windows to get the sysData pointer from CreateWindowEx() and store it in the window memory instead of being given it via a closure. This will lead to having only one window class for all Windows, which will come next. Also fixed an error in windowsconstgen's output related to GetWindowLongPtr()/SetWindowLongPtr().
Diffstat (limited to 'stdwndclass_windows.go')
-rw-r--r--stdwndclass_windows.go47
1 files changed, 46 insertions, 1 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())