blob: b4d919d75ba59bca05ca176d06c566a81c2d15f0 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/win32_window.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
14#include "rtc_base/logging.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015
16namespace rtc {
17
18///////////////////////////////////////////////////////////////////////////////
19// Win32Window
20///////////////////////////////////////////////////////////////////////////////
21
22static const wchar_t kWindowBaseClassName[] = L"WindowBaseClass";
deadbeef37f5ecf2017-02-27 14:06:41 -080023HINSTANCE Win32Window::instance_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024ATOM Win32Window::window_class_ = 0;
25
deadbeef37f5ecf2017-02-27 14:06:41 -080026Win32Window::Win32Window() : wnd_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000027
28Win32Window::~Win32Window() {
deadbeef37f5ecf2017-02-27 14:06:41 -080029 RTC_DCHECK(nullptr == wnd_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030}
31
Yves Gerey665174f2018-06-19 15:03:05 +020032bool Win32Window::Create(HWND parent,
33 const wchar_t* title,
34 DWORD style,
35 DWORD exstyle,
36 int x,
37 int y,
38 int cx,
39 int cy) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040 if (wnd_) {
41 // Window already exists.
42 return false;
43 }
44
45 if (!window_class_) {
Mirko Bonadei673f7e52019-03-25 09:01:02 +010046 if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
47 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
48 reinterpret_cast<LPCWSTR>(&Win32Window::WndProc),
49 &instance_)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010050 RTC_LOG_GLE(LS_ERROR) << "GetModuleHandleEx failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000051 return false;
52 }
53
54 // Class not registered, register it.
Mirko Bonadei673f7e52019-03-25 09:01:02 +010055 WNDCLASSEXW wcex;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056 memset(&wcex, 0, sizeof(wcex));
57 wcex.cbSize = sizeof(wcex);
58 wcex.hInstance = instance_;
59 wcex.lpfnWndProc = &Win32Window::WndProc;
60 wcex.lpszClassName = kWindowBaseClassName;
Mirko Bonadei673f7e52019-03-25 09:01:02 +010061 window_class_ = ::RegisterClassExW(&wcex);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 if (!window_class_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010063 RTC_LOG_GLE(LS_ERROR) << "RegisterClassEx failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064 return false;
65 }
66 }
Mirko Bonadei673f7e52019-03-25 09:01:02 +010067 wnd_ = ::CreateWindowExW(exstyle, kWindowBaseClassName, title, style, x, y,
68 cx, cy, parent, nullptr, instance_, this);
deadbeef37f5ecf2017-02-27 14:06:41 -080069 return (nullptr != wnd_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070}
71
72void Win32Window::Destroy() {
nissec16fa5e2017-02-07 07:18:43 -080073 const bool success = ::DestroyWindow(wnd_);
74 RTC_DCHECK(success);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000075}
76
77void Win32Window::Shutdown() {
78 if (window_class_) {
79 ::UnregisterClass(MAKEINTATOM(window_class_), instance_);
80 window_class_ = 0;
81 }
82}
83
Yves Gerey665174f2018-06-19 15:03:05 +020084bool Win32Window::OnMessage(UINT uMsg,
85 WPARAM wParam,
86 LPARAM lParam,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000087 LRESULT& result) {
88 switch (uMsg) {
Yves Gerey665174f2018-06-19 15:03:05 +020089 case WM_CLOSE:
90 if (!OnClose()) {
91 result = 0;
92 return true;
93 }
94 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095 }
96 return false;
97}
98
Steve Anton9de3aac2017-10-24 10:08:26 -070099bool Win32Window::OnClose() {
100 return true;
101}
102
103void Win32Window::OnNcDestroy() {
104 // Do nothing. }
105}
106
107LRESULT Win32Window::WndProc(HWND hwnd,
108 UINT uMsg,
109 WPARAM wParam,
110 LPARAM lParam) {
111 Win32Window* that =
112 reinterpret_cast<Win32Window*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000113 if (!that && (WM_CREATE == uMsg)) {
114 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
115 that = static_cast<Win32Window*>(cs->lpCreateParams);
116 that->wnd_ = hwnd;
117 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
118 }
119 if (that) {
120 LRESULT result;
121 bool handled = that->OnMessage(uMsg, wParam, lParam, result);
122 if (WM_DESTROY == uMsg) {
123 for (HWND child = ::GetWindow(hwnd, GW_CHILD); child;
124 child = ::GetWindow(child, GW_HWNDNEXT)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100125 RTC_LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000126 }
127 }
128 if (WM_NCDESTROY == uMsg) {
129 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
deadbeef37f5ecf2017-02-27 14:06:41 -0800130 that->wnd_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000131 that->OnNcDestroy();
132 }
133 if (handled) {
134 return result;
135 }
136 }
137 return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
138}
139
140} // namespace rtc