OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "chrome_frame/find_dialog.h" | |
6 | |
7 #include <richedit.h> | |
8 | |
9 #include "base/guid.h" | |
10 #include "base/strings/utf_string_conversions.h" | |
11 #include "chrome_frame/chrome_frame_automation.h" | |
12 | |
13 const int kMaxFindChars = 1024; | |
14 | |
15 HHOOK CFFindDialog::msg_hook_ = NULL; | |
16 | |
17 CFFindDialog::CFFindDialog() {} | |
18 | |
19 void CFFindDialog::Init(ChromeFrameAutomationClient* automation_client) { | |
20 automation_client_ = automation_client; | |
21 } | |
22 | |
23 LRESULT CFFindDialog::OnDestroy(UINT msg, WPARAM wparam, LPARAM lparam, | |
24 BOOL& handled) { | |
25 // In order to cancel the selection when the Find dialog is dismissed, we | |
26 // do a fake search for a string that is unlikely to appear on the page. | |
27 // TODO(robertshield): Change this to plumb through a StopFinding automation | |
28 // message that triggers a ViewMsg_StopFinding. | |
29 std::string guid(base::GenerateGUID()); | |
30 automation_client_->FindInPage(base::ASCIIToWide(guid), | |
31 FWD, CASE_SENSITIVE, false); | |
32 | |
33 UninstallMessageHook(); | |
34 return 0; | |
35 } | |
36 | |
37 LRESULT CFFindDialog::OnFind(WORD wNotifyCode, WORD wID, HWND hWndCtl, | |
38 BOOL& bHandled) { | |
39 base::string16 find_text(kMaxFindChars, L'\0'); | |
40 find_text.resize(GetDlgItemText(IDC_FIND_TEXT, &find_text[0], kMaxFindChars)); | |
41 | |
42 // Repeated searches for the same string should move to the next instance. | |
43 bool find_next = (find_text == last_find_text_); | |
44 if (!find_next) | |
45 last_find_text_ = find_text; | |
46 | |
47 bool match_case = IsDlgButtonChecked(IDC_MATCH_CASE) == BST_CHECKED; | |
48 bool search_down = IsDlgButtonChecked(IDC_DIRECTION_DOWN) == BST_CHECKED; | |
49 | |
50 automation_client_->FindInPage(find_text, | |
51 search_down ? FWD : BACK, | |
52 match_case ? CASE_SENSITIVE : IGNORE_CASE, | |
53 find_next); | |
54 | |
55 return 0; | |
56 } | |
57 | |
58 LRESULT CFFindDialog::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, | |
59 BOOL& bHandled) { | |
60 DestroyWindow(); | |
61 return 0; | |
62 } | |
63 | |
64 LRESULT CFFindDialog::OnInitDialog(UINT msg, WPARAM wparam, LPARAM lparam, | |
65 BOOL& handled) { | |
66 // Init() must be called before Create() or DoModal()! | |
67 DCHECK(automation_client_.get()); | |
68 | |
69 InstallMessageHook(); | |
70 SendDlgItemMessage(IDC_FIND_TEXT, EM_EXLIMITTEXT, 0, kMaxFindChars); | |
71 BOOL result = CheckRadioButton(IDC_DIRECTION_DOWN, IDC_DIRECTION_UP, | |
72 IDC_DIRECTION_DOWN); | |
73 | |
74 HWND text_field = GetDlgItem(IDC_FIND_TEXT); | |
75 ::SetFocus(text_field); | |
76 | |
77 return FALSE; // we set the focus ourselves. | |
78 } | |
79 | |
80 LRESULT CALLBACK CFFindDialog::GetMsgProc(int code, WPARAM wparam, | |
81 LPARAM lparam) { | |
82 // Mostly borrowed from http://support.microsoft.com/kb/q187988/ | |
83 // and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx. | |
84 LPMSG msg = reinterpret_cast<LPMSG>(lparam); | |
85 if (code >= 0 && wparam == PM_REMOVE && | |
86 msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST) { | |
87 HWND hwnd = GetActiveWindow(); | |
88 if (::IsWindow(hwnd) && ::IsDialogMessage(hwnd, msg)) { | |
89 // The value returned from this hookproc is ignored, and it cannot | |
90 // be used to tell Windows the message has been handled. To avoid | |
91 // further processing, convert the message to WM_NULL before | |
92 // returning. | |
93 msg->hwnd = NULL; | |
94 msg->message = WM_NULL; | |
95 msg->lParam = 0L; | |
96 msg->wParam = 0; | |
97 } | |
98 } | |
99 | |
100 // Passes the hook information to the next hook procedure in | |
101 // the current hook chain. | |
102 return ::CallNextHookEx(msg_hook_, code, wparam, lparam); | |
103 } | |
104 | |
105 bool CFFindDialog::InstallMessageHook() { | |
106 // Make sure we only call this once. | |
107 DCHECK(msg_hook_ == NULL); | |
108 msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, &CFFindDialog::GetMsgProc, | |
109 _AtlBaseModule.m_hInst, GetCurrentThreadId()); | |
110 DCHECK(msg_hook_ != NULL); | |
111 return msg_hook_ != NULL; | |
112 } | |
113 | |
114 bool CFFindDialog::UninstallMessageHook() { | |
115 DCHECK(msg_hook_ != NULL); | |
116 BOOL result = ::UnhookWindowsHookEx(msg_hook_); | |
117 DCHECK(result); | |
118 msg_hook_ = NULL; | |
119 | |
120 return result != FALSE; | |
121 } | |
OLD | NEW |