| 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 |