1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include "lib/scritchui/scritchuiTypes.h"
11 #include "lib/scritchui/win32/win32.h"
12 #include "lib/scritchui/win32/win32Intern.h"
14 sjme_errorCode
sjme_scritchui_win32_windowContentMinimumSize(
15 sjme_attrInNotNull sjme_scritchui inState
,
16 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow
,
17 sjme_attrInPositiveNonZero sjme_jint width
,
18 sjme_attrInPositiveNonZero sjme_jint height
)
21 WINDOWPLACEMENT placement
;
24 sjme_scritchui_dim
* overhead
;
25 sjme_jboolean notReady
;
27 if (inState
== NULL
|| inWindow
== NULL
)
28 return SJME_ERROR_NULL_ARGUMENTS
;
31 window
= inWindow
->component
.common
.handle
[SJME_SUI_WIN32_H_HWND
];
33 /* Calculate the overhead of the window, we need to do this with knowing */
34 /* the client rectangle and the window rectangle as GetSystemMetrics */
35 /* returns old information for compatibility purposes, which breaks */
36 /* on HiDPI or Vista Glass. */
37 overhead
= &inWindow
->minOverhead
;
38 memset(&winRect
, 0, sizeof(winRect
));
39 memset(&clientPoint
, 0, sizeof(clientPoint
));
41 /* If either of these fail, the window exists but is not on the screen */
42 /* so any attempts to place it will fail. */
43 notReady
= SJME_JNI_FALSE
;
44 if (0 == GetWindowRect(window
, &winRect
))
45 notReady
= SJME_JNI_TRUE
;
46 if (0 == ClientToScreen(window
, &clientPoint
))
47 notReady
= SJME_JNI_TRUE
;
49 /* Do nothing yet if this is the case. */
51 return SJME_ERROR_NONE
;
53 /* The X coordinates are effectively a lie. */
54 overhead
->width
= (clientPoint
.x
- winRect
.left
) +
55 (GetSystemMetrics(SM_CXSIZEFRAME
) * 2) +
56 (GetSystemMetrics(SM_CXEDGE
) * 2);
58 /* This is correct. */
59 overhead
->height
= (clientPoint
.y
- winRect
.top
) +
60 GetSystemMetrics(SM_CYSIZEFRAME
) +
61 GetSystemMetrics(SM_CYEDGE
);
63 /* Add menu bar height? */
64 if (inWindow
->menuBar
!= NULL
)
65 overhead
->height
+= GetSystemMetrics(SM_CYMENU
);
67 /* Setup new placement information. */
68 memset(&placement
, 0, sizeof(placement
));
69 placement
.length
= sizeof(placement
);
70 placement
.flags
= WPF_SETMINPOSITION
;
71 placement
.ptMinPosition
.x
= width
+ overhead
->width
;
72 placement
.ptMinPosition
.y
= height
+ overhead
->height
;
74 /* Set the window placement. */
76 if (0 == SetWindowPlacement(window
, &placement
))
77 return inState
->implIntern
->getLastError(inState
,
78 SJME_ERROR_NATIVE_WIDGET_FAILURE
);
81 return inState
->implIntern
->getLastError(inState
, SJME_ERROR_NONE
);
84 sjme_errorCode
sjme_scritchui_win32_windowNew(
85 sjme_attrInNotNull sjme_scritchui inState
,
86 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow
,
87 sjme_attrInNullable sjme_pointer ignored
)
90 WNDCLASSEX windowClass
;
93 if (inState
== NULL
|| inWindow
== NULL
)
94 return SJME_ERROR_NULL_ARGUMENTS
;
96 /* Register window class for this window. */
97 memset(&windowClass
, 0, sizeof(windowClass
));
98 windowClass
.cbSize
= sizeof(windowClass
);
99 windowClass
.hInstance
= GetModuleHandle(NULL
);
100 windowClass
.lpszClassName
= inWindow
->component
.strId
;
101 windowClass
.lpfnWndProc
= inState
->implIntern
->windowProcWin32
;
103 classAtom
= RegisterClassEx(&windowClass
);
105 return inState
->implIntern
->getLastError(inState
,
106 SJME_ERROR_NATIVE_WIDGET_FAILURE
);
108 /* Create new window. */
110 window
= CreateWindowEx(
111 WS_EX_APPWINDOW
| WS_EX_CONTROLPARENT
|
112 WS_EX_OVERLAPPEDWINDOW
,
113 inWindow
->component
.strId
,
116 CW_USEDEFAULT
, CW_USEDEFAULT
,
117 CW_USEDEFAULT
, CW_USEDEFAULT
,
120 GetModuleHandle(NULL
),
123 return inState
->implIntern
->getLastError(inState
,
124 SJME_ERROR_NATIVE_WIDGET_CREATE_FAILED
);
127 inWindow
->component
.common
.handle
[SJME_SUI_WIN32_H_HWND
] = window
;
128 inWindow
->component
.common
.handle
[SJME_SUI_WIN32_H_HWNDATOM
] =
129 (sjme_scritchui_handle
)classAtom
;
131 /* Link back to this window. */
133 SetWindowLongPtr(window
, GWLP_USERDATA
,
137 return inState
->implIntern
->getLastError(inState
, SJME_ERROR_NONE
);
140 sjme_errorCode
sjme_scritchui_win32_windowSetMenuBar(
141 sjme_attrInNotNull sjme_scritchui inState
,
142 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow
,
143 sjme_attrInNullable sjme_scritchui_uiMenuBar inMenuBar
)
148 if (inState
== NULL
|| inWindow
== NULL
)
149 return SJME_ERROR_NULL_ARGUMENTS
;
151 /* Recover window and menu. */
152 window
= inWindow
->component
.common
.handle
[SJME_SUI_WIN32_H_HWND
];
153 menu
= (inMenuBar
== NULL
? NULL
:
154 inMenuBar
->menuKind
.common
.handle
[SJME_SUI_WIN32_H_HMENU
]);
156 /* Set the new menu. */
158 if (0 == SetMenu(window
, menu
))
159 return inState
->implIntern
->getLastError(inState
,
160 SJME_ERROR_NATIVE_WIDGET_FAILURE
);
163 return inState
->implIntern
->getLastError(inState
, SJME_ERROR_NONE
);
166 sjme_errorCode
sjme_scritchui_win32_windowSetVisible(
167 sjme_attrInNotNull sjme_scritchui inState
,
168 sjme_attrInNotNull sjme_scritchui_uiWindow inWindow
,
169 sjme_attrInValue sjme_jboolean isVisible
)
173 if (inState
== NULL
|| inWindow
== NULL
)
174 return SJME_ERROR_NULL_ARGUMENTS
;
176 /* Recover window. */
177 window
= inWindow
->component
.common
.handle
[SJME_SUI_WIN32_H_HWND
];
179 /* Change visibility. */
181 ShowWindow(window
, (isVisible
? SW_SHOW
: SW_HIDE
));
184 return inState
->implIntern
->getLastError(inState
, SJME_ERROR_NONE
);