1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "common.h" 27 28 #include "BaseWnd.h" 29 #include "GlassApplication.h" 30 31 32 //NOTE: it's not thread-safe 33 unsigned int BaseWnd::sm_classNameCounter = 0; 34 35 static LPCTSTR szBaseWndProp = TEXT("BaseWndProp"); 36 37 BaseWnd::BaseWnd(HWND ancestor) : 38 m_hWnd(NULL), 39 m_ancestor(ancestor), 40 m_wndClassAtom(0), 41 m_isCommonDialogOwner(false), 42 m_hCursor(NULL) 43 { 44 45 } 46 47 BaseWnd::~BaseWnd() 48 { 49 if (m_wndClassAtom) 50 { 51 // This is called from WM_NCDESTROY, and ::UnregisterClass() will fail. 52 // Schedule the operation for later time when the HWND is dead and 53 // the window class is really free already. 54 ENTER_MAIN_THREAD() 55 { 56 if (!::UnregisterClass(reinterpret_cast<LPCTSTR>(wndClassAtom), 57 ::GetModuleHandle(NULL))) 58 { 59 _tprintf_s(L"BaseWnd::UnregisterClass(%i) error: %u\n", 60 (int)wndClassAtom, ::GetLastError()); 61 } 62 } 63 ATOM wndClassAtom; 64 LEAVE_MAIN_THREAD_LATER; 65 66 ARG(wndClassAtom) = m_wndClassAtom; 67 68 PERFORM_LATER(); 69 } 70 } 71 72 /*static*/ 73 BaseWnd* BaseWnd::FromHandle(HWND hWnd) 74 { 75 return (BaseWnd *)::GetProp(hWnd, szBaseWndProp); 76 } 77 78 HWND BaseWnd::Create(HWND hParent, int x, int y, int width, int height, 79 LPCTSTR lpWindowName, DWORD dwExStyle, DWORD dwStyle, HBRUSH hbrBackground) 80 { 81 HINSTANCE hInst = ::GetModuleHandle(NULL); 82 TCHAR szClassName[256]; 83 84 ::ZeroMemory(szClassName, sizeof(szClassName)); 85 _stprintf_s(szClassName, sizeof(szClassName)/sizeof(szClassName[0]), 86 _T("GlassWndClass-%s-%u"), GetWindowClassNameSuffix(), ++BaseWnd::sm_classNameCounter); 87 88 WNDCLASSEX wndcls; 89 wndcls.cbSize = sizeof(WNDCLASSEX); 90 wndcls.style = CS_HREDRAW | CS_VREDRAW; 91 wndcls.lpfnWndProc = StaticWindowProc; 92 wndcls.cbClsExtra = 0; 93 wndcls.cbWndExtra = 0; 94 wndcls.hInstance = hInst; 95 wndcls.hIcon = NULL; 96 wndcls.hCursor = ::LoadCursor(NULL, IDC_ARROW); 97 wndcls.hbrBackground = hbrBackground; 98 wndcls.lpszMenuName = NULL; 99 wndcls.lpszClassName = szClassName; 100 wndcls.hIconSm = NULL; 101 102 m_hCursor = wndcls.hCursor; 103 104 m_wndClassAtom = ::RegisterClassEx(&wndcls); 105 106 if (!m_wndClassAtom) { 107 _tprintf_s(L"BaseWnd::RegisterClassEx(%s) error: %u\n", szClassName, ::GetLastError()); 108 } else { 109 if (lpWindowName == NULL) { 110 lpWindowName = TEXT(""); 111 } 112 ::CreateWindowEx(dwExStyle, szClassName, lpWindowName, 113 dwStyle, x, y, width, height, hParent, 114 NULL, hInst, (void *)this); 115 116 if (GetHWND() == NULL) { 117 _tprintf_s(L"BaseWnd::Create(%s) error: %u\n", szClassName, ::GetLastError()); 118 } 119 } 120 121 return m_hWnd; 122 123 } 124 125 /*static*/ 126 BOOL BaseWnd::GetDefaultWindowBounds(LPRECT r) 127 { 128 HINSTANCE hInst = ::GetModuleHandle(NULL); 129 TCHAR* szClassName = L"GLASSDEFAULTWINDOW"; 130 131 WNDCLASS wndcls; 132 ::ZeroMemory(&wndcls, sizeof(WNDCLASS)); 133 wndcls.lpfnWndProc = StaticWindowProc; 134 wndcls.hInstance = hInst; 135 wndcls.lpszClassName = szClassName; 136 ::RegisterClass(&wndcls); 137 138 HWND hwnd = ::CreateWindow(szClassName, L"", WS_OVERLAPPED, 139 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 140 0, 0, 0, 0); 141 BOOL res = ::GetWindowRect(hwnd, r); 142 ::DestroyWindow(hwnd); 143 ::UnregisterClass(szClassName, hInst); 144 145 return res; 146 } 147 148 /*static*/ 149 LRESULT CALLBACK BaseWnd::StaticWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 150 { 151 BaseWnd *pThis = NULL; 152 if (msg == WM_CREATE) { 153 pThis = (BaseWnd *)((CREATESTRUCT *)lParam)->lpCreateParams; 154 ::SetProp(hWnd, szBaseWndProp, (HANDLE)pThis); 155 if (pThis != NULL) { 156 pThis->m_hWnd = hWnd; 157 } 158 } else { 159 pThis = (BaseWnd *)::GetProp(hWnd, szBaseWndProp); 160 } 161 if (pThis != NULL) { 162 LRESULT result = pThis->WindowProc(msg, wParam, lParam); 163 if (msg == WM_NCDESTROY) { 164 ::RemoveProp(hWnd, szBaseWndProp); 165 delete pThis; 166 } 167 return result; 168 } 169 return ::DefWindowProc(hWnd, msg, wParam, lParam); 170 } 171 172 /*virtual*/ 173 MessageResult BaseWnd::CommonWindowProc(UINT msg, WPARAM wParam, LPARAM lParam) 174 { 175 static const MessageResult NOT_PROCESSED; 176 177 switch (msg) { 178 case WM_SETCURSOR: 179 if (LOWORD(lParam) == HTCLIENT) { 180 ::SetCursor(m_hCursor); 181 return TRUE; 182 } 183 break; 184 } 185 186 return NOT_PROCESSED; 187 } 188 189 void BaseWnd::SetCursor(HCURSOR cursor) 190 { 191 m_hCursor = cursor; 192 193 // Might be worth checking the current cursor position. 194 // However, we've always set cursor unconditionally relying on the caller 195 // invoking this method only when it processes mouse_move or alike events. 196 // As long as there's no bugs filed, let it be. 197 ::SetCursor(m_hCursor); 198 } 199