// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved. #include "header.h" #include "strtable.h" #include "hhctrl.h" #include "resource.h" #include "secwin.h" #include "htmlhelp.h" #include "cpaldc.h" #include "system.h" #include "fts.h" #include "TCHAR.h" #include "parserhh.h" #include "collect.h" #include "hhtypes.h" #include "toc.h" #include "search.h" #include "csubset.h" #include "cctlww.h" // Common Control Macros #include #ifdef _DEBUG #undef THIS_FILE static const char THIS_FILE[] = __FILE__; #endif /////////////////////////////////////////////////////////// // // Contants // //TODO: Sizes and spaces should not be hard coded! const int BUTTON_WIDTH = 80; const int BUTTON_HEIGHT = 24; const int S_BOX_HEIGHT = 17; const int BOX_HEIGHT = 24; const int c_MaxSearchKeywordLength=256 ; const int c_StaticControlSpacing = 3; // Space between text and static control. const int c_ControlSpacing = 8 ; // Space between two controls. /////////////////////////////////////////////////////////// // // Static Member functions // WNDPROC CSearch::s_lpfnlComboWndProc = NULL; WNDPROC CSearch::s_lpfnlListViewWndProc = NULL; WNDPROC lpfnlSearchDisplayBtnWndProc = NULL; WNDPROC lpfnlSearchListBtnWndProc = NULL; /////////////////////////////////////////////////////////// // // Construction // /////////////////////////////////////////////////////////// // // Constructor // CSearch::CSearch(CHHWinType* phh) : m_hwndResizeToParent(NULL) { ASSERT(phh) ; m_phh = phh; m_pTitleCollection = phh->m_phmData->m_pTitleCollection; ASSERT(m_pTitleCollection); m_padding = 2; // padding to put around the window m_NavTabPos = phh->tabpos ; m_plistview = NULL; } /////////////////////////////////////////////////////////// // // Destructor // CSearch::~CSearch() { DESTROYIFVALID(m_hwndListBox); DESTROYIFVALID(m_hwndDisplayButton); DESTROYIFVALID(m_hwndListTopicsButton); DESTROYIFVALID(m_hwndComboBox); DESTROYIFVALID(m_hwndStaticKeyword); DESTROYIFVALID(m_hwndStaticTopic); if(m_plistview && m_plistview->m_pResults != NULL ) { // Free the results list // m_pTitleCollection->m_pFullTextSearch->FreeResults(m_plistview->m_pResults); } if( m_plistview ) delete m_plistview; } /////////////////////////////////////////////////////////// // // Create // static const char txtHHSearchClass[] = "HH FTSearch"; BOOL CSearch::Create(HWND hwndParent) { /* Note: hwndParent is either the Naviagtion Frame or its the tab ctrl. This class does not parent to the tab ctrl, but to the navigation frame. GetParentSize will always return the hwndNaviation, if hwndParent is the tabctrl. The reason that it doesn't parent to the tab ctrl is that the tab ctrl steals commands. What should really have happened is that all of the windows in this control should be contained in another window. However, its too late to change this now. */ RECT rcParent, rcChild, rcStatic, rcButton; DWORD dwExt; PCSTR psz; HFONT hfUI = _Resource.GetUIFont(); BOOL fUnicodeWindow; // Save the hwndParent for ResizeWindow. m_hwndResizeToParent = hwndParent ; // Note: GetParentSize will return hwndNavigation if hwndParent is the tab ctrl. hwndParent = GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos); rcParent.top += GetSystemMetrics(SM_CYSIZEFRAME)*2 ; //HACK: Fudge the top since we are not parented to the tabctrl. CopyRect(&rcChild, &rcParent); // Place the "Keyword" static text on top of the edit control m_hwndStaticKeyword = CreateWindowEx(WS_EX_TRANSPARENT, "STATIC", "", WS_CHILD , rcChild.left, rcChild.top, RECT_WIDTH(rcChild), S_BOX_HEIGHT, hwndParent, (HMENU) ID_STATIC_KEYWORDS, _Module.GetModuleInstance(), NULL); // set the font SendMessage(m_hwndStaticKeyword, WM_SETFONT, (WPARAM)hfUI, FALSE); // Get the dimensions of the text for sizing and spacing needs. if(g_bWinNT5) { WCHAR *pwz = (WCHAR *) GetStringResourceW(IDS_TYPE_KEYWORD); dwExt = GetStaticDimensionsW( m_hwndStaticKeyword, hfUI, pwz, RECT_WIDTH(rcChild) ); rcChild.bottom = rcChild.top + HIWORD(dwExt) ; MoveWindow(m_hwndStaticKeyword, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), FALSE ); SetWindowTextW(m_hwndStaticKeyword, pwz); } else { psz = GetStringResource(IDS_TYPE_KEYWORD); dwExt = GetStaticDimensions( m_hwndStaticKeyword, hfUI, psz, RECT_WIDTH(rcChild) ); rcChild.bottom = rcChild.top + HIWORD(dwExt) ; MoveWindow(m_hwndStaticKeyword, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), FALSE ); SetWindowText(m_hwndStaticKeyword, psz); } rcChild.top = rcChild.bottom + c_StaticControlSpacing; // Add space between static and control. rcChild.bottom = rcChild.top + BOX_HEIGHT; // create the edit control for entering the search text // leave room for the static text on top m_hwndComboBox = W_CreateWindowEx(WS_EX_CLIENTEDGE | g_RTL_Style, L"EDIT", L"", WS_CHILD | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent, (HMENU) IDSIMPLESEARCH_COMBO, _Module.GetModuleInstance(), NULL, &fUnicodeWindow); if (!m_hwndComboBox) goto _Error; // Sub-class the combo box if (NULL == s_lpfnlComboWndProc) s_lpfnlComboWndProc = (WNDPROC) W_GetWndProc(m_hwndComboBox, fUnicodeWindow); W_SubClassWindow(m_hwndComboBox, (LONG_PTR) ComboProc, fUnicodeWindow); SETTHIS(m_hwndComboBox); // Limit the amount of text which can be typed in. Edit_LimitText(m_hwndComboBox, c_MaxSearchKeywordLength-1) ; // set the font SendMessage(m_hwndComboBox, WM_SETFONT, (WPARAM) m_phh->GetContentFont(), FALSE); // create the "List Topics" button and place it // below the edit control and to the parent's right edge rcChild.top = rcChild.bottom + c_ControlSpacing; rcChild.bottom = rcChild.top + BUTTON_HEIGHT; if(g_bWinNT5) { m_hwndListTopicsButton = CreateWindowW(L"BUTTON", GetStringResourceW(IDS_LIST_TOPICS), WS_CHILD | WS_TABSTOP, rcChild.right-(BUTTON_WIDTH+2), rcChild.top, BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent, (HMENU) IDBTN_LIST_TOPICS, _Module.GetModuleInstance(), NULL); } else { m_hwndListTopicsButton = CreateWindow("BUTTON", GetStringResource(IDS_LIST_TOPICS), WS_CHILD | WS_TABSTOP, rcChild.right-(BUTTON_WIDTH+2), rcChild.top, BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent, (HMENU) IDBTN_LIST_TOPICS, _Module.GetModuleInstance(), NULL); } if (!m_hwndListTopicsButton) goto _Error; if (NULL == lpfnlSearchListBtnWndProc) lpfnlSearchListBtnWndProc= (WNDPROC) GetWindowLongPtr(m_hwndListTopicsButton, GWLP_WNDPROC); SetWindowLongPtr(m_hwndListTopicsButton, GWLP_WNDPROC, (LONG_PTR) ListBtnProc); SETTHIS(m_hwndListTopicsButton); rcChild.top = rcChild.bottom + c_ControlSpacing; rcChild.bottom = rcChild.top + S_BOX_HEIGHT; m_hwndStaticTopic = CreateWindowEx(WS_EX_TRANSPARENT, "STATIC", "", WS_CHILD , rcChild.left, rcChild.top - S_BOX_HEIGHT, RECT_WIDTH(rcChild), S_BOX_HEIGHT, hwndParent, (HMENU) ID_STATIC_SELECT_TOPIC, _Module.GetModuleInstance(), NULL); if (!m_hwndStaticTopic) goto _Error; GetWindowRect(m_hwndStaticTopic, &rcStatic); if(g_bWinNT5) { WCHAR *pwz = (WCHAR *) GetStringResourceW(IDS_SELECT_TOPIC); dwExt = GetStaticDimensionsW(m_hwndStaticTopic, hfUI, pwz, RECT_WIDTH(rcStatic) ); rcStatic.bottom = rcStatic.top+HIWORD(dwExt); MoveWindow(m_hwndStaticTopic, rcStatic.left, rcStatic.top, RECT_WIDTH(rcStatic), RECT_HEIGHT(rcStatic), FALSE); SendMessage(m_hwndStaticTopic, WM_SETFONT, (WPARAM) hfUI, FALSE); SetWindowTextW(m_hwndStaticTopic, pwz); } else { psz = GetStringResource(IDS_SELECT_TOPIC); dwExt = GetStaticDimensions( m_hwndStaticTopic, hfUI, psz, RECT_WIDTH(rcStatic) ); rcStatic.bottom = rcStatic.top+HIWORD(dwExt); MoveWindow(m_hwndStaticTopic, rcStatic.left, rcStatic.top, RECT_WIDTH(rcStatic), RECT_HEIGHT(rcStatic), FALSE); SendMessage(m_hwndStaticTopic, WM_SETFONT, (WPARAM) hfUI, FALSE); SetWindowText(m_hwndStaticTopic, psz); } // create the list view control and place it // +BOX_HEIGHT for combo box and adjust for spacing. // Note: leave space for the static text on top of the list box control rcChild.top = rcChild.bottom + c_StaticControlSpacing; // Space between static and control. rcChild.bottom = rcParent.bottom - (c_ControlSpacing) - BUTTON_HEIGHT; // BUG 2204: Also subtract off the space for the display button. m_hwndListBox = W_CreateControlWindow ( WS_EX_CLIENTEDGE | g_RTL_Style, WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VSCROLL | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER, W_ListView, L"HH FTSearch", rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent, (HMENU)IDSEARCH_LIST, _Module.GetModuleInstance(), NULL ); if (!m_hwndListBox) goto _Error; W_ListView_SetExtendedListViewStyle( m_hwndListBox, LVS_EX_FULLROWSELECT | g_RTL_Style); m_plistview = new CFTSListView(m_pTitleCollection, m_hwndListBox ); // Sub-class the list view fUnicodeWindow = IsWindowUnicode(m_hwndListBox); if (NULL == s_lpfnlListViewWndProc) s_lpfnlListViewWndProc = W_GetWndProc(m_hwndListBox, fUnicodeWindow); W_SubClassWindow(m_hwndListBox, reinterpret_cast(ListViewProc), fUnicodeWindow); SETTHIS(m_hwndListBox); // BUG 3204 --- // In 3204, the listview control was painting BEFORE the tabctrl which was then painting over the top of it. // Therefore, I've added code here and in resize to force the listbox to be the top most window in this grouping. if (hwndParent != m_hwndResizeToParent ) { SetWindowPos(m_hwndListBox, m_hwndResizeToParent, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE ); } SendMessage(m_hwndListBox, WM_SETFONT, (WPARAM) m_phh->GetAccessableContentFont(), FALSE); // create the "Display" button and place it rcChild.bottom = rcParent.bottom; rcChild.top = rcChild.bottom - BUTTON_HEIGHT; if(g_bWinNT5) { m_hwndDisplayButton = CreateWindowW(L"BUTTON", GetStringResourceW(IDS_ENGLISH_DISPLAY), WS_CHILD | WS_TABSTOP, rcChild.right-BUTTON_WIDTH-2, rcChild.top, BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent, (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL); } else { m_hwndDisplayButton = CreateWindow("BUTTON", GetStringResource(IDS_ENGLISH_DISPLAY), WS_CHILD | WS_TABSTOP, rcChild.right-BUTTON_WIDTH-2, rcChild.top, BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent, (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL); } if (!m_hwndDisplayButton) goto _Error; EnableWindow(m_hwndDisplayButton, FALSE); if (NULL == lpfnlSearchDisplayBtnWndProc) lpfnlSearchDisplayBtnWndProc = (WNDPROC) GetWindowLongPtr(m_hwndDisplayButton, GWLP_WNDPROC); SetWindowLongPtr(m_hwndDisplayButton, GWLP_WNDPROC, reinterpret_cast(DisplayBtnProc)); SETTHIS(m_hwndDisplayButton); SendMessage(m_hwndDisplayButton, WM_SETFONT, (WPARAM) hfUI, FALSE); GetWindowRect(m_hwndDisplayButton, &rcButton); dwExt = GetButtonDimensions(m_hwndDisplayButton, hfUI, GetStringResource(IDS_ENGLISH_DISPLAY)); MoveWindow(m_hwndDisplayButton, rcChild.right - LOWORD(dwExt), rcButton.top, LOWORD(dwExt), HIWORD(dwExt), FALSE); SendMessage(m_hwndListTopicsButton, WM_SETFONT, (WPARAM) hfUI, FALSE); GetWindowRect(m_hwndListTopicsButton, &rcButton); dwExt = GetButtonDimensions(m_hwndListTopicsButton, hfUI, GetStringResource(IDS_LIST_TOPICS)); MoveWindow(m_hwndListTopicsButton, rcChild.right - LOWORD(dwExt), rcButton.top, LOWORD(dwExt), HIWORD(dwExt), FALSE); ShowWindow(); SetFocus( m_hwndComboBox ); EnableWindow(m_hwndListTopicsButton, W_HasText(m_hwndComboBox)); // Initialize the array containing the dialog information. InitDlgItemArray() ; return TRUE; _Error: DESTROYIFVALID(m_hwndComboBox); DESTROYIFVALID(m_hwndListTopicsButton); DESTROYIFVALID(m_hwndListBox); DESTROYIFVALID(m_hwndStaticKeyword); DESTROYIFVALID(m_hwndStaticTopic); DESTROYIFVALID(m_hwndDisplayButton); return FALSE; } /////////////////////////////////////////////////////////// // // ResizeWindow // // if the parent window size changes, resize and place the child windows. void CSearch::ResizeWindow() { ASSERT(::IsValidWindow(m_hwndStaticKeyword)) ; // Resize to fit the client area of the tabctrl if it exists. ASSERT(::IsValidWindow(m_hwndResizeToParent )) ; RECT rcParent, rcChild; DWORD dwExt; HFONT hfUI = _Resource.GetUIFont(); GetParentSize(&rcParent, m_hwndResizeToParent, m_padding, m_NavTabPos); rcParent.top += GetSystemMetrics(SM_CYSIZEFRAME)*2 ; //HACK: Fudge the top since we are not parented to the tabctrl. CopyRect(&rcChild, &rcParent); // Resize the Static above the combo control dwExt = GetStaticDimensions( m_hwndStaticKeyword, hfUI, GetStringResource(IDS_TYPE_KEYWORD), RECT_WIDTH(rcChild) ); rcChild.bottom = rcChild.top+HIWORD(dwExt); if (g_fDBCSSystem || g_langSystem == LANG_ARABIC || g_langSystem == LANG_HEBREW) { PCSTR pszTabVertSize = GetStringResource(IDS_TAB_VERT_PADDING); DWORD dwPad = 2; if(pszTabVertSize && IsDigit((BYTE) *pszTabVertSize)) dwPad = Atoi(pszTabVertSize); MoveWindow(m_hwndStaticKeyword, rcParent.left, rcParent.top+dwPad, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE); } else MoveWindow(m_hwndStaticKeyword, rcParent.left, rcParent.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE); // Resize the Combo control rcChild.top = rcChild.bottom + c_StaticControlSpacing; //space for the static dwExt = GetStaticDimensions(m_hwndComboBox, GetContentFont(),"Test", RECT_WIDTH(rcChild) ); rcChild.bottom = rcChild.top+HIWORD(dwExt) + GetSystemMetrics(SM_CYSIZEFRAME)*2 ; MoveWindow(m_hwndComboBox, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE); // Resize the List Topics Button rcChild.top = rcChild.bottom + c_ControlSpacing; dwExt = GetButtonDimensions(m_hwndListTopicsButton, hfUI, GetStringResource(IDS_LIST_TOPICS)); rcChild.bottom = rcChild.top + HIWORD(dwExt); MoveWindow(m_hwndListTopicsButton, rcChild.right - LOWORD(dwExt), rcChild.top, LOWORD(dwExt), RECT_HEIGHT(rcChild), TRUE); // Resize the Static text above the list box rcChild.top = rcChild.bottom+ c_ControlSpacing; dwExt = GetStaticDimensions( m_hwndStaticTopic, hfUI, GetStringResource(IDS_SELECT_TOPIC), RECT_WIDTH(rcChild) ); rcChild.bottom = rcChild.top+HIWORD(dwExt); MoveWindow(m_hwndStaticTopic, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE); // Resize the List Box rcChild.top = rcChild.bottom + c_StaticControlSpacing; dwExt = GetButtonDimensions(m_hwndDisplayButton, hfUI, GetStringResource(IDS_ENGLISH_DISPLAY) ); rcChild.bottom = rcParent.bottom - (HIWORD(dwExt) + c_ControlSpacing); MoveWindow(m_hwndListBox, rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE); // BUG 3204 --- // In 3204, the listview control was painting BEFORE the tabctrl which was then painting over the top of it. // Therefore, I've added code here and in create to force the listbox to be the top most window in this grouping. SetWindowPos(m_hwndListBox, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE ); // Resize the Display Button rcChild.bottom = rcParent.bottom ; rcChild.top = rcChild.bottom - HIWORD(dwExt); MoveWindow(m_hwndDisplayButton, rcChild.right - LOWORD(dwExt), rcChild.top, LOWORD(dwExt), RECT_HEIGHT(rcChild), TRUE); m_plistview->SizeColumns(); } void CSearch::HideWindow(void) { ::ShowWindow(m_hwndListBox, SW_HIDE); ::ShowWindow(m_hwndDisplayButton, SW_HIDE); ::ShowWindow(m_hwndListTopicsButton, SW_HIDE); ::ShowWindow(m_hwndComboBox, SW_HIDE); ::ShowWindow(m_hwndStaticKeyword, SW_HIDE); ::ShowWindow(m_hwndStaticTopic, SW_HIDE); } void CSearch::ShowWindow(void) { ::ShowWindow(m_hwndListBox, SW_SHOW); ::ShowWindow(m_hwndDisplayButton, SW_SHOW); ::ShowWindow(m_hwndListTopicsButton, SW_SHOW); ::ShowWindow(m_hwndComboBox, SW_SHOW); ::ShowWindow(m_hwndStaticKeyword, SW_SHOW); ::ShowWindow(m_hwndStaticTopic, SW_SHOW); SetFocus(m_hwndComboBox); } /////////////////////////////////////////////////////////// // // OnCommand // LRESULT CSearch::OnCommand(HWND hwnd, UINT id, UINT uNotifiyCode, LPARAM lParam) { switch (id) { case IDSIMPLESEARCH_COMBO: if (uNotifiyCode == CBN_EDITCHANGE) m_plistview->ResetQuery(); return 0; case IDSEARCH_LIST: // the list view control return 0; case IDBTN_LIST_TOPICS: // The List Topics button WCHAR szQuery[500]; int cResultCount; HRESULT hr; // Get the query text // W_GetWindowText(m_hwndComboBox, szQuery, 500); if ( lstrlenW(szQuery) <= 0 ) return 0; { SEARCH_RESULT *pTempResults; // Submit the query // CHourGlass HourGlass; hr = m_pTitleCollection->m_pFullTextSearch->SimpleQuery(szQuery,&cResultCount, &pTempResults); // Check for search failure // if (FAILED(hr)) { BOOL bContinue = FALSE; UINT idMsg = IDS_SEARCH_FAILURE; switch (hr) { case FTS_NO_INDEX: idMsg = IDS_NO_FTS_DATA; break; case FTS_NOT_INITIALIZED: idMsg = IDS_BAD_ITIRCL; break; case FTS_E_SKIP_TITLE: // bContinue = TRUE; case FTS_E_SKIP_VOLUME:// bContinue = TRUE; case FTS_E_SKIP_ALL: bContinue = TRUE; break; case FTS_INVALID_SYNTAX: idMsg = IDS_INCORRECT_SYNTAX; break; } if( !bContinue ) { MsgBox(idMsg); SetFocus(m_hwndComboBox); return 0; } SetFocus(m_hwndComboBox); } // Check for no results // if(!cResultCount) { MsgBox(IDS_NO_TOPICS_FOUND); SetFocus(m_hwndComboBox); return 0; } else { m_plistview->ResetQuery(); m_plistview->SetResults(cResultCount, pTempResults) ; m_plistview->AddItems(); EnableWindow(m_hwndDisplayButton, TRUE); } } #if 0 // For testing purposes, I'm going to display a message box containing a // comma delmited list of topic numbers that contained the search term(s). // char szResultList[1000],szTemp[20]; szResultList[0]=0; int c; for(c=0;cm_pResults[c].dwTopicNumber); strcat(szResultList,szTemp); } szResultList[strlen(szResultList)-1] = 0; // Show the list of resulting topic numbers // MessageBox(NULL,szResultList,"Full-Text Search Results",MB_OK|MB_TASKMODAL); #endif return 0; case IDBTN_DISPLAY: if( (m_plistview->m_pResults != NULL) && (m_plistview->m_ItemNumber!= -1)) { DWORD dwtemp = m_plistview->m_pResults[m_plistview->m_ItemNumber].dwTopicNumber; CExTitle* pTitle = m_plistview->m_pResults[m_plistview->m_ItemNumber].pTitle; if ( pTitle ) { char szURL[MAX_URL]; if ((pTitle->GetTopicURL(dwtemp, szURL, sizeof(szURL)) == S_OK)) ChangeHtmlTopic(szURL, GetParent(m_plistview->m_hwndListView), 1); } } return 0; #ifdef _DEBUG case ID_VIEW_MEMORY: OnReportMemoryUsage(); return 0; #endif } return 0; } /////////////////////////////////////////////////////////// // // CALLBACKS // /////////////////////////////////////////////////////////// // // ComboProc // LRESULT WINAPI CSearch::ComboProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CHAR: { if (wParam == VK_TAB) // The virt code is the same as the tab character. { // Not handling this message was causing a beep. return 0 ; } } break ; case WM_KEYUP: EnableWindow(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton, W_HasText(GETTHIS(CSearch, hwnd)->m_hwndComboBox)); break; case WM_KEYDOWN: switch (wParam) { case VK_RETURN: SendMessage(FindMessageParent(hwnd), WM_COMMAND, MAKELONG(IDBTN_LIST_TOPICS, BN_CLICKED), 0); return 0; case VK_TAB: if (GetKeyState(VK_SHIFT) < 0) { if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton)) SetFocus(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton); else SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox); } else { if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton)) SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton); else SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox); } return 0; } // fall through } return W_DelegateWindowProc(s_lpfnlComboWndProc, hwnd, msg, wParam,lParam); } /////////////////////////////////////////////////////////// // // ListViewProc // LRESULT WINAPI CSearch::ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_KEYDOWN: if (wParam == VK_TAB) { if (GetKeyState(VK_SHIFT) < 0) { if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton)) SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton); else SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox); } else { if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton)) SetFocus(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton); else SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox); } return 0; } break; } return W_DelegateWindowProc(s_lpfnlListViewWndProc, hwnd, msg, wParam, lParam); } /////////////////////////////////////////////////////////// // // ListBtnProc // LRESULT WINAPI CSearch::ListBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: switch (wParam) { case VK_RETURN: SendMessage(FindMessageParent(hwnd), WM_COMMAND, MAKELONG(IDBTN_LIST_TOPICS, BN_CLICKED), 0); return 0; case VK_TAB: if (GetKeyState(VK_SHIFT) < 0) SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox); else SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox); return 0; } break; } return W_DelegateWindowProc(lpfnlSearchListBtnWndProc, hwnd, msg, wParam, lParam); } /////////////////////////////////////////////////////////// // // DisplayBtnProc // LRESULT WINAPI CSearch::DisplayBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: if (wParam == VK_RETURN) { SendMessage(FindMessageParent(hwnd), WM_COMMAND, MAKELONG( IDBTN_DISPLAY, BN_CLICKED), 0); return 0; } if (wParam == VK_TAB) { CSearch* pThis = (CSearch*) GetWindowLongPtr(hwnd, GWLP_USERDATA); if (GetKeyState(VK_SHIFT) < 0) SetFocus(pThis->m_hwndListBox); else SetFocus(pThis->m_hwndComboBox); } break; } return W_DelegateWindowProc(lpfnlSearchDisplayBtnWndProc, hwnd, msg, wParam, lParam); } /////////////////////////////////////////////////////////// // // INavUI New Interface functions // /////////////////////////////////////////////////////////// // // SetDefaultFocus // void CSearch::SetDefaultFocus() { if (IsValidWindow(m_hwndComboBox)) { ::SetFocus(m_hwndComboBox) ; } } /////////////////////////////////////////////////////////// // // ProcessMenuChar // bool CSearch::ProcessMenuChar(HWND hwndParent, int ch) { return ::ProcessMenuChar(this, hwndParent, m_aDlgItems, c_NumDlgItems, ch) ; } /////////////////////////////////////////////////////////// // // OnNotify // LRESULT CSearch::OnNotify(HWND hwnd, WPARAM wParam, LPARAM lParam) { // Delegate all of the WM_NOTIFY messages to the listview control. if ((wParam == IDSEARCH_LIST) && (::IsValidWindow(m_hwndListBox)) && m_plistview) { m_plistview->ListViewMsg(m_hwndListBox, (NM_LISTVIEW*) lParam); } return 0; } /////////////////////////////////////////////////////////// // // Helper Functions // /////////////////////////////////////////////////////////// // // InitDlgItemArray // void CSearch::InitDlgItemArray() { //TODO: This the m_aDlgItems array has not been fully utilized. Yet. Currently. we // are only using it here for accelerator handling. See Bookmark.cpp and adsearch.cpp for // the complete useage. //RECT rectCurrent ; //RECT rectDlg ; //::GetClientRect(m_hWnd, &rectDlg) ; //--- Setup the dlg array for each control. //--- Keyword Edit int i = c_KeywordEdit; m_aDlgItems[i].m_hWnd = m_hwndComboBox; //::GetDlgItem(m_hWnd, IDSIMPLESEARCH_COMBO) ; //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client m_aDlgItems[i].m_id = IDSIMPLESEARCH_COMBO; m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hwndStaticKeyword); m_aDlgItems[i].m_Type = ItemInfo::Generic; /* m_aDlgItems[i].m_bIgnoreEnabled = TRUE ; //m_aDlgItems[i].m_bEnabled; // Is the control enabled? m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding. m_aDlgItems[i].m_rectMin = rectCurrent; m_aDlgItems[i].m_rectCur = rectCurrent; //m_aDlgItems[i].m_rectMax ; // Max size. */ //--- ListTopics Btn i = c_ListTopicBtn; m_aDlgItems[i].m_hWnd = m_hwndListTopicsButton ;//::GetDlgItem(m_hWnd, IDBTN_LIST_TOPICS) ; //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client m_aDlgItems[i].m_id = IDBTN_LIST_TOPICS; m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd); m_aDlgItems[i].m_Type = ItemInfo::Button; /* m_aDlgItems[i].m_bIgnoreEnabled = TRUE ; //m_aDlgItems[i].m_bEnabled; // Is the control enabled? m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding. m_aDlgItems[i].m_rectMin = rectCurrent; m_aDlgItems[i].m_rectCur = rectCurrent; //m_aDlgItems[i].m_rectMax ; // Max size. */ //--- Results List i = c_ResultsList; m_aDlgItems[i].m_hWnd = m_hwndListBox;//::GetDlgItem(m_hWnd, IDSEARCH_LIST) ; //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client m_aDlgItems[i].m_id = IDSEARCH_LIST; m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hwndStaticTopic); m_aDlgItems[i].m_Type = ItemInfo::Generic; /* m_aDlgItems[i].m_bIgnoreEnabled = TRUE ; //m_aDlgItems[i].m_bEnabled; // Is the control enabled? m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding. m_aDlgItems[i].m_rectMin = rectCurrent; m_aDlgItems[i].m_rectCur = rectCurrent; //m_aDlgItems[i].m_rectMax ; // Max size. */ //--- Display Button i = c_DisplayBtn; m_aDlgItems[i].m_hWnd = m_hwndDisplayButton ; //::GetDlgItem(m_hWnd, IDBTN_DISPLAY) ; //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client m_aDlgItems[i].m_id = IDBTN_DISPLAY; m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd); m_aDlgItems[i].m_Type = ItemInfo::Button; /* m_aDlgItems[i].m_bIgnoreEnabled = TRUE ; //m_aDlgItems[i].m_bEnabled; // Is the control enabled? m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left; //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding. m_aDlgItems[i].m_rectMin = rectCurrent; m_aDlgItems[i].m_rectCur = rectCurrent; //m_aDlgItems[i].m_rectMax ; // Max size. */ }