620 lines
17 KiB
C++
620 lines
17 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999.
|
|
//
|
|
// File: brctrl.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// History: 15 Aug 1996 DLee Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#define TheView (*_pView)
|
|
#define TheModel (*_pModel)
|
|
|
|
// Member functions responding to messages
|
|
|
|
LRESULT WINAPI BrowseWndProc(
|
|
HWND hwnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LRESULT lr = 0;
|
|
CBrowseWindow *pbw = (CBrowseWindow *) GetWindowLongPtr( hwnd, 0 );
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
App.BrowseLastError() = S_OK;
|
|
CREATESTRUCT *pcs = (CREATESTRUCT *) lParam;
|
|
MDICREATESTRUCT *pmcs = (MDICREATESTRUCT *) pcs->lpCreateParams;
|
|
CQueryResult *pResults = (CQueryResult *) pmcs->lParam;
|
|
pbw = new CBrowseWindow();
|
|
SetWindowLongPtr( hwnd, 0, (LONG_PTR) pbw);
|
|
lr = pbw->TheBrowseController.Create( pResults,
|
|
hwnd,
|
|
&pbw->TheBrowseModel,
|
|
&pbw->TheBrowseView,
|
|
App.BrowseFont() );
|
|
break;
|
|
}
|
|
case WM_MDIACTIVATE :
|
|
pbw->TheBrowseController.Activate( hwnd, lParam );
|
|
break;
|
|
case WM_SIZE:
|
|
lr = DefMDIChildProc( hwnd, msg, wParam, lParam );
|
|
pbw->TheBrowseController.Size( hwnd, lParam );
|
|
break;
|
|
case WM_VSCROLL:
|
|
pbw->TheBrowseController.VScroll(hwnd, wParam, lParam);
|
|
break;
|
|
case WM_HSCROLL:
|
|
pbw->TheBrowseController.HScroll(hwnd, wParam, lParam);
|
|
break;
|
|
case WM_KEYDOWN:
|
|
pbw->TheBrowseController.KeyDown (hwnd, wParam );
|
|
lr = DefMDIChildProc(hwnd,msg,wParam,lParam);
|
|
break;
|
|
case WM_CHAR:
|
|
pbw->TheBrowseController.Char (hwnd, wParam);
|
|
lr = DefMDIChildProc(hwnd,msg,wParam,lParam);
|
|
break;
|
|
case WM_PAINT:
|
|
pbw->TheBrowseController.Paint(hwnd);
|
|
break;
|
|
case wmMenuCommand:
|
|
pbw->TheBrowseController.Command(hwnd, wParam);
|
|
break;
|
|
case wmInitMenu:
|
|
pbw->TheBrowseController.EnableMenus();
|
|
break;
|
|
case WM_DESTROY:
|
|
SetWindowLongPtr(hwnd,0,0);
|
|
delete pbw;
|
|
SetProcessWorkingSetSize( GetCurrentProcess(), -1, -1 );
|
|
break;
|
|
case wmNewFont:
|
|
pbw->TheBrowseController.NewFont(hwnd, wParam);
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
pbw->TheBrowseView.ButtonUp( wParam, lParam );
|
|
break;
|
|
case WM_LBUTTONDOWN:
|
|
pbw->TheBrowseView.ButtonDown( wParam, lParam );
|
|
break;
|
|
case WM_LBUTTONDBLCLK:
|
|
pbw->TheBrowseView.DblClk( wParam, lParam );
|
|
break;
|
|
case WM_MOUSEMOVE :
|
|
pbw->TheBrowseView.MouseMove( wParam, lParam );
|
|
break;
|
|
case WM_MOUSEWHEEL :
|
|
lr = pbw->TheBrowseController.MouseWheel( hwnd, wParam, lParam );
|
|
break;
|
|
case WM_CONTEXTMENU :
|
|
pbw->TheBrowseController.ContextMenu( hwnd, wParam, lParam );
|
|
break;
|
|
case EM_GETSEL:
|
|
{
|
|
if ( pbw->TheBrowseView.GetSelection().SelectionExists() )
|
|
lr = MAKELRESULT( 1, 2 );
|
|
else
|
|
lr = 0;
|
|
break;
|
|
}
|
|
default:
|
|
lr = DefMDIChildProc(hwnd,msg,wParam,lParam);
|
|
break;
|
|
}
|
|
|
|
return lr;
|
|
} //BrowseWndProc
|
|
|
|
void Control::ContextMenu(
|
|
HWND hwnd,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
POINT pt;
|
|
pt.x = LOWORD( lParam );
|
|
pt.y = HIWORD( lParam );
|
|
|
|
GetCursorPos( &pt );
|
|
|
|
HMENU hMenu = LoadMenu( App.Instance(), L"BrowseContextMenu" );
|
|
|
|
if ( 0 != hMenu )
|
|
{
|
|
HMENU hTrackMenu = GetSubMenu( hMenu, 0 );
|
|
if ( 0 != hTrackMenu )
|
|
{
|
|
if ( !TheView.GetSelection().SelectionExists() )
|
|
EnableMenuItem( hTrackMenu,
|
|
IDM_EDITCOPY,
|
|
MF_BYCOMMAND | MF_GRAYED );
|
|
|
|
// yes, the function returns a BOOL that you switch on
|
|
|
|
BOOL b = TrackPopupMenuEx( hTrackMenu,
|
|
TPM_LEFTALIGN | TPM_RIGHTBUTTON |
|
|
TPM_RETURNCMD,
|
|
pt.x,
|
|
pt.y,
|
|
hwnd,
|
|
0 );
|
|
switch ( b )
|
|
{
|
|
case IDM_BROWSE_OPEN :
|
|
{
|
|
ViewFile( TheModel.Filename(),
|
|
fileOpen );
|
|
break;
|
|
}
|
|
case IDM_BROWSE_EDIT :
|
|
{
|
|
POINT winpt;
|
|
winpt.x = 0;
|
|
winpt.y = 0;
|
|
ClientToScreen( hwnd, &winpt );
|
|
ViewFile( TheModel.Filename(),
|
|
fileEdit,
|
|
TheView.ParaFromY( pt.y - winpt.y ) );
|
|
break;
|
|
}
|
|
case IDM_EDITCOPY :
|
|
{
|
|
Command( hwnd, b );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
DestroyMenu( hMenu );
|
|
}
|
|
} //ContextMenu
|
|
|
|
LRESULT Control::Create(
|
|
CQueryResult * pResults,
|
|
HWND hwnd,
|
|
Model * pModel,
|
|
View * pView,
|
|
HFONT hFont )
|
|
{
|
|
LRESULT lr = 0;
|
|
|
|
_iWheelRemainder = 0;
|
|
_pModel = pModel;
|
|
_pView = pView;
|
|
SCODE sc = TheModel.CollectFiles( pResults );
|
|
|
|
if ( SUCCEEDED( sc ) )
|
|
{
|
|
TheView.Init( hwnd, _pModel, hFont );
|
|
|
|
// Go to first query hit (if any)
|
|
|
|
Position pos;
|
|
|
|
if ( TheModel.GetPositionCount() != 0 )
|
|
pos = TheModel.GetPosition(0);
|
|
|
|
TheView.SetRange ( TheModel.MaxParaLen(), TheModel.Paras());
|
|
|
|
RECT rc;
|
|
GetClientRect(hwnd,&rc);
|
|
|
|
TheView.Size( rc.right, rc.bottom );
|
|
|
|
TheView.SetScroll (pos);
|
|
|
|
EnableMenus();
|
|
}
|
|
else
|
|
{
|
|
// no better way to get the error back
|
|
|
|
App.BrowseLastError() = sc;
|
|
lr = -1; // don't continue creating the window
|
|
}
|
|
|
|
return lr;
|
|
} //Create
|
|
|
|
void Control::Activate( HWND hwnd, LPARAM lParam )
|
|
{
|
|
if ( hwnd == (HWND) lParam )
|
|
{
|
|
int apos[3] = { 0, 0, 0 };
|
|
int cPos = 2;
|
|
|
|
HDC hdc = GetDC( hwnd );
|
|
|
|
if ( 0 == hdc )
|
|
return;
|
|
|
|
SIZE size;
|
|
|
|
WCHAR awcLines[100];
|
|
CResString strLines( IDS_BRSTAT_CLINES );
|
|
wsprintf( awcLines, strLines.Get(), TheModel.ParaCount() );
|
|
GetTextExtentPoint( hdc, awcLines, wcslen( awcLines ), &size );
|
|
apos[0] = 2 * size.cx;
|
|
|
|
WCHAR awcHits[100];
|
|
CResString strHits( IDS_BRSTAT_CHITS );
|
|
wsprintf( awcHits, strHits.Get(), TheModel.HitCount(), TheModel.HitCount() );
|
|
GetTextExtentPoint( hdc, awcHits, wcslen( awcHits ), &size );
|
|
apos[1] = 2 * size.cx + apos[0];
|
|
|
|
ReleaseDC( hwnd, hdc );
|
|
|
|
SendMessage( App.StatusBarWindow(), SB_SETPARTS, cPos, (LPARAM) apos );
|
|
|
|
SendMessage( App.StatusBarWindow(), SB_SETTEXT, 0, (LPARAM) awcLines );
|
|
|
|
static UINT aDisable[] = { IDM_SEARCH,
|
|
IDM_SEARCHCLASSDEF,
|
|
IDM_SEARCHFUNCDEF,
|
|
IDM_BROWSE,
|
|
IDM_DISPLAY_PROPS };
|
|
UpdateButtons( aDisable, 5, FALSE );
|
|
|
|
EnableMenus();
|
|
}
|
|
} //Activate
|
|
|
|
void Control::NewFont ( HWND hwnd, WPARAM wParam)
|
|
{
|
|
TheView.FontChange ( hwnd, (HFONT) wParam );
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
} //NewFont
|
|
|
|
void Control::SetScrollBars ( HWND hwnd )
|
|
{
|
|
SetScrollPos ( hwnd, SB_VERT, TheView.VScrollPara(), TRUE );
|
|
SetScrollPos ( hwnd, SB_HORZ, TheView.HScrollPos(), TRUE );
|
|
} //SetScrollBars
|
|
|
|
// Go to next query hit when 'n' pressed
|
|
|
|
void Control::Char ( HWND hwnd, WPARAM wparam )
|
|
{
|
|
Position pos;
|
|
HCURSOR hCursor;
|
|
BOOL success;
|
|
|
|
switch ( wparam )
|
|
{
|
|
case 'n':
|
|
{
|
|
if ( !TheModel.NextHit() )
|
|
break;
|
|
|
|
pos = TheModel.GetPosition(0);
|
|
TheView.SetScroll( pos );
|
|
SetScrollBars (hwnd);
|
|
|
|
EnableMenus();
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
break;
|
|
}
|
|
case 'p':
|
|
{
|
|
if ( !TheModel.PrevHit() )
|
|
break;
|
|
|
|
pos = TheModel.GetPosition(0);
|
|
TheView.SetScroll( pos );
|
|
SetScrollBars(hwnd);
|
|
|
|
EnableMenus();
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
break;
|
|
}
|
|
case 'N':
|
|
{
|
|
hCursor = SetCursor (LoadCursor(0, IDC_WAIT));
|
|
ShowCursor (TRUE);
|
|
success = S_OK == TheModel.NextDoc();
|
|
ShowCursor(FALSE);
|
|
SetCursor (hCursor);
|
|
|
|
if ( success )
|
|
{
|
|
if ( TheModel.GetPositionCount() != 0 )
|
|
{
|
|
pos = TheModel.GetPosition(0);
|
|
}
|
|
TheView.SetRange ( TheModel.MaxParaLen(), TheModel.Paras());
|
|
TheView.SetScrollMax();
|
|
TheView.SetScroll (pos);
|
|
UpdateScroll(hwnd);
|
|
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
EnableMenus();
|
|
SetWindowText( hwnd, TheModel.Filename() );
|
|
}
|
|
break;
|
|
}
|
|
case 'P':
|
|
{
|
|
hCursor = SetCursor (LoadCursor(0, IDC_WAIT));
|
|
ShowCursor (TRUE);
|
|
success = TheModel.PrevDoc();
|
|
ShowCursor(FALSE);
|
|
SetCursor (hCursor);
|
|
if ( success )
|
|
{
|
|
if ( TheModel.GetPositionCount() != 0 )
|
|
pos = TheModel.GetPosition(0);
|
|
|
|
TheView.SetRange ( TheModel.MaxParaLen(), TheModel.Paras());
|
|
TheView.SetScrollMax();
|
|
TheView.SetScroll (pos);
|
|
UpdateScroll(hwnd);
|
|
InvalidateRect(hwnd, NULL, TRUE);
|
|
EnableMenus();
|
|
SetWindowText( hwnd, TheModel.Filename() );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} //Char
|
|
|
|
void Control::EnableMenus()
|
|
{
|
|
UINT ui = IDM_NEXT_HIT;
|
|
UpdateButtons( &ui, 1, ! TheModel.isLastHit() );
|
|
ui = IDM_PREVIOUS_HIT;
|
|
UpdateButtons( &ui, 1, ! TheModel.isFirstHit() );
|
|
|
|
HMENU hmenu = GetMenu( App.AppWindow() );
|
|
|
|
EnableMenuItem(hmenu,IDM_NEXT_HIT,MF_BYCOMMAND |
|
|
(TheModel.isLastHit() ? MF_GRAYED | MF_DISABLED :
|
|
MF_ENABLED) );
|
|
|
|
EnableMenuItem(hmenu,IDM_PREVIOUS_HIT,MF_BYCOMMAND |
|
|
(TheModel.isFirstHit() ? MF_GRAYED | MF_DISABLED :
|
|
MF_ENABLED) );
|
|
|
|
EnableMenuItem( hmenu, IDM_NEWSEARCH, MF_ENABLED );
|
|
|
|
int cHits = TheModel.HitCount();
|
|
|
|
WCHAR awcHits[100];
|
|
if ( 0 == cHits )
|
|
{
|
|
awcHits[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
CResString strHits( IDS_BRSTAT_CHITS );
|
|
wsprintf( awcHits,
|
|
strHits.Get(),
|
|
TheModel.CurrentHit() + 1,
|
|
cHits );
|
|
}
|
|
SendMessage( App.StatusBarWindow(), SB_SETTEXT, 1, (LPARAM) awcHits );
|
|
} //EnableMenus
|
|
|
|
void Control::Size ( HWND hwnd, LPARAM lParam )
|
|
{
|
|
TheView.Size ( LOWORD(lParam), HIWORD(lParam) );
|
|
TheView.SetScrollMax();
|
|
UpdateScroll( hwnd );
|
|
// in case we have to scroll to close up the gap
|
|
// at the bottom of the window
|
|
int delta = TheView.IncVScrollPos( 0 );
|
|
if (delta != 0)
|
|
{
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0 );
|
|
SetScrollPos (hwnd, SB_VERT, TheView.VScrollPara(), TRUE );
|
|
UpdateWindow(hwnd);
|
|
}
|
|
} //Size
|
|
|
|
void Control::UpdateScroll( HWND hwnd)
|
|
{
|
|
TheView.SetRange ( TheModel.MaxParaLen(), TheModel.Paras());
|
|
|
|
SetScrollRange(hwnd, SB_VERT, 0, TheView.VScrollMax(), FALSE );
|
|
SetScrollRange(hwnd, SB_HORZ, 0, TheView.HScrollMax(), FALSE );
|
|
|
|
SetScrollBars (hwnd);
|
|
|
|
// proportional scroll box
|
|
SCROLLINFO si;
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_PAGE;
|
|
si.nPage = TheView.VisibleLines();
|
|
SetScrollInfo( hwnd, SB_VERT, &si, TRUE );
|
|
} //UpdateScroll
|
|
|
|
LRESULT Control::MouseWheel( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
// forward what we don't process
|
|
|
|
if ( wParam & ( MK_SHIFT | MK_CONTROL ) )
|
|
return DefMDIChildProc( hwnd, WM_MOUSEWHEEL, wParam, lParam );
|
|
|
|
// add the current scroll to the remainder from last time
|
|
|
|
int iDelta = (int) (short) HIWORD( wParam );
|
|
iDelta += _iWheelRemainder;
|
|
|
|
// if there isn't enough to process this time, just return
|
|
|
|
if ( abs( iDelta ) < WHEEL_DELTA )
|
|
{
|
|
_iWheelRemainder = iDelta;
|
|
return 0;
|
|
}
|
|
|
|
// compute the remainder and amount to scroll
|
|
|
|
_iWheelRemainder = ( iDelta % WHEEL_DELTA );
|
|
iDelta /= WHEEL_DELTA;
|
|
|
|
BOOL fDown;
|
|
if ( iDelta < 0 )
|
|
{
|
|
fDown = TRUE;
|
|
iDelta = -iDelta;
|
|
}
|
|
else
|
|
fDown = FALSE;
|
|
|
|
// get the # of lines to scroll per WHEEL_DELTA
|
|
|
|
int cLines;
|
|
SystemParametersInfo( SPI_GETWHEELSCROLLLINES, 0, &cLines, 0 );
|
|
if ( 0 == cLines )
|
|
return 0;
|
|
|
|
int cVisibleLines = TheView.VisibleLines();
|
|
|
|
// if scrolling a page, do so. don't scroll more than one page
|
|
|
|
if ( WHEEL_PAGESCROLL == cLines )
|
|
iDelta = __max( 1, (cVisibleLines - 1) );
|
|
else
|
|
{
|
|
iDelta *= cLines;
|
|
if ( iDelta >= cVisibleLines )
|
|
iDelta = __max( 1, (cVisibleLines - 1) );
|
|
}
|
|
|
|
// phew. do the scroll
|
|
|
|
if ( 0 != iDelta )
|
|
{
|
|
int delta = TheView.IncVScrollPos( fDown ? iDelta : -iDelta );
|
|
MyScrollWindow( hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
SetScrollPos( hwnd, SB_VERT, TheView.VScrollPara(), TRUE );
|
|
UpdateWindow( hwnd );
|
|
}
|
|
|
|
return iDelta;
|
|
} //MouseWheel
|
|
|
|
void Control::VScroll( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
int nVScrollInc;
|
|
int delta = 0;
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case SB_TOP:
|
|
TheView.Home();
|
|
InvalidateRect (hwnd, 0, TRUE);
|
|
delta = 1;
|
|
break;
|
|
case SB_BOTTOM:
|
|
TheView.End();
|
|
InvalidateRect (hwnd, 0, TRUE);
|
|
delta = 1;
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
delta = TheView.IncVScrollPos( -1 );
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
break;
|
|
case SB_LINEDOWN:
|
|
nVScrollInc = 1;
|
|
delta = TheView.IncVScrollPos( 1 );
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
nVScrollInc = - max ( 1, TheView.VisibleLines() - 1);
|
|
delta = TheView.IncVScrollPos( nVScrollInc );
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
break;
|
|
case SB_PAGEDOWN:
|
|
nVScrollInc = max ( 1, TheView.VisibleLines() - 1);
|
|
delta = TheView.IncVScrollPos( nVScrollInc );
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
delta = TheView.JumpToPara ( HIWORD(wParam) );
|
|
MyScrollWindow (hwnd, 0, -delta * TheView.LineHeight(), 0, 0, FALSE );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ( delta != 0 )
|
|
{
|
|
SetScrollPos (hwnd, SB_VERT, TheView.VScrollPara(), TRUE );
|
|
UpdateWindow(hwnd);
|
|
}
|
|
} //VScroll
|
|
|
|
void Control::HScroll( HWND hwnd, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
}
|
|
|
|
void Control::KeyDown ( HWND hwnd, WPARAM wparam )
|
|
{
|
|
switch(wparam)
|
|
{
|
|
case VK_HOME:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_TOP, 0L );
|
|
break;
|
|
case VK_END:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_BOTTOM, 0L );
|
|
break;
|
|
case VK_PRIOR:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_PAGEUP, 0L );
|
|
break;
|
|
case VK_NEXT:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_PAGEDOWN, 0L );
|
|
break;
|
|
case VK_UP:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_LINEUP, 0L );
|
|
break;
|
|
case VK_DOWN:
|
|
SendMessage( hwnd, WM_VSCROLL, SB_LINEDOWN, 0L );
|
|
break;
|
|
case VK_LEFT:
|
|
SendMessage( hwnd, WM_HSCROLL, SB_PAGEUP, 0L );
|
|
break;
|
|
case VK_RIGHT:
|
|
SendMessage( hwnd, WM_HSCROLL, SB_PAGEDOWN, 0L );
|
|
break;
|
|
}
|
|
} //KeyDown
|
|
|
|
// Menu commands processing
|
|
|
|
void Control::Command ( HWND hwnd, WPARAM wParam )
|
|
{
|
|
switch ( wParam )
|
|
{
|
|
case IDM_NEXT_HIT:
|
|
SendMessage ( hwnd, WM_CHAR, 'n', 0L );
|
|
break;
|
|
case IDM_PREVIOUS_HIT:
|
|
SendMessage ( hwnd, WM_CHAR, 'p', 0L );
|
|
break;
|
|
case IDM_NEWSEARCH:
|
|
// close the browser window
|
|
PostMessage( hwnd, WM_CLOSE, 0, 0 );
|
|
break;
|
|
case IDM_EDITCOPY :
|
|
TheView.EditCopy( hwnd, wParam );
|
|
}
|
|
} //Command
|
|
|
|
|
|
|