// StatusView.cpp : implementation file // #include "stdafx.h" #include "p4win.h" #include "StatusView.h" #include "MainFrm.h" #include "MsgBox.h" #include "ImageList.h" #include "cmd_where.h" #pragma warning (push) #pragma warning (disable: 4201) #include #pragma warning (pop) #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CStatusView IMPLEMENT_DYNCREATE(CStatusView, CListView) CStatusView::CStatusView() { m_HeadIndex=0; m_ErrFound = m_RowAdded = FALSE; m_ShowStatusMsgs = GET_P4REGPTR()->GetShowStatusMsgs(); OnMaxStatusLines(); CString tempPath= GET_P4REGPTR()->GetTempDir(); CreateDirectory(tempPath, NULL); // make sure the directory exists for (int i = -1; ++i < 256; ) { m_ErrFile.Format(_T("%s\\P4Werr%02x.txt"), tempPath, i); if ((m_hErrFile=CreateFile(m_ErrFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0)) != INVALID_HANDLE_VALUE) { #ifdef UNICODE TCHAR msg[] = {0xFEFF}; DWORD NumberOfBytesWritten; WriteFile(m_hErrFile, msg, 2, &NumberOfBytesWritten, NULL); #endif break; } } EnableToolTips(); } CStatusView::~CStatusView() { CloseHandle(m_hErrFile); } BEGIN_MESSAGE_MAP(CStatusView, CListView) //{{AFX_MSG_MAP(CStatusView) ON_WM_SIZE() ON_WM_SETCURSOR() ON_WM_KEYDOWN() ON_WM_CONTEXTMENU() ON_NOTIFY_EX( TTN_NEEDTEXTW, 0, OnToolTipText ) ON_NOTIFY_EX( TTN_NEEDTEXTA, 0, OnToolTipText ) ON_COMMAND(ID_WINDOW_CLEAR, OnWindowClear) ON_COMMAND(ID_SHOW_COMMAND_TRACE, OnShowCommandTrace ) ON_COMMAND(ID_SHOW_TIMESTAMP, OnShowTimestamp) ON_COMMAND(ID_SHOW_STATUSMSGS, OnShowStatusMsgs) ON_UPDATE_COMMAND_UI(ID_VIEW_WARNANDERR, OnUpdateViewWarnAndErrs) ON_COMMAND(ID_VIEW_WARNANDERR, OnViewWarnAndErrs) ON_UPDATE_COMMAND_UI(ID_WINDOW_COPYSELECTED, OnUpdateWindowCopyselected) ON_COMMAND(ID_EDIT_COPY, OnWindowCopyselected) ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll) ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) ON_UPDATE_COMMAND_UI(ID_POSITIONDEPOT, OnUpdateFindInDepot) ON_COMMAND(ID_POSITIONDEPOT, OnFindInDepot) ON_UPDATE_COMMAND_UI(ID_POSITIONCHGS, OnUpdateFindInChgs) ON_COMMAND(ID_POSITIONCHGS, OnFindInChgs) ON_COMMAND(ID_PERFORCE_OPTIONS, OnPerforceOptions) //}}AFX_MSG_MAP ON_MESSAGE( WM_FINDPATTERN, OnFindPattern ) ON_WM_SYSCOLORCHANGE() END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CStatusView diagnostics #ifdef _DEBUG void CStatusView::AssertValid() const { CListView::AssertValid(); } void CStatusView::Dump(CDumpContext& dc) const { CListView::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CStatusView message handlers void CStatusView::Clear() { ListView_DeleteAllItems(m_hWnd); m_HeadIndex=0; } void CStatusView::OnInitialUpdate() { CListView::OnInitialUpdate(); // Set image shared list CListCtrl& list= (CListCtrl&) GetListCtrl(); list.SetImageList(TheApp()->GetImageList(), LVSIL_SMALL); LV_COLUMN lvCol; lvCol.mask= LVCF_FMT | LVCF_SUBITEM | LVCF_WIDTH; lvCol.fmt=LVCFMT_LEFT; lvCol.iSubItem=0; lvCol.cx=1800; list.InsertColumn(0, &lvCol); } void CStatusView::AddItem(LPCTSTR text, StatusView level, bool showDialog, BOOL ensureVisible /*=TRUE */) { ASSERT( text != NULL); ASSERT( level >= SV_MSG && level < SV_MAX); int len= lstrlen(text); BOOL didFirstRow= FALSE; BOOL write2file = (showDialog==true || level==SV_WARNING || level==SV_ERROR || level==SV_WARNSUMMARY) ? TRUE : FALSE; if (write2file && TheApp()->m_RunClientWizOnly) showDialog = TRUE; // Alloc a large enough buffer and initialize cleanText CString cleanText(_T(' '), len + 10); cleanText.Empty(); if (GET_P4REGPTR()->ShowStatusTime()) { SYSTEMTIME st; GetLocalTime(&st); if (GET_P4REGPTR()->Use24hourClock()) { cleanText.Format(_T("%02d:%02d:%02d "), st.wHour, st.wMinute, st.wSecond); } else { cleanText.Format(_T("%d:%02d:%02d "), (st.wHour > 12) ? st.wHour - 12 : st.wHour, st.wMinute, st.wSecond); } } for(int i=0; i < len; i++) { // Split out multiple rows as required if(text[i] == _T('\n') && cleanText.GetLength() > 0) { if(!didFirstRow) { AddOneRow(cleanText, level, ensureVisible, write2file); didFirstRow= TRUE; } else { // Dont show bitmap for continuation lines AddOneRow(cleanText, SV_BLANK, ensureVisible, write2file); } cleanText.Empty(); } // Get rid of misc control chars else if(text[i] != _T('\r') && text[i] != _T('\t') && text[i] != _T('\n')) cleanText+= text[i]; } if(cleanText.GetLength() > 0) { if(!didFirstRow) { AddOneRow(cleanText, level, ensureVisible, write2file); didFirstRow=TRUE; } else { // Dont show bitmap for continuation lines AddOneRow(cleanText, SV_BLANK, ensureVisible, write2file); } } if(didFirstRow) { // Play a sound. The nodefault flag is used so PlaySound is silent when the // sound is not defined. if(level== SV_WARNING) PlaySound(_T("PerforceWarning"), NULL, SND_ALIAS | SND_ASYNC | SND_NOWAIT | SND_NODEFAULT); else if(level== SV_COMPLETION) PlaySound(_T("PerforceCompleted"), NULL, SND_ALIAS | SND_ASYNC | SND_NOWAIT | SND_NODEFAULT); else if(level== SV_ERROR) { // Check to see if the main menu or Status pane context menu is open BOOL bMenuOpen = FALSE; MENUBARINFO mbi; mbi.cbSize = sizeof(MENUBARINFO); if (MainFrame()->m_InPopUpMenu || (MainFrame()->GetMenuBarInfo(OBJID_MENU, 0, &mbi) && mbi.fBarFocused)) bMenuOpen = TRUE; // If the mouse is captured - release it and pump the message loop. // This can happen if the user is dragging the toolbar to a new // location when we get here. We only do this however if all menus // are closed - if one is open and we mess with the Capture, it // makes another mess. Things are still a mess cuz MS still doesn't // clean up from the drag and leaves the main window on top with the // upcoming messagebox hidden. Yuck - and I still can't figure a way // out of that mess. while (!bMenuOpen && ::GetCapture()) { MSG msg; ::ReleaseCapture(); if (!MainFrame()->IsQuitting()) { while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { if (!::GetMessage(&msg, NULL, NULL, NULL)) { ::PostQuitMessage(0); break; } if (!(TheApp( )->PreTranslateMessage(&msg))) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } } } // Note: there is no real app modal message box, so set a flag to // kill the autopoll timer, thus preventing a billion error boxes // if the machine is unattended if (!showDialog) { SET_APP_HALTED(TRUE); PlaySound(_T("PerforceError"), NULL, SND_ALIAS | SND_SYNC | SND_NOWAIT | SND_NODEFAULT); AfxMessageBox(text, MB_ICONSTOP | MB_SYSTEMMODAL); SET_APP_HALTED(FALSE); } } } if(didFirstRow && showDialog) { CString str = CString(_T("OK\t")) + text; str.Replace('\t', ' '); str.SetAt(2, '\t'); int i, j; for (i = j = 0; (i = str.Find('\n', i)) != -1; i++) j++; BOOL b = (j > 5 || str.GetLength() > 200) ? TRUE : FALSE; switch(level) { case SV_WARNING: MsgBox( str, MB_ICONEXCLAMATION, IDC_BUTTON2, this, NULL, b ); break; default: MsgBox( str, MB_ICONSTOP, IDC_BUTTON2, this, NULL, b ); break; } MainFrame()->SetStatusBarLevel(level); } } void CStatusView::AddOneRow(LPCTSTR text, StatusView level, BOOL ensureVisible, BOOL write2file, BOOL bSave/*=TRUE*/) { DWORD NumberOfBytesWritten; ASSERT( text != NULL); ASSERT( level >= SV_MSG && level < SV_MAX); // Add the image and text LV_ITEM lvItem; lvItem.mask=LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvItem.iItem= m_HeadIndex; lvItem.iSubItem= 0; lvItem.iImage = CP4ViewImageList::VI_STATUS_MSG + level; lvItem.pszText= const_cast(text); lvItem.lParam= level; if (write2file || m_ShowStatusMsgs || level== SV_COMPLETION || level== SV_WARNING || level== SV_ERROR || level== SV_WARNSUMMARY) { // If the output window has too many rows, delete oldest row if(ListView_GetItemCount(m_hWnd) >= m_MaxStatusLines) ListView_DeleteItem(m_hWnd, 0); // Add the item to the status listview m_HeadIndex=ListView_InsertItem(m_hWnd, &lvItem); if( ensureVisible ) ListView_EnsureVisible(m_hWnd, m_HeadIndex, FALSE); m_HeadIndex++; m_RowAdded = TRUE; } CString msg; msg.Format(_T("%d %s\r\n"), level, text); if (bSave) { if (m_StatusRows.GetCount() > m_MaxSaveLines) m_StatusRows.RemoveHead(); m_StatusRows.AddTail(msg); } if (write2file) { m_ErrFound = TRUE; WriteFile(m_hErrFile, msg, msg.GetLength()*sizeof(TCHAR), &NumberOfBytesWritten, NULL); MainFrame()->SetStatusBarLevel(level); } if (GET_P4REGPTR()->GetStatusUpdateInterval() && m_ShowStatusMsgs) SendMessage(WM_SETREDRAW, FALSE, 0); } BOOL CStatusView::PreCreateWindow(CREATESTRUCT& cs) { cs.style|= LVS_NOCOLUMNHEADER | LVS_SHAREIMAGELISTS | LVS_ALIGNLEFT | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CStatusView::OnSize(UINT nType, int cx, int cy) { CListView::OnSize(nType, cx, cy); } BOOL CStatusView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(SERVER_BUSY()) return SET_BUSYCURSOR(); else return CListView::OnSetCursor(pWnd, nHitTest, message); } void CStatusView::OnWindowClear() { Clear(); } void CStatusView::OnContextMenu(CWnd* pWnd, CPoint point) { CMenu popMenu; MainFrame()->m_InPopUpMenu = TRUE; if (point.x <= 0 && point.y <= 0) // Position NOT actually in status window? { point.x = point.y = 0; ClientToScreen(&point); // re-position to upper left corner of status window } popMenu.LoadMenu(IDR_STATUS); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_COMMAND_TRACE, MF_BYCOMMAND | (GET_P4REGPTR()->ShowCommandTrace( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_TIMESTAMP, MF_BYCOMMAND | (GET_P4REGPTR()->ShowStatusTime( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->CheckMenuItem(ID_SHOW_STATUSMSGS, MF_BYCOMMAND | (GET_P4REGPTR()->GetShowStatusMsgs( ) ? MF_CHECKED : MF_UNCHECKED)); popMenu.GetSubMenu(0)->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd( )); MainFrame()->m_InPopUpMenu = FALSE; } /* _________________________________________________________________ toggle the show command trace flag in the registry. _________________________________________________________________ */ void CStatusView::OnShowCommandTrace() { GET_P4REGPTR()->SetShowCommandTrace( ! GET_P4REGPTR()->ShowCommandTrace() ); } void CStatusView::OnUpdateViewWarnAndErrs(CCmdUI* pCmdUI) { pCmdUI->Enable( m_ErrFound ); } void CStatusView::CallOnUpdateViewWarnAndErrs(CCmdUI* pCmdUI) { OnUpdateViewWarnAndErrs(pCmdUI); } void CStatusView::OnMaxStatusLines() { m_MaxStatusLines = GET_P4REGPTR()->GetMaxStatusLines(); m_MaxSaveLines = min(2000, max(m_MaxStatusLines >> 4, 250)); if (m_MaxSaveLines > m_MaxStatusLines) m_MaxSaveLines = m_MaxStatusLines; } void CStatusView::OnViewWarnAndErrs() { if (GET_P4REGPTR()->UseNotepad4WarnAndErr()) { #ifdef UNICODE DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT; #else DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS; #endif PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; GetStartupInfo(&startInfo); startInfo.lpReserved= startInfo.lpDesktop= NULL; startInfo.dwFlags |= STARTF_USESHOWWINDOW; startInfo.wShowWindow = SW_SHOWNORMAL; TCHAR commandLine[_MAX_PATH+1]; CString cmdline = _T("notepad.exe ") + m_ErrFile; lstrcpy(commandLine, cmdline); CreateProcess( NULL, // pointer to name of executable module commandLine, // pointer to command line string NULL, NULL, // default security rot FALSE, // handle inheritance flag dwCreationFlags, // creation flags NULL, // env NULL, //default dir &startInfo, &procInfo); } else ShellExecute( AfxGetApp( )->m_pMainWnd->m_hWnd, _T("open"), m_ErrFile, NULL, NULL, SW_SHOWNORMAL); MainFrame()->SetStatusBarLevel(SV_MSG); } void CStatusView::CallOnViewWarnAndErrs() { OnViewWarnAndErrs(); } void CStatusView::OnUpdateWindowCopyselected(CCmdUI* pCmdUI) { pCmdUI->Enable( GetSelectedCount() > 0 ); } void CStatusView::OnWindowCopyselected() { CString text; GetPaneText( text, TRUE ); CopyTextToClipboard( text ); } void CStatusView::GetPaneText( CString &txt, BOOL onlySelectedText) { TCHAR buf[1024]; txt.Empty(); for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) { if( !onlySelectedText || ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_GetItemText( m_hWnd, i, 0, buf, 1023 ); switch( GetListCtrl().GetItemData( i ) ) { case SV_TOOL: txt+= LoadStringResource(IDS_STATUS_TOOL); break; case SV_DEBUG: txt+= LoadStringResource(IDS_STATUS_DEBUG); break; case SV_WARNING: txt+= LoadStringResource(IDS_STATUS_WARNING); break; case SV_ERROR: txt+= LoadStringResource(IDS_STATUS_ERROR); break; case SV_MSG: txt+= LoadStringResource(IDS_STATUS_STATUS); break; case SV_COMPLETION: case SV_WARNSUMMARY: txt+= LoadStringResource(IDS_STATUS_COMPLETION); break; case SV_BLANK: // Indent rows following lead row txt+= _T(" "); break; default: break; } txt+= buf; txt+= _T("\r\n"); } } } int CStatusView::GetSelectedCount() { int selected= 0; for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) selected++; return selected; } void CStatusView::OnUpdateEditSelectAll(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); } void CStatusView::OnEditSelectAll() { for( int i = 0; i < ListView_GetItemCount( m_hWnd ); i++ ) ListView_SetItemState( m_hWnd, i, LVIS_SELECTED, LVIS_SELECTED ); } void CStatusView::OnShowTimestamp() { BOOL showStatusTime = !GET_P4REGPTR()->ShowStatusTime( ); GET_P4REGPTR()->SetShowStatusTime( showStatusTime ); } void CStatusView::OnShowStatusMsgs() { m_ShowStatusMsgs = !GET_P4REGPTR()->GetShowStatusMsgs( ); GET_P4REGPTR()->SetShowStatusMsgs( m_ShowStatusMsgs ); int i; LPTSTR p, q; OnWindowClear(); if (m_ShowStatusMsgs) { CString row; for (POSITION pos = m_StatusRows.GetHeadPosition(); pos != NULL; ) { row = m_StatusRows.GetNext(pos); p = row.GetBuffer(row.GetLength()+1); i = _tstoi(p); while (*++p != _T(' ')) ; q = p++; while(*++q != _T('\r')) ; *q = _T('\0'); AddOneRow(p, (StatusView)i, TRUE, FALSE, FALSE); } } else { DWORD dw = GetFileSize(m_hErrFile, 0); CString buf(_T('\0'), dw+1); if (dw) { SetFilePointer(m_hErrFile, 0, 0, FILE_BEGIN); if (ReadFile(m_hErrFile, p = buf.GetBuffer(dw+1), dw, &dw, 0)) { while(*p) { i = _tstoi(p); while (*++p != _T(' ')) ; q = p++; while(*++q != _T('\r')) ; *q = _T('\0'); AddOneRow(p, (StatusView)i, TRUE, FALSE, FALSE); for (p = q; *++p && *p < _T(' '); ) ; } } SetFilePointer(m_hErrFile, 0, 0, FILE_END); } } } CString CStatusView::Extract1stFilename(CString &str) { int i; CString itemStr = str; if (itemStr.GetAt(0) != _T('/') && itemStr.GetAt(1) != _T(':')) { if ((i = itemStr.Find(_T("//"))) > 0) { // we have something like "STATUS: 3:33:26 Sync preview: //depot/main/www/perforce/customers/bycountry.html#16 - updating c:\workspac\main\www\perforce\customers\bycountry.html" // so throw away everything before the "//" itemStr = itemStr.Right(itemStr.GetLength() - i); } else if ((i = itemStr.Find(_T(":\\"))) > 0) { // we have something like "STATUS: 11:48:04 Executing p4 where c:\workspac\P4CONFIG" // so throw away everything before the "c:\" itemStr = itemStr.Right(itemStr.GetLength() - i + 1); } itemStr.TrimRight(); } // if we find a 2nd "//", throw it and the following chars away if ((i = itemStr.Find(_T("//"), 2)) > 0) itemStr = itemStr.Left(i); // if we find a 2nd "c:\", throw it and the following chars away if ((i = itemStr.Find(_T(":\\"), 3)) > 0) itemStr = itemStr.Left(i-1); return itemStr; } void CStatusView::OnUpdateFindInDepot(CCmdUI* pCmdUI) { BOOL b = FALSE; CString text; GetPaneText( text, TRUE ); if ((GetSelectedCount() == 1) && ((text.Find(_T("//")) != -1) || (text.Find(_T(":\\")) != -1))) { b = TRUE; } pCmdUI->Enable(b); if (pCmdUI->m_pParentMenu == MainFrame()->GetMenu()) pCmdUI->SetText(LoadStringResource(IDS_FINDSELFILEINDEPOT)); } void CStatusView::OnFindInDepot() { CString itemStr; GetPaneText( itemStr, TRUE ); itemStr = Extract1stFilename(itemStr); itemStr.TrimRight(_T("*/\\")); ((CMainFrame *)AfxGetMainWnd())->ExpandDepotString( itemStr, TRUE ); } void CStatusView::OnUpdateFindInChgs(CCmdUI* pCmdUI) { CString text; GetPaneText( text, TRUE ); BOOL b = ((GetSelectedCount() == 1) && ((text.Find(_T("//")) != -1) || (text.Find(_T(":\\")) != -1))); if (b) { text = Extract1stFilename(text); b = ((text.Find(_T("...")) == -1) && (text.Find(_T("*")) == -1)); } pCmdUI->Enable(b); } void CStatusView::OnFindInChgs() { int i; CString itemStr; GetPaneText( itemStr, TRUE ); itemStr = Extract1stFilename(itemStr); if ((itemStr.Find(_T("...")) == -1) && (itemStr.Find(_T("*")) == -1)) { if ((i = itemStr.FindOneOf(_T("#@"))) != -1) itemStr = itemStr.Left(i); itemStr.TrimRight(_T("*/\\ ")); if (itemStr.GetAt(0) != _T('/')) { // have to convert to depot syntax CCmd_Where *pCmd1 = new CCmd_Where; pCmd1->Init(NULL, RUN_SYNC); if ( pCmd1->Run(itemStr) && !pCmd1->GetError() && pCmd1->GetDepotFiles()->GetCount() ) { itemStr = pCmd1->GetDepotSyntax(); itemStr.TrimRight(); } delete pCmd1; } if (((CMainFrame *)AfxGetMainWnd())->PositionChgs( itemStr, TRUE, TRUE ) != -1) return; // found it } MainFrame()->SetMessageText(LoadStringResource(SERVER_BUSY() ? IDS_FILE_NOT_FOUND_YOUR_CHGS : IDS_FILE_NOT_FOUND_IN_CHGS)); } void CStatusView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) { int i; if (bActivate) { SendMessage(WM_SETREDRAW, TRUE, 0); ((CMainFrame *)AfxGetMainWnd())->SetStatusBarLevel(SV_MSG); if (m_RowAdded || (ListView_GetSelectedCount( m_hWnd ) == 0)) { m_RowAdded = FALSE; i = ListView_GetItemCount( m_hWnd ); if (i--) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED, LVIS_SELECTED ); ListView_EnsureVisible( m_hWnd, i, FALSE ); } } else { for( i = ListView_GetItemCount( m_hWnd ); i--; ) if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) break; ListView_EnsureVisible( m_hWnd, i, FALSE ); } } CListView::OnActivateView(bActivate, pActivateView, pDeactiveView); } void CStatusView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { switch ( nChar ) { case VK_TAB: if ( ::GetKeyState(VK_CONTROL) & 0x8000 ) // Ctrl+TAB switches to depot pane MainFrame()->SwitchPanes((CView *)this, FALSE); break; } CListView::OnKeyDown(nChar, nRepCnt, nFlags); } void CStatusView::OnSysColorChange() { CListView::OnSysColorChange(); CListCtrl& list= (CListCtrl&) GetListCtrl(); list.SetImageList(TheApp()->GetImageList(), LVSIL_SMALL); } void CStatusView::OnPerforceOptions() { MainFrame()->OnPerforceOptions(TRUE, FALSE, IDS_PAGE_STATUS); } LRESULT CStatusView::OnFindPattern(WPARAM wParam, LPARAM lParam) { TCHAR str[ 1024 ]; CString text; CString what = (TCHAR *)lParam; int flags = (int)wParam; int prev = -1; if (!(flags & FR_MATCHCASE)) what.MakeLower(); int i, j; CListCtrl& list= (CListCtrl&) GetListCtrl(); int columns = list.GetHeaderCtrl()->GetItemCount(); if (flags & FR_DOWN) { for( i = 0; i < ListView_GetItemCount(m_hWnd); i++ ) { if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_SetItemState( m_hWnd, prev = i, 0, LVIS_SELECTED|LVIS_FOCUSED ); while (ListView_GetSelectedCount(m_hWnd)) // clear remaining selections { if( ListView_GetItemState( m_hWnd, ++i, LVIS_SELECTED ) == LVIS_SELECTED ) ListView_SetItemState( m_hWnd, i, 0, LVIS_SELECTED|LVIS_FOCUSED ); } i = prev; break; } } if (flags < 0) i++; while( i < ListView_GetItemCount(m_hWnd) ) { for (j =-1; ++j < columns; ) { ListView_GetItemText( m_hWnd, i, j, str, sizeof(str)/sizeof(TCHAR) ); text = _T(""); switch( GetListCtrl().GetItemData( i ) ) { case SV_ERROR: text = LoadStringResource(IDS_STATUS_ERROR); case SV_WARNING: case SV_WARNSUMMARY: text+= LoadStringResource(IDS_STATUS_WARNING) + str; break; case SV_COMPLETION: text = LoadStringResource(IDS_STATUS_COMPLETION) + str; break; case SV_TOOL: text = LoadStringResource(IDS_STATUS_TOOL) + str; break; default: text = str; break; } if (!(flags & FR_MATCHCASE)) text.MakeLower(); if (text.Find(what) != -1) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); list.EnsureVisible(i, FALSE); MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND)); return 0; } } i++; } } else { for( i = ListView_GetItemCount(m_hWnd); --i >= 0; ) { if( ListView_GetItemState( m_hWnd, i, LVIS_SELECTED ) == LVIS_SELECTED ) { ListView_SetItemState( m_hWnd, prev = i, 0, LVIS_SELECTED|LVIS_FOCUSED ); while (ListView_GetSelectedCount(m_hWnd)) // clear remaining selections { if( ListView_GetItemState( m_hWnd, --i, LVIS_SELECTED ) == LVIS_SELECTED ) ListView_SetItemState( m_hWnd, i, 0, LVIS_SELECTED|LVIS_FOCUSED ); } i = prev; break; } } if (flags < 0) i--; while( i >= 0 ) { for (j =-1; ++j < columns; ) { ListView_GetItemText( m_hWnd, i, j, str, sizeof(str)/sizeof(TCHAR) ); text = _T(""); switch( GetListCtrl().GetItemData( i ) ) { case SV_ERROR: text = LoadStringResource(IDS_STATUS_ERROR); case SV_WARNING: case SV_WARNSUMMARY: text+= LoadStringResource(IDS_STATUS_WARNING) + str; break; case SV_COMPLETION: text = LoadStringResource(IDS_STATUS_COMPLETION) + str; break; case SV_TOOL: text = LoadStringResource(IDS_STATUS_TOOL) + str; break; default: text = str; break; } if (!(flags & FR_MATCHCASE)) text.MakeLower(); if (text.Find(what) != -1) { ListView_SetItemState( m_hWnd, i, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); list.EnsureVisible(i, FALSE); MainFrame()->SetMessageText(LoadStringResource(IDS_FOUND)); return 0; } } i--; } } MessageBeep(0); MainFrame()->SetMessageText(LoadStringResource(IDS_NOT_FOUND)); if (prev != -1) ListView_SetItemState( m_hWnd, prev, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED ); return 0; } static int indexNbr = -1; int CStatusView::OnToolHitTest(CPoint point, TOOLINFO* pTI) const { // CWnd implementation won't do us any good, so we have to handle this. // watch out! sometimes get called with null pointer if (pTI == 0 || !GET_P4REGPTR()->GetShowTruncTooltip( )) return -1; // don't want to show tooltip if nothing is hidden // the tooltip is only there to show truncated text int index; LVHITTESTINFO info; info.pt = point; ListView_HitTest(m_hWnd, &info); if ((index = info.iItem) == -1) return -1; // retun because not on a line with text TCHAR buf[1024]; ListView_GetItemText( m_hWnd, index, 0, buf, 1023 ); int lgth = lstrlen(buf); if (lgth < 50) return -1; // return - line has less than 50 characters CRect rect; GetWindowRect(&rect); HDC hDC = ::GetDC(m_hWnd); SIZE size; GetTextExtentPoint32(hDC, buf, lgth, &size); ::ReleaseDC(m_hWnd, hDC); if ((size.cx < rect.Width()) && (size.cx < 1700)) return -1; // return - line is fully visible if (indexNbr != index) { // If this is the 1st time for this line, just return // in order to remove any current tooltip; we will be // called again and will put up the tooltip then. indexNbr = index; return -1; } // we want to show a tooltip, so set up for the normal callback pTI->hwnd = m_hWnd; // us pTI->uId = (UINT_PTR)m_hWnd; // us pTI->uFlags |= TTF_IDISHWND; // uId is HWND, not ID pTI->lpszText = LPSTR_TEXTCALLBACK; indexNbr = index; // save in a static since this function Must be const! return (int)pTI->uId; } BOOL CStatusView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult ) { // first, check for my tooltip text request // and handle it here TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; UINT nID =pNMHDR->idFrom; if (pTTT->uFlags & TTF_IDISHWND) { if(nID == (UINT)m_hWnd) { TCHAR buf[1024]; CRect rect; GetClientRect(&rect); ::SendMessage(pTTT->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, max(480, 2*rect.Width()/3)); ListView_GetItemText( m_hWnd, indexNbr, 0, buf, 1023 ); m_ToolTipText = buf; pTTT->lpszText = (LPTSTR)(LPCTSTR)m_ToolTipText; pTTT->hinst = NULL; return TRUE; } } // for other cases, just pass it along to mainframe return MainFrame()->OnToolTipText(id, pNMHDR, pResult); }