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.
3777 lines
112 KiB
3777 lines
112 KiB
//
|
|
// contwnd.cpp
|
|
//
|
|
// Implementation of CContainerWnd
|
|
// TS Client Shell Top-Level ActiveX container window
|
|
//
|
|
// Copyright(C) Microsoft Corporation 2000
|
|
// Author: Nadim Abdo (nadima)
|
|
//
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define TRC_GROUP TRC_GROUP_UI
|
|
#define TRC_FILE "contwnd"
|
|
#include <atrcapi.h>
|
|
|
|
|
|
#include "contwnd.h"
|
|
|
|
#include "maindlg.h"
|
|
#include "discodlg.h"
|
|
#include "aboutdlg.h"
|
|
#include "shutdowndlg.h"
|
|
#ifdef DC_DEBUG
|
|
#include "mallocdbgdlg.h"
|
|
#include "thruputdlg.h"
|
|
#endif //DC_DEBUG
|
|
#include "cachewrndlg.h"
|
|
#include "tscsetting.h"
|
|
|
|
#include "commctrl.h"
|
|
|
|
#include "security.h"
|
|
//
|
|
// COMPILE_MULTIMON_STUBS must be defined in only one
|
|
// file. Any other file that wants to use multimon
|
|
// enabled functions should re-include multimon.h
|
|
//
|
|
|
|
#ifdef OS_WINNT
|
|
#define COMPILE_MULTIMON_STUBS
|
|
#include <multimon.h>
|
|
#endif
|
|
|
|
#ifdef OS_WINCE
|
|
#include <ceconfig.h>
|
|
#endif
|
|
|
|
//
|
|
// maximum string length for menu strings
|
|
//
|
|
#define UI_MENU_STRING_MAX_LENGTH 256
|
|
|
|
CContainerWnd::CContainerWnd()
|
|
{
|
|
DC_BEGIN_FN("CContainerWnd");
|
|
|
|
_pTsClient = NULL;
|
|
_hwndMainDialog = NULL;
|
|
_hwndStatusDialog = NULL;
|
|
_fLoginComplete = FALSE;
|
|
|
|
_bContainerIsFullScreen = FALSE;
|
|
_fPreventClose = FALSE;
|
|
_fBeenThroughDestroy = FALSE;
|
|
_fBeenThroughNCDestroy = FALSE;
|
|
_PostedQuit=0;
|
|
_pWndView = NULL;
|
|
_fFirstTimeToLogonDlg = TRUE;
|
|
_cInEventHandlerCount = 0;
|
|
_fInOnCloseHandler = FALSE;
|
|
_pMainDlg = NULL;
|
|
_pTscSet = NULL;
|
|
_pSh = NULL;
|
|
memset(_szAppName, 0, sizeof(_szAppName));
|
|
_fHaveConnected = FALSE;
|
|
_fClosePending = FALSE;
|
|
|
|
#ifndef OS_WINCE
|
|
_pTaskBarList2 = NULL;
|
|
_fQueriedForTaskBarList2 = FALSE;
|
|
#endif
|
|
|
|
_fInSizeMove = FALSE;
|
|
_maxMainWindowSize.width = 100;
|
|
_maxMainWindowSize.height = 100;
|
|
|
|
SetCurrentDesktopWidth(DEFAULT_DESKTOP_WIDTH);
|
|
SetCurrentDesktopHeight(DEFAULT_DESKTOP_HEIGHT);
|
|
|
|
_fClientWindowIsUp = FALSE;
|
|
_successConnectCount = 0;
|
|
_fRunningOnWin9x = FALSE;
|
|
SET_CONTWND_STATE(stateNotInitialized);
|
|
ResetConnectionSuccessFlag();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
CContainerWnd::~CContainerWnd()
|
|
{
|
|
//
|
|
// Release our cached interface ptr to the taskbar
|
|
//
|
|
#ifndef OS_WINCE
|
|
if (_pTaskBarList2)
|
|
{
|
|
_pTaskBarList2->Release();
|
|
_pTaskBarList2 = NULL;
|
|
}
|
|
#endif
|
|
|
|
delete _pMainDlg;
|
|
|
|
if (_pWndView)
|
|
{
|
|
_pWndView->Cleanup();
|
|
delete _pWndView;
|
|
_pWndView = NULL;
|
|
}
|
|
}
|
|
|
|
DCBOOL CContainerWnd::Init(HINSTANCE hInstance, CTscSettings* pTscSet, CSH* pSh)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DC_BEGIN_FN("Init");
|
|
|
|
TRC_ASSERT(hInstance && pTscSet && pSh,
|
|
(TB,_T("Invalid param(s)")));
|
|
if (!(hInstance && pTscSet && pSh))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_fRunningOnWin9x = CSH::SH_IsRunningOn9x();
|
|
TRC_NRM((TB,_T("Running on 9x :%d"), _fRunningOnWin9x));
|
|
|
|
_pSh = pSh;
|
|
_hInst = hInstance;
|
|
//
|
|
// Window is created with dummy size, it is resized before
|
|
// connection
|
|
//
|
|
RECT rcNormalizedPos = {0,0,1,1};
|
|
|
|
INITCOMMONCONTROLSEX cmCtl;
|
|
cmCtl.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
|
|
#ifndef OS_WINCE
|
|
//Load ComboBoxEx class
|
|
cmCtl.dwICC = ICC_USEREX_CLASSES;
|
|
if (!InitCommonControlsEx( &cmCtl))
|
|
{
|
|
TRC_ABORT((TB, _T("InitCommonControlsEx failed")));
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
_pTscSet = pTscSet;
|
|
|
|
if (!LoadString(hInstance,
|
|
UI_IDS_APP_NAME,
|
|
_szAppName,
|
|
SIZECHAR(_szAppName)))
|
|
{
|
|
TRC_ERR((TB,_T("LoadString UI_IDS_APP_NAME failed")));
|
|
}
|
|
|
|
//
|
|
// Cache the path to the default file
|
|
//
|
|
#ifndef OS_WINCE
|
|
_pSh->SH_GetPathToDefaultFile(_szPathToDefaultFile,
|
|
SIZECHAR(_szPathToDefaultFile));
|
|
#else
|
|
_tcscpy(_szPathToDefaultFile, _T(""));
|
|
#endif
|
|
|
|
//Create invisible top level container window
|
|
if(!CreateWnd(hInstance, NULL,
|
|
MAIN_CLASS_NAME,
|
|
_pSh->_fullFrameTitleStr,
|
|
#ifndef OS_WINCE
|
|
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
|
|
WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
|
|
#else
|
|
WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_EX_WINDOWEDGE,
|
|
#endif
|
|
&rcNormalizedPos,
|
|
_pSh->GetAppIcon()))
|
|
{
|
|
TRC_ERR((TB,_T("Failed to create top level window")));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Load the Ax control
|
|
//
|
|
// CreateTsControl pops message boxes to indicate
|
|
// common failures
|
|
//
|
|
hr = CreateTsControl();
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ERR((TB, _T("Failed to create control\n")));
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
|
|
TRC_ASSERT(_pTsClient, (TB,_T(" _pTsClient not created")));
|
|
if (!_pTsClient)
|
|
{
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
if (!_pSh->SH_ReadControlVer( _pTsClient))
|
|
{
|
|
_pTsClient->Release();
|
|
_pTsClient=NULL;
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
|
|
IMsRdpClientAdvancedSettings* pAdvSettings;
|
|
hr = _pTsClient->get_AdvancedSettings2( &pAdvSettings);
|
|
if (FAILED(hr) || !pAdvSettings)
|
|
{
|
|
_pTsClient->Release();
|
|
_pTsClient=NULL;
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set the container handled fullscreen prop
|
|
//
|
|
hr = pAdvSettings->put_ContainerHandledFullScreen( TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
_pTsClient->Release();
|
|
pAdvSettings->Release();
|
|
_pTsClient=NULL;
|
|
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
pAdvSettings->Release();
|
|
|
|
SetupSystemMenu();
|
|
|
|
SET_CONTWND_STATE(stateNotConnected);
|
|
|
|
if (_pSh->GetAutoConnect() && _pSh->SH_ValidateParams(_pTscSet))
|
|
{
|
|
//Auto connect
|
|
if (!StartConnection())
|
|
{
|
|
//
|
|
// Autoconnection failed, this could have been because
|
|
// the user cancelled out of a security warning dialog
|
|
// in which case we brought up the main UI - in that
|
|
// case do not exit, all other cases bail out.
|
|
//
|
|
if (!IsUsingDialogUI())
|
|
{
|
|
TRC_ERR((TB,_T("StartConnection failed")));
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Start the main dialog
|
|
TRC_NRM((TB, _T("Bringing up connection dialog")));
|
|
|
|
//
|
|
// Start the dialog in the expanded state if the file
|
|
// was opened for edit (first parameter)
|
|
//
|
|
if (!StartConnectDialog(_pSh->SH_GetCmdFileForEdit(), TAB_GENERAL_IDX))
|
|
{
|
|
TRC_ERR((TB,_T("Error bringing up connect dialog")));
|
|
DestroyWindow();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Exit and quit the app
|
|
//
|
|
void CContainerWnd::ExitAndQuit()
|
|
{
|
|
DC_BEGIN_FN("ExitAndQuit");
|
|
if (_pTsClient)
|
|
{
|
|
_pTsClient->Release();
|
|
_pTsClient = NULL;
|
|
}
|
|
|
|
if (::IsWindow(_hwndMainDialog))
|
|
{
|
|
::DestroyWindow(_hwndMainDialog);
|
|
_hwndMainDialog = NULL;
|
|
}
|
|
|
|
_PostedQuit=2;
|
|
::PostQuitMessage(0);
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
BOOL CContainerWnd::SetupSystemMenu()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
#ifndef OS_WINCE
|
|
HMENU hHelpMenu;
|
|
DCTCHAR menuStr[UI_MENU_STRING_MAX_LENGTH];
|
|
#if DC_DEBUG
|
|
HMENU hDebugMenu;
|
|
#endif // DC_DEBUG
|
|
#endif // OS_WINCE
|
|
|
|
DC_BEGIN_FN("SetupSystemMenu");
|
|
|
|
|
|
#ifndef OS_WINCE // These won't work in full screen anyway
|
|
|
|
// Set up the main window's menu information.
|
|
_hSystemMenu = GetSystemMenu(GetHwnd(), FALSE);
|
|
if (_hSystemMenu)
|
|
{
|
|
// Update the System Menu Alt-F4 menu text
|
|
if (LoadString(_hInst,
|
|
UI_MENU_APPCLOSE,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
if (!ModifyMenu(_hSystemMenu, SC_CLOSE, MF_BYCOMMAND |
|
|
MF_STRING, SC_CLOSE, menuStr))
|
|
{
|
|
TRC_ERR((TB, _T("Unable to ModifyMenu")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB, _T("Unable to Load App close text")));
|
|
}
|
|
|
|
// Add Help Menu to the System Menu
|
|
hHelpMenu = CreateMenu();
|
|
|
|
if (hHelpMenu)
|
|
{
|
|
//load the string from the resources
|
|
if (LoadString(_hInst,
|
|
UI_MENU_MAINHELP,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(_hSystemMenu, MF_POPUP | MF_STRING,
|
|
(INT_PTR)hHelpMenu, menuStr);
|
|
|
|
//load the string for the client help sub menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_CLIENTHELP,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hHelpMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_HELP_ON_CLIENT,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Client Help Sub Menu string ID:%u"),
|
|
UI_MENU_CLIENTHELP));
|
|
}
|
|
|
|
//load the string for the about help sub menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_ABOUT,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hHelpMenu, MF_UNCHECKED|MF_STRING, UI_IDM_ABOUT,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load About Help Sub Menu string ID:%u"),
|
|
UI_MENU_ABOUT));
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
//load string for the main help menu failed
|
|
|
|
TRC_ERR((TB, _T("Failed to load Main Help Menu string ID:%u"),
|
|
UI_MENU_MAINHELP));
|
|
}
|
|
|
|
_hHelpMenu = hHelpMenu;
|
|
}
|
|
|
|
|
|
// Add Debug Menu to the System Menu
|
|
#ifdef DC_DEBUG
|
|
hDebugMenu = CreateMenu();
|
|
|
|
if (hDebugMenu)
|
|
{
|
|
//load the string for the DEBUG menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_DEBUG,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(_hSystemMenu, MF_POPUP | MF_STRING,
|
|
(INT_PTR)hDebugMenu, menuStr);
|
|
|
|
//load the string for the hatch Bitmap pdu debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_BITMAPPDU,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_HATCHBITMAPPDUDATA,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_BITMAPPDU));
|
|
}
|
|
|
|
//load the string for the hatch SS Border data debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_SSBORDER,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_HATCHSSBORDERDATA,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_SSBORDER));
|
|
}
|
|
|
|
//load the string for the Hatch MemBlt order data debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_HATCHMEMBIT,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_HATCHMEMBLTORDERDATA,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_HATCHMEMBIT));
|
|
}
|
|
|
|
//load the string for the hatch index pdu debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_INDEXPDU,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_HATCHINDEXPDUDATA,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_INDEXPDU));
|
|
}
|
|
|
|
//load the string for the label Membit data debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_LABELMEMBIT,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_LABELMEMBLTORDERS,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_LABELMEMBIT));
|
|
}
|
|
|
|
//load the string for the hatch Bitmap Cahche Monitor debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_CACHE,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_BITMAPCACHEMONITOR,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_CACHE));
|
|
}
|
|
|
|
//load the string for the malloc Failure debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_MALLOC,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_MALLOCFAILURE,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_MALLOC));
|
|
}
|
|
|
|
//load the string for the Malloc Huge Failure debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_MALLOCHUGE,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_MALLOCHUGEFAILURE,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_MALLOCHUGE));
|
|
}
|
|
|
|
//load the string for the network Throughput.. debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_NETWORK,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
AppendMenu(hDebugMenu, MF_UNCHECKED|MF_STRING,
|
|
UI_IDM_NETWORKTHROUGHPUT,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_NETWORK));
|
|
}
|
|
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
|
|
#ifdef SMART_SIZING
|
|
//load the string for the SmartSize debug menu
|
|
if (LoadString(_hInst,
|
|
UI_MENU_SMARTSIZING,
|
|
menuStr,
|
|
UI_MENU_STRING_MAX_LENGTH) != 0)
|
|
{
|
|
UINT flags;
|
|
flags = MF_STRING;
|
|
if (_fRunningOnWin9x) {
|
|
flags |= MF_GRAYED;
|
|
}
|
|
|
|
AppendMenu(hDebugMenu, flags,
|
|
UI_IDM_SMARTSIZING,
|
|
menuStr);
|
|
}
|
|
else
|
|
{
|
|
//failed to load the sub menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug Sub Menu string ID:%u"),
|
|
UI_MENU_HATCHMEMBIT));
|
|
}
|
|
#endif // SMART_SIZING
|
|
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (!_pTsClient)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr) && pDebugger)
|
|
{
|
|
//
|
|
// Now check the menu items as needed
|
|
//
|
|
BOOL bEnabled;
|
|
TRACE_HR(pDebugger->get_HatchBitmapPDU(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_HATCHBITMAPPDUDATA,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
|
|
TRACE_HR(pDebugger->get_HatchIndexPDU(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_HATCHINDEXPDUDATA,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
|
|
TRACE_HR(pDebugger->get_HatchSSBOrder(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_HATCHSSBORDERDATA,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
|
|
TRACE_HR(pDebugger->get_HatchMembltOrder(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_HATCHMEMBLTORDERDATA,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
|
|
TRACE_HR(pDebugger->get_LabelMemblt(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_LABELMEMBLTORDERS,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
|
|
TRACE_HR(pDebugger->get_BitmapCacheMonitor(&bEnabled));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(hDebugMenu,
|
|
UI_IDM_BITMAPCACHEMONITOR,
|
|
bEnabled ? MF_CHECKED :
|
|
MF_UNCHECKED);
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//failed to load the debug menu string
|
|
TRC_ERR((TB, _T("Failed to load Debug menu string ID:%u"),
|
|
UI_MENU_DEBUG));
|
|
}
|
|
|
|
_hDebugMenu = hDebugMenu;
|
|
}
|
|
#endif // DC_DEBUG
|
|
}
|
|
#endif // OS_WINCE
|
|
DC_END_FN();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
LRESULT CContainerWnd::OnCreate(UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
DC_BEGIN_FN("OnCreate");
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Create TS Control Window.
|
|
//
|
|
HRESULT CContainerWnd::CreateTsControl()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DC_BEGIN_FN("CreateTsControl");
|
|
|
|
if (_pWndView)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
_pWndView = new CAxHostWnd(this);
|
|
if (!_pWndView)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (!_pWndView->Init())
|
|
{
|
|
TRC_ABORT((TB,_T("Init of AxHostWnd failed")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// CreateControl is the crucial part that goes
|
|
// and loads the control dll.
|
|
//
|
|
INT rc = _pWndView->CreateControl(&_pTsClient);
|
|
if (AXHOST_SUCCESS == rc)
|
|
{
|
|
if (!_pWndView->CreateHostWnd(GetHwnd(), _hInst))
|
|
{
|
|
TRC_ABORT((TB,_T("CreateHostWnd failed")));
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("CreateControl failed")));
|
|
//
|
|
// Pop meaningful errmsg boxes to the user
|
|
// as this is a fatal error and we can't go on
|
|
//
|
|
INT errStringID;
|
|
switch (rc)
|
|
{
|
|
case ERR_AXHOST_DLLNOTFOUND:
|
|
errStringID = UI_IDS_ERR_DLLNOTFOUND;
|
|
break;
|
|
case ERR_AXHOST_VERSIONMISMATCH:
|
|
errStringID = UI_IDS_ERR_DLLBADVERSION;
|
|
break;
|
|
default:
|
|
errStringID = UI_IDS_ERR_LOADINGCONTROL;
|
|
break;
|
|
}
|
|
|
|
TCHAR errLoadingControl[MAX_PATH];
|
|
if (LoadString(_hInst,
|
|
errStringID,
|
|
errLoadingControl,
|
|
SIZECHAR(errLoadingControl)) != 0)
|
|
{
|
|
MessageBox(GetHwnd(), errLoadingControl, _szAppName,
|
|
MB_ICONERROR | MB_OK);
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
DC_END_FN();
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Kick off a connection with the current settings
|
|
//
|
|
BOOL CContainerWnd::StartConnection()
|
|
{
|
|
DC_BEGIN_FN("StartConnection");
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
PWINDOWPLACEMENT pwndplc;
|
|
BOOL fResult = FALSE;
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TCHAR szPlainServerName[TSC_MAX_ADDRESS_LENGTH];
|
|
|
|
TRC_ASSERT(_pTsClient, (TB,_T(" Ts client control does not exist!\n")));
|
|
if (!_pTsClient)
|
|
{
|
|
return FALSE;
|
|
}
|
|
TRC_ASSERT(_pTscSet, (TB,_T(" tsc settings does not exist!\n")));
|
|
|
|
TRC_ASSERT(_state != stateConnecting &&
|
|
_state != stateConnected,
|
|
(TB,_T("Can't connect in connecting state: 0x%d"),
|
|
_state));
|
|
|
|
|
|
ResetConnectionSuccessFlag();
|
|
|
|
pwndplc = _pTscSet->GetWindowPlacement();
|
|
//
|
|
// Positition the window before connecting
|
|
// so that if it's a fullscreen connection
|
|
// we can determine the correct resolution to connect at.
|
|
// This has to be set before the connection starts
|
|
//
|
|
#ifndef OS_WINCE
|
|
TRC_ASSERT(pwndplc->rcNormalPosition.right - pwndplc->rcNormalPosition.left,
|
|
(TB,_T("0 width")));
|
|
|
|
TRC_ASSERT(pwndplc->rcNormalPosition.bottom - pwndplc->rcNormalPosition.top,
|
|
(TB,_T("0 height")));
|
|
#endif
|
|
|
|
//
|
|
// For fullscreen force the deskwidth/height
|
|
// to match the monitor we're going to connect on
|
|
//
|
|
if (_pTscSet->GetStartFullScreen())
|
|
{
|
|
RECT rcMonitor;
|
|
int deskX,deskY;
|
|
|
|
CSH::MonitorRectFromNearestRect(&pwndplc->rcNormalPosition,
|
|
&rcMonitor);
|
|
|
|
deskX = min(rcMonitor.right - rcMonitor.left,MAX_DESKTOP_WIDTH);
|
|
deskY = min(rcMonitor.bottom - rcMonitor.top,MAX_DESKTOP_HEIGHT);
|
|
_pTscSet->SetDesktopWidth( deskX );
|
|
_pTscSet->SetDesktopHeight( deskY );
|
|
}
|
|
|
|
//
|
|
// Do security checks on the plain server name (no port, no params)
|
|
//
|
|
hr = _pTscSet->GetConnectString().GetServerNamePortion(
|
|
szPlainServerName,
|
|
SIZE_TCHARS(szPlainServerName)
|
|
);
|
|
if (FAILED(hr)) {
|
|
TRC_ERR((TB,_T("Failed to get plain server name 0x%x"), hr));
|
|
DC_QUIT;
|
|
}
|
|
|
|
if (!CTSSecurity::AllowConnection(_hwndMainDialog, _hInst,
|
|
szPlainServerName,
|
|
_pTscSet->GetDriveRedirection(),
|
|
_pTscSet->GetCOMPortRedirection()))
|
|
{
|
|
TRC_ERR((TB,_T("AllowConnection check returned FALSE. Skip connect")));
|
|
fResult = FALSE;
|
|
|
|
//
|
|
// If this was an autoconnection then start the dialog
|
|
// up at the LocalResources tab so the user can easily change
|
|
// device redirection options
|
|
//
|
|
if (_pSh->GetAutoConnect())
|
|
{
|
|
//
|
|
// From now on this is not an autoconnection
|
|
//
|
|
_pSh->SetAutoConnect(FALSE);
|
|
|
|
#ifdef OS_WINCE //dont bring up mstsc ui on WBT.
|
|
if (g_CEConfig == CE_CONFIG_WBT)
|
|
DC_QUIT;
|
|
#endif
|
|
//
|
|
// Start the dialog expanded at the local resources tab
|
|
//
|
|
if (!StartConnectDialog(TRUE, TAB_LOCAL_RESOURCES_IDX))
|
|
{
|
|
TRC_ERR((TB,_T("Error bringing up connect dialog")));
|
|
DestroyWindow();
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
|
|
DC_QUIT;
|
|
}
|
|
|
|
hr = _pTscSet->ApplyToControl(_pTsClient);
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ERR((TB,_T("Failed ApplyToControl: %d"), hr));
|
|
fResult = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
//The desktop size from the settings can
|
|
//change during the connection..e.g when a shadow happens.
|
|
//CurrentDesktopWidth/Height stores the instantaneous values
|
|
SetCurrentDesktopWidth( _pTscSet->GetDesktopWidth());
|
|
SetCurrentDesktopHeight( _pTscSet->GetDesktopHeight());
|
|
|
|
RecalcMaxWindowSize();
|
|
|
|
//Now apply settings that don't come from the settings collection
|
|
hr = _pTsClient->get_Debugger(&pDebugger);
|
|
if (FAILED(hr) || !pDebugger)
|
|
{
|
|
fResult = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
hr = pDebugger->put_CLXCmdLine( T2OLE(_pSh->GetClxCmdLine()));
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ERR((TB,_T("Failed put_CLXCmdLine: %d"), hr));
|
|
fResult = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
pDebugger->Release();
|
|
pDebugger = NULL;
|
|
|
|
//Reset the login complete flag (login event occurs after connect)
|
|
_fLoginComplete = FALSE;
|
|
|
|
//Initiate the connection
|
|
hr = _pTsClient->Connect();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SET_CONTWND_STATE(stateConnecting);
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("Connect method failed: %d"), hr));
|
|
|
|
TCHAR errConnecting[MAX_PATH];
|
|
if (LoadString(_hInst,
|
|
UI_IDS_ERR_CONNECTCALLFAILED,
|
|
errConnecting,
|
|
SIZECHAR(errConnecting)) != 0)
|
|
{
|
|
MessageBox(GetHwnd(), errConnecting, _szAppName,
|
|
MB_ICONERROR | MB_OK);
|
|
}
|
|
|
|
fResult = FALSE;
|
|
DC_QUIT;
|
|
}
|
|
|
|
//Bring up the connecting dialog and wait for the Connected event
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
if(!IsUsingDialogUI())
|
|
{
|
|
//
|
|
// Only bring this up if we're not using the
|
|
// dialog UI. E.g for autolaunched connections.
|
|
//
|
|
// The dialog UI displays it's own progress indicator
|
|
//
|
|
TCHAR szServerName[TSC_MAX_ADDRESS_LENGTH];
|
|
_pTscSet->GetConnectString().GetServerPortion(
|
|
szServerName,
|
|
SIZE_TCHARS(szServerName)
|
|
);
|
|
CConnectingDlg connectingDlg(
|
|
_hwndMainDialog, _hInst,
|
|
this, szServerName
|
|
);
|
|
connectingDlg.DoModal();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
DC_EXIT_POINT:
|
|
if (pDebugger)
|
|
{
|
|
pDebugger->Release();
|
|
pDebugger = NULL;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return fResult;
|
|
}
|
|
|
|
DCBOOL CContainerWnd::Disconnect()
|
|
{
|
|
HRESULT hr;
|
|
short connectionState = 0;
|
|
DC_BEGIN_FN("Disconnect");
|
|
TRC_ASSERT(_pTsClient, (TB,_T(" Ts client control does not exist!\n")));
|
|
if (!_pTsClient)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
TRC_NRM((TB,_T("Container calling control's disconnect")));
|
|
|
|
//
|
|
// In some cases the control might already be disconnected
|
|
// check for that
|
|
//
|
|
// NOTE that becasue we are in a STA the connected state
|
|
// of the control can't change after the get_Connected call
|
|
// (untill we go back to pumping messages) so there are no
|
|
// timing issues here.
|
|
//
|
|
TRACE_HR(_pTsClient->get_Connected( & connectionState ));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if( connectionState )
|
|
{
|
|
// Still connected disconnect
|
|
hr = _pTsClient->Disconnect();
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Successfully initiated disconnect (note it is async)
|
|
// need to wait for OnDisconnected
|
|
//
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("Disconnect() failed 0x%x\n"), hr));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_NRM((TB,_T("Not calling disconnected because already discon")));
|
|
return TRUE; // success
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnDestroy(HWND hWnd, UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnDestroy");
|
|
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
BOOL fShouldDestroy = FALSE;
|
|
|
|
if (_fBeenThroughDestroy)
|
|
{
|
|
TRC_ERR((TB,_T("Been through WM_DESTROY before!!!")));
|
|
return 0;
|
|
}
|
|
_fBeenThroughDestroy = TRUE;
|
|
|
|
if (InControlEventHandler())
|
|
{
|
|
//
|
|
// Don't allow the close. We are in a code path that fired
|
|
// from the control. Without this, we sometimes see the client
|
|
// receiving close notifications from tclient while a disconnected
|
|
// dialog is up (i.e in an OnDicsconnected handler) - destroying
|
|
// the control at this time causes bad things to happen during
|
|
// the return into the control (which has now been deleted).
|
|
//
|
|
TRC_ERR((TB,_T("OnDestroy called during a control event handler")));
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
fShouldDestroy = TRUE;
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
LRESULT lResult = 0;
|
|
#endif
|
|
if(fShouldDestroy)
|
|
{
|
|
//Terminate the app
|
|
_PostedQuit=1;
|
|
#ifdef OS_WINCE
|
|
lResult = DefWindowProc( hWnd, uMsg, wParam, lParam);
|
|
#else
|
|
return DefWindowProc( hWnd, uMsg, wParam, lParam);
|
|
#endif
|
|
}
|
|
|
|
#ifdef OS_WINCE //CE does not support WM_NCDESTROY. So destroy the activex control and send a WM_NCDESTROY
|
|
if (_pWndView)
|
|
{
|
|
HWND hwndCtl = _pWndView->GetHwnd();
|
|
::DestroyWindow(hwndCtl);
|
|
SendMessage(hWnd, WM_NCDESTROY, 0, 0L);
|
|
}
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
#ifdef OS_WINCE
|
|
return lResult;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnNCDestroy(HWND hWnd, UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnNCDestroy");
|
|
|
|
//This is the right time to call postquit message.
|
|
//As the child windows (e.g the control) have been
|
|
//completely destroyed and cleaned up by this point
|
|
if(_fBeenThroughNCDestroy)
|
|
{
|
|
TRC_ERR((TB,_T("Been through WM_NCDESTROY before!!!")));
|
|
return 1L;
|
|
}
|
|
_fBeenThroughNCDestroy = TRUE;
|
|
ExitAndQuit();
|
|
|
|
DC_END_FN();
|
|
return 0L;
|
|
}
|
|
|
|
//
|
|
// Name: SetMinMaxPlacement
|
|
//
|
|
// Purpose: Reset the minimized / maximized placement
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Params: windowplacement structure to update
|
|
//
|
|
// Operation: Allow for the window border width.
|
|
//
|
|
//
|
|
VOID CContainerWnd::SetMinMaxPlacement(WINDOWPLACEMENT& windowPlacement)
|
|
{
|
|
DC_BEGIN_FN("UISetMinMaxPlacement");
|
|
|
|
//
|
|
// Set the maximized position to the top left - allow for the window
|
|
// frame width.
|
|
//
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
windowPlacement.ptMaxPosition.x = -GetSystemMetrics(SM_CXFRAME);
|
|
windowPlacement.ptMaxPosition.y = -GetSystemMetrics(SM_CYFRAME);
|
|
#else // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
windowPlacement.ptMaxPosition.x = 0;
|
|
windowPlacement.ptMaxPosition.y = 0;
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
|
|
//
|
|
// Minimized position is 0, 0
|
|
//
|
|
windowPlacement.ptMinPosition.x = 0;
|
|
windowPlacement.ptMinPosition.y = 0;
|
|
|
|
#ifndef OS_WINCE
|
|
if (IsZoomed(GetHwnd()))
|
|
{
|
|
windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
|
|
}
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
return;
|
|
} // UISetMinMaxPlacement
|
|
|
|
//
|
|
// Name: RecalcMaxWindowSize
|
|
//
|
|
// Purpose: Recalculates _maxMainWindowSize given the current remote desktop
|
|
// size and frame style. The maximum main window size is the
|
|
// size of window needed such that the client area is the same
|
|
// size as the container.
|
|
//
|
|
// Params: None
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
//
|
|
VOID CContainerWnd::RecalcMaxWindowSize(DCVOID)
|
|
{
|
|
#ifndef OS_WINCE
|
|
RECT rect;
|
|
#ifdef OS_WIN32
|
|
BOOL errorRc;
|
|
#endif
|
|
#endif
|
|
|
|
DC_BEGIN_FN("RecalcMaxWindowSize");
|
|
|
|
//
|
|
// If current mode is full screen, then the maximum window size is the
|
|
// same as the screen size - unless the container is larger still,
|
|
// which is possible if we're shadowing a session larger than
|
|
// ourselves.
|
|
//
|
|
// In this case, or if the current mode is not full screen then we want
|
|
// the size of window which is required for a client area of the size
|
|
// of the container. Passing the container size to AdjustWindowRect
|
|
// returns this window size. Such a window may be bigger than the
|
|
// screen, eg server and client are 640x480, container is 640x480.
|
|
// AdjustWindowRect adds on the border, title bar and menu sizes and
|
|
// returns something like 648x525. So, UI.maxMainWindowSize can only
|
|
// match the actual window size when the client screen is bigger than
|
|
// the server screen or when operating in full screen mode. This means
|
|
// that UI.maxMainWindowSize should *never* be used to set the window
|
|
// size, eg by passing it to SetWindowPos. It can be used to determine
|
|
// whether scroll bars are required, ie they are needed if the current
|
|
// window size is less than UI.maxMainWindowSize (in other words,
|
|
// always unless in full screen mode or client screen is larger than
|
|
// server screen).
|
|
//
|
|
// To set the window size, calculate a value based on:
|
|
// - the desired window size given the container size
|
|
// - the size of the client screen.
|
|
//
|
|
#ifndef OS_WINCE
|
|
//
|
|
// Recalc window size based on container
|
|
//
|
|
rect.left = 0;
|
|
rect.right = GetCurrentDesktopWidth();
|
|
rect.top = 0;
|
|
rect.bottom = GetCurrentDesktopHeight();
|
|
|
|
#ifdef OS_WIN32
|
|
errorRc = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
TRC_ASSERT((errorRc != 0), (TB, _T("AdjustWindowRect failed")));
|
|
#else
|
|
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
|
#endif
|
|
|
|
_maxMainWindowSize.width = rect.right - rect.left;
|
|
_maxMainWindowSize.height = rect.bottom - rect.top;
|
|
#endif
|
|
|
|
TRC_NRM((TB, _T("Main Window maxSize (%d,%d)"),
|
|
_maxMainWindowSize.width,
|
|
_maxMainWindowSize.height));
|
|
|
|
DC_END_FN();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Name: GetMaximizedWindowSize
|
|
//
|
|
// Purpose: Calculates the size to which the main window should be
|
|
// maximized, base on the screen size and the size of window
|
|
// which would have a client area the same size as the
|
|
// container (UI.maxMainWindowSize).
|
|
//
|
|
// Returns: The calculated size.
|
|
//
|
|
// Params: None.
|
|
//
|
|
//
|
|
DCSIZE CContainerWnd::GetMaximizedWindowSize(DCSIZE& maximizedSize)
|
|
{
|
|
DCUINT xSize;
|
|
DCUINT ySize;
|
|
RECT rc;
|
|
|
|
DC_BEGIN_FN("UIGetMaximizedWindowSize");
|
|
|
|
//
|
|
// The maximum size we set a window to is the smaller of:
|
|
// - UI.maxMainWindowSize
|
|
// - the screen size plus twice the border width (so the borders are
|
|
// not visible).
|
|
// Always query the monitor rect as it may change
|
|
// width, as these can change dynamically.
|
|
//
|
|
CSH::MonitorRectFromHwnd(GetHwnd(), &rc);
|
|
|
|
xSize = rc.right - rc.left;
|
|
ySize = rc.bottom - rc.top;
|
|
|
|
#ifdef OS_WINCE
|
|
maximizedSize.width = DC_MIN(_maxMainWindowSize.width,xSize);
|
|
|
|
maximizedSize.height = DC_MIN(_maxMainWindowSize.height,ySize);
|
|
|
|
#else // This section NOT OS_WINCE
|
|
maximizedSize.width = DC_MIN(_maxMainWindowSize.width,
|
|
xSize + (2 * GetSystemMetrics(SM_CXFRAME)));
|
|
|
|
maximizedSize.height = DC_MIN(_maxMainWindowSize.height,
|
|
ySize + (2 * GetSystemMetrics(SM_CYFRAME)));
|
|
#endif // OS_WINCE
|
|
|
|
TRC_NRM((TB, _T("Main Window maxSize (%d,%d) maximizedSize (%d,%d) "),
|
|
_maxMainWindowSize.width,
|
|
_maxMainWindowSize.height,
|
|
maximizedSize.width,
|
|
maximizedSize.height));
|
|
|
|
DC_END_FN();
|
|
|
|
return(maximizedSize);
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnMove(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnMove");
|
|
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
#ifndef OS_WINCE
|
|
|
|
//No-op when fullscreen
|
|
if (!_bContainerIsFullScreen)
|
|
{
|
|
WINDOWPLACEMENT* pWindowPlacement = NULL;
|
|
|
|
pWindowPlacement = _pTscSet->GetWindowPlacement();
|
|
TRC_ASSERT(pWindowPlacement, (TB, _T("pWindowPlacement is NULL\n")));
|
|
if (pWindowPlacement)
|
|
{
|
|
GetWindowPlacement(GetHwnd(), pWindowPlacement);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
DC_EXIT_POINT:
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DC_BEGIN_FN("OnSize");
|
|
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
WINDOWPLACEMENT* pWindowPlacement = NULL;
|
|
|
|
#ifndef OS_WINCE
|
|
if (!_bContainerIsFullScreen)
|
|
{
|
|
// We're non-fullscreen, so keep the window placement structure
|
|
// up-to-date
|
|
pWindowPlacement = _pTscSet->GetWindowPlacement();
|
|
TRC_ASSERT(pWindowPlacement, (TB, _T("pWindowPlacement is NULL\n")));
|
|
if (!pWindowPlacement)
|
|
{
|
|
return 0;
|
|
}
|
|
//
|
|
// Update ShellUtil's current windowplacement info
|
|
//
|
|
GetWindowPlacement(GetHwnd(), pWindowPlacement);
|
|
|
|
TRC_DBG((TB, _T("Got window placement in WM_SIZE")));
|
|
|
|
if (wParam == SIZE_MAXIMIZED)
|
|
{
|
|
TRC_DBG((TB, _T("Maximize")));
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
//
|
|
// Override the maximized / minimized positions with our
|
|
// hardcoded valued - required if the maximized window is
|
|
// moved.
|
|
//
|
|
if (pWindowPlacement)
|
|
{
|
|
SetMinMaxPlacement(*pWindowPlacement);
|
|
SetWindowPlacement(GetHwnd(), pWindowPlacement);
|
|
}
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_WINDOWPLACEMENT)
|
|
|
|
//
|
|
// We need to be accurate about the maximized window size.
|
|
// It is not possible to use UI.maxMainWindowSize as this
|
|
// may be greater than screen size, eg server and client
|
|
// are 640x480, container is 640x480 then UI.maxWindowSize
|
|
// (obtained via AdjustWindowRect in UIRecalcMaxMainWindow)
|
|
// is something like 648x525.
|
|
// Passing this value to SetWindowPos has results which
|
|
// vary with different shells:
|
|
// Win95/NT4.0: the resulting window is 648x488 at -4, -4,
|
|
// ie all the window, except the border, is
|
|
// on-screen
|
|
// Win31/NT3.51: the resulting window is 648x525 at -4, -4,
|
|
// ie the size passed to SetWindowPos, so
|
|
// the bottom 40 pixels are off-screen.
|
|
// To avoid such differences calculate a maximized window
|
|
// size value which takes account of both the physical
|
|
// screen size and the ideal window size.
|
|
//
|
|
RecalcMaxWindowSize();
|
|
DCSIZE maximized;
|
|
GetMaximizedWindowSize(maximized);
|
|
SetWindowPos( GetHwnd(),
|
|
NULL,
|
|
0, 0,
|
|
maximized.width,
|
|
maximized.height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
}
|
|
}
|
|
#endif
|
|
//
|
|
// Size the child window (activeX control) accordingly
|
|
//
|
|
|
|
RECT rcClient;
|
|
GetClientRect(GetHwnd(), &rcClient);
|
|
if (_pWndView)
|
|
{
|
|
HWND hwndCtl = _pWndView->GetHwnd();
|
|
::MoveWindow(hwndCtl,rcClient.left, rcClient.top,
|
|
rcClient.right, rcClient.bottom,
|
|
TRUE);
|
|
}
|
|
|
|
DC_END_FN();
|
|
DC_EXIT_POINT:
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnCommand");
|
|
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
switch (DC_GET_WM_COMMAND_ID(wParam))
|
|
{
|
|
case UI_IDM_CONNECT:
|
|
{
|
|
if (!StartConnectDialog())
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// StartConnectionDialog
|
|
// Params: fStartExpanded - startup the dialog in the expanded state
|
|
// nStartTabIndex - index of the tab to show on startup (only applies
|
|
// if fStartExpanded is set)
|
|
//
|
|
//
|
|
BOOL CContainerWnd::StartConnectDialog(BOOL fStartExpanded,
|
|
INT nStartTabIndex)
|
|
{
|
|
DC_BEGIN_FN("StartConnectDialog");
|
|
|
|
TRC_DBG((TB, _T("Connect selected")));
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
//Show the dialog box only if auto connect is not enabled or
|
|
//if UIValidateCurrentParams fails.
|
|
if (!_pSh->GetAutoConnect() || !_pSh->SH_ValidateParams(_pTscSet))
|
|
{
|
|
if (!_pMainDlg)
|
|
{
|
|
_pMainDlg = new CMainDlg( NULL, _hInst, _pSh,
|
|
this,
|
|
_pTscSet,
|
|
fStartExpanded,
|
|
nStartTabIndex);
|
|
}
|
|
|
|
TRC_ASSERT(_pMainDlg, (TB,_T("Could not create main dialog")));
|
|
if (_pMainDlg)
|
|
{
|
|
if (_fFirstTimeToLogonDlg)
|
|
{
|
|
TRC_ASSERT(_hwndMainDialog == NULL,
|
|
(TB,(_T("Dialog exists before first time create!!!\n"))));
|
|
|
|
_pSh->SH_AutoFillBlankSettings(_pTscSet);
|
|
|
|
_hwndMainDialog = _pMainDlg->StartModeless();
|
|
::ShowWindow( _hwndMainDialog, SW_RESTORE);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just show the dialog
|
|
//
|
|
TRC_ASSERT(_hwndMainDialog,
|
|
(TB,_T("_hwndMainDialog is not present")));
|
|
::ShowWindow( _hwndMainDialog, SW_RESTORE);
|
|
SetForegroundWindow(_hwndMainDialog);
|
|
}
|
|
|
|
_fFirstTimeToLogonDlg = FALSE;
|
|
}
|
|
else
|
|
{
|
|
#ifdef OS_WINCE
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#ifdef OS_WINCE
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
return TRUE;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnSysCommand(UINT uMsg, WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ULONG scCode = 0;
|
|
DC_BEGIN_FN("OnSysCommand");
|
|
|
|
#ifndef OS_WINCE
|
|
scCode = (LOWORD(wParam) & 0xFFF0);
|
|
if (scCode == SC_MAXIMIZE)
|
|
{
|
|
//
|
|
// If the remote resolution matches
|
|
// the current monitor then maximize
|
|
// becomes 'go fullscreen'
|
|
//
|
|
if ( IsRemoteResMatchMonitorSize() )
|
|
{
|
|
hr = _pTsClient->put_FullScreen( VARIANT_TRUE );
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ERR((TB,_T("put_FullScreen failed 0x%x\n"),
|
|
hr));
|
|
}
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Default maximize behavior
|
|
//
|
|
return DefWindowProc( GetHwnd(), uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
else if (scCode == SC_MINIMIZE)
|
|
{
|
|
//
|
|
// If we are minimizing while still fullscreen tell the shell
|
|
// we are no longer fullscreen otherwise it treats us as a rude
|
|
// app and nasty stuff happens. E.g. we get switched to and maximized
|
|
// on a timer.
|
|
//
|
|
if (_bContainerIsFullScreen) {
|
|
CUT::NotifyShellOfFullScreen( GetHwnd(),
|
|
FALSE,
|
|
&_pTaskBarList2,
|
|
&_fQueriedForTaskBarList2 );
|
|
}
|
|
}
|
|
else if (scCode == SC_RESTORE)
|
|
{
|
|
//
|
|
// If we are restoring and going back to Fscreen
|
|
// tell the shell to mark us
|
|
//
|
|
if (_bContainerIsFullScreen) {
|
|
CUT::NotifyShellOfFullScreen( GetHwnd(),
|
|
TRUE,
|
|
&_pTaskBarList2,
|
|
&_fQueriedForTaskBarList2 );
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
switch (DC_GET_WM_COMMAND_ID(wParam))
|
|
{
|
|
case UI_IDM_ABOUT:
|
|
{
|
|
// Show the about box dialog
|
|
CAboutDlg aboutDialog( GetHwnd(),
|
|
_hInst,
|
|
_pSh->GetCipherStrength(),
|
|
_pSh->GetControlVersionString());
|
|
aboutDialog.DoModal();
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_HELP_ON_CLIENT:
|
|
{
|
|
//
|
|
// Display help for the connect dialog.
|
|
//
|
|
#ifndef OS_WINCE
|
|
TRC_NRM((TB, _T("Display the appropriate help page")));
|
|
|
|
if (GetHwnd() && _pSh)
|
|
{
|
|
_pSh->SH_DisplayClientHelp(
|
|
GetHwnd(),
|
|
HH_DISPLAY_TOPIC);
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
#ifdef DC_DEBUG
|
|
case UI_IDM_BITMAPCACHEMONITOR:
|
|
{
|
|
//
|
|
// Toggle the Bitmap Cache Monitor setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL bmpCacheMonitor;
|
|
TRACE_HR(pDebugger->get_BitmapCacheMonitor(&bmpCacheMonitor));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
bmpCacheMonitor = !bmpCacheMonitor;
|
|
TRACE_HR(pDebugger->put_BitmapCacheMonitor(bmpCacheMonitor));
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_BITMAPCACHEMONITOR,
|
|
bmpCacheMonitor ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_HATCHBITMAPPDUDATA:
|
|
{
|
|
//
|
|
// Toggle the hatch bitmap PDU data setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL hatchBitmapPDU;
|
|
TRACE_HR(pDebugger->get_HatchBitmapPDU(&hatchBitmapPDU));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hatchBitmapPDU = !hatchBitmapPDU;
|
|
TRACE_HR(pDebugger->put_HatchBitmapPDU(hatchBitmapPDU));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_HATCHBITMAPPDUDATA,
|
|
hatchBitmapPDU ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_HATCHINDEXPDUDATA:
|
|
{
|
|
//
|
|
// Toggle the hatch index PDU data setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL hatchIndexPDU;
|
|
TRACE_HR(pDebugger->get_HatchIndexPDU(&hatchIndexPDU));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hatchIndexPDU = !hatchIndexPDU;
|
|
TRACE_HR(pDebugger->put_HatchIndexPDU(hatchIndexPDU));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_HATCHINDEXPDUDATA,
|
|
hatchIndexPDU ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_HATCHSSBORDERDATA:
|
|
{
|
|
//
|
|
// Toggle the hatch SSB order data setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL hatchSSBorder;
|
|
TRACE_HR(pDebugger->get_HatchSSBOrder(&hatchSSBorder));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hatchSSBorder = !hatchSSBorder;
|
|
TRACE_HR(pDebugger->put_HatchSSBOrder(hatchSSBorder));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_HATCHSSBORDERDATA,
|
|
hatchSSBorder ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_HATCHMEMBLTORDERDATA:
|
|
{
|
|
//
|
|
// Toggle the hatch memblt order data setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL hatchMemBlt;
|
|
TRACE_HR(pDebugger->get_HatchMembltOrder(&hatchMemBlt));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hatchMemBlt = !hatchMemBlt;
|
|
hr = pDebugger->put_HatchMembltOrder(hatchMemBlt);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_HATCHMEMBLTORDERDATA,
|
|
hatchMemBlt ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_LABELMEMBLTORDERS:
|
|
{
|
|
//
|
|
// Toggle the label memblt orders setting.
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL labelMemBltOrders;
|
|
TRACE_HR(pDebugger->get_LabelMemblt(&labelMemBltOrders));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
labelMemBltOrders = !labelMemBltOrders;
|
|
hr = pDebugger->put_LabelMemblt(labelMemBltOrders);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_LABELMEMBLTORDERS,
|
|
labelMemBltOrders ? MF_CHECKED : MF_UNCHECKED);
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_MALLOCFAILURE:
|
|
{
|
|
//
|
|
// Malloc failures dialog box
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
LONG failPercent;
|
|
TRACE_HR(pDebugger->get_MallocFailuresPercent(&failPercent));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CMallocDbgDlg mallocFailDialog(GetHwnd(), _hInst, (DCINT)failPercent,
|
|
FALSE); //don't use malloc huge dialog
|
|
if (IDOK == mallocFailDialog.DoModal())
|
|
{
|
|
failPercent = mallocFailDialog.GetFailPercent();
|
|
TRC_NRM((TB,_T("Setting malloc FAILURE PERCENT to:%d"), failPercent));
|
|
TRACE_HR(pDebugger->put_MallocFailuresPercent(failPercent));
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_MALLOCHUGEFAILURE:
|
|
{
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
LONG failPercent;
|
|
TRACE_HR(pDebugger->get_MallocHugeFailuresPercent(&failPercent));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CMallocDbgDlg mallocFailDialog(GetHwnd(), _hInst, (DCINT)failPercent,
|
|
TRUE); //use malloc huge dialog
|
|
if (IDOK == mallocFailDialog.DoModal())
|
|
{
|
|
failPercent = mallocFailDialog.GetFailPercent();
|
|
TRC_NRM((TB,_T("Setting malloc FAILURE PERCENT to:%d"), failPercent));
|
|
TRACE_HR(pDebugger->put_MallocHugeFailuresPercent(failPercent));
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case UI_IDM_NETWORKTHROUGHPUT:
|
|
{
|
|
//
|
|
// Limit net thruput
|
|
//
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsTscDebug* pDebugger = NULL;
|
|
TRACE_HR(_pTsClient->get_Debugger(&pDebugger));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
LONG netThruPut;
|
|
TRACE_HR(pDebugger->get_NetThroughput(&netThruPut));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CThruPutDlg thruPutDialog(GetHwnd(), _hInst, (DCINT)netThruPut);
|
|
|
|
if (IDOK == thruPutDialog.DoModal())
|
|
{
|
|
netThruPut = thruPutDialog.GetNetThruPut();
|
|
TRC_NRM((TB,_T("Setting thruput to:%d"), netThruPut));
|
|
TRACE_HR(pDebugger->put_NetThroughput(netThruPut));
|
|
|
|
}
|
|
}
|
|
pDebugger->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef SMART_SIZING
|
|
case UI_IDM_SMARTSIZING:
|
|
{
|
|
TRC_ASSERT(_pTsClient,(TB, _T("_pTsClient is NULL on syscommand")));
|
|
if (_pTsClient)
|
|
{
|
|
IMsRdpClientAdvancedSettings* pAdvSettings = NULL;
|
|
HRESULT hr = _pTsClient->get_AdvancedSettings2(&pAdvSettings);
|
|
|
|
VARIANT_BOOL fSmartSizing;
|
|
if (SUCCEEDED(hr)) {
|
|
hr = pAdvSettings->get_SmartSizing(&fSmartSizing);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
fSmartSizing = !fSmartSizing;
|
|
hr = pAdvSettings->put_SmartSizing(fSmartSizing);
|
|
}
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
#ifndef OS_WINCE // no menus available
|
|
CheckMenuItem(_hSystemMenu,
|
|
UI_IDM_SMARTSIZING,
|
|
fSmartSizing ? MF_CHECKED : MF_UNCHECKED);
|
|
#endif
|
|
|
|
_pTscSet->SetSmartSizing(fSmartSizing);
|
|
}
|
|
|
|
|
|
if (pAdvSettings != NULL) {
|
|
pAdvSettings->Release();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
#endif // SMART_SIZING
|
|
|
|
#endif //DC_DEBUG
|
|
|
|
default:
|
|
{
|
|
DefWindowProc(GetHwnd(), uMsg, wParam, lParam);
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
#ifndef OS_WINCE
|
|
LRESULT CContainerWnd::OnInitMenu(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
|
|
::EnableMenuItem((HMENU)wParam, SC_MOVE ,
|
|
_bContainerIsFullScreen ? MF_GRAYED : MF_ENABLED);
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnGetMinMaxInfo");
|
|
|
|
LPMINMAXINFO pinfo = (LPMINMAXINFO)lParam;
|
|
DCSIZE maxTrack;
|
|
|
|
RECT rc;
|
|
GetClientRect( GetHwnd(), &rc);
|
|
CalcTrackingMaxWindowSize( rc.right - rc.left,
|
|
rc.bottom - rc.top,
|
|
&maxTrack.width,
|
|
&maxTrack.height );
|
|
|
|
pinfo->ptMaxTrackSize.x = maxTrack.width;
|
|
pinfo->ptMaxTrackSize.y = maxTrack.height;
|
|
|
|
DC_END_FN();
|
|
|
|
return 0;
|
|
}
|
|
#endif //OS_WINCE
|
|
|
|
LRESULT CContainerWnd::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(wParam);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
DC_BEGIN_FN("OnSetFocus");
|
|
|
|
//
|
|
// Give focus to the control when we get activated
|
|
// Except when we are in a size/move modal loop
|
|
//
|
|
if (IsOkToToggleFocus() && !_fInSizeMove)
|
|
{
|
|
TRC_NRM((TB,_T("Passing focus to control")));
|
|
::SetFocus(_pWndView->GetHwnd());
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(uMsg);
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
DC_BEGIN_FN("OnActivate");
|
|
|
|
if (WA_INACTIVE != wParam)
|
|
{
|
|
//Give focus to the control when we get activated
|
|
if (IsOkToToggleFocus() && !_fInSizeMove)
|
|
{
|
|
TRC_NRM((TB,_T("Passing focus to control")));
|
|
::SetFocus(_pWndView->GetHwnd());
|
|
}
|
|
}
|
|
#ifdef OS_WINCE
|
|
AutoHideCE(_pWndView->GetHwnd(), wParam);
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnWindowPosChanging");
|
|
|
|
#ifndef OS_WINCE
|
|
LPWINDOWPOS lpwp;
|
|
DCUINT maxWidth;
|
|
DCUINT maxHeight;
|
|
DCUINT cliWidth, cliHeight;
|
|
|
|
if (_bContainerIsFullScreen)
|
|
{
|
|
TRC_DBG((TB, _T("WM_WINDOWPOSCHANGING; no-op when fullscreen")));
|
|
DC_QUIT;
|
|
}
|
|
|
|
|
|
lpwp = (LPWINDOWPOS)lParam;
|
|
|
|
if (lpwp->flags & SWP_NOSIZE)
|
|
{
|
|
//
|
|
// We're not sizing so we don't care.
|
|
//
|
|
TRC_DBG((TB, _T("WM_WINDOWPOSCHANGING, but no sizing")));
|
|
DC_QUIT;
|
|
}
|
|
|
|
TRC_DBG((TB, _T("WM_WINDOWPOSCHANGING, new size %dx%d"),
|
|
lpwp->cx, lpwp->cy));
|
|
|
|
//
|
|
// Max size of the window changes depending on w/not scroll bars are
|
|
// visible. The control has properties for scroll bar visibility but
|
|
// we can't use these because the control is a child window so there is
|
|
// no guarantee that it has update it's scroll bar visilibity in response
|
|
// to this message yet.
|
|
// which means there could be a moment where a gray border appears around the
|
|
// client container window.
|
|
// instead we just compute if scroll bars would be visible in the core.
|
|
//
|
|
|
|
cliWidth = lpwp->cx;
|
|
cliHeight = lpwp->cy;
|
|
|
|
CalcTrackingMaxWindowSize( cliWidth, cliHeight, &maxWidth, &maxHeight);
|
|
|
|
//
|
|
// Restrict size of window
|
|
//
|
|
if ((DCUINT)lpwp->cx > maxWidth)
|
|
{
|
|
RECT rect;
|
|
|
|
//
|
|
// Clip the width - reset SWP_NOSIZE as a size change is
|
|
// required.
|
|
//
|
|
TRC_NRM((TB, _T("Clip cx from %u to %u"), lpwp->cx, maxWidth));
|
|
lpwp->cx = maxWidth;
|
|
lpwp->flags &= ~SWP_NOSIZE;
|
|
|
|
GetWindowRect(GetHwnd(), &rect);
|
|
|
|
if (lpwp->x < rect.left)
|
|
{
|
|
//
|
|
// If dragging left then we need to stop at the point
|
|
// where the window is maxWidth wide. Reset SWP_NOMOVE
|
|
// as a move is required.
|
|
//
|
|
TRC_NRM((TB, _T("Reset x from %d to %d"),
|
|
lpwp->x, rect.right-maxWidth));
|
|
lpwp->x = rect.right - maxWidth;
|
|
lpwp->flags &= ~SWP_NOMOVE;
|
|
}
|
|
}
|
|
|
|
if ((DCUINT)lpwp->cy > maxHeight)
|
|
{
|
|
RECT rect;
|
|
|
|
//
|
|
// Clip the height - reset SWP_NOSIZE as a size change is
|
|
// required.
|
|
//
|
|
TRC_NRM((TB, _T("Clip cy from %u to %u"), lpwp->cy, maxHeight));
|
|
lpwp->cy = maxHeight;
|
|
lpwp->flags &= ~SWP_NOSIZE;
|
|
|
|
GetWindowRect( GetHwnd(),&rect);
|
|
|
|
if (lpwp->y < rect.top)
|
|
{
|
|
//
|
|
// If dragging upward then we need to stop at the point
|
|
// where the window is maxHeight high. Reset SWP_NOMOVE
|
|
// as a move is required.
|
|
//
|
|
TRC_NRM((TB, _T("Reset y from %d to %d"),
|
|
lpwp->y, rect.bottom-maxHeight));
|
|
lpwp->y = rect.bottom - maxHeight;
|
|
lpwp->flags &= ~SWP_NOMOVE;
|
|
}
|
|
}
|
|
#endif //OS_WINCE
|
|
|
|
DC_EXIT_POINT:
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
DCVOID CContainerWnd::OnConnected()
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
BOOL fFullScreen = FALSE;
|
|
VARIANT_BOOL vbfFScreen = VARIANT_FALSE;
|
|
|
|
DC_BEGIN_FN("OnConnected");
|
|
|
|
EnterEventHandler();
|
|
|
|
//Signal that we've connected at least once
|
|
_fHaveConnected = TRUE;
|
|
|
|
SET_CONTWND_STATE(stateConnected);
|
|
|
|
_successConnectCount++;
|
|
SetConnectionSuccessFlag();
|
|
|
|
//
|
|
/// Make sure the 'connecting...' dialog is gone.
|
|
//
|
|
if (!IsUsingDialogUI() && ::IsWindow(_hwndStatusDialog))
|
|
{
|
|
PostMessage( _hwndStatusDialog, WM_CLOSE, __LINE__, 0xBEEBBAAB);
|
|
}
|
|
if (::IsWindow(_hwndMainDialog))
|
|
{
|
|
//
|
|
//Inform the dialog that connection has happened
|
|
//
|
|
PostMessage(_hwndMainDialog, WM_TSC_CONNECTED, 0, 0);
|
|
ShowWindow( _hwndMainDialog, SW_HIDE);
|
|
}
|
|
|
|
TCHAR fullFrameTitleStr[SH_FRAME_TITLE_RESOURCE_MAX_LENGTH +
|
|
SH_REGSESSION_MAX_LENGTH];
|
|
|
|
TCHAR frameTitleString[SH_FRAME_TITLE_RESOURCE_MAX_LENGTH];
|
|
|
|
//
|
|
// Set the window title.
|
|
// include the session name (unless we're on the default file)
|
|
//
|
|
if (_tcscmp(_szPathToDefaultFile,
|
|
_pTscSet->GetFileName()))
|
|
{
|
|
if (LoadString( _hInst,
|
|
UI_IDS_FRAME_TITLE_CONNECTED,
|
|
frameTitleString,
|
|
SH_FRAME_TITLE_RESOURCE_MAX_LENGTH ))
|
|
{
|
|
TCHAR szSessionName[MAX_PATH];
|
|
if (!_pSh->GetRegSessionSpecified())
|
|
{
|
|
//
|
|
// Session name is parsed from the current
|
|
// connection file.
|
|
//
|
|
CSH::SH_GetNameFromPath(_pTscSet->GetFileName(),
|
|
szSessionName,
|
|
SIZECHAR(szSessionName));
|
|
}
|
|
else
|
|
{
|
|
_tcsncpy(szSessionName, _pSh->GetRegSession(),
|
|
SIZECHAR(szSessionName));
|
|
}
|
|
DC_TSPRINTF(fullFrameTitleStr,
|
|
frameTitleString,
|
|
szSessionName,
|
|
_pTscSet->GetFlatConnectString());
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("Failed to find UI frame title")));
|
|
fullFrameTitleStr[0] = (DCTCHAR) 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Title does not include session name
|
|
if (LoadString( _hInst,
|
|
UI_IDS_FRAME_TITLE_CONNECTED_DEFAULT,
|
|
frameTitleString,
|
|
SH_FRAME_TITLE_RESOURCE_MAX_LENGTH ))
|
|
{
|
|
DC_TSPRINTF(fullFrameTitleStr,
|
|
frameTitleString,
|
|
_pTscSet->GetFlatConnectString());
|
|
}
|
|
else
|
|
{
|
|
TRC_ERR((TB,_T("Failed to find UI frame title")));
|
|
fullFrameTitleStr[0] = (DCTCHAR) 0;
|
|
}
|
|
}
|
|
|
|
SetWindowText( GetHwnd(), fullFrameTitleStr);
|
|
|
|
//
|
|
// Inform the control of the window title (used when it goes fullscreen)
|
|
//
|
|
|
|
OLECHAR* poleTitle = T2OLE(fullFrameTitleStr);
|
|
TRC_ASSERT( poleTitle, (TB, _T("T2OLE failed on poleTitle\n")));
|
|
if (poleTitle)
|
|
{
|
|
hr = _pTsClient->put_FullScreenTitle( poleTitle);
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ABORT((TB,_T("put_FullScreenTitle failed\n")));
|
|
}
|
|
}
|
|
|
|
hr = _pTsClient->get_FullScreen( &vbfFScreen);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
fFullScreen = (vbfFScreen != VARIANT_FALSE);
|
|
}
|
|
else
|
|
{
|
|
TRC_ABORT((TB,_T("get_FullScreen failed\n")));
|
|
}
|
|
|
|
PWINDOWPLACEMENT pwndplc = _pTscSet->GetWindowPlacement();
|
|
if (pwndplc)
|
|
{
|
|
#ifndef OS_WINCE
|
|
EnsureWindowIsCompletelyOnScreen( &pwndplc->rcNormalPosition );
|
|
|
|
TRC_ASSERT(pwndplc->rcNormalPosition.right -
|
|
pwndplc->rcNormalPosition.left,
|
|
(TB,_T("0 width")));
|
|
|
|
TRC_ASSERT(pwndplc->rcNormalPosition.bottom -
|
|
pwndplc->rcNormalPosition.top,
|
|
(TB,_T("0 height")));
|
|
#endif
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
if (!fFullScreen)
|
|
{
|
|
if (!SetWindowPlacement( GetHwnd(), pwndplc))
|
|
{
|
|
TRC_ABORT((TB,_T("Failed to set window placement")));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef OS_WINCE
|
|
WINDOWPLACEMENT* pWndPlc = _pTscSet->GetWindowPlacement();
|
|
INT defaultShowWindowFlag = SW_SHOWNORMAL;
|
|
if(1 == _successConnectCount)
|
|
{
|
|
//On first connection, override the
|
|
//window placement with startup info (if specified)
|
|
|
|
//Use the 'A' version to avoid wrapping
|
|
//we only care about numeric fields anyway
|
|
STARTUPINFOA si;
|
|
GetStartupInfoA(&si);
|
|
if((si.dwFlags & STARTF_USESHOWWINDOW) &&
|
|
si.wShowWindow != SW_SHOWNORMAL)
|
|
{
|
|
defaultShowWindowFlag = si.wShowWindow;
|
|
}
|
|
}
|
|
if (pWndPlc)
|
|
{
|
|
if(SW_SHOWNORMAL != defaultShowWindowFlag)
|
|
{
|
|
pWndPlc->showCmd = defaultShowWindowFlag;
|
|
}
|
|
|
|
ShowWindow( GetHwnd(), pWndPlc->showCmd);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow( GetHwnd(), defaultShowWindowFlag);
|
|
}
|
|
#else //OS_WINCE
|
|
ShowWindow( GetHwnd(), SW_SHOWNORMAL);
|
|
#endif //OS_WINCE
|
|
|
|
_fClientWindowIsUp = TRUE;
|
|
|
|
LeaveEventHandler();
|
|
DC_END_FN();
|
|
}
|
|
|
|
DCVOID CContainerWnd::OnLoginComplete()
|
|
{
|
|
DC_BEGIN_FN("OnLoginComplete");
|
|
|
|
EnterEventHandler();
|
|
|
|
_fLoginComplete = TRUE;
|
|
|
|
LeaveEventHandler();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
DCVOID CContainerWnd::OnDisconnected(DCUINT discReason)
|
|
{
|
|
DC_BEGIN_FN("OnDisconnected");
|
|
|
|
#ifndef OS_WINCE
|
|
HRESULT hr;
|
|
#endif
|
|
UINT mainDiscReason;
|
|
ExtendedDisconnectReasonCode extendedDiscReason;
|
|
|
|
EnterEventHandler();
|
|
|
|
if(FAILED(_pTsClient->get_ExtendedDisconnectReason(&extendedDiscReason)))
|
|
{
|
|
extendedDiscReason = exDiscReasonNoInfo;
|
|
}
|
|
|
|
//
|
|
// We just got disconnected as part of the connection
|
|
//
|
|
SET_CONTWND_STATE(stateNotConnected);
|
|
|
|
|
|
//
|
|
// Once we've been disconnected can go through
|
|
// close again
|
|
//
|
|
_fPreventClose = FALSE;
|
|
|
|
//
|
|
// Make sure the 'connecting...' dialog is gone.
|
|
//
|
|
if (!IsUsingDialogUI() && ::IsWindow(_hwndStatusDialog))
|
|
{
|
|
::PostMessage(_hwndStatusDialog, WM_CLOSE, 0, 0);
|
|
}
|
|
|
|
if (IsUsingDialogUI() && ::IsWindow(_hwndMainDialog))
|
|
{
|
|
//Inform dialog of disconnection
|
|
PostMessage(_hwndMainDialog, WM_TSC_DISCONNECTED, 0, 0);
|
|
}
|
|
|
|
//
|
|
// If this is a user-initiated disconnect, don't do a popup.
|
|
//
|
|
mainDiscReason = NL_GET_MAIN_REASON_CODE(discReason);
|
|
if (((discReason != UI_MAKE_DISCONNECT_ERR(UI_ERR_NORMAL_DISCONNECT)) &&
|
|
(mainDiscReason != NL_DISCONNECT_REMOTE_BY_USER) &&
|
|
(mainDiscReason != NL_DISCONNECT_LOCAL)) ||
|
|
(exDiscReasonReplacedByOtherConnection == extendedDiscReason))
|
|
{
|
|
TRC_ERR((TB, _T("Unexpected disconnect - inform user")));
|
|
|
|
//Normal disconnect dialog displayed
|
|
if (!_fClientWindowIsUp && ::IsWindow(_hwndMainDialog))
|
|
{
|
|
// If the connection dialog is around, we need to get that to
|
|
// display the error popup, otherwise the popup won't be modal
|
|
// and could get left lying around. That can cause state
|
|
// problems with the client.
|
|
//
|
|
// It would be nice to use SendMessage here, so that we always
|
|
// block at this point when displaying the dialog. However,
|
|
// using SendMessage results in a disconnect dialog that is not
|
|
// modal with respect to the connect dialog.
|
|
//
|
|
// However, because PostMessage is asynchronous, the dialog box
|
|
// procedure calls back into CContainerWnd to finish the disconnection
|
|
// process.
|
|
TRC_NRM((TB, _T("Connection dialog present - use it to show popup")));
|
|
::PostMessage(_hwndMainDialog, UI_SHOW_DISC_ERR_DLG,
|
|
discReason,
|
|
(LPARAM)extendedDiscReason);
|
|
}
|
|
else
|
|
{
|
|
TRC_NRM((TB, _T("Connection dialog not present - do popup here")));
|
|
CDisconnectedDlg disconDlg(GetHwnd(), _hInst, this);
|
|
disconDlg.SetDisconnectReason( discReason);
|
|
disconDlg.SetExtendedDiscReason( extendedDiscReason);
|
|
disconDlg.DoModal();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Pickup settings that the server may have updated
|
|
//
|
|
HRESULT hr = _pTscSet->GetUpdatesFromControl(_pTsClient);
|
|
if (FAILED(hr))
|
|
{
|
|
TRC_ERR((TB,_T("GetUpdatesFromControl failed")));
|
|
}
|
|
|
|
if( GetConnectionSuccessFlag() )
|
|
{
|
|
//
|
|
// Update the MRU list if we just
|
|
// disconnected from a successful connect
|
|
//
|
|
_pTscSet->UpdateRegMRU((LPTSTR)_pTscSet->GetFlatConnectString());
|
|
}
|
|
|
|
if (::IsWindow(_hwndMainDialog))
|
|
{
|
|
::SendMessage( _hwndMainDialog, WM_UPDATEFROMSETTINGS,0,0);
|
|
}
|
|
|
|
//
|
|
// If login has completed then we should exit the app on
|
|
// disconnection.
|
|
//
|
|
FinishDisconnect(_fLoginComplete);
|
|
}
|
|
|
|
_fClientWindowIsUp = FALSE;
|
|
|
|
LeaveEventHandler();
|
|
DC_END_FN();
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnClose");
|
|
|
|
HRESULT hr;
|
|
BOOL fShouldClose = FALSE;
|
|
|
|
//Don't allow more than one close
|
|
//This mainly fixes problem in stress where
|
|
//we get posted more than one close message
|
|
if (_fPreventClose)
|
|
{
|
|
fShouldClose = FALSE;
|
|
TRC_ERR((TB,_T("More than one WM_CLOSE msg was received!!!")));
|
|
return 0;
|
|
}
|
|
_fPreventClose = TRUE;
|
|
|
|
if (InControlEventHandler())
|
|
{
|
|
//
|
|
// Don't allow the close we are in a code path that fired
|
|
// from the control. Without this, we sometimes see the client
|
|
// receiving close notifications from tclient while a disconnected
|
|
// dialog is up (i.e in an OnDicsconnected handler) - destroying
|
|
// the control at this time causes bad things to happen during
|
|
// the return into the control (which has now been deleted).
|
|
//
|
|
TRC_ERR((TB,_T("OnClose called during a control event handler")));
|
|
fShouldClose = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
if (_fInOnCloseHandler)
|
|
{
|
|
//
|
|
// STRESS fix:
|
|
// Don't allow nested Closes
|
|
// can happen if the main window receives a WM_CLOSE
|
|
// message while a dialog is up... Somehow the stress dll
|
|
// sends us repeated WM_CLOSE
|
|
//
|
|
//
|
|
TRC_ERR((TB,_T("Nested OnClose detected, bailing out")));
|
|
fShouldClose = FALSE;
|
|
return 0;
|
|
}
|
|
_fInOnCloseHandler = TRUE;
|
|
|
|
if (_pTsClient)
|
|
{
|
|
ControlCloseStatus ccs;
|
|
hr = _pTsClient->RequestClose( &ccs );
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if (controlCloseCanProceed == ccs)
|
|
{
|
|
//Immediate close
|
|
fShouldClose = TRUE;
|
|
}
|
|
else if (controlCloseWaitForEvents == ccs)
|
|
{
|
|
// Wait for events from control
|
|
// e.g ConfirmClose
|
|
fShouldClose = FALSE;
|
|
_fClosePending = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Allow close to prevent hang if client load failed
|
|
//
|
|
TRC_ERR((TB,_T("No _pTsClient loaded, allow close anyway")));
|
|
fShouldClose = TRUE;
|
|
}
|
|
|
|
if (fShouldClose)
|
|
{
|
|
//
|
|
// Only save out MRU if last connection
|
|
// was successful
|
|
//
|
|
if (GetConnectionSuccessFlag())
|
|
{
|
|
DCBOOL bRet = _pTscSet->SaveRegSettings();
|
|
TRC_ASSERT(bRet, (TB, _T("SaveRegSettings\n")));
|
|
}
|
|
//Proceed with the close.
|
|
return DefWindowProc( GetHwnd(), uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
_fInOnCloseHandler = FALSE;
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// This handles the tail end of the disconnection.
|
|
// it may be called back from the Disconnecting dialog box
|
|
//
|
|
// Params:
|
|
// fExit - If true exit the app otherwise go back
|
|
// to the connection UI
|
|
//
|
|
DCBOOL CContainerWnd::FinishDisconnect(BOOL fExit)
|
|
{
|
|
DC_BEGIN_FN("FinishDisconnect");
|
|
|
|
//
|
|
// Hide the main window, do this twice because the first ShowWindow
|
|
// may be ignored if the window is maximized
|
|
//
|
|
if (GetHwnd())
|
|
{
|
|
ShowWindow( GetHwnd(),SW_HIDE);
|
|
ShowWindow( GetHwnd(),SW_HIDE);
|
|
}
|
|
|
|
//
|
|
// Just exit if:
|
|
// 1) we autoconnected
|
|
// or
|
|
// 2) A close is pending e.g we got disconnected
|
|
// because the user hit the close button
|
|
// or
|
|
// 3) The caller has determined that the client should exit
|
|
//
|
|
if (_pSh->GetAutoConnect() || _fClosePending || fExit)
|
|
{
|
|
PostMessage( GetHwnd(),WM_CLOSE, __LINE__, 0xBEEBBEEB);
|
|
}
|
|
else if (::IsWindow(_hwndMainDialog))
|
|
{
|
|
//
|
|
// Bring up the connect dialog for
|
|
// the next connections
|
|
//
|
|
::ShowWindow( _hwndMainDialog, SW_SHOWNORMAL);
|
|
SetForegroundWindow(_hwndMainDialog);
|
|
|
|
//
|
|
// Trigger an update
|
|
//
|
|
InvalidateRect(_hwndMainDialog, NULL, TRUE);
|
|
UpdateWindow(_hwndMainDialog);
|
|
|
|
SendMessage(_hwndMainDialog, WM_TSC_RETURNTOCONUI,
|
|
0L, 0L);
|
|
}
|
|
else
|
|
{
|
|
//If we get here it means we didn't autoconnect
|
|
//i.e we started with the connect UI, but somehow the
|
|
//connect UI has now disappeared
|
|
TRC_ABORT((TB,_T("Connect dialog is gone")));
|
|
}
|
|
|
|
DC_END_FN();
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Handle event from control requesting
|
|
// we go fullscreen
|
|
//
|
|
//
|
|
DCVOID CContainerWnd::OnEnterFullScreen()
|
|
{
|
|
DCUINT32 style;
|
|
LONG wID;
|
|
WINDOWPLACEMENT* pWindowPlacement = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
// multi-monitor support
|
|
RECT screenRect;
|
|
|
|
DC_BEGIN_FN("OnEnterFullScreen");
|
|
|
|
//
|
|
//Go full screen
|
|
//
|
|
|
|
EnterEventHandler();
|
|
|
|
//Save setting for next connection
|
|
_pTscSet->SetStartFullScreen(TRUE);
|
|
|
|
if (_bContainerIsFullScreen)
|
|
{
|
|
//Nothing to do
|
|
DC_QUIT;
|
|
}
|
|
#ifndef OS_WINCE
|
|
::LockWindowUpdate(GetHwnd());
|
|
#endif
|
|
_bContainerIsFullScreen = TRUE;
|
|
|
|
#if !defined(OS_WINCE)
|
|
if (_hSystemMenu)
|
|
{
|
|
//
|
|
// We need to show the system menu so that the ts icon
|
|
// appears in the taskbar. But we need MOVE to be disabled
|
|
// when fullscreen
|
|
//
|
|
//EnableMenuItem(_hSystemMenu, SC_MOVE, MF_GRAYED);
|
|
}
|
|
#endif
|
|
|
|
#ifndef OS_WINCE
|
|
pWindowPlacement = _pTscSet->GetWindowPlacement();
|
|
TRC_ASSERT(pWindowPlacement, (TB, _T("pWindowPlacement is NULL\n")));
|
|
|
|
//
|
|
// Store the current window state (only if the client window is up)
|
|
//
|
|
if (pWindowPlacement && _fClientWindowIsUp)
|
|
{
|
|
GetWindowPlacement(GetHwnd(), pWindowPlacement);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Take away the title bar and borders
|
|
//
|
|
style = GetWindowLong( GetHwnd(),GWL_STYLE );
|
|
|
|
#if !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
style &= ~(WS_DLGFRAME |
|
|
WS_THICKFRAME | WS_BORDER |
|
|
WS_MAXIMIZEBOX);
|
|
|
|
#else // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
style &= ~(WS_DLGFRAME | WS_SYSMENU | WS_BORDER);
|
|
#endif // !defined(OS_WINCE) || defined(OS_WINCE_NONFULLSCREEN)
|
|
SetWindowLong( GetHwnd(),GWL_STYLE, style );
|
|
|
|
//
|
|
// Set the window ID (to remove the menu titles).
|
|
//
|
|
wID = SetWindowLong( GetHwnd(),GWL_ID, 0 );
|
|
|
|
//
|
|
// Note that two calls to SetWindowPos are required here in order to
|
|
// adjust the position to allow for frame removal and also to correctly
|
|
// set the Z-ordering.
|
|
//
|
|
|
|
// default screen size
|
|
CSH::MonitorRectFromNearestRect(
|
|
&pWindowPlacement->rcNormalPosition, &screenRect );
|
|
|
|
//
|
|
// Reposition and size the window with the frame changes, and place at
|
|
// the top of the Z-order (by not setting SWP_NOOWNERZORDER or
|
|
// SWP_NOZORDER and specifying HWND_TOP).
|
|
//
|
|
SetWindowPos( GetHwnd(),
|
|
HWND_TOP,
|
|
screenRect.left, screenRect.top,
|
|
screenRect.right - screenRect.left,
|
|
screenRect.bottom - screenRect.top,
|
|
SWP_NOACTIVATE | SWP_FRAMECHANGED );
|
|
|
|
//
|
|
// Reposition the window again - otherwise the fullscreen window is
|
|
// positioned as if it still had borders.
|
|
//
|
|
SetWindowPos( GetHwnd(),
|
|
NULL,
|
|
screenRect.left, screenRect.top,
|
|
0, 0,
|
|
SWP_NOZORDER | SWP_NOACTIVATE |
|
|
SWP_NOOWNERZORDER | SWP_NOSIZE );
|
|
|
|
#ifndef OS_WINCE
|
|
::LockWindowUpdate(NULL);
|
|
//Notify the shell that we've gone fullscreen
|
|
CUT::NotifyShellOfFullScreen( GetHwnd(),
|
|
TRUE,
|
|
&_pTaskBarList2,
|
|
&_fQueriedForTaskBarList2 );
|
|
#endif //OS_WINCE
|
|
|
|
DC_EXIT_POINT:
|
|
|
|
LeaveEventHandler();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
DCVOID CContainerWnd::OnLeaveFullScreen()
|
|
{
|
|
DC_BEGIN_FN("OnLeaveFullScreen");
|
|
|
|
#ifndef OS_WINCE
|
|
DCUINT32 style;
|
|
RECT rect;
|
|
DCUINT width;
|
|
DCUINT height;
|
|
WINDOWPLACEMENT* pWindowPlacement = NULL;
|
|
|
|
TRC_NRM((TB, _T("Entering Windowed Mode")));
|
|
|
|
EnterEventHandler();
|
|
|
|
//Save setting for next connection
|
|
_pTscSet->SetStartFullScreen(FALSE);
|
|
|
|
if (!_bContainerIsFullScreen)
|
|
{
|
|
//Nothing to do
|
|
DC_QUIT;
|
|
}
|
|
::LockWindowUpdate(GetHwnd());
|
|
_bContainerIsFullScreen = FALSE;
|
|
RecalcMaxWindowSize();
|
|
|
|
//
|
|
// Check that the saved window placement values aren't too big for the
|
|
// client size we're using, and set the window placement accordingly.
|
|
//
|
|
pWindowPlacement = _pTscSet->GetWindowPlacement();
|
|
TRC_ASSERT(pWindowPlacement, (TB, _T("pWindowPlacement is NULL\n")));
|
|
if (!pWindowPlacement)
|
|
{
|
|
DC_QUIT;
|
|
}
|
|
|
|
width = pWindowPlacement->rcNormalPosition.right -
|
|
pWindowPlacement->rcNormalPosition.left;
|
|
height = pWindowPlacement->rcNormalPosition.bottom -
|
|
pWindowPlacement->rcNormalPosition.top;
|
|
if (width > _maxMainWindowSize.width)
|
|
{
|
|
pWindowPlacement->rcNormalPosition.right =
|
|
pWindowPlacement->rcNormalPosition.left +
|
|
_maxMainWindowSize.width;
|
|
}
|
|
if (height > _maxMainWindowSize.height)
|
|
{
|
|
pWindowPlacement->rcNormalPosition.bottom =
|
|
pWindowPlacement->rcNormalPosition.top +
|
|
_maxMainWindowSize.height;
|
|
}
|
|
|
|
if (!::SetWindowPlacement( GetHwnd(), pWindowPlacement))
|
|
{
|
|
TRC_ABORT((TB,_T("Failed to set window placement")));
|
|
}
|
|
|
|
//
|
|
// In case the window is maximised make sure it knows what size to be
|
|
//
|
|
GetWindowRect( GetHwnd(),&rect);
|
|
|
|
//
|
|
// Reset the style
|
|
//
|
|
style = GetWindowLong( GetHwnd(),GWL_STYLE );
|
|
|
|
style |= (WS_DLGFRAME |
|
|
WS_THICKFRAME | WS_BORDER |
|
|
WS_MAXIMIZEBOX);
|
|
|
|
SetWindowLong( GetHwnd(),GWL_STYLE,
|
|
style );
|
|
|
|
#if !defined(OS_WINCE)
|
|
if (_hSystemMenu)
|
|
{
|
|
//
|
|
// We need to show the system menu so that the ts icon
|
|
// appears in the taskbar. But we need MOVE to be disabled
|
|
// when fullscreen
|
|
//
|
|
//EnableMenuItem(_hSystemMenu, SC_MOVE, MF_ENABLED);
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// Tell the window frame to recalculate its size.
|
|
// Position below any topmost windows (but above any non-topmost
|
|
// windows.
|
|
//
|
|
SetWindowPos( GetHwnd(),
|
|
HWND_NOTOPMOST,
|
|
0, 0,
|
|
rect.right - rect.left,
|
|
rect.bottom - rect.top,
|
|
SWP_NOMOVE | SWP_NOACTIVATE | SWP_FRAMECHANGED );
|
|
|
|
//
|
|
// If we are in res match mode
|
|
// then after a leave full screen
|
|
// restore the window so the next state
|
|
// is 'maximize' i.e get back in fullscreen
|
|
//
|
|
if(IsRemoteResMatchMonitorSize())
|
|
{
|
|
ShowWindow( GetHwnd(), SW_SHOWNORMAL);
|
|
}
|
|
|
|
::LockWindowUpdate(NULL);
|
|
// Notify shell that we've left fullscreen
|
|
//Notify the shell that we've gone fullscreen
|
|
CUT::NotifyShellOfFullScreen( GetHwnd(),
|
|
FALSE,
|
|
&_pTaskBarList2,
|
|
&_fQueriedForTaskBarList2 );
|
|
|
|
DC_EXIT_POINT:
|
|
LeaveEventHandler();
|
|
#else //OS_WINCE
|
|
TRC_ABORT((TB,_T("clshell can't leave fullscreen in CE")));
|
|
#endif
|
|
|
|
DC_END_FN();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Notify the server a device change, either a new device comes online
|
|
// or an existing redirected device goes away
|
|
//
|
|
LRESULT CContainerWnd::OnDeviceChange(HWND hWnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
HRESULT hr;
|
|
IMsRdpClientNonScriptable *pNonScriptable;
|
|
UNREFERENCED_PARAMETER(hWnd);
|
|
|
|
DC_BEGIN_FN("OnDeviceChange");
|
|
|
|
if(_pTsClient)
|
|
{
|
|
hr = _pTsClient->QueryInterface(IID_IMsRdpClientNonScriptable,
|
|
(PVOID *)&pNonScriptable);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
pNonScriptable->NotifyRedirectDeviceChange(wParam, lParam);
|
|
pNonScriptable->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TRC_NRM((TB,_T("Got OnDeviceChange but _pTsClient not available")));
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Invoked to handle WM_HELP (i.e F1 key)
|
|
//
|
|
LRESULT CContainerWnd::OnHelp(HWND hWnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnHelp");
|
|
|
|
//
|
|
// Don't pop help if we are connected
|
|
// as the F1 should then go to the session. Otherwise
|
|
// you get both local and remote help. Note the user can
|
|
// still launch help while connected but they need to
|
|
// select it from the system menu.
|
|
//
|
|
if (GetHwnd() && _pSh && !IsConnected())
|
|
{
|
|
_pSh->SH_DisplayClientHelp(
|
|
GetHwnd(),
|
|
HH_DISPLAY_TOPIC);
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0L;
|
|
}
|
|
|
|
//
|
|
// Forward the palette change to the control
|
|
//
|
|
LRESULT CContainerWnd::OnPaletteChange(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnPaletteChange");
|
|
|
|
if (_pWndView) {
|
|
|
|
HWND hwndCtl = _pWndView->GetHwnd();
|
|
return SendMessage(hwndCtl, uMsg, wParam, lParam);
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Give focus back to the control
|
|
// when the system menu is dismissed
|
|
//
|
|
LRESULT CContainerWnd::OnExitMenuLoop(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnExitMenuLoop");
|
|
|
|
//Give focus to the control when we get activated
|
|
if (IsOkToToggleFocus())
|
|
{
|
|
TRC_NRM((TB,_T("Setting focus to control")));
|
|
::SetFocus(_pWndView->GetHwnd());
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnCaptureChanged(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnCaptureChanged");
|
|
|
|
//
|
|
// We don't always get WM_EXITSIZE move but we seem
|
|
// to always get WM_CAPTURECHANGED so go on that
|
|
//
|
|
if (_fInSizeMove)
|
|
{
|
|
TRC_NRM((TB, _T("Capture Changed when in Size/Move")));
|
|
_fInSizeMove = FALSE;
|
|
|
|
if (IsOkToToggleFocus())
|
|
{
|
|
TRC_NRM((TB,_T("Setting focus to control")));
|
|
::SetFocus(_pWndView->GetHwnd());
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnEnterSizeMove(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnEnterSizeMove");
|
|
|
|
//
|
|
// We're entering the modal size/move loop
|
|
// need to give the focus back to the frame window
|
|
// otherwise win9x will not move the window because
|
|
// the IH is on another thread and the modal loop on 9x
|
|
// will never see the arrow keystrokes
|
|
//
|
|
_fInSizeMove = TRUE;
|
|
|
|
//
|
|
// Note: Only do this toggle on 9x as that is
|
|
// where it is needed. NT can handle the async modal
|
|
// size/move loop and so there is no problem with ALT-SPACE.
|
|
//
|
|
// The reason for not doing this toggle on NT is that
|
|
// it causes multiple a flurry of focus gain/loses
|
|
// that rapidly hide/unhide the Cicero language bar.
|
|
//
|
|
if (IsOkToToggleFocus() && _fRunningOnWin9x)
|
|
{
|
|
TRC_NRM((TB,_T("Setting focus to frame")));
|
|
::SetFocus(GetHwnd());
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CContainerWnd::OnExitSizeMove(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnExitSizeMove");
|
|
|
|
_fInSizeMove = FALSE;
|
|
|
|
//
|
|
// Note: Only do this toggle on 9x as that is
|
|
// where it is needed. NT can handle the async modal
|
|
// size/move loop and so there is no problem with ALT-SPACE.
|
|
//
|
|
// The reason for not doing this toggle on NT is that
|
|
// it causes multiple a flurry of focus gain/loses
|
|
// that rapidly hide/unhide the Cicero language bar.
|
|
//
|
|
if (IsOkToToggleFocus() && _fRunningOnWin9x)
|
|
{
|
|
TRC_NRM((TB,_T("Setting focus to control")));
|
|
::SetFocus(_pWndView->GetHwnd());
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Handle system color change notifications
|
|
//
|
|
LRESULT CContainerWnd::OnSysColorChange(UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
DC_BEGIN_FN("OnSysColorChange");
|
|
|
|
//
|
|
// Foward the message to the ActiveX control
|
|
//
|
|
|
|
if (_pWndView && _pWndView->GetHwnd())
|
|
{
|
|
return SendMessage(_pWndView->GetHwnd(), uMsg, wParam, lParam);
|
|
}
|
|
|
|
DC_END_FN();
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Predicate that returns true if it's ok to toggle
|
|
// focus between the control and the frame
|
|
//
|
|
BOOL CContainerWnd::IsOkToToggleFocus()
|
|
{
|
|
DC_BEGIN_FN("IsOkToToggleFocus");
|
|
|
|
BOOL fDialogIsUp = ::IsWindow(_hwndMainDialog);
|
|
if (_fClientWindowIsUp &&
|
|
(!fDialogIsUp ||
|
|
(fDialogIsUp && !::IsWindowVisible(_hwndMainDialog))))
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
//
|
|
// Notification from control that a fatal error has occurred
|
|
//
|
|
DCVOID CContainerWnd::OnFatalError(LONG errorCode)
|
|
{
|
|
DC_BEGIN_FN("OnFatalError");
|
|
|
|
EnterEventHandler();
|
|
|
|
DisplayFatalError(GetFatalString(errorCode), errorCode);
|
|
|
|
LeaveEventHandler();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
//
|
|
// Warning notifcation from control
|
|
// e.g if bitmap cache is corrutpted a warning is fired
|
|
// these are non-fatal errors
|
|
//
|
|
DCVOID CContainerWnd::OnWarning(LONG warnCode)
|
|
{
|
|
DC_BEGIN_FN("OnWarning");
|
|
|
|
EnterEventHandler();
|
|
|
|
TRC_ERR((TB, _T("WARNING recevived from core: %d"), warnCode));
|
|
switch (warnCode)
|
|
{
|
|
case DC_WARN_BITMAPCACHE_CORRUPTED:
|
|
{
|
|
//
|
|
// Display the bitmap cache warning dialog
|
|
//
|
|
CCacheWrnDlg bmpCacheWrn(GetHwnd(), _hInst);
|
|
bmpCacheWrn.DoModal();
|
|
}
|
|
break;
|
|
}
|
|
|
|
LeaveEventHandler();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
//Notification from the control
|
|
//of new width/height of the desktop
|
|
//this can change from the requested width/height in the event
|
|
//of a shadow operation
|
|
DCVOID CContainerWnd::OnRemoteDesktopSizeNotify(long width, long height)
|
|
{
|
|
DC_BEGIN_FN("OnRemoteDesktopSizeNotify");
|
|
|
|
EnterEventHandler();
|
|
|
|
TRC_NRM((TB, _T("OnRemoteDesktopSizeNotify: width %d. height %d"), width, height));
|
|
|
|
SetCurrentDesktopWidth(width);
|
|
SetCurrentDesktopHeight(height);
|
|
RecalcMaxWindowSize();
|
|
|
|
//
|
|
//Trigger an update of the window size
|
|
//in response to the shadow
|
|
//but only do this if the client window is up otherwise the following
|
|
//bug can happen:
|
|
// -Launch connection
|
|
// -As part of initial connection but before OnConnected is fired we
|
|
// get a RemoteDesktopSizeNotify. This causes us to update the
|
|
// windowplacement
|
|
// -thrashing user selected options
|
|
//
|
|
if(_fClientWindowIsUp && !_bContainerIsFullScreen)
|
|
{
|
|
SetWindowPos( GetHwnd(),
|
|
NULL,
|
|
0, 0,
|
|
width,
|
|
height,
|
|
SWP_NOZORDER | SWP_NOMOVE |
|
|
SWP_NOACTIVATE | SWP_NOOWNERZORDER );
|
|
}
|
|
|
|
LeaveEventHandler();
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
//
|
|
// Calculate the current maximum tracking
|
|
// size limits for the window's client area given
|
|
// a current client area size (cliWidth, cliHeight).
|
|
//
|
|
// Returns the maxX, maxY values in *pMaxX, *pMaxY
|
|
//
|
|
// The max is not static because we have logic that
|
|
// expands the width/height if only one scroll bar
|
|
// is visible.
|
|
//
|
|
// This value is _not_ the same as the Maximized size
|
|
// of the window
|
|
//
|
|
void CContainerWnd::CalcTrackingMaxWindowSize(UINT /*in*/ cliWidth,
|
|
UINT /*in*/ cliHeight,
|
|
UINT* /*out*/ pMaxWidth,
|
|
UINT* /*out*/ pMaxHeight)
|
|
{
|
|
BOOL fHScroll, fVScroll;
|
|
DC_BEGIN_FN("CalcTrackingMaxWindowSize");
|
|
|
|
//
|
|
// Calculate the neccessity for the scrollbars
|
|
//
|
|
fHScroll = fVScroll = FALSE;
|
|
if ( (cliWidth >= GetCurrentDesktopWidth()) &&
|
|
(cliHeight >= GetCurrentDesktopHeight()) )
|
|
{
|
|
fHScroll = fVScroll = FALSE;
|
|
}
|
|
else if ( (cliWidth < GetCurrentDesktopWidth()) &&
|
|
(cliHeight >=
|
|
(GetCurrentDesktopHeight() + GetSystemMetrics(SM_CYHSCROLL))) )
|
|
{
|
|
fHScroll = TRUE;
|
|
}
|
|
else if ( (cliHeight < GetCurrentDesktopHeight()) &&
|
|
(cliWidth >=
|
|
(GetCurrentDesktopWidth() + GetSystemMetrics(SM_CXVSCROLL))) )
|
|
{
|
|
fVScroll = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fHScroll = fVScroll = TRUE;
|
|
}
|
|
|
|
|
|
*pMaxWidth = _maxMainWindowSize.width;
|
|
*pMaxHeight = _maxMainWindowSize.height;
|
|
|
|
if (fHScroll)
|
|
{
|
|
*pMaxHeight += GetSystemMetrics(SM_CYHSCROLL);
|
|
}
|
|
|
|
if (fVScroll)
|
|
{
|
|
*pMaxWidth += GetSystemMetrics(SM_CXVSCROLL);
|
|
}
|
|
|
|
TRC_NRM((TB,_T("Calculated max width/height - %d,%d"),
|
|
*pMaxWidth, *pMaxHeight));
|
|
DC_END_FN();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Name: GetFatalString
|
|
//
|
|
// Purpose: Return the specified error string
|
|
//
|
|
// Returns: Error string
|
|
//
|
|
// Params: IN errorID - error code
|
|
//
|
|
//
|
|
LPTSTR CContainerWnd::GetFatalString(DCINT errorID)
|
|
{
|
|
DC_BEGIN_FN("GetFatalString");
|
|
DC_IGNORE_PARAMETER(errorID);
|
|
|
|
//
|
|
// Load the fatal error string from resources - this is more specific
|
|
// for a debug build.
|
|
//
|
|
if (LoadString(_hInst,
|
|
#ifdef DC_DEBUG
|
|
UI_ERR_STRING_ID(errorID),
|
|
#else
|
|
UI_FATAL_ERROR_MESSAGE,
|
|
#endif
|
|
_errorString,
|
|
UI_ERR_MAX_STRLEN) == 0)
|
|
{
|
|
TRC_ABORT((TB, _T("Missing resource string (Fatal Error) %d"),
|
|
errorID));
|
|
DC_TSTRCPY(_errorString, _T("Invalid resources"));
|
|
}
|
|
|
|
DC_END_FN();
|
|
return(_errorString);
|
|
} // UI_GetFatalString
|
|
|
|
|
|
//
|
|
// Name: UI_DisplayFatalError
|
|
//
|
|
// Purpose: Display a fatal error popup
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Params: IN errorString - error text
|
|
//
|
|
//
|
|
VOID CContainerWnd::DisplayFatalError(PDCTCHAR errorString, DCINT error)
|
|
{
|
|
DCINT action;
|
|
DCTCHAR titleString[UI_ERR_MAX_STRLEN];
|
|
DCTCHAR fullTitleString[UI_ERR_MAX_STRLEN];
|
|
|
|
DC_BEGIN_FN("UI_DisplayFatalError");
|
|
|
|
//
|
|
// Load the title string from resources.
|
|
//
|
|
if (LoadString(_hInst,
|
|
UI_FATAL_ERR_TITLE_ID,
|
|
titleString,
|
|
UI_ERR_MAX_STRLEN) == 0)
|
|
{
|
|
//
|
|
// Continue to display the error anyway on retail build.
|
|
//
|
|
TRC_ABORT((TB, _T("Missing resource string (Fatal Error title)")));
|
|
DC_TSTRCPY(titleString, _T("Fatal Error"));
|
|
}
|
|
|
|
DC_TSPRINTF(fullTitleString, titleString, error);
|
|
|
|
action = MessageBox( GetHwnd(), errorString,
|
|
fullTitleString,
|
|
#ifdef DC_DEBUG
|
|
MB_ABORTRETRYIGNORE |
|
|
#else
|
|
MB_OK |
|
|
#endif
|
|
MB_ICONSTOP |
|
|
MB_APPLMODAL |
|
|
MB_SETFOREGROUND );
|
|
|
|
TRC_NRM((TB, _T("Action %d selected"), action));
|
|
switch (action)
|
|
{
|
|
case IDOK:
|
|
case IDABORT:
|
|
{
|
|
#ifdef OS_WIN32
|
|
TerminateProcess(GetCurrentProcess(), 0);
|
|
#else //OS_WIN32
|
|
exit(1);
|
|
#endif //OS_WIN32
|
|
}
|
|
break;
|
|
|
|
case IDRETRY:
|
|
{
|
|
DebugBreak();
|
|
}
|
|
break;
|
|
|
|
case IDIGNORE:
|
|
default:
|
|
{
|
|
TRC_ALT((TB, _T("User chose to ignore fatal error!")));
|
|
}
|
|
break;
|
|
}
|
|
|
|
DC_END_FN();
|
|
return;
|
|
} // UI_DisplayFatalError
|
|
|
|
|
|
//
|
|
// Called to flag entry into an event handler
|
|
// Does not need to use InterlockedIncrement
|
|
// only called on the STA thread.
|
|
//
|
|
LONG CContainerWnd::EnterEventHandler()
|
|
{
|
|
return ++_cInEventHandlerCount;
|
|
}
|
|
|
|
//
|
|
// Called to flag leaving an event handler
|
|
// Does not need to use InterlockedIncrement
|
|
// only called on the STA thread.
|
|
//
|
|
LONG CContainerWnd::LeaveEventHandler()
|
|
{
|
|
DC_BEGIN_FN("LeaveEventHandler");
|
|
_cInEventHandlerCount--;
|
|
TRC_ASSERT(_cInEventHandlerCount >= 0,
|
|
(TB,_T("_cInEventHandlerCount went negative %d"),
|
|
_cInEventHandlerCount));
|
|
|
|
DC_END_FN();
|
|
return _cInEventHandlerCount;
|
|
}
|
|
|
|
//
|
|
// Tests if we are in an event handler
|
|
//
|
|
BOOL CContainerWnd::InControlEventHandler()
|
|
{
|
|
return _cInEventHandlerCount;
|
|
}
|
|
|
|
//
|
|
// Return TRUE if we're using the connection UI
|
|
// note that when autoconnecting to a connectoid, we
|
|
// don't use the UI
|
|
//
|
|
BOOL CContainerWnd::IsUsingDialogUI()
|
|
{
|
|
return _hwndMainDialog ? TRUE : FALSE;
|
|
}
|
|
|
|
VOID CContainerWnd::OnRequestMinimize()
|
|
{
|
|
HWND hwnd = GetHwnd();
|
|
if(::IsWindow(hwnd))
|
|
{
|
|
#ifndef OS_WINCE
|
|
//
|
|
// Mimimize the window (don't just use CloseWindow() as
|
|
// that doesn't pass the focus on to the next app
|
|
//
|
|
PostMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0L);
|
|
#else
|
|
ShowWindow(hwnd, SW_MINIMIZE);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//
|
|
// Event handler from control
|
|
// prompt user if they really want to close their session
|
|
//
|
|
//
|
|
HRESULT CContainerWnd::OnConfirmClose(BOOL* pfConfirmClose)
|
|
{
|
|
EnterEventHandler();
|
|
|
|
CShutdownDlg shutdownDlg(GetHwnd(), _hInst, _pSh);
|
|
INT dlgRetVal = shutdownDlg.DoModal();
|
|
|
|
//If the message is not handled then the default proc destroys the window
|
|
if ( IDCANCEL == dlgRetVal )
|
|
{
|
|
*pfConfirmClose = FALSE; //reset this
|
|
_fPreventClose = FALSE;
|
|
_fClosePending = FALSE;
|
|
}
|
|
else
|
|
{
|
|
*pfConfirmClose = TRUE;
|
|
|
|
//
|
|
// Allow close to go thru
|
|
// we will receive an OnDisconnected when it
|
|
// has completed
|
|
//
|
|
}
|
|
|
|
LeaveEventHandler();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Check if the remote desktop size
|
|
// matches the current monitor's size
|
|
// return TRUE on match
|
|
//
|
|
//
|
|
BOOL CContainerWnd::IsRemoteResMatchMonitorSize()
|
|
{
|
|
RECT rc;
|
|
DC_BEGIN_FN("IsRemoteResMatchMonitorSize");
|
|
CSH::MonitorRectFromHwnd(GetHwnd(),&rc);
|
|
|
|
if( (rc.right - rc.left) == (LONG)GetCurrentDesktopWidth() &&
|
|
(rc.bottom - rc.top) == (LONG)GetCurrentDesktopHeight() )
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DC_END_FN();
|
|
}
|
|
|
|
#ifndef OS_WINCE
|
|
BOOL CALLBACK GetDesktopRegionEnumProc (HMONITOR hMonitor, HDC hdcMonitor,
|
|
RECT* prc, LPARAM lpUserData)
|
|
|
|
{
|
|
MONITORINFO monitorInfo;
|
|
|
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
|
if (GetMonitorInfo(hMonitor, &monitorInfo) != 0)
|
|
{
|
|
HRGN hRgnDesktop;
|
|
CRGN rgnMonitorWork(monitorInfo.rcWork);
|
|
|
|
hRgnDesktop = *reinterpret_cast<CRGN*>(lpUserData);
|
|
CombineRgn(hRgnDesktop, hRgnDesktop, rgnMonitorWork, RGN_OR);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
#endif
|
|
|
|
#ifndef OS_WINCE
|
|
//
|
|
// This code shamelessley modified from shell code
|
|
// \shell\browseui\shbrows2.cpp
|
|
//
|
|
// from vtan: This function exists because user32 only determines
|
|
// whether ANY part of the window is visible on the screen. It's possible to
|
|
// place a window without an accessible title. Pretty useless when using the
|
|
// mouse and forces the user to use the VERY un-intuitive alt-space.
|
|
//
|
|
void CContainerWnd::EnsureWindowIsCompletelyOnScreen(RECT *prc)
|
|
{
|
|
HMONITOR hMonitor;
|
|
MONITORINFO monitorInfo;
|
|
|
|
DC_BEGIN_FN("EnsureWindowIsCompletelyOnScreen");
|
|
|
|
// First find the monitor that the window resides on using GDI.
|
|
|
|
hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
|
|
TRC_ASSERT(hMonitor, (TB,_T("hMonitor is null")));
|
|
monitorInfo.cbSize = sizeof(monitorInfo);
|
|
if (GetMonitorInfo(hMonitor, &monitorInfo) != 0)
|
|
{
|
|
LONG lOffsetX, lOffsetY;
|
|
RECT *prcWorkArea, rcIntersect;
|
|
CRGN rgnDesktop, rgnIntersect, rgnWindow;
|
|
|
|
// Because the WINDOWPLACEMENT rcNormalPosition field is in WORKAREA
|
|
// co-ordinates this causes a displacement problem. If the taskbar is
|
|
// at the left or top of the primary monitor the RECT passed even though
|
|
// at (0, 0) may be at (100, 0) on the primary monitor in GDI co-ordinates
|
|
// and GetMonitorInfo() will return a MONITORINFO in GDI co-ordinates.
|
|
// The safest generic algorithm is to offset the WORKAREA RECT into GDI
|
|
// co-ordinates and apply the algorithm in that system. Then offset the
|
|
// WORKAREA RECT back into WORKAREA co-ordinates.
|
|
|
|
prcWorkArea = &monitorInfo.rcWork;
|
|
if (EqualRect(&monitorInfo.rcMonitor, &monitorInfo.rcWork) == 0)
|
|
{
|
|
|
|
// Taskbar is on this monitor - offset required.
|
|
|
|
lOffsetX = prcWorkArea->left - monitorInfo.rcMonitor.left;
|
|
lOffsetY = prcWorkArea->top - monitorInfo.rcMonitor.top;
|
|
}
|
|
else
|
|
{
|
|
|
|
// Taskbar is NOT on this monitor - no offset required.
|
|
|
|
lOffsetX = lOffsetY = 0;
|
|
}
|
|
OffsetRect(prc, lOffsetX, lOffsetY);
|
|
|
|
// WORKAREA RECT is in GDI co-ordinates. Apply the algorithm.
|
|
|
|
// Check to see if this window already fits the current visible screen
|
|
// area. This is a direct region comparison.
|
|
|
|
// This enumeration may cause a performance problem. In the event that
|
|
// a cheap and simple solution is required it would be best to do a
|
|
// RECT intersection with the monitor and the window before resorting
|
|
// to the more expensive region comparison. Get vtan if necessary.
|
|
|
|
EnumDisplayMonitors(NULL, NULL, GetDesktopRegionEnumProc,
|
|
reinterpret_cast<LPARAM>(&rgnDesktop));
|
|
rgnWindow.SetRegion(*prc);
|
|
CombineRgn(rgnIntersect, rgnDesktop, rgnWindow, RGN_AND);
|
|
if (EqualRgn(rgnIntersect, rgnWindow) == 0)
|
|
{
|
|
LONG lDeltaX, lDeltaY;
|
|
|
|
// Some part of the window is not within the visible desktop region
|
|
// Move it until it all fits. Size it if it's too big.
|
|
|
|
lDeltaX = lDeltaY = 0;
|
|
if (prc->left < prcWorkArea->left)
|
|
lDeltaX = prcWorkArea->left - prc->left;
|
|
if (prc->top < prcWorkArea->top)
|
|
lDeltaY = prcWorkArea->top - prc->top;
|
|
if (prc->right > prcWorkArea->right)
|
|
lDeltaX = prcWorkArea->right - prc->right;
|
|
if (prc->bottom > prcWorkArea->bottom)
|
|
lDeltaY = prcWorkArea->bottom - prc->bottom;
|
|
OffsetRect(prc, lDeltaX, lDeltaY);
|
|
IntersectRect(&rcIntersect, prc, prcWorkArea);
|
|
CopyRect(prc, &rcIntersect);
|
|
}
|
|
|
|
// Put WORKAREA RECT back into WORKAREA co-ordinates.
|
|
OffsetRect(prc, -lOffsetX, -lOffsetY);
|
|
}
|
|
DC_END_FN();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Predicate returns TRUE if connected
|
|
//
|
|
BOOL CContainerWnd::IsConnected()
|
|
{
|
|
BOOL fConnected = FALSE;
|
|
HRESULT hr = E_FAIL;
|
|
short connectionState = 0;
|
|
|
|
DC_BEGIN_FN("IsConnected");
|
|
|
|
if (_pTsClient)
|
|
{
|
|
TRACE_HR(_pTsClient->get_Connected( & connectionState ));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
fConnected = (connectionState != 0);
|
|
}
|
|
}
|
|
|
|
DC_END_FN();
|
|
return fConnected;
|
|
}
|
|
|
|
//
|
|
// Main window procedure for the top-level window
|
|
//
|
|
LRESULT CALLBACK CContainerWnd::WndProc(HWND hwnd,UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
return OnCreate( uMsg, wParam, lParam);
|
|
break;
|
|
case WM_DESTROY:
|
|
return OnDestroy( hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
case WM_SIZE:
|
|
return OnSize( uMsg, wParam, lParam);
|
|
break;
|
|
case WM_MOVE:
|
|
return OnMove( uMsg, wParam, lParam);
|
|
break;
|
|
case WM_COMMAND:
|
|
return OnCommand( uMsg, wParam, lParam);
|
|
break;
|
|
#ifndef OS_WINCE
|
|
case WM_WINDOWPOSCHANGING:
|
|
return OnWindowPosChanging(uMsg, wParam, lParam);
|
|
break;
|
|
#endif
|
|
case WM_CLOSE:
|
|
return OnClose(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_SETFOCUS:
|
|
return OnSetFocus(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_ACTIVATE:
|
|
return OnActivate(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_SYSCOMMAND:
|
|
return OnSysCommand(uMsg, wParam, lParam);
|
|
break;
|
|
#ifndef OS_WINCE
|
|
case WM_INITMENU:
|
|
return OnInitMenu(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_GETMINMAXINFO:
|
|
return OnGetMinMaxInfo(uMsg, wParam, lParam);
|
|
break;
|
|
#endif
|
|
case WM_NCDESTROY:
|
|
return OnNCDestroy(hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
#ifndef OS_WINCE
|
|
case WM_DEVICECHANGE:
|
|
return OnDeviceChange(hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
#endif
|
|
case WM_HELP:
|
|
return OnHelp(hwnd, uMsg, wParam, lParam);
|
|
break;
|
|
#ifdef OS_WINCE
|
|
case WM_QUERYNEWPALETTE: //intentional fall through. OnPaletteChange only calls SendMessage
|
|
#endif
|
|
case WM_PALETTECHANGED:
|
|
return OnPaletteChange(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_EXITMENULOOP:
|
|
return OnExitMenuLoop(uMsg, wParam, lParam);
|
|
break;
|
|
#ifndef OS_WINCE
|
|
case WM_ENTERSIZEMOVE:
|
|
return OnEnterSizeMove(uMsg, wParam, lParam);
|
|
break;
|
|
case WM_EXITSIZEMOVE:
|
|
return OnExitSizeMove(uMsg, wParam, lParam);
|
|
break;
|
|
#endif
|
|
case WM_CAPTURECHANGED:
|
|
return OnCaptureChanged(uMsg, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
return OnSysColorChange(uMsg, wParam, lParam);
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc (hwnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|