windows-nt/Source/XPSP1/NT/enduser/stuff/hhctrl/bookmark.cpp
2020-09-26 16:20:57 +08:00

1753 lines
53 KiB
C++

///////////////////////////////////////////////////////////
//
//
// AdSearch.cpp - Implementation of the Advanced Search UI
//
// This source file implements the Advanced Search Navigation
// pane class.
///////////////////////////////////////////////////////////
//
// Include section
//
#include "header.h"
#include "strtable.h" // These headers were copied from search.cpp. Are they all needed?
#include "system.h"
#include "hhctrl.h"
#include "resource.h"
#include "secwin.h"
#include "htmlhelp.h"
#include "cpaldc.h"
#include "TCHAR.h"
#include "parserhh.h"
#include "collect.h"
#include "hhtypes.h"
#include "toc.h"
#include "contain.h"
#include "cctlww.h"
// Our header file.
#include "bookmark.h"
// Common Control Macros
#include <windowsx.h>
#define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring
///////////////////////////////////////////////////////////
//
// Constants
//
const char c_PersistFolder[] = "Bookmarks\\v1" ;
const char c_TopicFolder[] = "Topic" ;
const char c_UrlFolder[] = "Url" ;
const char c_CountFolder[] = "Bookmarks\\v1\\Count" ;
const wchar_t c_KeywordSeparator[] = L"\n" ;
// This is the maximum bookmarks we store.
// The main reason for this is to ensure that we have a reasonable value
// when we read the collection in.
const int c_MaxBookmarks = 1024;
extern BOOL g_fUnicodeListView;
///////////////////////////////////////////////////////////
//
// Static Member functions
//
WNDPROC CBookmarksNavPane::s_lpfnlListViewWndProc = NULL;
WNDPROC CBookmarksNavPane::s_lpfnlCurrentTopicEditProc = NULL;
WNDPROC CBookmarksNavPane::s_lpfnlGenericBtnProc = NULL;
//WNDPROC CBookmarksNavPane::s_lpfnlGenericKeyboardProc = NULL ;
///////////////////////////////////////////////////////////
//
// Non-Member helper functions.
//
// Convert a rect from screen to client.
void ScreenRectToClientRect(HWND hWnd, /*in/out*/ RECT* prect) ;
///////////////////////////////////////////////////////////
//
// Construction
//
///////////////////////////////////////////////////////////
//
// CBookmarksNavPane();
//
CBookmarksNavPane::CBookmarksNavPane(CHHWinType* pWinType)
: m_hWnd(NULL),
m_hfont(NULL),
m_padding(2), // padding to put around the window
m_pWinType(pWinType),
m_pszCurrentUrl(NULL),
m_bChanged(false)
{
ASSERT(pWinType) ;
m_pTitleCollection = pWinType->m_phmData->m_pTitleCollection;
ASSERT(m_pTitleCollection);
m_NavTabPos = pWinType->tabpos ;
}
///////////////////////////////////////////////////////////
//
// ~CBookmarksNavPane
//
CBookmarksNavPane::~CBookmarksNavPane()
{
//--- Persist Keywords in combo
SaveBookmarks() ;
//--- Empty the listview.
int items = ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
if (items > 0)
{
// Iterate through each item get its size.
for (int i = 0 ; i < items ; i++)
{
TCHAR* pUrl = GetUrl(i) ;
ASSERT(pUrl) ;
if (pUrl)
{
// Delete the attached url.
delete [] pUrl ;
}
}
// Delete all of the items
W_ListView_DeleteAllItems(m_aDlgItems[c_TopicsList].m_hWnd) ;
}
//--- CleanUp
if (m_hfont)
{
::DeleteObject(m_hfont);
}
if (m_hWnd)
{
::DestroyWindow(m_hWnd) ;
}
if (m_pszCurrentUrl)
{
delete m_pszCurrentUrl ;
}
//Don't free m_pTitleCollection
}
///////////////////////////////////////////////////////////
//
// INavUI Interface functions.
//
///////////////////////////////////////////////////////////
//
// Create
//
BOOL
CBookmarksNavPane::Create(HWND hwndParent)
{
bool bReturn = false ;
if (m_hWnd)
{
return true ;
}
// ---Create the dialog.
bool bUnicode = true;
if (! (m_hWnd = CreateDialogParamW(
_Module.GetResourceInstance(),
MAKEINTRESOURCEW(IDPAGE_TAB_BOOKMARKS),
hwndParent,
s_DialogProc,
reinterpret_cast<LPARAM>(this))) ) // Pass over the this pointer.
{
bUnicode = FALSE;
if (! (m_hWnd = CreateDialogParamA(
_Module.GetResourceInstance(),
MAKEINTRESOURCEA(IDPAGE_TAB_BOOKMARKS),
hwndParent,
s_DialogProc,
reinterpret_cast<LPARAM>(this))) ) // Pass over the this pointer.
return FALSE;
}
//--- Initialize the DlgItem Array.
InitDlgItemArray() ;
//--- Initialize the bookmarks list
// Setup the columnsin the listview ;
LV_COLUMNW column;
column.mask = LVCF_FMT | LVCF_WIDTH;
column.cx = 1500; //TODO FIX
column.fmt = LVCFMT_LEFT;
//column.iSubItem = 0;
W_EnableUnicode(m_aDlgItems[c_TopicsList].m_hWnd, W_ListView);
W_ListView_InsertColumn(m_aDlgItems[c_TopicsList].m_hWnd, 0, &column );
// Sub-class the list view
if (s_lpfnlListViewWndProc == NULL)
{
s_lpfnlListViewWndProc = W_GetWndProc(m_aDlgItems[c_TopicsList].m_hWnd, bUnicode);
}
W_SubClassWindow(m_aDlgItems[c_TopicsList].m_hWnd, reinterpret_cast<LONG_PTR>(s_ListViewProc), bUnicode);
SETTHIS(m_aDlgItems[c_TopicsList].m_hWnd);
//--- Initialize the Current Topic Edit Control
// Limit the amount of text which can be typed in.
Edit_LimitText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, MAX_PATH-1) ;
// Subclass the keyword combo so that we can process the keys
if (s_lpfnlCurrentTopicEditProc == NULL)
{
s_lpfnlCurrentTopicEditProc = W_GetWndProc(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, bUnicode);
}
W_SubClassWindow(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, reinterpret_cast<LONG_PTR>(s_CurrentTopicEditProc), bUnicode);
SETTHIS(m_aDlgItems[c_CurrentTopicEdit].m_hWnd);
//--- Subclass all of the buttons
// Start with the StartSearch button ;
if (s_lpfnlGenericBtnProc == NULL)
{
s_lpfnlGenericBtnProc = W_GetWndProc(m_aDlgItems[c_DeleteBtn].m_hWnd, bUnicode);
}
W_SubClassWindow(m_aDlgItems[c_DeleteBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
SETTHIS(m_aDlgItems[c_DeleteBtn].m_hWnd);
// Bitmap btn
W_SubClassWindow(m_aDlgItems[c_DisplayBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
SETTHIS(m_aDlgItems[c_DisplayBtn].m_hWnd);
// c_DisplayBtn
W_SubClassWindow(m_aDlgItems[c_AddBookmarkBtn].m_hWnd, reinterpret_cast<LONG_PTR>(s_GenericBtnProc), bUnicode);
SETTHIS(m_aDlgItems[c_AddBookmarkBtn].m_hWnd);
#if 0
//--- Set the font. This will fix some dbcs issues.
for (int i = 0 ; i < c_NumDlgItems ; i++)
{
SendMessage(m_aDlgItems[i].m_hWnd, WM_SETFONT, (WPARAM) GetFont(), FALSE);
}
#endif
SendMessage(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, WM_SETFONT, (WPARAM) GetFont(), FALSE);
SendMessage(m_aDlgItems[c_TopicsList].m_hWnd, WM_SETFONT, (WPARAM) GetAccessableContentFont(), FALSE);
//--- Fill the combobox with persisted data.
LoadBookmarks() ;
// Set the focus to the appropriate control.
SetDefaultFocus() ;
//TODO: Fix
return true;
}
///////////////////////////////////////////////////////////
//
// OnCommand
//
LRESULT
CBookmarksNavPane::OnCommand(HWND hwnd, UINT id, UINT NotifyCode, LPARAM lParam)
{
switch(NotifyCode)
{
case BN_CLICKED:
switch(id)
{
case IDC_BOOKMARKS_DELETE_BTN:
OnDelete() ;
break;
case IDC_BOOKMARKS_DISPLAY_BTN:
OnDisplay() ;
break ;
case IDC_BOOKMARKS_ADDBOOKMARK_BTN:
OnAddBookmark();
break;
case IDC_BOOKMARKS_EDIT_BTN:
OnEdit() ;
break;
default:
return 0 ;
}
return 1 ;
}
return 0 ;
}
///////////////////////////////////////////////////////////
//
// ResizeWindow
//
void
CBookmarksNavPane::ResizeWindow()
{
ASSERT(::IsValidWindow(m_hWnd)) ;
// Resize to fit the client area of the parent.
HWND hwndParent = GetParent(m_hWnd) ;
ASSERT(::IsValidWindow(hwndParent)) ;
//--- Get the size of the window
RECT rcParent;
GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
//--- Move and size the dialog box itself.
::SetWindowPos( m_hWnd, NULL, rcParent.left, rcParent.top,
rcParent.right-rcParent.left,
rcParent.bottom-rcParent.top,
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOREDRAW);
//---Fix the painting bugs. However, this is a little on the flashy side.
::InvalidateRect(m_hWnd, NULL, TRUE) ;
RECT rcDlg;
::GetClientRect(m_hWnd, &rcDlg) ;
//--- Now position each control within this space.
for (int i = 0 ; i < c_NumDlgItems ; i++)
{
// Get Current Settings.
int X = m_aDlgItems[i].m_rectCur.left;
int Y = m_aDlgItems[i].m_rectCur.top;
int CX = m_aDlgItems[i].m_rectCur.right - m_aDlgItems[i].m_rectCur.left;
int CY = m_aDlgItems[i].m_rectCur.bottom - m_aDlgItems[i].m_rectCur.top;
bool bChanged = false ;
//--- RIGHT JUSTIFICATION
if (m_aDlgItems[i].m_JustifyH == Justify::Right)
{
int NewX = rcDlg.right-m_aDlgItems[i].m_iOffsetH ; // subtract the offset
int MinX = m_aDlgItems[i].m_rectMin.left;
if (NewX < MinX)
{
NewX = MinX; // Don't go below min.
}
if (X != NewX)
{
X = NewX ; // Update the current setting.
bChanged = true ;
}
}
//--- BOTTOM JUSTIFICATION
if (m_aDlgItems[i].m_JustifyV == Justify::Bottom)
{
int NewY = rcDlg.bottom - m_aDlgItems[i].m_iOffsetV;
int MinY = m_aDlgItems[i].m_rectMin.top ;
if (NewY < MinY)
{
NewY = MinY ;
}
if (Y != NewY)
{
Y = NewY ; // Update Setting.
bChanged = true ;
}
}
//--- HORIZONTAL GROWING
if (m_aDlgItems[i].m_bGrowH)
{
int MaxCX = m_aDlgItems[i].m_rectMax.right - m_aDlgItems[i].m_rectMax.left ;
int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left ;
int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top ;
int NewRight = rcDlg.right - m_aDlgItems[i].m_iPadH ;
int NewCX = NewRight - m_aDlgItems[i].m_rectMin.left;
if (NewCX < MinCX)
{
NewCX = MinCX;
}
else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCX > MaxCX)
{
NewCX = MaxCX ;
}
if (CX != NewCX)
{
CX = NewCX ; // Update Current ;
bChanged = true ;
}
}
//--- VERTICAL GROWING
if (m_aDlgItems[i].m_bGrowV)
{
int MaxCY = m_aDlgItems[i].m_rectMax.bottom - m_aDlgItems[i].m_rectMax.top;
int MinCY = m_aDlgItems[i].m_rectMin.bottom - m_aDlgItems[i].m_rectMin.top ;
int MinCX = m_aDlgItems[i].m_rectMin.right - m_aDlgItems[i].m_rectMin.left;
int NewBottom = rcDlg.bottom - m_aDlgItems[i].m_iPadV ;
int NewCY = NewBottom - m_aDlgItems[i].m_rectMin.top;
if (NewCY < MinCY)
{
NewCY = MinCY;
}
else if ((!m_aDlgItems[i].m_bIgnoreMax) && NewCY > MaxCY)
{
NewCY = MaxCY ;
}
if (CY != NewCY)
{
CY = NewCY ;
bChanged = true ;
}
}
if (bChanged)
{
m_aDlgItems[i].m_rectCur.left = X ;
m_aDlgItems[i].m_rectCur.top = Y ;
m_aDlgItems[i].m_rectCur.right = X + CX ;
m_aDlgItems[i].m_rectCur.bottom = Y + CY ;
::SetWindowPos(m_aDlgItems[i].m_hWnd, NULL,
X, Y, CX, CY,
SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOREDRAW*/);
// If we have to change the size of the results list, lets change the size of the columns.
/*
if (i == c_ResultsList)
{
m_plistview->SizeColumns() ;
}
*/
}
}
}
///////////////////////////////////////////////////////////
//
// HideWindow
//
void
CBookmarksNavPane::HideWindow()
{
if (::IsValidWindow(m_hWnd))
{
::ShowWindow(m_hWnd, SW_HIDE) ;
}
}
///////////////////////////////////////////////////////////
//
// ShowWindow
//
void
CBookmarksNavPane::ShowWindow()
{
if (::IsValidWindow(m_hWnd))
{
// Turn the dialog items on/off
ShowDlgItemsEnabledState() ;
// Show the dialog window.
::ShowWindow(m_hWnd, SW_SHOW) ;
}
}
///////////////////////////////////////////////////////////
//
// SetPadding
//
void
CBookmarksNavPane::SetPadding(int pad)
{
m_padding = pad;
}
///////////////////////////////////////////////////////////
//
// SetTabPos
//
void
CBookmarksNavPane::SetTabPos(int tabpos)
{
m_NavTabPos = tabpos;
}
///////////////////////////////////////////////////////////
//
// SetDefaultFocus --- Set focus to the most expected control, usually edit combo.
//
void
CBookmarksNavPane::SetDefaultFocus()
{
if (::IsValidWindow(m_aDlgItems[c_TopicsList].m_hWnd))
{
BookmarkDlgItemInfoIndex ctrl ;
int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
if (items > 0)
{
// Set focus to the topics list if we have any entries in it.
ctrl = c_TopicsList ;
// Set the focus if nothing selected.
if (GetSelectedItem() < 0)
{
W_ListView_SetItemState(m_aDlgItems[c_TopicsList].m_hWnd, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED) ;
}
}
else
{
// Set focus to the edit control if the topic listis empty.
ctrl = c_CurrentTopicEdit ;
}
SetFocus(m_aDlgItems[ctrl].m_hWnd) ;
}
}
///////////////////////////////////////////////////////////
//
// ProcessMenuChar --- Process accelerator keys.
//
bool
CBookmarksNavPane::ProcessMenuChar(HWND hwndParent, int ch)
{
return ::ProcessMenuChar(this, hwndParent, m_aDlgItems, c_NumDlgItems, ch) ;
}
///////////////////////////////////////////////////////////
//
// OnNotify --- Process WM_NOTIFY messages. Used by embedded Tree and List view controls.
//
LRESULT
CBookmarksNavPane::OnNotify(HWND hwnd, WPARAM idCtrl, LPARAM lParam)
{
switch(idCtrl)
{
case IDC_BOOKMARKS_TOPICS_LISTVIEW:
if (::IsValidWindow(m_aDlgItems[c_TopicsList].m_hWnd))
{
return ListViewMsg(m_aDlgItems[c_TopicsList].m_hWnd, (NM_LISTVIEW*) lParam);
}
break ;
default:
//return DefDlgProc(m_hWnd, WM_NOTIFY, idCtrl, lParam);
return 0 ;
}
return 0 ;
}
///////////////////////////////////////////////////////////
//
// OnDrawItem --- Process WM_DRAWITEM messages.
//
void
CBookmarksNavPane::OnDrawItem(UINT id, LPDRAWITEMSTRUCT pdis)
{
}
///////////////////////////////////////////////////////////
//
// Seed --- Seed the nav ui with a search term or keyword.
//
void
CBookmarksNavPane::Seed(LPCSTR pszSeed)
{
}
///////////////////////////////////////////////////////////
//
// Synchronize
//
BOOL
CBookmarksNavPane::Synchronize(PSTR pNotUsed, CTreeNode* pNotUsed2)
{
if (pNotUsed == NULL && pNotUsed2 == NULL)
{
FillCurrentTopicEdit() ;
return TRUE ;
}
else
{
return FALSE ;
}
}
///////////////////////////////////////////////////////////
//
// Helper Functions.
//
///////////////////////////////////////////////////////////
//
// InitDlgItemArray
//
void
CBookmarksNavPane::InitDlgItemArray()
{
RECT rectCurrent ;
RECT rectDlg ;
::GetClientRect(m_hWnd, &rectDlg) ;
//--- Setup the dlg array for each control.
//--- Topics ListView
int i = c_TopicsList;
m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_TOPICS_LISTVIEW) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
DWORD_PTR dwCurrentExtendedStyles = GetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE);
SetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE, dwCurrentExtendedStyles | g_RTL_Mirror_Style);
m_aDlgItems[i].m_id = IDC_BOOKMARKS_TOPICS_LISTVIEW;
m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_BOOKMARKS_TOPICS_STATIC); // No accelerator.
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 = TRUE; // Grow Horizontally.
m_aDlgItems[i].m_bGrowV = TRUE ; // 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::Left; // Do we stick to the right or the left
//m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
m_aDlgItems[i].m_iPadV = rectDlg.bottom - rectCurrent.bottom;
m_aDlgItems[i].m_rectMin = rectCurrent;
m_aDlgItems[i].m_rectCur = rectCurrent;
//m_aDlgItems[i].m_rectMax ; // Max size.
//--- Delete Button
i = c_DeleteBtn;
m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_DELETE_BTN) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
m_aDlgItems[i].m_id = IDC_BOOKMARKS_DELETE_BTN;
m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd) ;
m_aDlgItems[i].m_Type = ItemInfo::Button;
m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
m_aDlgItems[i].m_bEnabled = FALSE; // 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::Bottom; // Do we stick to the top or the bottom.
m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // 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 = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_DISPLAY_BTN) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
m_aDlgItems[i].m_id = IDC_BOOKMARKS_DISPLAY_BTN;
m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd) ;
m_aDlgItems[i].m_Type = ItemInfo::Button;
m_aDlgItems[i].m_bIgnoreEnabled = FALSE;
m_aDlgItems[i].m_bEnabled = FALSE; // 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::Bottom; // Do we stick to the top or the bottom.
m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // 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.
//--- Current Topics Static
i = c_CurrentTopicStatic;
m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_STATIC) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
m_aDlgItems[i].m_id = IDC_BOOKMARKS_CURRENTTOPIC_STATIC;
m_aDlgItems[i].m_accelkey = 0 ;
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::Bottom; // Do we stick to the top or the bottom.
m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
//m_aDlgItems[i].m_iOffsetH =
//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.
//--- Current Topics Edit control
i = c_CurrentTopicEdit;
m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_EDIT) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
dwCurrentExtendedStyles = GetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE);
SetWindowLongPtr(m_aDlgItems[i].m_hWnd, GWL_EXSTYLE, dwCurrentExtendedStyles | g_RTL_Style);
m_aDlgItems[i].m_id = IDC_BOOKMARKS_CURRENTTOPIC_EDIT;
m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hWnd, IDC_BOOKMARKS_CURRENTTOPIC_STATIC);
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 = TRUE; // Grow Horizontally.
m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
m_aDlgItems[i].m_JustifyV = Justify::Bottom; // Do we stick to the top or the bottom.
m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // Distance from our justification point.
m_aDlgItems[i].m_JustifyH = Justify::Left; // Do we stick to the right or the left
//m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
m_aDlgItems[i].m_iPadH = rectDlg.right - rectCurrent.right; // Maintain same distance. If someone to the right grows we are broken.
//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.
//--- Add Button
i = c_AddBookmarkBtn ;
m_aDlgItems[i].m_hWnd = ::GetDlgItem(m_hWnd, IDC_BOOKMARKS_ADDBOOKMARK_BTN) ;
::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
m_aDlgItems[i].m_id = IDC_BOOKMARKS_ADDBOOKMARK_BTN;
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::Bottom; // Do we stick to the top or the bottom.
m_aDlgItems[i].m_iOffsetV = rectDlg.bottom - rectCurrent.top ; // 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.
}
///////////////////////////////////////////////////////////
//
// SetEnabledState
//
void
CBookmarksNavPane::ShowDlgItemsEnabledState()
{
// Enable/Disable all the controls
for (int i = 0 ; i < c_NumDlgItems ; i++)
{
if (!m_aDlgItems[i].m_bIgnoreEnabled && ::IsValidWindow(m_aDlgItems[i].m_hWnd))
{
EnableWindow(m_aDlgItems[i].m_hWnd, m_aDlgItems[i].m_bEnabled) ;
}
}
}
///////////////////////////////////////////////////////////
//
// EnableDlgItem
//
void
CBookmarksNavPane::EnableDlgItem(BookmarkDlgItemInfoIndex index, bool bEnable)
{
ASSERT(index >= 0 && index < c_NumDlgItems) ;
if (!m_aDlgItems[index].m_bIgnoreEnabled)
{
// Are we enabled or not?
m_aDlgItems[index].m_bEnabled = bEnable ;
// Do it for real.
if (::IsValidWindow(m_aDlgItems[index].m_hWnd))
{
EnableWindow(m_aDlgItems[index].m_hWnd, bEnable) ;
}
}
}
///////////////////////////////////////////////////////////
//
// SaveBookmarks --- Persists the bookmars to the storage
//
// The bookmarks are stored using the following format:
// Bookmarks
// \v1 - Version.
// \Count - Number of bookmarks written.
// \0 - First bookmark.
// \Topic - Topic Unicode String
// \Url - Url Unicode String
// \1 - Second bookmark.
// ...
// \(count-1)
//
void
CBookmarksNavPane::SaveBookmarks()
{
// Also save the bookmarks, if they have changed.
if (!Changed())
{
return ;
}
// Keep track of the number of bookmarks written.
int cWritten = 0 ;
// Buffer for path to the state folder.
char statepath[64] ;
// Get the state pointer.
CState* pstate = m_pTitleCollection->GetState();
ASSERT(pstate) ;
// Are there any keywords to save.
int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
if (items > 0)
{
// Limit the number. I hate limiting the number, but its much more robust.
if (items > c_MaxBookmarks)
{
items = c_MaxBookmarks ;
}
// Buffer for retrieving the text.
WCHAR Topic[MAX_URL] ;
// Iterate through the items.
for (int i = 0 ; i < items ; i++)
{
TCHAR* pUrl = NULL ;
if (GetTopicAndUrl(i, Topic, sizeof(Topic), &pUrl))
{
//--- Write out topic.
// Construct the path.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, cWritten, c_TopicFolder);
if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
{
DWORD cb = (wcslen(Topic)+1)*sizeof(wchar_t) ;
DWORD dwResult = pstate->Write(Topic, cb);
pstate->Close();
// Is result okay?
if (cb == dwResult)
{
//--- Write out the URL.
// Convert to unicode.
CWStr url(pUrl) ;
ASSERT(url.pw) ;
// Construt the path.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, cWritten, c_UrlFolder);
// Write out.
if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
{
cb = (wcslen(url.pw)+1)*sizeof(wchar_t) ;
dwResult = pstate->Write(url.pw, cb);
pstate->Close();
// Check result.
if (cb == dwResult)
{
// We have been successful. So Increment the count.
cWritten++ ;
}
}
}
}
} //if
} // for
} // if items
// How many entries are currently stored.
int StoredCount = 0;
if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_READ)))
{
DWORD cbReadIn = 0 ;
pstate->Read(&StoredCount , sizeof(StoredCount), &cbReadIn) ;
pstate->Close() ;
if (cbReadIn != sizeof(StoredCount))
{
// Assume that we don't have any stored.
StoredCount = 0 ;
}
}
// Delete the extra entries.
if (StoredCount > cWritten)
{
// Delete extra entries.
for(int j = cWritten ; j < StoredCount ; j++)
{
// Remove the URL folder.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, j, c_UrlFolder);
if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
{
HRESULT hr = pstate->Delete() ;
ASSERT(SUCCEEDED(hr)) ;
pstate->Close() ;
}
// Remove the topic folder.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, j, c_TopicFolder);
if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
{
HRESULT hr = pstate->Delete() ;
ASSERT(SUCCEEDED(hr)) ;
pstate->Close() ;
}
// Remove branch.
wsprintf(statepath, "%s\\%d", c_PersistFolder, j);
if (SUCCEEDED(pstate->Open(statepath, STGM_WRITE)))
{
HRESULT hr = pstate->Delete() ;
ASSERT(SUCCEEDED(hr)) ;
pstate->Close() ;
}
}
}
// Write out the count.
if (cWritten >= 0) // We may have deleted everything, so count can be zero.
{
// Write out the new count.
if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_WRITE)))
{
DWORD cb = pstate->Write(&cWritten, sizeof(cWritten));
ASSERT(cb == sizeof(cWritten)) ; // TODO: Handle error.
pstate->Close() ;
// Reset dirty flag ;
SetChanged(false) ;
}
}
else
{
//TODO: Erase everything. That is there.
}
}
///////////////////////////////////////////////////////////
//
// LoadBookmarks - Loads the results list from the storage
//
void
CBookmarksNavPane::LoadBookmarks()
{
CState* pstate = m_pTitleCollection->GetState();
if (SUCCEEDED(pstate->Open(c_CountFolder, STGM_READ)))
{
// Read in the topics stored.
DWORD cbReadIn = 0 ;
int StoredCount = 0;
pstate->Read(&StoredCount , sizeof(StoredCount), &cbReadIn) ;
pstate->Close() ;
// Did we get a reasonable number?
if (cbReadIn == sizeof(StoredCount) &&
StoredCount > 0 &&
StoredCount < c_MaxBookmarks) // We check the max here just to sure we have reasonable numbers.
{
// Buffer for path to the state folder.
char statepath[64] ;
WCHAR buffer[MAX_URL] ;
// Now let's read them in.
for (int i=0 ; i < StoredCount ; i++)
{
//--- Read in the URL.
TCHAR* pUrl = NULL ;
// Construct the path.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, i, c_UrlFolder);
// Open Topic in.
if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
{
// Read it into the buffer.
DWORD cb = NULL ;
HRESULT hr = pstate->Read(&buffer, sizeof(buffer), &cb);
pstate->Close();
// Check result.
if (SUCCEEDED(hr))
{
// Convert from unicode.
CStr strUrl(buffer) ;
ASSERT(strUrl.psz) ;
//--- Read in the topic.
// Construct the path.
wsprintf(statepath, "%s\\%d\\%s", c_PersistFolder, i, c_TopicFolder);
if (SUCCEEDED(pstate->Open(statepath, STGM_READ)))
{
cb = NULL;
hr = pstate->Read(&buffer, sizeof(buffer), &cb);
pstate->Close();
if (SUCCEEDED(hr))
{
//--- Save the URL.
TCHAR* pszUrl = new TCHAR[strUrl.strlen()+1] ;
_tcscpy(pszUrl, strUrl.psz) ;
//--- Add the string to the listview.
LV_ITEMW item;
item.mask = LVIF_TEXT | LVIF_PARAM ; //| LVIF_STATE;
item.iImage = 0;
//item.state = LVIS_FOCUSED | LVIS_SELECTED;
//item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
item.iItem = 0 ;
item.iSubItem = 0;
item.lParam = (LPARAM)pszUrl;
item.pszText = buffer;
W_ListView_InsertItem( m_aDlgItems[c_TopicsList].m_hWnd, &item );
}
}
}
} // if --- opened topic.
} // for
// We haven't changed.
SetChanged(false) ;
} //if --- count valid
} //if --- Can read count
}
///////////////////////////////////////////////////////////
//
// FillCurrentTopicEdit
//
void
CBookmarksNavPane::FillCurrentTopicEdit()
{
ASSERT(m_pWinType && m_pWinType->m_pCIExpContainer && m_pWinType->m_pCIExpContainer->m_pWebBrowserApp) ;
ASSERT(m_pTitleCollection) ;
//--- Prepare to be re-entered!
// Delete the current URL.
if (m_pszCurrentUrl)
{
delete m_pszCurrentUrl ;
m_pszCurrentUrl = NULL ;
}
// Clear out the edit control.
W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, L"") ;
//--- Get to work.
CStr url ;
if (m_pWinType && m_pWinType->m_pCIExpContainer && m_pWinType->m_pCIExpContainer->m_pWebBrowserApp)
{
// Get the URL of the current topic.
m_pWinType->m_pCIExpContainer->m_pWebBrowserApp->GetLocationURL(&url); //Urg there is no error return!!!
if (!url.IsEmpty())
{
//--- Save the URL before we normalize it.
m_pszCurrentUrl = new TCHAR[url.strlen()+1] ;
_tcscpy(m_pszCurrentUrl,url.psz) ;
// Nomalize the URL
NormalizeUrlInPlace(url) ;
// Use the url to get a CExTitle pointer.
bool bFoundTitle = false; // Did we find a title?
CExTitle *pTitle = NULL ;
HRESULT hr = m_pTitleCollection->URL2ExTitle(m_pszCurrentUrl, &pTitle);
if (SUCCEEDED(hr) && pTitle)
{
// Use the pTitle to get the topic number.
//TOC_TOPIC topic ; // Don't need
DWORD topicnumber;
hr = pTitle->URL2Topic(url, NULL/*&topic*/, &topicnumber);
if (SUCCEEDED(hr))
{
// Now that we have a topic number we can get the location string.
WCHAR wszCurrentTopic[MAX_PATH] ;
hr = pTitle->GetTopicName(topicnumber, wszCurrentTopic, (MAX_PATH/2)) ;
if (SUCCEEDED(hr))
{
// Yea, we finally have a location
W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, wszCurrentTopic) ;
// We have found the title!
bFoundTitle = true ;
}
}
}
// We have not found the title. Maybe its a web site.
if (!bFoundTitle)
{
ASSERT(m_pszCurrentUrl) ;
// convert URL to wide...
CWStr wurl(url) ;
ASSERT(wurl.pw) ;
// So put he normalized URL into the edit control.
W_SetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, wurl.pw) ;
}
}
}
}
///////////////////////////////////////////////////////////
//
// Get the selected item
//
CBookmarksNavPane::GetSelectedItem() const
{
int indexSelected = -1 ;
int selections = W_ListView_GetSelectedCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
if (selections > 0)
{
ASSERT(selections == 1) ;
indexSelected = W_ListView_GetNextItem(m_aDlgItems[c_TopicsList].m_hWnd, -1, LVNI_SELECTED) ;
}
return indexSelected ;
}
///////////////////////////////////////////////////////////
//
// Get the Url for the item
//
TCHAR*
CBookmarksNavPane::GetUrl(int index) const
{
TCHAR* pReturn = NULL ;
if ((index >= 0) && (index < W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd)))
{
LV_ITEMW item ;
item.mask = LVIF_PARAM;
item.iItem = index;
item.iSubItem = 0;
item.lParam = NULL;
W_ListView_GetItem(m_aDlgItems[c_TopicsList].m_hWnd, &item) ;
pReturn = (TCHAR*)item.lParam ;
}
return pReturn ;
}
///////////////////////////////////////////////////////////
//
// Get the URL and the Topic name.
//
bool
CBookmarksNavPane::GetTopicAndUrl(
int index, //[in] Index
WCHAR* pTopicBuffer, //[in] Buffer for the topic.
int TopicBufferSize, //[in] Size of the topic buffer.
TCHAR** pUrl //[out] Pointer to Url.
) const
{
bool bReturn = false ;
if ((index >= 0) && (index < W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd)))
{
LV_ITEMW item ;
item.mask = LVIF_PARAM | LVIF_TEXT ;
item.iItem = index;
item.iSubItem = 0;
item.lParam = NULL ;
item.pszText = pTopicBuffer;
item.cchTextMax = TopicBufferSize ;
if (W_ListView_GetItem(m_aDlgItems[c_TopicsList].m_hWnd, &item))
{
*pUrl = (TCHAR*)item.lParam ;
ASSERT(*pUrl) ;
if (*pUrl) //TODO: Validate pTopicBuffer ;
{
bReturn = true;
}
}
else
{
bReturn = false ;
}
}
return bReturn ;
}
///////////////////////////////////////////////////////////
//
// ContextMenu
//
void
CBookmarksNavPane::ContextMenu(bool bUseCursor)
{
// Create the menu.
HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDM_BOOKMARKS_OPTIONS_MENU)) ;
ASSERT(hMenu) ;
// Get the Popup Menu
HMENU hPopupMenu = GetSubMenu(hMenu, 0) ;
// Is an item selected?
int bState ;
int selection = GetSelectedItem() ;
if (selection < 0)
{
// Nothing selected.
bState = MF_GRAYED ;
}
else
{
bState = MF_ENABLED ;
}
// Set state of menu items.
EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_DELETE_BTN, MF_BYCOMMAND | bState) ;
EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_DISPLAY_BTN, MF_BYCOMMAND | bState ) ;
EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_EDIT_BTN, MF_BYCOMMAND | bState) ;
// Always enabled.
EnableMenuItem(hPopupMenu, IDC_BOOKMARKS_ADDBOOKMARK_BTN, MF_BYCOMMAND | MF_ENABLED) ;
// Set the style of the menu.
DWORD style = TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON;
//--- Get the location to display the menu
POINT pt ;
if (bUseCursor)
{
// Use the mouse cursor position.
GetCursorPos(&pt) ;
}
else
{
// Use the upper right of the client area. Probably invoked by shift-F10
RECT rc;
GetClientRect(m_aDlgItems[c_TopicsList].m_hWnd, &rc) ; //REVIEW: Upper corner should always be 0,0. Remove?
pt.x = rc.left;
pt.y = rc.top ;
ClientToScreen(m_aDlgItems[c_TopicsList].m_hWnd, &pt);
}
// Display the menu.
int iCmd = TrackPopupMenuEx(hPopupMenu,
style ,
pt.x, pt.y,
m_hWnd,
NULL) ;
// Act on the item.
if (iCmd != 0)
{
OnCommand(m_hWnd, iCmd, BN_CLICKED, NULL);
}
// Cleanup
DestroyMenu(hMenu) ;
}
///////////////////////////////////////////////////////////
//
// Message Handlers
//
///////////////////////////////////////////////////////////
//
// OnDelete
//
void
CBookmarksNavPane::OnDelete()
{
int indexSelected = GetSelectedItem() ;
HWND hwndFocus = ::GetFocus();
BOOL bDeletedLast = FALSE;
if (indexSelected >= 0)
{
TCHAR* pUrl = GetUrl(indexSelected) ;
ASSERT(pUrl) ;
if (pUrl)
{
// Delete the attached url.
delete [] pUrl ;
}
// Delete the item
BOOL b = W_ListView_DeleteItem(m_aDlgItems[c_TopicsList].m_hWnd, indexSelected) ;
ASSERT(b) ;
// Set changed flag.
SetChanged() ;
// Select the item below the one we just deleted.
int items = W_ListView_GetItemCount(m_aDlgItems[c_TopicsList].m_hWnd) ;
if (items > 0)
{
if (indexSelected >= items)
{
indexSelected = items-1 ;
}
// The following should never happen, but its better safe in beta2...
if (indexSelected < 0)
{
ASSERT(indexSelected < 0) ;
indexSelected = 0 ;
}
W_ListView_SetItemState(m_aDlgItems[c_TopicsList].m_hWnd, indexSelected, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED) ;
}
else
bDeletedLast = TRUE;
}
if (bDeletedLast == TRUE)
::SetFocus(m_aDlgItems[c_AddBookmarkBtn].m_hWnd);
else
if (hwndFocus != m_aDlgItems[c_TopicsList].m_hWnd)
::SetFocus(hwndFocus);
}
///////////////////////////////////////////////////////////
//
// OnDisplay
//
void
CBookmarksNavPane::OnDisplay()
{
// Get the selected URL.
TCHAR* pUrl = GetSelectedUrl() ;
if (pUrl)
{
// Change to this URL.
ChangeHtmlTopic(pUrl, m_hWnd, 0);
}
}
///////////////////////////////////////////////////////////
//
// OnAddBookmark
//
void
CBookmarksNavPane::OnAddBookmark()
{
int len = W_GetTextLengthExact(m_aDlgItems[c_CurrentTopicEdit].m_hWnd) ;
if (len > 0)
{
// Get the string from the edit control
WCHAR* pCurrentTopicTitle = new WCHAR[len+1] ;
W_GetWindowText(m_aDlgItems[c_CurrentTopicEdit].m_hWnd, pCurrentTopicTitle, len+1) ;
//--- Copy the URL.
ASSERT(m_pszCurrentUrl) ;
TCHAR* pszUrl = new TCHAR[_tcslen(m_pszCurrentUrl)+1] ;
_tcscpy(pszUrl, m_pszCurrentUrl) ;
//--- Add the string to the listview.
LV_ITEMW item;
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
item.iImage = 0;
item.state = LVIS_FOCUSED | LVIS_SELECTED;
item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
item.iItem = 0 ;
item.iSubItem = 0;
item.lParam = (LPARAM)pszUrl;
item.pszText = pCurrentTopicTitle ;
int i = W_ListView_InsertItem( m_aDlgItems[c_TopicsList].m_hWnd, &item );
//Setfocus to list view
SetFocus(m_aDlgItems[c_TopicsList].m_hWnd) ;
// Cleanup
delete [] pCurrentTopicTitle ;
// Set changed flag.
SetChanged() ;
}
}
///////////////////////////////////////////////////////////
//
// OnEdit - Handles the edit menu item.
//
void
CBookmarksNavPane::OnEdit()
{
// Edit the currently selected item.
int selection = GetSelectedItem() ;
if (selection >=0)
{
W_ListView_EditLabel(m_aDlgItems[c_TopicsList].m_hWnd, selection) ;
// Set changed flag.
SetChanged() ;
}
}
///////////////////////////////////////////////////////////
//
// OnTab - Handles pressing of the tab key.
//
void
CBookmarksNavPane::OnTab(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/)
{
//if (index == c_NumDlgItems) --- caller doesn't know the index.
ASSERT(::IsValidWindow(hwndReceivedTab)) ;
//--- Is the shift key down?
BOOL bPrevious = (GetKeyState(VK_SHIFT) < 0) ;
{
//--- Move to the next control .
// Get the next tab item.
HWND hWndNext = GetNextDlgTabItem(m_hWnd, hwndReceivedTab, bPrevious) ;
// Set focus to it.
::SetFocus(hWndNext) ;
}
}
///////////////////////////////////////////////////////////
//
// OnArrow
//
void
CBookmarksNavPane::OnArrow(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/, INT_PTR key)
{
//if (index == c_NumDlgItems) --- caller doesn't know the index.
ASSERT(::IsValidWindow(hwndReceivedTab)) ;
BOOL bPrevious = FALSE ;
if (key == VK_LEFT || key == VK_UP)
{
bPrevious = TRUE ;
}
// Get the next tab item.
HWND hWndNext = GetNextDlgGroupItem(m_hWnd, hwndReceivedTab, bPrevious) ;
// Set focus to it.
::SetFocus(hWndNext) ;
}
///////////////////////////////////////////////////////////
//
// OnReturn - Default handling of the return key.
//
bool
CBookmarksNavPane::OnReturn(HWND hwndReceivedTab, BookmarkDlgItemInfoIndex /*index*/)
{
//if (index == c_NumDlgItems) --- caller doesn't know the index.
// Do the default button action.
// Always do a search topic, if its enabled.
if (::IsWindowEnabled(m_aDlgItems[c_DisplayBtn].m_hWnd))
{
OnDisplay();
return true ;
}
else
{
return false ;
}
}
///////////////////////////////////////////////////////////
//
// ListViewMsg
//
LRESULT
CBookmarksNavPane::ListViewMsg(HWND hwnd, NM_LISTVIEW* lParam)
{
switch(lParam->hdr.code)
{
case NM_DBLCLK:
case NM_RETURN:
OnDisplay() ;
break;
case NM_RCLICK:
ContextMenu() ;
break ;
case LVN_ITEMCHANGED:
{
bool bEnable = GetSelectedItem() >= 0 ;
EnableDlgItem(c_DisplayBtn, bEnable) ;
EnableDlgItem(c_DeleteBtn, bEnable) ;
}
break ;
case LVN_BEGINLABELEDITA:
case LVN_BEGINLABELEDITW:
/*
//ListView_GetEditControl();
//LimitText;
*/
return FALSE ;
case LVN_ENDLABELEDITA:
case LVN_ENDLABELEDITW:
{
LV_DISPINFOW* pDispInfo = (LV_DISPINFOW*)lParam ;
if (pDispInfo->item.iItem != -1 &&
pDispInfo->item.pszText &&
lstrlenW(pDispInfo->item.pszText) > 0)
{
if(g_fUnicodeListView)
{
W_ListView_SetItemText(m_aDlgItems[c_TopicsList].m_hWnd,
pDispInfo->item.iItem,
0,
pDispInfo->item.pszText) ;
}
else
{
ListView_SetItemText(m_aDlgItems[c_TopicsList].m_hWnd,
pDispInfo->item.iItem,
0,
(char *)pDispInfo->item.pszText) ;
}
// Set changed flag.
SetChanged() ;
return TRUE ; // Accept Edit
}
}
break ;
}
return 0;
}
///////////////////////////////////////////////////////////
//
// Callback Functions.
//
///////////////////////////////////////////////////////////
//
// Static DialogProc
//
INT_PTR CALLBACK
CBookmarksNavPane::s_DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Call member function dialog proc.
if (msg == WM_INITDIALOG)
{
// The lParam is the this pointer for this dialog box.
// Save it in the window userdata section.
::SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
}
// Get the this pointer and call the non-static callback function.
CBookmarksNavPane* p = reinterpret_cast<CBookmarksNavPane*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA)) ;
if (p)
{
return p->DialogProc(hwnd, msg, wParam, lParam) ;
}
else
{
return FALSE ;
}
}
///////////////////////////////////////////////////////////
//
// ListViewProc
//
LRESULT WINAPI
CBookmarksNavPane::s_ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
switch (msg)
{
case WM_KEYDOWN:
if (wParam == VK_RETURN)
{
// A return means that we want to display the currently selected topic.
pThis->OnDisplay() ; //Todo: Should this be a send message?
return 0 ;
}
else if (wParam == VK_TAB)
{
pThis->OnTab(hwnd, c_TopicsList) ;
}
else if (wParam == VK_F2)
{
pThis->OnEdit() ;
return 0 ;
}
break ;
case WM_SYSKEYDOWN:
if (wParam == VK_F10 && (GetKeyState(VK_SHIFT) < 0)) // SHIFT-F10
{
pThis->ContextMenu(false) ;
return 0 ;
}
break;
}
return W_DelegateWindowProc(s_lpfnlListViewWndProc, hwnd, msg, wParam, lParam);
}
///////////////////////////////////////////////////////////
//
// KeywordComboEditProc - Subclassed the Edit Control in the Keyword Combo Box
// The original reason for doing this was to save the selection location.
//
LRESULT WINAPI
CBookmarksNavPane::s_CurrentTopicEditProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
switch (msg)
{
case WM_KEYDOWN:
if (wParam == VK_TAB)
{
pThis->OnTab(hwnd,c_CurrentTopicEdit) ;
return 0 ;
}
else if (wParam == VK_RETURN)
{
pThis->OnAddBookmark();
}
break;
case WM_CHAR:
if (wParam == VK_TAB)
{
//Stops the beep!
return 0 ;
}
}
return W_DelegateWindowProc(s_lpfnlCurrentTopicEditProc, hwnd, msg, wParam, lParam);
}
///////////////////////////////////////////////////////////
//
// Generic keyboard handling for all btns.
//
LRESULT WINAPI
CBookmarksNavPane::s_GenericBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
if (wParam == VK_RETURN)
{
// Do the command associated with this btn.
CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
return pThis->OnCommand(pThis->m_hWnd, ::GetDlgCtrlID(hwnd), BN_CLICKED, lParam) ; // TODO: Should this be a sendmessage?
}
else if (wParam == VK_TAB)
{
CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
pThis->OnTab(hwnd,c_NumDlgItems) ;
return 0 ;
}
else if (wParam == VK_LEFT ||
wParam == VK_RIGHT ||
wParam == VK_UP ||
wParam == VK_DOWN)
{
CBookmarksNavPane* pThis = reinterpret_cast<CBookmarksNavPane*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
pThis->OnArrow(hwnd,c_NumDlgItems, wParam) ;
return 0 ;
}
break;
}
return W_DelegateWindowProc(s_lpfnlGenericBtnProc, hwnd, msg, wParam, lParam);
}
///////////////////////////////////////////////////////////
//
// DialogProc
//
INT_PTR
CBookmarksNavPane::DialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
return OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), lParam) ;
break ;
case WM_NOTIFY:
return OnNotify(hwnd, wParam, lParam) ;
case WM_INITDIALOG:
break;
case WM_SHOWWINDOW:
{
BOOL bActive = (BOOL) wParam ;
if (bActive)
{
FillCurrentTopicEdit() ;
}
}
break ;
case WM_ACTIVATE:
{
int active = LOWORD(wParam) ;
if (active != WA_INACTIVE)
{
FillCurrentTopicEdit() ;
}
}
break ;
}
return FALSE;
}