|
|
//
// 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); } }
|