Leaked source code of windows server 2003
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.
 
 
 
 
 
 

864 lines
24 KiB

/*++
Copyright (C) 1997-1999 Microsoft Corporation
Module Name:
ctvctl.cpp
Abstract:
This module implements TreeView OCX for Device Manager snapin
Author:
William Hsieh (williamh) created
Revision History:
--*/
// CTVCtl.cpp : Implementation of the CTVCtrl OLE control class.
#include "stdafx.h"
#include <afxcmn.h>
#include "ctv.h"
#include "CTVCtl.h"
#include "resource.h"
#define GET_X_LPARAM(lParam) (int)(short)LOWORD(lParam)
#define GET_Y_LPARAM(lParam) (int)(short)HIWORD(lParam)
IMPLEMENT_DYNCREATE(CTVCtrl, COleControl)
BEGIN_INTERFACE_MAP(CTVCtrl, COleControl)
INTERFACE_PART(CTVCtrl, IID_IDMTVOCX, DMTVOCX)
END_INTERFACE_MAP()
const IID IID_IDMTVOCX = {0x142525f2,0x59d8,0x11d0,{0xab,0xf0,0x00,0x20,0xaf,0x6b,0x0b,0x7a}};
const IID IID_ISnapinCallback = {0x8e0ba98a,0xd161,0x11d0,{0x83,0x53,0x00,0xa0,0xc9,0x06,0x40,0xbf}};
ULONG EXPORT CTVCtrl::XDMTVOCX::AddRef()
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->ExternalAddRef();
}
ULONG EXPORT CTVCtrl::XDMTVOCX::Release()
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->ExternalRelease();
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::QueryInterface(
REFIID iid,
void ** ppvObj
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->ExternalQueryInterface(&iid, ppvObj);
}
HTREEITEM EXPORT CTVCtrl::XDMTVOCX::InsertItem(
LPTV_INSERTSTRUCT pis
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->InsertItem(pis);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::DeleteItem(
HTREEITEM hitem
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->DeleteItem(hitem);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::DeleteAllItems(
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->DeleteAllItems();
}
HIMAGELIST EXPORT CTVCtrl::XDMTVOCX::SetImageList(
INT iImage,
HIMAGELIST himl
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SetImageList(iImage, himl);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::SetItem(
TV_ITEM* pitem
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SetItem(pitem);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::Expand(
UINT Flags,
HTREEITEM hitem
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->Expand(Flags, hitem);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::SelectItem(
UINT Flags,
HTREEITEM hitem
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SelectItem(Flags, hitem);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::SetStyle(
DWORD dwStyle
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SetStyle(dwStyle);
}
HWND EXPORT CTVCtrl::XDMTVOCX::GetWindowHandle(
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetWindowHandle();
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::GetItem(
TV_ITEM* pti
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetItem(pti);
}
HTREEITEM EXPORT CTVCtrl::XDMTVOCX::GetNextItem(
UINT Flags,
HTREEITEM htiRef
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetNextItem(Flags, htiRef);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::SelectItem(
HTREEITEM hti
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SelectItem(hti);
}
UINT EXPORT CTVCtrl::XDMTVOCX::GetCount(
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetCount();
}
HTREEITEM EXPORT CTVCtrl::XDMTVOCX::GetSelectedItem(
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetSelectedItem();
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::Connect(
IComponent* pIComponent,
MMC_COOKIE cookie
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->Connect(pIComponent, cookie);
}
HRESULT EXPORT CTVCtrl::XDMTVOCX::SetActiveConnection(
MMC_COOKIE cookie
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SetActiveConnection(cookie);
}
MMC_COOKIE EXPORT CTVCtrl::XDMTVOCX::GetActiveConnection()
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->GetActiveConnection();
}
long EXPORT CTVCtrl::XDMTVOCX::SetRedraw(BOOL Redraw)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->SetRedraw(Redraw);
}
BOOL EXPORT CTVCtrl::XDMTVOCX::EnsureVisible(
HTREEITEM hitem
)
{
METHOD_PROLOGUE(CTVCtrl, DMTVOCX)
return pThis->EnsureVisible(hitem);
}
/////////////////////////////////////////////////////////////////////////////
// Message map
BEGIN_MESSAGE_MAP(CTVCtrl, COleControl)
//{{AFX_MSG_MAP(CTVCtrl)
ON_WM_DESTROY()
ON_WM_CONTEXTMENU()
//}}AFX_MSG_MAP
ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
ON_MESSAGE(OCM_NOTIFY, OnOcmNotify)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CTVCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CTVCtrl)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
/////////////////////////////////////////////////////////////////////////////
// Event map
BEGIN_EVENT_MAP(CTVCtrl, COleControl)
//{{AFX_EVENT_MAP(CTVCtrl)
// NOTE - ClassWizard will add and remove event map entries
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_EVENT_MAP
END_EVENT_MAP()
/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CTVCtrl, "CTREEVIEW.CTreeViewCtrl.1",
0xcd6c7868, 0x5864, 0x11d0, 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a)
/////////////////////////////////////////////////////////////////////////////
// Type library ID and version
IMPLEMENT_OLETYPELIB(CTVCtrl, _tlid, _wVerMajor, _wVerMinor)
/////////////////////////////////////////////////////////////////////////////
// Interface IDs
const IID BASED_CODE IID_DTV =
{ 0xcd6c7866, 0x5864, 0x11d0, { 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a}};
const IID BASED_CODE IID_DTVEvents =
{ 0xcd6c7867, 0x5864, 0x11d0, { 0xab, 0xf0, 0, 0x20, 0xaf, 0x6b, 0xb, 0x7a}};
/////////////////////////////////////////////////////////////////////////////
// Control type information
static const DWORD BASED_CODE _dwTVOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CTVCtrl, IDS_TV, _dwTVOleMisc)
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::CTVCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CTVCtrl
BOOL CTVCtrl::CTVCtrlFactory::UpdateRegistry(BOOL bRegister)
{
if (bRegister) {
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_TV,
IDB_TV,
afxRegApartmentThreading,
_dwTVOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
} else {
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::CTVCtrl - Constructor
CTVCtrl::CTVCtrl()
{
InitializeIIDs(&IID_DTV, &IID_DTVEvents);
m_nConnections = 0;
m_pIComponent = NULL;
m_pISnapinCallback = NULL;
m_Destroyed = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::~CTVCtrl - Destructor
CTVCtrl::~CTVCtrl()
{
if (m_pISnapinCallback) {
m_pISnapinCallback->Release();
}
if (m_pIComponent) {
m_pIComponent->Release();
}
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::OnDraw - Drawing function
void CTVCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
DoSuperclassPaint(pdc, rcBounds);
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::DoPropExchange - Persistence support
void CTVCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::OnResetState - Reset control to default state
void CTVCtrl::OnResetState()
{
COleControl::OnResetState(); // Resets defaults found in DoPropExchange
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::PreCreateWindow - Modify parameters for CreateWindowEx
BOOL CTVCtrl::PreCreateWindow(CREATESTRUCT& cs)
{
cs.lpszClass = _T("SysTreeView32");
//
// Turn off WS_EX_NOPARENTNOTIFY style bit so that our parents
// receive mouse clicks on our window. I do not know why MFC
// fundation class turns this on for an OCX.
//
cs.dwExStyle &= ~(WS_EX_NOPARENTNOTIFY);
return COleControl::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::IsSubclassedControl - This is a subclassed control
BOOL CTVCtrl::IsSubclassedControl()
{
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl::OnOcmCommand - Handle command messages
LRESULT CTVCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN32
WORD wNotifyCode = HIWORD(wParam);
#else
WORD wNotifyCode = HIWORD(lParam);
#endif
return 0;
}
/////////////////////////////////////////////////////////////////////////////
// CTVCtrl message handlers
///////////////////////////////////////////////////////////////////////
///
/// Tree View functions
///
HRESULT
CTVCtrl::Connect(
IComponent* pIComponent,
MMC_COOKIE cookie
)
{
HRESULT hr = S_OK;
if (0 == m_nConnections) {
ASSERT(NULL == m_pIComponent);
m_pIComponent = pIComponent;
m_pIComponent->AddRef();
hr = m_pIComponent->QueryInterface(IID_ISnapinCallback,
reinterpret_cast<void**>(&m_pISnapinCallback)
);
}
// A single snapin may have multiple nodes that uses us as result pane
// display media, therefore, we may be connected mutlple times.
// However, we get created only when MMC creates a new snapin instance.
// This means, every connection call must provide the same
// pIComponent and pConsole.
//
ASSERT(m_pIComponent == pIComponent);
if (SUCCEEDED(hr)) {
m_nConnections++;
hr = SetActiveConnection(cookie);
}
return hr;
}
HRESULT
CTVCtrl::SetActiveConnection(
MMC_COOKIE cookie
)
{
m_ActiveCookie = cookie;
return S_OK;
}
MMC_COOKIE
CTVCtrl::GetActiveConnection()
{
return m_ActiveCookie;
}
HTREEITEM CTVCtrl::InsertItem(
LPTV_INSERTSTRUCT pis
)
{
return (HTREEITEM)SendMessage(TVM_INSERTITEM, 0, (LPARAM)pis);
}
HRESULT CTVCtrl::DeleteItem(
HTREEITEM hitem
)
{
if (SendMessage(TVM_DELETEITEM, 0, (LPARAM)hitem)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HRESULT CTVCtrl::DeleteAllItems()
{
return DeleteItem((HTREEITEM)TVI_ROOT);
}
HIMAGELIST CTVCtrl::SetImageList(
INT iImage,
HIMAGELIST hmil
)
{
return (HIMAGELIST)SendMessage(TVM_SETIMAGELIST, (WPARAM)iImage, (LPARAM)hmil);
}
HRESULT CTVCtrl::SetItem(
TV_ITEM* pitem
)
{
if (SendMessage(TVM_SETITEM, 0, (LPARAM)pitem)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HRESULT CTVCtrl::Expand(
UINT Flags,
HTREEITEM hitem
)
{
if (SendMessage(TVM_EXPAND, (WPARAM) Flags, (LPARAM)hitem)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HRESULT CTVCtrl::SelectItem(
UINT Flags,
HTREEITEM hitem
)
{
if (SendMessage(TVM_SELECTITEM, (WPARAM)Flags, (LPARAM)hitem)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HRESULT CTVCtrl::SetStyle(
DWORD dwStyle
)
{
if (ModifyStyle(0, dwStyle)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HWND CTVCtrl::GetWindowHandle(
)
{
return m_hWnd;
}
HRESULT CTVCtrl::GetItem(
TV_ITEM* pti
)
{
if (SendMessage(TVM_GETITEM, 0, (LPARAM)pti)) {
return S_OK;
} else {
return E_UNEXPECTED;
}
}
HTREEITEM CTVCtrl::GetNextItem(
UINT Flags,
HTREEITEM htiRef
)
{
return (HTREEITEM) SendMessage(TVM_GETNEXTITEM, (WPARAM)Flags, (LPARAM)htiRef);
}
HRESULT CTVCtrl::SelectItem(
HTREEITEM hti
)
{
if (SendMessage(TVM_SELECTITEM, 0, (LPARAM) hti)) {
return S_OK;
} else {
return S_FALSE;
}
}
UINT CTVCtrl::GetCount(
)
{
return (UINT)SendMessage(TVM_GETCOUNT, 0, 0);
}
HTREEITEM CTVCtrl::HitTest(
LONG x,
LONG y,
UINT* pFlags
)
{
POINT pt;
pt.x = x;
pt.y = y;
ScreenToClient(&pt);
TV_HITTESTINFO tvhti;
tvhti.pt = pt;
HTREEITEM hti = (HTREEITEM)SendMessage(TVM_HITTEST, 0, (LPARAM)&tvhti);
if (hti && pFlags) {
*pFlags = tvhti.flags;
}
return hti;
}
HTREEITEM CTVCtrl::GetSelectedItem(
)
{
return (HTREEITEM)SendMessage(TVM_GETNEXTITEM, TVGN_CARET, 0);
}
HRESULT CTVCtrl::SetRedraw(
BOOL Redraw
)
{
if (Redraw) {
Invalidate();
}
return S_OK;
}
BOOL CTVCtrl::EnsureVisible(
HTREEITEM hitem
)
{
return (BOOL)SendMessage(TVM_ENSUREVISIBLE, 0, (LPARAM)hitem);
}
LRESULT
CTVCtrl::OnOcmNotify(
WPARAM wParam,
LPARAM lParam
)
{
LPARAM param, arg;
MMC_COOKIE cookie = 0;
HRESULT hr = S_FALSE;
TV_NOTIFY_CODE NotifyCode;
TV_ITEM TI;
NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
switch (((NMHDR*)lParam)->code) {
case NM_RCLICK:
case NM_RDBLCLK:
case NM_CLICK:
case NM_DBLCLK:
NotifyCode = DoMouseNotification(((NMHDR*)lParam)->code, &cookie,
&arg, &param);
break;
case TVN_KEYDOWN:
TI.hItem = GetSelectedItem();
TI.mask = TVIF_PARAM;
if (TI.hItem && SUCCEEDED(GetItem(&TI))) {
cookie = (MMC_COOKIE)TI.lParam;
NotifyCode = TV_NOTIFY_CODE_KEYDOWN;
param = ((TV_KEYDOWN*)lParam)->wVKey;
arg = (LPARAM)TI.hItem;
}
break;
case NM_SETFOCUS:
TI.hItem = GetSelectedItem();
TI.mask = TVIF_PARAM;
if (TI.hItem && SUCCEEDED(GetItem(&TI))) {
cookie = (MMC_COOKIE)TI.lParam;
NotifyCode = TV_NOTIFY_CODE_FOCUSCHANGED;
param = 1;
arg = (LPARAM)TI.hItem;
}
break;
case TVN_SELCHANGEDA:
case TVN_SELCHANGEDW:
NotifyCode = TV_NOTIFY_CODE_SELCHANGED;
arg = (LPARAM)((NM_TREEVIEW*)lParam)->itemNew.hItem;
cookie = (MMC_COOKIE)((NM_TREEVIEW*)lParam)->itemNew.lParam;
param = (LPARAM)((NM_TREEVIEW*)lParam)->action;
break;
case TVN_ITEMEXPANDEDA:
case TVN_ITEMEXPANDEDW:
NotifyCode = TV_NOTIFY_CODE_EXPANDED;
arg = (LPARAM)((NM_TREEVIEW*)lParam)->itemNew.hItem;
cookie = (MMC_COOKIE)((NM_TREEVIEW*)lParam)->itemNew.lParam;
param = (LPARAM)((NM_TREEVIEW*)lParam)->action;
break;
default:
NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
break;
}
if (TV_NOTIFY_CODE_UNKNOWN != NotifyCode && m_pISnapinCallback) {
hr = m_pISnapinCallback->tvNotify(*this, cookie, NotifyCode, arg, param);
if (S_FALSE == hr) {
//
// Translate RCLICK to context menu
//
if (TV_NOTIFY_CODE_RCLICK == NotifyCode) {
SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, GetMessagePos());
hr = S_OK;
}
//
// Translate Shift-F10 or VK_APPS to context menu
//
else if (TV_NOTIFY_CODE_KEYDOWN == NotifyCode &&
(VK_F10 == param && GetKeyState(VK_SHIFT) < 0) ||
(VK_APPS == param)) {
RECT rect;
*((HTREEITEM*)&rect) = (HTREEITEM)arg;
if (SendMessage(TVM_GETITEMRECT, TRUE, (LPARAM)&rect)) {
POINT pt;
pt.x = (rect.left + rect.right) / 2;
pt.y = (rect.top + rect.bottom) / 2;
ClientToScreen(&pt);
SendMessage(WM_CONTEXTMENU, (WPARAM)m_hWnd, MAKELPARAM(pt.x, pt.y));
hr = S_OK;
}
}
}
}
//
// On a TVN_KEYDOWN we should always return 0, otherwise the treeview
// control gets confused.
//
if (((NMHDR*)lParam)->code == TVN_KEYDOWN) {
hr = S_FALSE;
}
ASSERT(S_OK == hr || S_FALSE == hr);
if (S_OK == hr) {
return 1;
}
return 0;
}
TV_NOTIFY_CODE
CTVCtrl::DoMouseNotification(
UINT Code,
MMC_COOKIE* pcookie,
LPARAM* parg,
LPARAM* pparam
)
{
DWORD MsgPos;
POINT point;
ASSERT(pparam && parg && pcookie);
*pparam = 0;
*parg = 0;
MsgPos = GetMessagePos();
point.x = GET_X_LPARAM(MsgPos);
point.y = GET_Y_LPARAM(MsgPos);
UINT htFlags;
HTREEITEM hti = HitTest(point.x, point.y, &htFlags);
TV_NOTIFY_CODE NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
if (hti && (htFlags & TVHT_ONITEM)) {
TV_ITEM TI;
TI.hItem = hti;
TI.mask = TVIF_PARAM;
if (SUCCEEDED(GetItem(&TI))) {
switch (Code) {
case NM_RCLICK:
NotifyCode = TV_NOTIFY_CODE_RCLICK;
break;
case NM_RDBLCLK:
NotifyCode = TV_NOTIFY_CODE_RDBLCLK;
break;
case NM_CLICK:
NotifyCode = TV_NOTIFY_CODE_CLICK;
break;
case NM_DBLCLK:
NotifyCode = TV_NOTIFY_CODE_DBLCLK;
break;
default:
NotifyCode = TV_NOTIFY_CODE_UNKNOWN;
break;
}
if (TV_NOTIFY_CODE_UNKNOWN != NotifyCode) {
*parg = (LPARAM)hti;
*pparam = htFlags;
*pcookie = (MMC_COOKIE)TI.lParam;
}
}
}
return NotifyCode;
}
// OnDestroy may be called on two occasions:
// (1). We are the current active result pane window and MMC
// is destroying our parent window(MDI client). Note that
// if we are not the active result pane window, this function
// will not get called until (2).
// (2). our reference count has reached zero.
//
// When (1) happens, the snapin may be still holding reference to us
// thus, even though our window has been destroyed (2) still happens
// (unless PostNcDestory is done which MFC reset m_hWnd)and we end up
// destoying the window twice.
// So, we keep an eye on OnDestroy and do nothing after it has been called.
// We can not wait for PostNcDestroy because we have no idea when it would
// come.
//
void CTVCtrl::OnDestroy()
{
if (!m_Destroyed) {
COleControl::OnDestroy();
m_Destroyed = TRUE;
}
}
void CTVCtrl::OnContextMenu(CWnd* pWnd, CPoint point)
{
POINT pt = point;
UINT htFlags;
HTREEITEM hti = HitTest(pt.x, pt.y, &htFlags);
if (hti) {
TV_ITEM TI;
TI.hItem = hti;
TI.mask = TVIF_PARAM;
if (SUCCEEDED(GetItem(&TI))) {
m_pISnapinCallback->tvNotify(*this, (MMC_COOKIE)TI.lParam,
TV_NOTIFY_CODE_CONTEXTMENU,
(LPARAM)hti, (LPARAM)&point );
}
}
}
// The upmost frame window may have its own accelerator table and may take
// away certain key combinations we really need.
BOOL CTVCtrl::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYDOWN == pMsg->message &&
(VK_DELETE == pMsg->wParam ||
VK_RETURN == pMsg->wParam)) {
OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
return TRUE;
}
else if (WM_SYSKEYDOWN == pMsg->message && VK_F10 == pMsg->wParam &&
GetKeyState(VK_SHIFT) < 0) {
// Shift-F10 will be translated to WM_CONTEXTMENU
OnSysKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
return TRUE;
}
return COleControl::PreTranslateMessage(pMsg);
}