You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1132 lines
35 KiB
1132 lines
35 KiB
/////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// MODULE: GrpDlg.cpp
|
|
//
|
|
// PURPOSE: Implements the CGroupListDlg class.
|
|
//
|
|
|
|
#include "pch.hxx"
|
|
#include <iert.h>
|
|
#include <instance.h>
|
|
#include "subscr.h"
|
|
#include "resource.h"
|
|
#include "strconst.h"
|
|
#include "thormsgs.h"
|
|
#include "goptions.h"
|
|
#include "mailnews.h"
|
|
#include "shlwapip.h"
|
|
#include "imnact.h"
|
|
#include "error.h"
|
|
#include "acctutil.h"
|
|
#include <ras.h>
|
|
#include "imagelst.h"
|
|
#include "conman.h"
|
|
#include "xpcomm.h"
|
|
#include <storutil.h>
|
|
#include "demand.h"
|
|
#include "menures.h"
|
|
#include "storecb.h"
|
|
|
|
|
|
UINT g_rgCtlMap[] = { idcFindText, idcUseDesc, idcGroupList, idcSubscribe,
|
|
idcUnsubscribe, idcResetList, idcGoto, IDOK, IDCANCEL, idcServers, idcStaticNewsServers,
|
|
idcStaticHorzLine, idcTabs};
|
|
|
|
const static HELPMAP g_rgCtxMapGrpDlg[] = {
|
|
{idcFindText, IDH_NEWS_SEARCH_GROUPS_CONTAINING},
|
|
{idcDispText, IDH_NEWS_SEARCH_GROUPS_CONTAINING},
|
|
{idcUseDesc, IDH_NEWS_SEARCH_GROUPS_DESC},
|
|
{idcGroupList, IDH_NEWS_GROUP_LISTS},
|
|
{idcSubscribe, IDH_NEWS_ADD_SELECTED_GROUP},
|
|
{idcUnsubscribe, IDH_NEWS_REMOVE_SELECTED_GROUP},
|
|
{idcResetList, IDH_NEWS_RESET_NEW_LIST},
|
|
{idcGoto, IDH_NEWS_OPEN_SELECTED_GROUP},
|
|
{idcServers, IDH_NEWS_SERVER_LIST},
|
|
{idcStaticNewsServers, IDH_NEWS_SERVER_LIST},
|
|
{idcTabs, IDH_NEWSGROUP_LIST_ALL},
|
|
{0, 0}
|
|
};
|
|
|
|
const static HELPMAP g_rgCtxMapGrpDlgIMAP[] = {
|
|
{idcFindText, 50505},
|
|
{idcDispText, 50505},
|
|
{idcGroupList, 50510},
|
|
{idcSubscribe, 50520},
|
|
{idcUnsubscribe, 50525},
|
|
{idcResetList, 50530},
|
|
{idcGoto, 50515},
|
|
{idcServers, 50500},
|
|
{idcStaticNewsServers, 50500},
|
|
{0, 0}
|
|
};
|
|
|
|
HRESULT DoSubscriptionDialog(HWND hwnd, BOOL fNews, FOLDERID idFolder, BOOL fShowNew)
|
|
{
|
|
CGroupListDlg *pDlg;
|
|
FOLDERID id, idDefault;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
FOLDERTYPE type;
|
|
|
|
#ifdef DEBUG
|
|
if (fShowNew)
|
|
Assert(fNews);
|
|
#endif // DEBUG
|
|
|
|
type = fNews ? FOLDER_NEWS : FOLDER_IMAP;
|
|
|
|
pDlg = new CGroupListDlg;
|
|
if (pDlg == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
if (idFolder == FOLDERID_ROOT)
|
|
{
|
|
idFolder = FOLDERID_INVALID;
|
|
}
|
|
else if (idFolder != FOLDERID_INVALID)
|
|
{
|
|
hr = GetFolderStoreInfo(idFolder, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (type == info.tyFolder)
|
|
idFolder = info.idFolder;
|
|
else
|
|
idFolder = FOLDERID_INVALID;
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
else
|
|
{
|
|
idFolder = FOLDERID_INVALID;
|
|
}
|
|
}
|
|
|
|
if (idFolder == FOLDERID_INVALID)
|
|
{
|
|
hr = GetDefaultServerId(fNews ? ACCT_NEWS : ACCT_MAIL, &idDefault);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = g_pStore->GetFolderInfo(idDefault, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (type == info.tyFolder)
|
|
idFolder = idDefault;
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
pDlg->Release();
|
|
return(hr);
|
|
}
|
|
}
|
|
|
|
if (pDlg->FCreate(hwnd, type, &id, fShowNew ? 2 : 0, TRUE, idFolder))
|
|
{
|
|
if (id != FOLDERID_INVALID)
|
|
g_pInstance->BrowseToObject(SW_SHOWNORMAL, id);
|
|
}
|
|
|
|
pDlg->Release();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
CGroupListDlg::CGroupListDlg()
|
|
{
|
|
m_cRef = 1;
|
|
|
|
// m_hwnd
|
|
// m_hwndFindText
|
|
// m_hwndOwner
|
|
|
|
m_fAllowDesc = TRUE;
|
|
m_pszPrevQuery = 0;
|
|
m_cchPrevQuery = 0;
|
|
|
|
m_cxHorzSep = 0;
|
|
m_cyVertSep = 0;
|
|
m_rgst = 0;
|
|
m_sizeDlg.cx = 0;
|
|
m_sizeDlg.cy = 0;
|
|
m_ptDragMin.x = 0;
|
|
m_ptDragMin.y = 0;
|
|
|
|
m_himlServer = NULL;
|
|
m_pGrpList = NULL;
|
|
// m_type
|
|
// m_iTabSelect
|
|
// m_idSel
|
|
m_idGoto = FOLDERID_INVALID;
|
|
// m_fEnableGoto
|
|
m_fServerListInited = FALSE;
|
|
m_idCurrent = FOLDERID_INVALID;
|
|
m_hIcon = NULL;
|
|
|
|
m_pColumns = NULL;
|
|
}
|
|
|
|
CGroupListDlg::~CGroupListDlg()
|
|
{
|
|
SafeMemFree(m_pszPrevQuery);
|
|
SafeMemFree(m_rgst);
|
|
|
|
if (m_pColumns != NULL)
|
|
m_pColumns->Release();
|
|
|
|
if (m_pGrpList != NULL)
|
|
m_pGrpList->Release();
|
|
|
|
if (m_hIcon)
|
|
SideAssert(DestroyIcon(m_hIcon));
|
|
|
|
if (m_himlServer != NULL)
|
|
ImageList_Destroy(m_himlServer);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGroupListDlg::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (void*) (IUnknown *)(IGroupListAdvise *)this;
|
|
else if (IsEqualIID(riid, IID_IGroupListAdvise))
|
|
*ppvObj = (void*) (IGroupListAdvise *) this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CGroupListDlg::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CGroupListDlg::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::FCreate()
|
|
//
|
|
// PURPOSE: Handles initialization of the data and creation of the
|
|
// Newsgroups dialog.
|
|
//
|
|
BOOL CGroupListDlg::FCreate(HWND hwndOwner, FOLDERTYPE type, FOLDERID *pGotoId,
|
|
UINT iTabSelect, BOOL fEnableGoto, FOLDERID idSel)
|
|
{
|
|
MSG msg;
|
|
HWND hwndDlg;
|
|
UINT idd;
|
|
HRESULT hr;
|
|
|
|
Assert(pGotoId != NULL);
|
|
|
|
m_hwndOwner = hwndOwner;
|
|
|
|
Assert(type == FOLDER_IMAP || type == FOLDER_NEWS);
|
|
m_type = type;
|
|
|
|
m_iTabSelect = iTabSelect;
|
|
m_fEnableGoto = fEnableGoto;
|
|
m_idSel = idSel;
|
|
|
|
m_pGrpList = new CGroupList;
|
|
if (m_pGrpList == NULL)
|
|
return(FALSE);
|
|
|
|
idd = type == FOLDER_NEWS ? iddSubscribe : iddSubscribeImap;
|
|
|
|
if (GetParent(m_hwndOwner))
|
|
{
|
|
while (GetParent(m_hwndOwner))
|
|
m_hwndOwner = GetParent(m_hwndOwner);
|
|
}
|
|
|
|
// Fake this modeless dialog into behaving like a modal dialog
|
|
EnableWindow(m_hwndOwner, FALSE);
|
|
hwndDlg = CreateDialogParam(g_hLocRes, MAKEINTRESOURCE(idd), hwndOwner,
|
|
GroupListDlgProc, (LPARAM) this);
|
|
ShowWindow(hwndDlg, SW_SHOW);
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
if (IsGrpDialogMessage(msg.hwnd, &msg))
|
|
continue;
|
|
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
if (IsWindow(m_hwnd))
|
|
{
|
|
// GetMessage returned FALSE (WM_QUIT), but we still exist. This
|
|
// means someone else posted the WM_QUIT, so we should close and
|
|
// put the WM_QUIT back in the queue
|
|
SendMessage(m_hwnd, WM_COMMAND, IDCANCEL, 0L);
|
|
PostQuitMessage((int)(msg.wParam)); // repost quit for next enclosing loop
|
|
}
|
|
EnableWindow(m_hwndOwner, TRUE);
|
|
|
|
*pGotoId = m_idGoto;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::IsGrpDialogMessage()
|
|
//
|
|
// PURPOSE: Because there are people who think that because we have a tab
|
|
// control on this dialog it should behave like a property sheet,
|
|
// we need to fake the dialog modeless and filter our own
|
|
// keystrokes. I've stolen this function from the comctl32 sources
|
|
// so if we get any bugs saying the behavior isn't the same the
|
|
// person is full of it.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the window to check the messages for.
|
|
// pMsg - Message to check.
|
|
//
|
|
// RETURN VALUE:
|
|
// Returns TRUE if the message was dispatched, FALSE otherwise.
|
|
//
|
|
BOOL CGroupListDlg::IsGrpDialogMessage(HWND hwnd, LPMSG pMsg)
|
|
{
|
|
if ((pMsg->message == WM_KEYDOWN) && (GetAsyncKeyState(VK_CONTROL) < 0))
|
|
{
|
|
BOOL bBack = FALSE;
|
|
|
|
switch (pMsg->wParam)
|
|
{
|
|
case VK_TAB:
|
|
bBack = GetAsyncKeyState(VK_SHIFT) < 0;
|
|
break;
|
|
|
|
case VK_PRIOR: // VK_PAGE_UP
|
|
case VK_NEXT: // VK_PAGE_DOWN
|
|
bBack = (pMsg->wParam == VK_PRIOR);
|
|
break;
|
|
|
|
default:
|
|
goto NoKeys;
|
|
}
|
|
|
|
int iCur = TabCtrl_GetCurSel(GetDlgItem(m_hwnd, idcTabs));
|
|
|
|
// tab in reverse if shift is down
|
|
if (bBack)
|
|
iCur += (iTabMax - 1);
|
|
else
|
|
iCur++;
|
|
|
|
iCur %= iTabMax;
|
|
TabCtrl_SetCurSel(GetDlgItem(m_hwnd, idcTabs), iCur);
|
|
OnSwitchTabs(hwnd, iCur);
|
|
return TRUE;
|
|
}
|
|
|
|
NoKeys:
|
|
if (IsWindow(m_hwnd) && IsDialogMessage(m_hwnd, pMsg))
|
|
return TRUE;
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK CGroupListDlg::GroupListDlgProc(HWND hwnd, UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
CGroupListDlg* pThis = 0;
|
|
pThis = (CGroupListDlg*) GetWindowLongPtr(hwnd, DWLP_USER);
|
|
LRESULT lResult;
|
|
|
|
// Bug #16910 - For some reason we get messages before we set the this
|
|
// pointer into the window extra bytes. If this happens
|
|
// we should blow the message off.
|
|
if (uMsg != WM_INITDIALOG && 0 == pThis)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// Stash the this pointer so we can use it for all the messages.
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
pThis = (CGroupListDlg*) lParam;
|
|
|
|
return (BOOL)HANDLE_WM_INITDIALOG(hwnd, wParam, lParam,
|
|
pThis->OnInitDialog);
|
|
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
return OnContextHelp(hwnd, uMsg, wParam, lParam, (pThis->m_type == FOLDER_IMAP) ? g_rgCtxMapGrpDlgIMAP : g_rgCtxMapGrpDlg);
|
|
|
|
case WM_COMMAND:
|
|
Assert(pThis);
|
|
HANDLE_WM_COMMAND(hwnd, wParam, lParam, pThis->OnCommand);
|
|
return (TRUE);
|
|
|
|
case WM_NOTIFY:
|
|
Assert(pThis);
|
|
lResult = HANDLE_WM_NOTIFY(hwnd, wParam, lParam, pThis->OnNotify);
|
|
SetDlgMsgResult(hwnd, WM_NOTIFY, lResult);
|
|
return (TRUE);
|
|
|
|
case WM_TIMER:
|
|
Assert(pThis);
|
|
HANDLE_WM_TIMER(hwnd, wParam, lParam, pThis->OnTimer);
|
|
return (TRUE);
|
|
|
|
case WM_PAINT:
|
|
Assert(pThis);
|
|
HANDLE_WM_PAINT(hwnd, wParam, lParam, pThis->OnPaint);
|
|
return (FALSE);
|
|
|
|
case WM_SIZE:
|
|
Assert(pThis);
|
|
HANDLE_WM_SIZE(hwnd, wParam, lParam, pThis->OnSize);
|
|
return (TRUE);
|
|
|
|
case WM_GETMINMAXINFO:
|
|
Assert(pThis);
|
|
HANDLE_WM_GETMINMAXINFO(hwnd, wParam, lParam, pThis->OnGetMinMaxInfo);
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
Assert(pThis);
|
|
HANDLE_WM_CLOSE(hwnd, wParam, lParam, pThis->OnClose);
|
|
return (TRUE);
|
|
|
|
case WM_DESTROY:
|
|
Assert(pThis);
|
|
HANDLE_WM_DESTROY(hwnd, wParam, lParam, pThis->OnDestroy);
|
|
return (TRUE);
|
|
|
|
case WM_NCHITTEST:
|
|
{
|
|
POINT pt = { LOWORD(lParam), HIWORD(lParam) };
|
|
RECT rc;
|
|
GetWindowRect(hwnd, &rc);
|
|
rc.left = rc.right - GetSystemMetrics(SM_CXSMICON);
|
|
rc.top = rc.bottom - GetSystemMetrics(SM_CYSMICON);
|
|
if (PtInRect(&rc, pt))
|
|
{
|
|
SetDlgMsgResult(hwnd, WM_NCHITTEST, HTBOTTOMRIGHT);
|
|
return (TRUE);
|
|
}
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
case NVM_CHANGESERVERS:
|
|
pThis->OnChangeServers(hwnd);
|
|
return (TRUE);
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
static const UINT c_rgNewsSubTab[] =
|
|
{
|
|
idsTabAll, idsTabSubscribed, idsTabNew
|
|
};
|
|
|
|
static const UINT c_rgImapSubTab[] =
|
|
{
|
|
idsTabAll, idsTabVisible
|
|
};
|
|
|
|
BOOL CGroupListDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
HRESULT hr;
|
|
HWND hwndT, hwndList;
|
|
WINDOWPLACEMENT wp;
|
|
TC_ITEM tci;
|
|
RECT rcDlg;
|
|
UINT i, cTab, *pTab;
|
|
char sz[CCHMAX_STRINGRES];
|
|
COLUMN_SET_TYPE set;
|
|
|
|
// It's handy to have these handles available
|
|
m_hwnd = hwnd;
|
|
m_hwndFindText = GetDlgItem(hwnd, idcFindText);
|
|
SetIntlFont(m_hwndFindText);
|
|
|
|
// Add some tabs to our tab control.
|
|
hwndT = GetDlgItem(hwnd, idcTabs);
|
|
Assert(IsWindow(hwndT));
|
|
|
|
if (m_type == FOLDER_NEWS)
|
|
{
|
|
set = COLUMN_SET_NEWS_SUB;
|
|
|
|
pTab = (UINT *)c_rgNewsSubTab;
|
|
cTab = ARRAYSIZE(c_rgNewsSubTab);
|
|
}
|
|
else
|
|
{
|
|
set = COLUMN_SET_IMAP_SUB;
|
|
|
|
pTab = (UINT *)c_rgImapSubTab;
|
|
cTab = ARRAYSIZE(c_rgImapSubTab);
|
|
}
|
|
|
|
tci.mask = TCIF_TEXT;
|
|
tci.pszText = sz;
|
|
for (i = 0; i < cTab; i++)
|
|
{
|
|
AthLoadString(*pTab, sz, ARRAYSIZE(sz));
|
|
TabCtrl_InsertItem(hwndT, i, &tci);
|
|
|
|
pTab++;
|
|
}
|
|
|
|
hwndList = GetDlgItem(hwnd, idcGroupList);
|
|
|
|
m_pColumns = new CColumns;
|
|
if (m_pColumns == NULL)
|
|
{
|
|
EnableWindow(m_hwndOwner, TRUE);
|
|
DestroyWindow(m_hwnd);
|
|
return (FALSE);
|
|
}
|
|
|
|
m_pColumns->Initialize(hwndList, set);
|
|
m_pColumns->ApplyColumns(COLUMN_LOAD_REGISTRY, 0, 0);
|
|
|
|
// Initialize the extended styles so we get full row select. Just because
|
|
// it looks better.
|
|
ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT);
|
|
|
|
Assert(m_pGrpList != NULL);
|
|
hr = m_pGrpList->Initialize((IGroupListAdvise *)this, m_pColumns, hwndList, m_type);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
// Add the list of servers to the list view if and only if there is more
|
|
// than one server.
|
|
hwndT = GetDlgItem(hwnd, idcServers);
|
|
|
|
FillServerList(hwndT, m_idSel);
|
|
|
|
// Build the control map array.
|
|
if (!MemAlloc((LPVOID*) &m_rgst, sizeof(SIZETABLE) * iCtlMax))
|
|
{
|
|
EnableWindow(m_hwndOwner, TRUE);
|
|
DestroyWindow(m_hwnd);
|
|
return (FALSE);
|
|
}
|
|
ZeroMemory(m_rgst, sizeof(SIZETABLE) * iCtlMax);
|
|
|
|
// Build a table of the controls on this dialog
|
|
for (i = 0; i < iCtlMax; i++)
|
|
{
|
|
m_rgst[i].hwndCtl = GetDlgItem(hwnd, g_rgCtlMap[i]);
|
|
if (m_rgst[i].hwndCtl)
|
|
{
|
|
m_rgst[i].id = g_rgCtlMap[i];
|
|
GetWindowRect(m_rgst[i].hwndCtl, &m_rgst[i].rc);
|
|
MapWindowPoints(GetDesktopWindow(), hwnd, (LPPOINT) &m_rgst[i].rc, 2);
|
|
}
|
|
}
|
|
|
|
GetWindowRect(hwnd, &rcDlg);
|
|
m_ptDragMin.x = rcDlg.right - rcDlg.left;
|
|
m_ptDragMin.y = rcDlg.bottom - rcDlg.top;
|
|
|
|
// Get the distance from the button to the edge of the dialog
|
|
GetClientRect(hwnd, &rcDlg);
|
|
m_cxHorzSep = rcDlg.right - m_rgst[iCtlCancel].rc.right;
|
|
|
|
// Get the distance from the "OK" to the "Cancel" button
|
|
m_cyVertSep = m_rgst[iCtlCancel].rc.left - m_rgst[iCtlOK].rc.right;
|
|
|
|
// Position the dialog
|
|
wp.length = sizeof(WINDOWPLACEMENT);
|
|
if (GetOption(OPT_NEWSDLGPOS, (LPVOID) &wp, sizeof(WINDOWPLACEMENT)))
|
|
{
|
|
SetWindowPlacement(hwnd, &wp);
|
|
|
|
// Bug #19258 - If SetWindowPlacement() doesn't actually resize the dialog,
|
|
// then a WM_SIZE doesn't happen automatically. We check for
|
|
// this now and force the message if this is the case.
|
|
GetWindowRect(hwnd, &rcDlg);
|
|
if (wp.rcNormalPosition.right == rcDlg.right &&
|
|
wp.rcNormalPosition.bottom == rcDlg.bottom)
|
|
{
|
|
GetClientRect(hwnd, &rcDlg);
|
|
SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rcDlg.right, rcDlg.bottom));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CenterDialog(hwnd);
|
|
SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rcDlg.right, rcDlg.bottom));
|
|
}
|
|
|
|
// If the view didn't invoke this dialog, than Goto has no meaning. Hide
|
|
// the button if this is the case.
|
|
if (!m_fEnableGoto)
|
|
ShowWindow(GetDlgItem(hwnd, idcGoto), SW_HIDE);
|
|
|
|
// Bug 23685: give it the right icon
|
|
m_hIcon= (HICON)LoadImage(g_hLocRes, m_type == FOLDER_NEWS ? MAKEINTRESOURCE(idiNewsGroup) : MAKEINTRESOURCE(idiFolder), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
|
|
SendMessage(hwnd, WM_SETICON, FALSE, (LPARAM)m_hIcon);
|
|
|
|
// Initialize the focus
|
|
SetFocus(m_hwndFindText);
|
|
|
|
// Tell ourself to update our group list after the dialog is done
|
|
// initializing.
|
|
PostMessage(hwnd, NVM_CHANGESERVERS, 0, 0L);
|
|
|
|
return (FALSE);
|
|
}
|
|
|
|
void CGroupListDlg::OnChangeServers(HWND hwnd)
|
|
{
|
|
// TODO: we need to fix the initialization so the filtering is only performed
|
|
// once (we should call IGroupList::Filter once and then IGroupList::SetServer once
|
|
// during creation of the dialog)
|
|
|
|
UpdateWindow(hwnd);
|
|
|
|
TabCtrl_SetCurSel(GetDlgItem(hwnd, idcTabs), m_iTabSelect);
|
|
OnSwitchTabs(hwnd, m_iTabSelect);
|
|
|
|
Assert(m_idCurrent != FOLDERID_INVALID);
|
|
ChangeServers(m_idCurrent, TRUE);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::OnCommand
|
|
//
|
|
// PURPOSE: Handles the command messages for the dialog.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the dialog box.
|
|
// id - Command id that needs processing.
|
|
// hwndCtl - Handle of the control that generated the command
|
|
// codeNotify - Specific notification the control generated
|
|
//
|
|
void CGroupListDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERID fldid;
|
|
int iSel;
|
|
FOLDERINFO info;
|
|
DWORD dw;
|
|
BOOL fDesc;
|
|
IImnAccount *pAcct;
|
|
|
|
switch (id)
|
|
{
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
if (codeNotify != BN_CLICKED)
|
|
break;
|
|
|
|
hr = S_OK;
|
|
if (id == IDOK)
|
|
{
|
|
hr = m_pGrpList->Commit(hwnd);
|
|
Assert(hr != E_PENDING);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
|
|
EnableWindow(m_hwndOwner, TRUE);
|
|
DestroyWindow(hwnd);
|
|
break;
|
|
|
|
case idcSubscribe:
|
|
case idcUnsubscribe:
|
|
if (codeNotify != BN_CLICKED)
|
|
break;
|
|
|
|
hr = m_pGrpList->Exec(NULL, id == idcSubscribe ? ID_SUBSCRIBE : ID_UNSUBSCRIBE, 0, NULL, NULL);
|
|
Assert(hr == S_OK);
|
|
break;
|
|
|
|
case idcGoto:
|
|
if (codeNotify != BN_CLICKED)
|
|
break;
|
|
|
|
hr = m_pGrpList->GetFocused(&fldid);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_idGoto = fldid;
|
|
SendMessage(m_hwnd, WM_COMMAND, IDOK, 0);
|
|
}
|
|
break;
|
|
|
|
case idcFindText:
|
|
// This is generated when someone types in the find text edit box.
|
|
// We set a timer and when that timer expires we assume the user is
|
|
// done typing and go ahead and perform the query.
|
|
if (EN_CHANGE == codeNotify)
|
|
{
|
|
KillTimer(hwnd, idtFindDelay);
|
|
SetTimer(hwnd, idtFindDelay, dtFindDelay, NULL);
|
|
}
|
|
break;
|
|
|
|
case idcUseDesc:
|
|
if (IsDlgButtonChecked(hwnd, idcUseDesc))
|
|
{
|
|
hr = m_pGrpList->HasDescriptions(&fDesc);
|
|
if (SUCCEEDED(hr) && !fDesc)
|
|
{
|
|
if (IDYES == AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(IDS_NO_DESCRIPTIONS_DOWNLOADED), NULL,
|
|
MB_YESNO | MB_ICONEXCLAMATION))
|
|
{
|
|
// turn on acct desc option
|
|
if (SUCCEEDED(g_pStore->GetFolderInfo(m_idCurrent, &info)))
|
|
{
|
|
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, info.pszAccountId, &pAcct)))
|
|
{
|
|
if (SUCCEEDED(pAcct->GetPropDw(AP_NNTP_USE_DESCRIPTIONS, &dw)) && dw == 0)
|
|
{
|
|
pAcct->SetPropDw(AP_NNTP_USE_DESCRIPTIONS, 1);
|
|
pAcct->SaveChanges();
|
|
}
|
|
|
|
pAcct->Release();
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
|
|
hr = m_pGrpList->Exec(NULL, ID_RESET_LIST, 0, NULL, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendMessage(hwndCtl, BM_SETCHECK, BST_UNCHECKED, 0);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
iSel = TabCtrl_GetCurSel(GetDlgItem(hwnd, idcTabs));
|
|
if (iSel != -1)
|
|
OnSwitchTabs(hwnd, iSel);
|
|
break;
|
|
|
|
case idcResetList:
|
|
hr = m_pGrpList->Exec(NULL, ID_RESET_LIST, 0, NULL, NULL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::OnNotify
|
|
//
|
|
// PURPOSE: Handles notifications from the common controls on the dialog.
|
|
//
|
|
LRESULT CGroupListDlg::OnNotify(HWND hwnd, int idFrom, LPNMHDR pnmhdr)
|
|
{
|
|
int iSel;
|
|
LRESULT lRes;
|
|
HRESULT hr;
|
|
NM_LISTVIEW *pnmlv;
|
|
|
|
hr = m_pGrpList->HandleNotify(hwnd, idFrom, pnmhdr, &lRes);
|
|
if (hr == S_OK)
|
|
return(lRes);
|
|
|
|
switch (pnmhdr->code)
|
|
{
|
|
case TCN_SELCHANGE:
|
|
if (idFrom == idcTabs)
|
|
{
|
|
// Find out which tab is currently active
|
|
iSel = TabCtrl_GetCurSel(pnmhdr->hwndFrom);
|
|
if (iSel != -1)
|
|
OnSwitchTabs(hwnd, iSel);
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
Assert(idFrom == idcServers);
|
|
|
|
pnmlv = (NM_LISTVIEW *)pnmhdr;
|
|
if (m_fServerListInited &&
|
|
!!(pnmlv->uChanged & LVIF_STATE) &&
|
|
0 == (pnmlv->uOldState & LVIS_FOCUSED) &&
|
|
!!(pnmlv->uNewState & LVIS_FOCUSED))
|
|
{
|
|
ChangeServers((FOLDERID)pnmlv->lParam, FALSE);
|
|
|
|
ItemUpdate();
|
|
}
|
|
break;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
void CGroupListDlg::OnClose(HWND hwnd)
|
|
{
|
|
int iReturn = IDNO;
|
|
|
|
if (m_pGrpList->Dirty() == S_OK)
|
|
iReturn = AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsDoYouWantToSave), 0,
|
|
MB_YESNOCANCEL | MB_ICONEXCLAMATION );
|
|
|
|
if (iReturn == IDYES)
|
|
OnCommand(hwnd, IDOK, 0, 0);
|
|
else if (iReturn == IDNO)
|
|
OnCommand(hwnd, IDCANCEL, 0, 0);
|
|
}
|
|
|
|
void CGroupListDlg::OnDestroy(HWND hwnd)
|
|
{
|
|
// Save the dialog position
|
|
WINDOWPLACEMENT wp;
|
|
|
|
wp.length = sizeof(WINDOWPLACEMENT);
|
|
if (GetWindowPlacement(hwnd, &wp))
|
|
SetOption(OPT_NEWSDLGPOS, (LPVOID) &wp, sizeof(WINDOWPLACEMENT), NULL, 0);
|
|
|
|
Assert(m_pColumns != NULL);
|
|
m_pColumns->Save(NULL, NULL);
|
|
|
|
PostQuitMessage(0);
|
|
}
|
|
|
|
void CGroupListDlg::OnTimer(HWND hwnd, UINT id)
|
|
{
|
|
DWORD iTab;
|
|
|
|
KillTimer(hwnd, id);
|
|
|
|
iTab = TabCtrl_GetCurSel(GetDlgItem(m_hwnd, idcTabs));
|
|
|
|
OnSwitchTabs(hwnd, iTab);
|
|
}
|
|
|
|
BOOL CGroupListDlg::ChangeServers(FOLDERID id, BOOL fForce)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = m_pGrpList->SetServer(id);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
m_idCurrent = id;
|
|
|
|
ItemUpdate();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::FillServerList
|
|
//
|
|
// PURPOSE: If the user has multiple servers configured, then a variant of
|
|
// this dialog appears that has a list of servers available. This
|
|
// function populates that list.
|
|
//
|
|
// PARAMETERS:
|
|
// hwndList - Handle of the list view that we add server names to.
|
|
// pszSelectServer - Name of the server to select in the list view.
|
|
//
|
|
// RETURN VALUE:
|
|
// Returns TRUE if successful, or FALSE otherwise.
|
|
//
|
|
BOOL CGroupListDlg::FillServerList(HWND hwndList, FOLDERID idSel)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERID id;
|
|
char szServer[CCHMAX_ACCOUNT_NAME];
|
|
LV_ITEM lvi;
|
|
LV_COLUMN lvc;
|
|
RECT rc;
|
|
DWORD dw;
|
|
int iItem, iSelect;
|
|
IImnAccount *pAcct;
|
|
IImnEnumAccounts *pEnum;
|
|
|
|
Assert(!m_fServerListInited);
|
|
Assert(hwndList != NULL);
|
|
Assert(IsWindow(hwndList));
|
|
|
|
SetIntlFont(hwndList);
|
|
|
|
// Create the image list and add it to the listview.
|
|
Assert(m_himlServer == NULL);
|
|
m_himlServer = ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbFoldersLarge), 32, 0, RGB(255, 0, 255));
|
|
if (m_himlServer == NULL)
|
|
return(FALSE);
|
|
ListView_SetImageList(hwndList, m_himlServer, LVSIL_NORMAL);
|
|
|
|
// Add a column to the listview.
|
|
GetClientRect(hwndList, &rc);
|
|
lvc.mask = LVCF_SUBITEM | LVCF_WIDTH;
|
|
lvc.iSubItem = 0;
|
|
lvc.cx = rc.right;
|
|
dw = ListView_InsertColumn(hwndList, 0, &lvc);
|
|
|
|
iSelect = -1;
|
|
iItem = 0;
|
|
|
|
if (SUCCEEDED(g_pAcctMan->Enumerate(m_type == FOLDER_NEWS ? SRV_NNTP : SRV_IMAP, &pEnum)))
|
|
{
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
|
|
lvi.iImage = m_type == FOLDER_NEWS ? iNewsServer : iMailServer;
|
|
|
|
while (E_EnumFinished != pEnum->GetNext(&pAcct))
|
|
{
|
|
if (SUCCEEDED(pAcct->GetPropSz(AP_ACCOUNT_ID, szServer, ARRAYSIZE(szServer))) &&
|
|
SUCCEEDED(g_pStore->FindServerId(szServer, &id)) &&
|
|
SUCCEEDED(pAcct->GetPropSz(AP_ACCOUNT_NAME, szServer, ARRAYSIZE(szServer))))
|
|
{
|
|
if (idSel == FOLDERID_INVALID ||
|
|
id == idSel)
|
|
{
|
|
Assert(iSelect == -1);
|
|
idSel = id;
|
|
iSelect = iItem;
|
|
|
|
lvi.state = LVIS_SELECTED | LVIS_FOCUSED;
|
|
lvi.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
|
|
}
|
|
else
|
|
{
|
|
lvi.state = 0;
|
|
lvi.stateMask = 0;
|
|
}
|
|
|
|
lvi.pszText = szServer;
|
|
lvi.iItem = iItem;
|
|
lvi.lParam = (LPARAM)id;
|
|
|
|
dw = ListView_InsertItem(hwndList, &lvi);
|
|
iItem++;
|
|
}
|
|
|
|
pAcct->Release();
|
|
}
|
|
|
|
pEnum->Release();
|
|
}
|
|
|
|
Assert(iItem > 0);
|
|
Assert(iSelect != -1);
|
|
Assert(idSel != FOLDERID_INVALID);
|
|
|
|
ListView_EnsureVisible(hwndList, iSelect, FALSE);
|
|
|
|
m_idCurrent = idSel;
|
|
m_fServerListInited = TRUE;
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
HRESULT CGroupListDlg::ItemUpdate(void)
|
|
{
|
|
FOLDERID id;
|
|
HRESULT hr;
|
|
HWND hwndSub, hwndUnsub, hwndFocus;
|
|
OLECMD rgCmds[2] = { { ID_SUBSCRIBE, 0 }, { ID_UNSUBSCRIBE, 0 } };
|
|
|
|
hr = m_pGrpList->GetFocused(&id);
|
|
EnableWindow(GetDlgItem(m_hwnd, idcGoto), hr == S_OK);
|
|
|
|
hr = m_pGrpList->QueryStatus(NULL, ARRAYSIZE(rgCmds), rgCmds, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hwndFocus = GetFocus();
|
|
|
|
hwndSub = GetDlgItem(m_hwnd, idcSubscribe);
|
|
hwndUnsub = GetDlgItem(m_hwnd, idcUnsubscribe);
|
|
|
|
EnableWindow(hwndSub, !!(rgCmds[0].cmdf & OLECMDF_ENABLED));
|
|
EnableWindow(hwndUnsub, !!(rgCmds[1].cmdf & OLECMDF_ENABLED));
|
|
|
|
if (!IsWindowEnabled(hwndFocus))
|
|
SetFocus(!!(rgCmds[0].cmdf & OLECMDF_ENABLED) ? hwndSub : hwndUnsub);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CGroupListDlg::ItemActivate(FOLDERID id)
|
|
{
|
|
m_pGrpList->Exec(NULL, ID_TOGGLE_SUBSCRIBE, 0, NULL, NULL);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: CGroupListDlg::OnSwitchTabs()
|
|
//
|
|
// PURPOSE: This function takes care of resetting the list of groups
|
|
// appropriately when the user selects a different tab.
|
|
//
|
|
// PARAMETERS:
|
|
// hwnd - Handle of the dialog window.
|
|
// iTab - Index of the tab to switch to.
|
|
//
|
|
// RETURN VALUE:
|
|
// Returns TRUE if successful, or FALSE otherwise.
|
|
//
|
|
BOOL CGroupListDlg::OnSwitchTabs(HWND hwnd, UINT iTab)
|
|
{
|
|
UINT cch;
|
|
LPSTR pszText;
|
|
HRESULT hr;
|
|
BOOL fUseDesc;
|
|
|
|
pszText = NULL;
|
|
|
|
cch = GetWindowTextLength(m_hwndFindText);
|
|
if (cch > 0)
|
|
{
|
|
cch++;
|
|
if (!MemAlloc((void **)&pszText, cch + 1))
|
|
return(FALSE);
|
|
|
|
GetWindowText(m_hwndFindText, pszText, cch);
|
|
}
|
|
|
|
fUseDesc = (m_type == FOLDER_NEWS && IsDlgButtonChecked(m_hwnd, idcUseDesc));
|
|
|
|
hr = m_pGrpList->Filter(pszText, iTab, fUseDesc);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
if (pszText != NULL)
|
|
MemFree(pszText);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
#define WIDTH(_rect) (_rect.right - _rect.left)
|
|
#define HEIGHT(_rect) (_rect.bottom - _rect.top)
|
|
|
|
void CGroupListDlg::OnSize(HWND hwnd, UINT state, int cx, int cy)
|
|
{
|
|
RECT rc;
|
|
|
|
rc.left = m_sizeDlg.cx - GetSystemMetrics(SM_CXSMICON);
|
|
rc.top = m_sizeDlg.cy - GetSystemMetrics(SM_CYSMICON);
|
|
rc.right = m_sizeDlg.cx;
|
|
rc.bottom = m_sizeDlg.cy;
|
|
InvalidateRect(hwnd, &rc, FALSE);
|
|
|
|
m_sizeDlg.cx = cx;
|
|
m_sizeDlg.cy = cy;
|
|
|
|
// First move the outside buttons so they are against the edge. These
|
|
// buttons only move horizontally.
|
|
m_rgst[iCtlSubscribe].rc.left = cx - m_cxHorzSep - WIDTH(m_rgst[iCtlSubscribe].rc);
|
|
m_rgst[iCtlSubscribe].rc.right = cx - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlSubscribe].hwndCtl, 0, m_rgst[iCtlSubscribe].rc.left,
|
|
m_rgst[iCtlSubscribe].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
m_rgst[iCtlUnsubscribe].rc.left = cx - m_cxHorzSep - WIDTH(m_rgst[iCtlUnsubscribe].rc);
|
|
m_rgst[iCtlUnsubscribe].rc.right = cx - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlUnsubscribe].hwndCtl, 0, m_rgst[iCtlUnsubscribe].rc.left,
|
|
m_rgst[iCtlUnsubscribe].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
m_rgst[iCtlResetList].rc.left = cx - m_cxHorzSep - WIDTH(m_rgst[iCtlResetList].rc);
|
|
m_rgst[iCtlResetList].rc.right = cx - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlResetList].hwndCtl, 0, m_rgst[iCtlResetList].rc.left,
|
|
m_rgst[iCtlResetList].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
|
|
// The Goto, OK, and Cancel buttons move both horizontally and vertically.
|
|
m_rgst[iCtlCancel].rc.left = cx - m_cxHorzSep - WIDTH(m_rgst[iCtlCancel].rc);
|
|
m_rgst[iCtlCancel].rc.right = cx - m_cxHorzSep;
|
|
m_rgst[iCtlCancel].rc.top = cy - m_cxHorzSep - HEIGHT(m_rgst[iCtlCancel].rc);
|
|
m_rgst[iCtlCancel].rc.bottom = cy - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlCancel].hwndCtl, 0, m_rgst[iCtlCancel].rc.left,
|
|
m_rgst[iCtlCancel].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
m_rgst[iCtlOK].rc.left = m_rgst[iCtlCancel].rc.left - m_cxHorzSep - WIDTH(m_rgst[iCtlCancel].rc);
|
|
m_rgst[iCtlOK].rc.right = m_rgst[iCtlCancel].rc.left - m_cxHorzSep;
|
|
m_rgst[iCtlOK].rc.top = cy - m_cxHorzSep - HEIGHT(m_rgst[iCtlOK].rc);
|
|
m_rgst[iCtlOK].rc.bottom = cy - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlOK].hwndCtl, 0, m_rgst[iCtlOK].rc.left,
|
|
m_rgst[iCtlOK].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
m_rgst[iCtlGoto].rc.left = m_rgst[iCtlOK].rc.left - m_cxHorzSep - WIDTH(m_rgst[iCtlGoto].rc);
|
|
m_rgst[iCtlGoto].rc.right = m_rgst[iCtlOK].rc.left - m_cxHorzSep;
|
|
m_rgst[iCtlGoto].rc.top = cy - m_cxHorzSep - HEIGHT(m_rgst[iCtlGoto].rc);
|
|
m_rgst[iCtlGoto].rc.bottom = cy - m_cxHorzSep;
|
|
SetWindowPos(m_rgst[iCtlGoto].hwndCtl, 0, m_rgst[iCtlGoto].rc.left,
|
|
m_rgst[iCtlGoto].rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
// Update the horizontal static line
|
|
m_rgst[iCtlStaticHorzLine].rc.left = m_cxHorzSep;
|
|
m_rgst[iCtlStaticHorzLine].rc.right = cx - m_cxHorzSep;
|
|
m_rgst[iCtlStaticHorzLine].rc.top = m_rgst[iCtlCancel].rc.top - m_cyVertSep - HEIGHT(m_rgst[iCtlStaticHorzLine].rc);
|
|
m_rgst[iCtlStaticHorzLine].rc.bottom = m_rgst[iCtlCancel].rc.top - m_cyVertSep;
|
|
SetWindowPos(m_rgst[iCtlStaticHorzLine].hwndCtl, 0, m_rgst[iCtlStaticHorzLine].rc.left,
|
|
m_rgst[iCtlStaticHorzLine].rc.top, WIDTH(m_rgst[iCtlStaticHorzLine].rc),
|
|
HEIGHT(m_rgst[iCtlStaticHorzLine].rc), SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
// If we have a server well, then update that and the vertical static line
|
|
if (m_rgst[iCtlServers].hwndCtl)
|
|
{
|
|
m_rgst[iCtlServers].rc.bottom = m_rgst[iCtlStaticHorzLine].rc.top - m_cyVertSep;
|
|
SetWindowPos(m_rgst[iCtlServers].hwndCtl, 0, 0, 0, WIDTH(m_rgst[iCtlServers].rc),
|
|
HEIGHT(m_rgst[iCtlServers].rc), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
// Finally update the tab control and listview
|
|
m_rgst[iCtlTabs].rc.right = m_rgst[iCtlSubscribe].rc.left - m_cxHorzSep;
|
|
m_rgst[iCtlTabs].rc.bottom = m_rgst[iCtlStaticHorzLine].rc.top - m_cyVertSep;
|
|
SetWindowPos(m_rgst[iCtlTabs].hwndCtl, 0, 0, 0, WIDTH(m_rgst[iCtlTabs].rc),
|
|
HEIGHT(m_rgst[iCtlTabs].rc), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
rc = m_rgst[iCtlTabs].rc;
|
|
TabCtrl_AdjustRect(m_rgst[iCtlTabs].hwndCtl, FALSE, &rc);
|
|
m_rgst[iCtlGroupList].rc.right = rc.right - (m_rgst[iCtlGroupList].rc.left - rc.left);
|
|
m_rgst[iCtlGroupList].rc.bottom = rc.bottom - m_cyVertSep; //(m_rgst[iCtlGroupList].rc.top - rc.top);
|
|
SetWindowPos(m_rgst[iCtlGroupList].hwndCtl, 0, 0, 0, WIDTH(m_rgst[iCtlGroupList].rc),
|
|
HEIGHT(m_rgst[iCtlGroupList].rc), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
|
|
rc.top = m_rgst[iCtlGroupList].rc.top;
|
|
rc.left = m_rgst[iCtlServers].rc.left;
|
|
rc.bottom = cy;
|
|
rc.right = cx;
|
|
InvalidateRect(hwnd, &rc, TRUE);
|
|
}
|
|
|
|
void CGroupListDlg::OnPaint(HWND hwnd)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rc;
|
|
|
|
GetClientRect(hwnd, &rc);
|
|
rc.left = rc.right - GetSystemMetrics(SM_CXSMICON);
|
|
rc.top = rc.bottom - GetSystemMetrics(SM_CYSMICON);
|
|
BeginPaint(hwnd, &ps);
|
|
|
|
if (!IsZoomed(hwnd))
|
|
DrawFrameControl(ps.hdc, &rc, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
|
|
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
|
|
void CGroupListDlg::OnGetMinMaxInfo(HWND hwnd, LPMINMAXINFO lpmmi)
|
|
{
|
|
DefWindowProc(hwnd, WM_GETMINMAXINFO, 0, (LPARAM) lpmmi);
|
|
lpmmi->ptMinTrackSize = m_ptDragMin;
|
|
}
|