1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/common.h" 29 #include "talk/base/logging.h" 30 #include "talk/base/win32window.h" 31 32 namespace talk_base { 33 34 /////////////////////////////////////////////////////////////////////////////// 35 // Win32Window 36 /////////////////////////////////////////////////////////////////////////////// 37 38 static const wchar_t kWindowBaseClassName[] = L"WindowBaseClass"; 39 HINSTANCE Win32Window::instance_ = NULL; 40 ATOM Win32Window::window_class_ = 0; 41 42 Win32Window::Win32Window() : wnd_(NULL) { 43 } 44 45 Win32Window::~Win32Window() { 46 ASSERT(NULL == wnd_); 47 } 48 49 bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style, 50 DWORD exstyle, int x, int y, int cx, int cy) { 51 if (wnd_) { 52 // Window already exists. 53 return false; 54 } 55 56 if (!window_class_) { 57 if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 58 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 59 reinterpret_cast<LPCWSTR>(&Win32Window::WndProc), 60 &instance_)) { 61 LOG_GLE(LS_ERROR) << "GetModuleHandleEx failed"; 62 return false; 63 } 64 65 // Class not registered, register it. 66 WNDCLASSEX wcex; 67 memset(&wcex, 0, sizeof(wcex)); 68 wcex.cbSize = sizeof(wcex); 69 wcex.hInstance = instance_; 70 wcex.lpfnWndProc = &Win32Window::WndProc; 71 wcex.lpszClassName = kWindowBaseClassName; 72 window_class_ = ::RegisterClassEx(&wcex); 73 if (!window_class_) { 74 LOG_GLE(LS_ERROR) << "RegisterClassEx failed"; 75 return false; 76 } 77 } 78 wnd_ = ::CreateWindowEx(exstyle, kWindowBaseClassName, title, style, 79 x, y, cx, cy, parent, NULL, instance_, this); 80 return (NULL != wnd_); 81 } 82 83 void Win32Window::Destroy() { 84 VERIFY(::DestroyWindow(wnd_) != FALSE); 85 } 86 87 void Win32Window::Shutdown() { 88 if (window_class_) { 89 ::UnregisterClass(MAKEINTATOM(window_class_), instance_); 90 window_class_ = 0; 91 } 92 } 93 94 bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, 95 LRESULT& result) { 96 switch (uMsg) { 97 case WM_CLOSE: 98 if (!OnClose()) { 99 result = 0; 100 return true; 101 } 102 break; 103 } 104 return false; 105 } 106 107 LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg, 108 WPARAM wParam, LPARAM lParam) { 109 Win32Window* that = reinterpret_cast<Win32Window*>( 110 ::GetWindowLongPtr(hwnd, GWLP_USERDATA)); 111 if (!that && (WM_CREATE == uMsg)) { 112 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam); 113 that = static_cast<Win32Window*>(cs->lpCreateParams); 114 that->wnd_ = hwnd; 115 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that)); 116 } 117 if (that) { 118 LRESULT result; 119 bool handled = that->OnMessage(uMsg, wParam, lParam, result); 120 if (WM_DESTROY == uMsg) { 121 for (HWND child = ::GetWindow(hwnd, GW_CHILD); child; 122 child = ::GetWindow(child, GW_HWNDNEXT)) { 123 LOG(LS_INFO) << "Child window: " << static_cast<void*>(child); 124 } 125 } 126 if (WM_NCDESTROY == uMsg) { 127 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL); 128 that->wnd_ = NULL; 129 that->OnNcDestroy(); 130 } 131 if (handled) { 132 return result; 133 } 134 } 135 return ::DefWindowProc(hwnd, uMsg, wParam, lParam); 136 } 137 138 } // namespace talk_base 139