1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/win/message_window.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/process/memory.h"
10 #include "base/profiler/scoped_tracker.h"
11 #include "base/win/wrapped_window_proc.h"
13 const wchar_t kMessageWindowClassName
[] = L
"Chrome_MessageWindow";
18 // Used along with LazyInstance to register a window class for message-only
19 // windows created by MessageWindow.
20 class MessageWindow::WindowClass
{
25 ATOM
atom() { return atom_
; }
26 HINSTANCE
instance() { return instance_
; }
32 DISALLOW_COPY_AND_ASSIGN(WindowClass
);
35 static LazyInstance
<MessageWindow::WindowClass
> g_window_class
=
36 LAZY_INSTANCE_INITIALIZER
;
38 MessageWindow::WindowClass::WindowClass()
40 instance_(base::GetModuleFromAddress(&MessageWindow::WindowProc
)) {
41 WNDCLASSEX window_class
;
42 window_class
.cbSize
= sizeof(window_class
);
43 window_class
.style
= 0;
44 window_class
.lpfnWndProc
= &base::win::WrappedWindowProc
<WindowProc
>;
45 window_class
.cbClsExtra
= 0;
46 window_class
.cbWndExtra
= 0;
47 window_class
.hInstance
= instance_
;
48 window_class
.hIcon
= NULL
;
49 window_class
.hCursor
= NULL
;
50 window_class
.hbrBackground
= NULL
;
51 window_class
.lpszMenuName
= NULL
;
52 window_class
.lpszClassName
= kMessageWindowClassName
;
53 window_class
.hIconSm
= NULL
;
54 atom_
= RegisterClassEx(&window_class
);
57 << "Failed to register the window class for a message-only window";
61 MessageWindow::WindowClass::~WindowClass() {
63 BOOL result
= UnregisterClass(MAKEINTATOM(atom_
), instance_
);
64 // Hitting this DCHECK usually means that some MessageWindow objects were
65 // leaked. For example not calling
66 // ui::Clipboard::DestroyClipboardForCurrentThread() results in a leaked
72 MessageWindow::MessageWindow()
76 MessageWindow::~MessageWindow() {
77 DCHECK(CalledOnValidThread());
79 if (window_
!= NULL
) {
80 BOOL result
= DestroyWindow(window_
);
85 bool MessageWindow::Create(const MessageCallback
& message_callback
) {
86 return DoCreate(message_callback
, NULL
);
89 bool MessageWindow::CreateNamed(const MessageCallback
& message_callback
,
90 const string16
& window_name
) {
91 return DoCreate(message_callback
, window_name
.c_str());
95 HWND
MessageWindow::FindWindow(const string16
& window_name
) {
96 return FindWindowEx(HWND_MESSAGE
, NULL
, kMessageWindowClassName
,
100 bool MessageWindow::DoCreate(const MessageCallback
& message_callback
,
101 const wchar_t* window_name
) {
102 DCHECK(CalledOnValidThread());
103 DCHECK(message_callback_
.is_null());
106 message_callback_
= message_callback
;
108 WindowClass
& window_class
= g_window_class
.Get();
109 window_
= CreateWindow(MAKEINTATOM(window_class
.atom()), window_name
, 0, 0, 0,
110 0, 0, HWND_MESSAGE
, 0, window_class
.instance(), this);
112 PLOG(ERROR
) << "Failed to create a message-only window";
120 LRESULT CALLBACK
MessageWindow::WindowProc(HWND hwnd
,
124 MessageWindow
* self
= reinterpret_cast<MessageWindow
*>(
125 GetWindowLongPtr(hwnd
, GWLP_USERDATA
));
128 // Set up the self before handling WM_CREATE.
130 CREATESTRUCT
* cs
= reinterpret_cast<CREATESTRUCT
*>(lparam
);
131 self
= reinterpret_cast<MessageWindow
*>(cs
->lpCreateParams
);
133 // Make |hwnd| available to the message handler. At this point the control
134 // hasn't returned from CreateWindow() yet.
135 self
->window_
= hwnd
;
137 // Store pointer to the self to the window's user data.
138 SetLastError(ERROR_SUCCESS
);
139 LONG_PTR result
= SetWindowLongPtr(
140 hwnd
, GWLP_USERDATA
, reinterpret_cast<LONG_PTR
>(self
));
141 CHECK(result
!= 0 || GetLastError() == ERROR_SUCCESS
);
145 // Clear the pointer to stop calling the self once WM_DESTROY is
148 SetLastError(ERROR_SUCCESS
);
149 LONG_PTR result
= SetWindowLongPtr(hwnd
, GWLP_USERDATA
, NULL
);
150 CHECK(result
!= 0 || GetLastError() == ERROR_SUCCESS
);
155 // Handle the message.
157 LRESULT message_result
;
158 if (self
->message_callback_
.Run(message
, wparam
, lparam
, &message_result
))
159 return message_result
;
162 return DefWindowProc(hwnd
, message
, wparam
, lparam
);