GME
13
|
00001 // ConsoleCtl.cpp : Implementation of the CConsoleCtrl ActiveX Control class. 00002 00003 #include "stdafx.h" 00004 #include "Console.h" 00005 #include "Console_i.h" 00006 #include "ConsoleCtl.h" 00007 #include "ConsolePpg.h" 00008 #include "GME.h" 00009 #include "MgaUtil.h" 00010 #include <mshtml.h> //IWeb objects 00011 #include <limits.h> 00012 #include <afx.h> 00013 #include "Strsafe.h" 00014 00015 #define BUTTON_ICON_SIZE 16 00016 00017 00018 #ifdef _DEBUG 00019 #define new DEBUG_NEW 00020 #undef THIS_FILE 00021 static char THIS_FILE[] = __FILE__; 00022 #endif 00023 00024 00025 IMPLEMENT_DYNCREATE(CConsoleCtrl, COleControl) 00026 00027 00028 // Message map 00029 00030 BEGIN_MESSAGE_MAP(CConsoleCtrl, COleControl) 00031 //{{AFX_MSG_MAP(CConsoleCtrl) 00032 ON_WM_CREATE() 00033 //}}AFX_MSG_MAP 00034 ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties) 00035 ON_COMMAND( IDC_MENU_COMMAND, OnShowMenu) 00036 ON_COMMAND( IDC_LOADSCRIPT_COMMAND, LoadScriptDlg) 00037 ON_COMMAND( IDC_RUNSCRIPT_COMMAND, runScript) 00038 ON_COMMAND( IDC_RELOAD_COMMAND, relScript) 00039 ON_COMMAND( IDC_RELOADRUN_COMMAND, rlrScript) 00040 ON_COMMAND( IDC_CLEARCONSOLE_COMMAND, Clear) 00041 ON_COMMAND( IDC_SELECTENGINE_COMMAND, selectEngine) 00042 ON_COMMAND( IDC_PREV_COMMAND, prevCommand) 00043 ON_COMMAND( IDC_NEXT_COMMAND, nextCommand) 00044 ON_COMMAND( IDC_RETURN_COMMAND, retCommand) 00045 ON_COMMAND_RANGE( IDC_RECENT_SCRIPT1, IDC_RECENT_SCRIPT5, loadRecent) 00046 ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify) 00047 END_MESSAGE_MAP() 00048 00049 00051 // Dispatch map 00052 00053 BEGIN_DISPATCH_MAP(CConsoleCtrl, COleControl) 00054 //{{AFX_DISPATCH_MAP(CConsoleCtrl) 00055 DISP_PROPERTY_EX(CConsoleCtrl, "Contents", GetContents, SetContents, VT_BSTR) 00056 DISP_FUNCTION(CConsoleCtrl, "Message", Message, VT_EMPTY, VTS_BSTR VTS_I2) 00057 DISP_FUNCTION(CConsoleCtrl, "Clear", Clear, VT_EMPTY, VTS_NONE) 00058 DISP_DEFVALUE(CConsoleCtrl, "Contents") 00059 DISP_FUNCTION(CConsoleCtrl, "SetGMEApp", SetGMEApp, VT_EMPTY, VTS_DISPATCH) 00060 DISP_FUNCTION(CConsoleCtrl, "SetGMEProj", SetGMEProj, VT_EMPTY, VTS_DISPATCH) 00061 DISP_FUNCTION_ID(CConsoleCtrl, "NavigateTo", dispidNavigateTo, NavigateTo, VT_EMPTY, VTS_BSTR) 00062 DISP_FUNCTION(CConsoleCtrl, "LoadScript", LoadScript, VT_EMPTY, VTS_BSTR) 00063 DISP_FUNCTION(CConsoleCtrl, "RunLoadedScript", RunScript, VT_EMPTY, VTS_NONE) 00064 DISP_FUNCTION(CConsoleCtrl, "SetContents", SetContents, VT_EMPTY, VTS_BSTR) 00065 DISP_FUNCTION(CConsoleCtrl, "RunCode", RunCode, VT_EMPTY, VTS_BSTR) 00066 DISP_PROPERTY_EX_ID(CConsoleCtrl, "GetCWnd", 0x43576E64, GetCWnd, SetCWnd, VT_I8) 00067 DISP_FUNCTION_ID(CConsoleCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) 00068 //}}AFX_DISPATCH_MAP 00069 END_DISPATCH_MAP() 00070 00071 00073 // Event map 00074 00075 BEGIN_EVENT_MAP(CConsoleCtrl, COleControl) 00076 //{{AFX_EVENT_MAP(CConsoleCtrl) 00077 EVENT_CUSTOM("ClickMGAID", FireClickMGAID, VTS_BSTR) 00078 //}}AFX_EVENT_MAP 00079 END_EVENT_MAP() 00080 00081 00083 // Property pages 00084 00085 // TODO: Add more property pages as needed. Remember to increase the count! 00086 BEGIN_PROPPAGEIDS(CConsoleCtrl, 1) 00087 PROPPAGEID(CConsolePropPage::guid) 00088 END_PROPPAGEIDS(CConsoleCtrl) 00089 00091 // Initialize class factory and guid 00092 00093 IMPLEMENT_OLECREATE_EX(CConsoleCtrl, "GME.Console.1", 00094 0xe4eb8324, 0x13f0, 0x46cb, 0x96, 0xa3, 0xf5, 0x39, 0xdf, 0x7f, 0x79, 0xd4) 00095 00096 00098 // Type library ID and version 00099 00100 IMPLEMENT_OLETYPELIB(CConsoleCtrl, _tlid, _wVerMajor, _wVerMinor) 00101 00102 00104 // Interface IDs 00105 00106 const IID BASED_CODE IID_DConsole = 00107 { 0x71655c2b, 0xd6dd, 0x4345, { 0xb2, 0x73, 0x5b, 0xd1, 0x42, 0x23, 0x70, 0xcb } }; 00108 const IID BASED_CODE IID_DConsoleEvents = 00109 { 0x39f56b4c, 0xe7db, 0x4a54, { 0x86, 0x8c, 0xca, 0xa7, 0xeb, 0xe2, 0x32, 0x33 } }; 00110 00111 00113 // Control type information 00114 00115 static const DWORD BASED_CODE _dwConsoleOleMisc = 00116 OLEMISC_ACTIVATEWHENVISIBLE | 00117 OLEMISC_SETCLIENTSITEFIRST | 00118 OLEMISC_INSIDEOUT | 00119 OLEMISC_CANTLINKINSIDE | 00120 OLEMISC_RECOMPOSEONRESIZE; 00121 00122 IMPLEMENT_OLECTLTYPE(CConsoleCtrl, IDS_CONSOLE, _dwConsoleOleMisc) 00123 00124 00125 00126 // CConsoleCtrl::CConsoleCtrlFactory::UpdateRegistry - 00127 // Adds or removes system registry entries for CConsoleCtrl 00128 00129 BOOL CConsoleCtrl::CConsoleCtrlFactory::UpdateRegistry(BOOL bRegister) 00130 { 00131 // TODO: Verify that your control follows apartment-model threading rules. 00132 // Refer to MFC TechNote 64 for more information. 00133 // If your control does not conform to the apartment-model rules, then 00134 // you must modify the code below, changing the 6th parameter from 00135 // afxRegApartmentThreading to 0. 00136 00137 if (bRegister) 00138 return AfxOleRegisterControlClass( 00139 AfxGetInstanceHandle(), 00140 m_clsid, 00141 m_lpszProgID, 00142 IDS_CONSOLE, 00143 IDB_CONSOLE, 00144 afxRegApartmentThreading, 00145 _dwConsoleOleMisc, 00146 _tlid, 00147 _wVerMajor, 00148 _wVerMinor); 00149 else 00150 return AfxOleUnregisterClass(m_clsid, m_lpszProgID); 00151 } 00152 00153 00155 // CConsoleCtrl::CConsoleCtrl - Constructor 00156 00157 CConsoleCtrl::CConsoleCtrl() 00158 : m_recent1(_T("")) 00159 , m_recent2(_T("")) 00160 , m_recent3(_T("")) 00161 , m_recent4(_T("")) 00162 , m_recent5(_T("")) 00163 , m_hIco1(NULL) 00164 , m_hIco2(NULL) 00165 , m_hIco3(NULL) 00166 , m_hIcou(NULL) 00167 , m_hIcod(NULL) 00168 , m_hIcor(NULL) 00169 { 00170 InitializeIIDs(&IID_DConsole, &IID_DConsoleEvents); 00171 00172 // TODO: Initialize your control's instance data here. 00173 } 00174 00175 00177 // CConsoleCtrl::~CConsoleCtrl - Destructor 00178 00179 CConsoleCtrl::~CConsoleCtrl() 00180 { 00181 // TODO: Cleanup your control's instance data here. 00182 if (m_hIco1) 00183 ::DestroyIcon(m_hIco1); 00184 if (m_hIco2) 00185 ::DestroyIcon(m_hIco2); 00186 if (m_hIco3) 00187 ::DestroyIcon(m_hIco3); 00188 if (m_hIcou) 00189 ::DestroyIcon(m_hIcou); 00190 if (m_hIcod) 00191 ::DestroyIcon(m_hIcod); 00192 if (m_hIcor) 00193 ::DestroyIcon(m_hIcor); 00194 } 00195 00196 // centeres a rectangle inside another one, so that a 00197 // square with p_bt_size side will sit in the center 00198 CRect centered( const CRect& p_rcIn, int p_vertic_size, int p_horiz_size, int p_bt_size) 00199 { 00200 CRect rc( p_rcIn); 00201 rc.top += (p_vertic_size - p_bt_size)/2; 00202 rc.bottom -= (p_vertic_size - p_bt_size)/2; 00203 rc.left += (p_horiz_size - p_bt_size)/2; 00204 rc.right -= (p_horiz_size - p_bt_size)/2; 00205 return rc; 00206 } 00207 00209 // CConsoleCtrl::OnDraw - Drawing function 00210 00211 void CConsoleCtrl::OnDraw( 00212 CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid) 00213 { 00214 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00215 00216 const int vertic_size = 26 * GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY) / 96 /* USER_DEFAULT_SCREEN_DPI */; 00217 const int horiz_size = 26 * GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY) / 96 /* USER_DEFAULT_SCREEN_DPI */; 00218 const int bt_size = 20 * GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY) / 96 /* USER_DEFAULT_SCREEN_DPI */; 00219 const int prnx_size = 19 * GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY) / 96 /* USER_DEFAULT_SCREEN_DPI */; // width of the prev/next buttons 00220 00221 00222 if (m_browser.GetSafeHwnd()) { 00223 bool anything_loaded = !m_edit.GetLoadedScript().IsEmpty(); 00224 CRect rcBrwsr, rcExtra, rcExtra2; // browser rect, extra rect 00225 rcExtra2 = rcBrwsr = rcExtra = rcBounds; 00226 00227 rcExtra2.left -= 1; 00228 rcExtra2.bottom += 1; 00229 // light gray background for the whole region 00230 DWORD dw = ::GetSysColor(COLOR_3DFACE); 00231 BYTE r = GetRValue(dw); 00232 BYTE g = GetGValue(dw); 00233 BYTE b = GetBValue(dw); 00234 COLORREF col = RGB(r,g,b); 00235 CBrush brush; 00236 brush.CreateSolidBrush(col); 00237 pdc->FillRect(&rcExtra2, &brush); 00238 00239 rcBrwsr.bottom -= vertic_size; // take from the browser's space 30 lines 00240 rcExtra.top = rcBrwsr.bottom; // extra is the remaining space 00241 rcBrwsr.bottom -= 1; // use less space for the browser to have a divide 00242 00243 00244 pdc->SelectStockObject( BLACK_PEN); 00245 pdc->SelectStockObject( GRAY_BRUSH); 00246 rcExtra2.top = rcBrwsr.bottom; 00247 rcExtra2.bottom = rcExtra2.top+1; 00248 pdc->Rectangle( rcExtra2); // a divider line between the browser and scripting 00249 00250 // place browser 00251 m_browser.MoveWindow( rcBrwsr, TRUE); 00252 00253 // place the generic command button 00254 CRect rcLoad( rcExtra); // load btn rect 00255 rcLoad.right = rcLoad.left + horiz_size; 00256 00257 m_cmdButton.MoveWindow( centered( rcLoad, vertic_size, horiz_size, bt_size), TRUE); 00258 00259 // place and show/hide 'Execute' button based on bool (anything_loaded) 00260 if (anything_loaded) { 00261 rcLoad.OffsetRect( horiz_size, 0); 00262 00263 m_exeButton.MoveWindow( centered( rcLoad, vertic_size, horiz_size, bt_size), TRUE); 00264 m_exeButton.ShowWindow(SW_SHOW); 00265 } 00266 else { 00267 m_exeButton.ShowWindow(SW_HIDE); 00268 } 00269 00270 // place 'Clear' 00271 CRect rcClean = rcExtra; // clear btn rect 00272 rcClean.left = rcClean.right - horiz_size; 00273 00274 CRect rcClrBtn(rcClean); 00275 m_clrButton.MoveWindow( centered( rcClrBtn, vertic_size, horiz_size, bt_size), TRUE); 00276 00277 // place 'Return' 00278 rcClean.right = rcClean.left; 00279 rcClean.left -= horiz_size; 00280 00281 m_retButton.MoveWindow( centered( rcClean, vertic_size, horiz_size, bt_size), TRUE); 00282 00283 // place history prev/next button pair to the left of Clean 00284 rcClean.right = rcClean.left; rcClean.left -= prnx_size; 00285 rcClean.bottom = rcClean.top + static_cast<int>(vertic_size/2); 00286 CRect rcUDBtn( rcClean); 00287 rcUDBtn.DeflateRect( 0, 2, 0, 0); 00288 m_upButton.MoveWindow( rcUDBtn, TRUE); 00289 00290 rcClean.top = rcClean.bottom; 00291 rcClean.bottom = rcExtra.bottom;//rcClean.OffsetRect( 0, vertic_size - static_cast<int>(vertic_size/2)); 00292 rcUDBtn = rcClean; 00293 rcUDBtn.DeflateRect( 0, 1, 0, 2); 00294 m_dnButton.MoveWindow( rcUDBtn, TRUE); 00295 00296 CRect rcRemain = rcExtra; // remaining rect 00297 rcRemain.left = rcLoad.right; // left side 00298 rcRemain.right= rcClean.left; // right side 00299 00300 rcRemain.top += 2; 00301 rcRemain.left += 2; 00302 rcRemain.bottom -= 2; 00303 rcRemain.right -= 2; 00304 00305 // move input control too 00306 m_edit.MoveWindow(rcRemain, TRUE); 00307 } 00308 else { 00309 CBrush brush (RGB(255,255,255)); 00310 pdc->FillRect (rcBounds, &brush); 00311 00312 CRect edge(rcBounds); 00313 pdc->DrawEdge(&edge, EDGE_BUMP, BF_RECT); 00314 00315 CString label(_T("GME Console OCX")); 00316 00317 BITMAP bm; 00318 CBitmap bitmap; 00319 bitmap.LoadBitmap(IDB_CONSOLE); 00320 bitmap.GetBitmap(&bm); 00321 CSize size(bm.bmWidth, bm.bmHeight); 00322 pdc->DPtoLP(&size); 00323 CPoint org(0,0); 00324 pdc->DPtoLP(&org); 00325 CPoint pos(rcBounds.Width()/2, rcBounds.Height()/2 - (pdc->GetTextExtent(label).cy) ); 00326 CDC dcMem; 00327 dcMem.CreateCompatibleDC(pdc); 00328 CBitmap *oldbitmap = dcMem.SelectObject(&bitmap); 00329 dcMem.SetMapMode (pdc->GetMapMode()); 00330 pdc->BitBlt(pos.x, pos.y, size.cx, size.cy, &dcMem, org.x, org.y, SRCCOPY); 00331 dcMem.SelectObject(oldbitmap); 00332 00333 pdc->SetTextAlign(TA_CENTER); 00334 pdc->TextOut(rcBounds.Width()/2, rcBounds.Height()/2, label); 00335 } 00336 } 00337 00338 00340 // CConsoleCtrl::DoPropExchange - Persistence support 00341 00342 void CConsoleCtrl::DoPropExchange(CPropExchange* pPX) 00343 { 00344 ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor)); 00345 COleControl::DoPropExchange(pPX); 00346 00347 // TODO: Call PX_ functions for each persistent custom property. 00348 00349 } 00350 00351 00353 // CConsoleCtrl::OnResetState - Reset control to default state 00354 00355 void CConsoleCtrl::OnResetState() 00356 { 00357 COleControl::OnResetState(); // Resets defaults found in DoPropExchange 00358 00359 // TODO: Reset any other control state here. 00360 } 00361 00362 00364 // CConsoleCtrl::AboutBox - Display an "About" box to the user 00365 00366 void CConsoleCtrl::AboutBox() 00367 { 00368 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00369 CDialog dlgAbout(IDD_ABOUTBOX_CONSOLE); 00370 dlgAbout.DoModal(); 00371 } 00372 00374 void CConsoleCtrl::SetGMEApp(IDispatch *disp) 00375 { 00376 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00377 m_edit.SetGMEApp(disp); 00378 m_gmeptr = disp; 00379 AddGMEToScript(); 00380 } 00381 00382 void CConsoleCtrl::SetGMEProj(IDispatch *disp) 00383 { 00384 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00385 m_edit.SetGMEProj(disp); 00386 } 00387 00388 void CConsoleCtrl::NavigateTo(LPCTSTR url) 00389 { 00390 AFX_MANAGE_STATE(AfxGetStaticModuleState()); 00391 m_browser.Navigate2(url); 00392 } 00394 // CConsoleCtrl message handlers 00395 00396 int CConsoleCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 00397 { 00398 if (COleControl::OnCreate(lpCreateStruct) == -1) 00399 return -1; 00400 00401 CRect rect(0,0,0,0); 00402 // create an input control too 00403 if (!m_browser.Create(NULL, _T("GME Console"), (WS_VISIBLE | WS_CHILD), 00404 rect, this, IDD_BROWSER)) 00405 // FIXME: warn user that GME requires IE (e.g. Windows Server Core 2008R2) 00406 return -1; 00407 m_browser.LoadFromResource(_T("BLANK.HTML")); 00408 00409 // KMS: need to pump messages here, since m_browser loads in a different thread and 00410 // posts messages to initialize. If RPC wins the race, it can call SetContents et al and 00411 // get_body will return NULL 00412 // (out-of-proc CoCreateInstance("GMEOleApp") will block until after this method returns) 00413 CComPtr<IHTMLDocument2> pHtmlDoc; 00414 CComPtr<IDispatch> pDispatch = m_browser.GetHtmlDocument(); 00415 COMTHROW(pDispatch.QueryInterface(&pHtmlDoc)); 00416 ASSERT(pHtmlDoc != NULL); 00417 MSG msg; 00418 while (GetMessage(&msg, NULL, 0, 0)) 00419 { 00420 TranslateMessage(&msg); 00421 DispatchMessage(&msg); 00422 CComPtr<IHTMLElement> pElement; 00423 COMTHROW(pHtmlDoc->get_body( &pElement )); 00424 if (pElement != NULL) 00425 break; 00426 } 00427 00428 m_edit.Create((ES_AUTOHSCROLL | WS_VISIBLE | WS_CHILD | WS_BORDER), rect, this, IDD_EDIT); 00429 m_edit.LimitText(300); 00430 bool ret = m_edit.Init(this); 00431 if (!ret) { 00432 ASSERT(false); 00433 return -1; 00434 } 00435 m_edit.ModifyStyleEx(WS_EX_CLIENTEDGE, WS_EX_STATICEDGE); 00436 00437 00438 m_hIco1 = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_LOADSCR), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00439 m_hIco2 = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_EXECSCR), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00440 m_hIco3 = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_CLEANCON), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00441 m_hIcou = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_BTNUP), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00442 m_hIcod = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_BTNDN), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00443 m_hIcor = (HICON)::LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_BTNRET), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); 00444 00445 rect.bottom = rect.right = 100; 00446 rect.left = rect.right - BUTTON_ICON_SIZE; 00447 rect.bottom = rect.top - BUTTON_ICON_SIZE; 00448 00449 m_cmdButton.Create( _T("MenuButton"), WS_CHILD|WS_VISIBLE|BS_ICON, rect, this, IDC_MENU_COMMAND); 00450 m_cmdButton.SetIcon(m_hIco1); 00451 00452 rect.right += BUTTON_ICON_SIZE; 00453 rect.left += BUTTON_ICON_SIZE; 00454 m_exeButton.Create( _T("ExecButton"), WS_CHILD/*|WS_VISIBLE*/|BS_ICON, rect, this, IDC_RUNSCRIPT_COMMAND); 00455 m_exeButton.SetIcon(m_hIco2); 00456 00457 rect.left += BUTTON_ICON_SIZE; 00458 rect.right += BUTTON_ICON_SIZE; 00459 m_clrButton.Create( _T("ClearConsButton"), WS_CHILD|WS_VISIBLE|BS_ICON, rect, this, IDC_CLEARCONSOLE_COMMAND); 00460 m_clrButton.SetIcon(m_hIco3); 00461 00462 CRect rec2 = rect; 00463 //rec2.right = rec2.left + 40; rec2.bottom = rec2.top + BUTTON_ICON_SIZE; 00464 rec2.right = rec2.left + BUTTON_ICON_SIZE + 3; //bmuSize.cx + 3; 00465 rec2.bottom = rec2.top + BUTTON_ICON_SIZE; //bmuSize.cy + 3; 00466 m_upButton.Create(_T("Prev"), WS_CHILD|WS_VISIBLE|BS_ICON, rec2, this, IDC_PREV_COMMAND); 00467 m_upButton.SetIcon(m_hIcou); 00468 00469 m_dnButton.Create(_T("Next"), WS_CHILD|WS_VISIBLE|BS_ICON, rec2, this, IDC_NEXT_COMMAND); 00470 m_dnButton.SetIcon(m_hIcod); 00471 00472 m_retButton.Create(_T("Return"), WS_CHILD|WS_VISIBLE|BS_ICON, rec2, this, IDC_RETURN_COMMAND); 00473 m_retButton.SetIcon(m_hIcor); 00474 00475 EnableToolTips(); 00476 00477 return 0; 00478 } 00479 00480 00481 static const TCHAR* icons[] = { 00482 _T("NORMAL.GIF"), 00483 _T("INFO.GIF"), 00484 _T("WARNING.GIF"), 00485 _T("ERROR.GIF") 00486 }; 00487 00488 void CConsoleCtrl::Message(LPCTSTR str, short type) 00489 { 00490 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00491 00492 if (type < MSG_NORMAL || type > MSG_ERROR) { 00493 type = MSG_ERROR; 00494 } 00495 CComPtr<IDispatch> pDispatch = m_browser.GetHtmlDocument(); 00496 if( pDispatch != NULL ) 00497 { 00498 CString line; 00499 00500 line.Format(_T("<IMG SRC=\"%s\" ALIGN=MIDDLE > %s<BR>"), icons[type], str); 00501 00502 VARIANT_BOOL time_stamping = VARIANT_FALSE; // default 00503 try { 00504 CComPtr<IMgaRegistrar> registrar; 00505 COMTHROW( registrar.CoCreateInstance(L"Mga.MgaRegistrar") ); 00506 00507 COMTHROW( registrar->GetTimeStamping(REGACCESS_USER, &time_stamping)); 00508 if(time_stamping != VARIANT_FALSE) 00509 { 00510 CTime time = CTime::GetCurrentTime(); 00511 line = time.Format(_T("[%H:%M:%S] ")) + line; 00512 } 00513 } catch(hresult_exception &) 00514 { 00515 } 00516 00517 try { 00518 CComPtr<IHTMLDocument2> pHtmlDoc; 00519 COMTHROW(pDispatch.QueryInterface(&pHtmlDoc)); 00520 ASSERT(pHtmlDoc != NULL); 00521 CComPtr<IHTMLElement> pElement; 00522 COMTHROW(pHtmlDoc->get_body( &pElement )); 00523 ASSERT(pElement != NULL); 00524 CComBSTR where(L"BeforeEnd"); 00525 CComBSTR text(line); 00526 COMTHROW(pElement->insertAdjacentHTML(where, text)); 00527 00528 // Scroll 00529 CComPtr<IHTMLWindow2> parentWindow; 00530 COMTHROW(pHtmlDoc->get_parentWindow( &parentWindow )); 00531 ASSERT(parentWindow != NULL); 00532 HRESULT hhh = (parentWindow->scrollTo( 0, LONG_MAX/16)); // Starting from IE8 we need this /16 hack. 00533 // If you know the proper way of scrolling to the bottom, fix this. 00534 //COMTHROW(parentWindow->scrollTo( 0, LONG_MAX)); 00535 } 00536 catch (hresult_exception &) 00537 { 00538 } 00539 } 00540 00541 } 00542 00543 void CConsoleCtrl::Clear() 00544 { 00545 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00546 m_browser.LoadFromResource(_T("BLANK.HTML")); 00547 } 00548 00549 BSTR CConsoleCtrl::GetContents() 00550 { 00551 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00552 CComBSTR contents; 00553 00554 CComPtr<IDispatch> pDispatch = m_browser.GetHtmlDocument(); 00555 if( pDispatch != NULL ) 00556 { 00557 try { 00558 CComPtr<IHTMLDocument2> pHtmlDoc; 00559 COMTHROW(pDispatch.QueryInterface(&pHtmlDoc)); 00560 ASSERT(pHtmlDoc != NULL); 00561 CComPtr<IHTMLElement> pElement; 00562 COMTHROW(pHtmlDoc->get_body( &pElement )); 00563 ASSERT(pElement != NULL); 00564 // FIXME: under wine, access violation in ieframe.dll 00565 COMTHROW(pElement->get_innerHTML(&contents)); 00566 } 00567 catch (hresult_exception &) 00568 { 00569 } 00570 } 00571 00572 return contents.Detach(); 00573 } 00574 00575 void CConsoleCtrl::SetContents(LPCTSTR lpszNewValue) 00576 { 00577 AFX_MANAGE_STATE(AfxGetStaticModuleState( )); 00578 CComBSTR contents(lpszNewValue); 00579 00580 CComPtr<IDispatch> pDispatch = m_browser.GetHtmlDocument(); 00581 if( pDispatch != NULL ) 00582 { 00583 try { 00584 CComPtr<IHTMLDocument2> pHtmlDoc; 00585 COMTHROW(pDispatch.QueryInterface(&pHtmlDoc)); 00586 ASSERT(pHtmlDoc != NULL); 00587 CComPtr<IHTMLElement> pElement; 00588 COMTHROW(pHtmlDoc->get_body( &pElement )); 00589 ASSERT(pElement != NULL); 00590 COMTHROW(pElement->put_innerHTML(contents)); 00591 } 00592 catch (hresult_exception &) 00593 { 00594 } 00595 } 00596 00597 SetModifiedFlag(); 00598 } 00599 00600 void CConsoleCtrl::OnShowMenu() 00601 { 00602 if( 0 > ::GetKeyState( VK_CONTROL)) 00603 { 00604 runScript(); 00605 return; 00606 } 00607 else if( 0 > ::GetKeyState( VK_SHIFT)) 00608 { 00609 LoadScriptDlg(); 00610 return; 00611 } 00612 00613 CMenu r; // recentMenu; 00614 if( r.CreatePopupMenu()) 00615 { 00616 if( !m_recent1.IsEmpty()) r.AppendMenu( MF_STRING, IDC_RECENT_SCRIPT1, m_recent1); 00617 if( !m_recent2.IsEmpty()) r.AppendMenu( MF_STRING, IDC_RECENT_SCRIPT2, m_recent2); 00618 if( !m_recent3.IsEmpty()) r.AppendMenu( MF_STRING, IDC_RECENT_SCRIPT3, m_recent3); 00619 if( !m_recent4.IsEmpty()) r.AppendMenu( MF_STRING, IDC_RECENT_SCRIPT4, m_recent4); 00620 if( !m_recent5.IsEmpty()) r.AppendMenu( MF_STRING, IDC_RECENT_SCRIPT5, m_recent5); 00621 } 00622 00623 CMenu p; 00624 if( p.CreatePopupMenu()) 00625 { 00626 p.AppendMenu( MF_STRING, IDC_LOADSCRIPT_COMMAND, _T("Load Script")); 00627 if( !m_edit.GetLoadedScriptFileName().IsEmpty()) 00628 p.AppendMenu( MF_STRING,IDC_RELOAD_COMMAND, _T("Reload Current")); // or IDC_RELOADRUN_COMMAND 00629 if( !m_recent1.IsEmpty()) // m_recent1 can tell us if there is anything in the recent list 00630 p.AppendMenu( MF_POPUP, (UINT_PTR) r.GetSafeHmenu(), _T("Recent Scripts")); 00631 p.AppendMenu( MF_STRING, IDC_SELECTENGINE_COMMAND, _T("Settings")); 00632 00633 CRect rc; 00634 m_cmdButton.GetWindowRect( &rc); 00635 p.TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON, rc.left + rc.Width()/2, rc.top + rc.Height()/2, this); 00636 Invalidate(); 00637 } 00638 } 00639 00640 void CConsoleCtrl::RunScript() 00641 { 00642 if( !m_edit.GetLoadedScript().IsEmpty()) 00643 { 00644 Message( CString( _T("Executing script: ")) + m_edit.GetLoadedScriptFileName(), MSG_INFO); 00645 m_edit.ExecuteScript( m_edit.GetLoadedScript()); 00646 } 00647 else 00648 Message( _T("Script not found!"), MSG_INFO); 00649 } 00650 00651 void CConsoleCtrl::LoadScript(BSTR p_fileName) 00652 { 00653 m_edit.SetLoadedScript(_T("")); // erase old loaded script contents 00654 00655 CStdioFile _file; 00656 00657 // open file 00658 if( _file.Open( p_fileName, CFile::modeRead | CFile::typeBinary) == 0) { 00659 Message( CString(_T("Unable to open file '")) + static_cast<const TCHAR*>(p_fileName) + _T("'"), MSG_ERROR); 00660 return; 00661 } 00662 00663 unsigned char utf16_bom[] = { 0xFF, 0xFE }; 00664 unsigned char bytes[2]; 00665 _file.Read(bytes, 2); 00666 if (memcmp(utf16_bom, bytes, 2) == 0) 00667 { 00668 CString script_buf; 00669 unsigned int sizeof_file = _file.GetLength(); 00670 // skipping BOM 00671 sizeof_file -= 2; 00672 sizeof_file = _file.Read(script_buf.GetBuffer(sizeof_file / sizeof(wchar_t)), sizeof_file); 00673 script_buf.ReleaseBuffer(); 00674 _file.Close(); 00675 m_edit.SetLoadedScript(script_buf); 00676 } 00677 else 00678 { 00679 _file.SeekToBegin(); 00680 CStringA script_buf; 00681 unsigned int sizeof_file = _file.GetLength(); 00682 sizeof_file = _file.Read(script_buf.GetBuffer(sizeof_file), sizeof_file); 00683 script_buf.ReleaseBuffer(); 00684 _file.Close(); 00685 m_edit.SetLoadedScript(CString(script_buf)); 00686 } 00687 00688 m_edit.SetScriptFileName( p_fileName); 00689 00690 Message( CString( _T("Loaded script: ")) + p_fileName, MSG_INFO); 00691 Invalidate(); 00692 } 00693 00694 void CConsoleCtrl::LoadScriptDlg() 00695 { 00696 CFileDialog dlg(TRUE, _T("py"), 0, 00697 OFN_EXPLORER | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, 00698 _T("Script Files (*.js;*.py;*.vbs)|*.js;*.vbs;*.py|") 00699 _T("Python Script Files (*.py)|*.py|") 00700 _T("JScript Files (*.js)|*.js|") 00701 _T("VBScript Files (*.vbs)|*.vbs|") 00702 _T("Text Files (*.txt)|*.txt|") 00703 _T("HTML Files (*.html;*.htm)|*.html;*.htm|") 00704 _T("All Files (*.*)|*.*||")); 00705 00706 if( dlg.DoModal() == IDOK) 00707 { 00708 CString fpath = dlg.GetPathName(); 00709 CString ext = dlg.GetFileExt().MakeLower(); 00710 if (ext == _T("html") || ext == _T("htm")) { 00711 m_browser.Navigate2(fpath); 00712 return; 00713 } 00714 00715 LoadScript(_bstr_t(fpath)); 00716 00717 if( m_recent1.IsEmpty()) 00718 m_recent1 = fpath; 00719 else if( m_recent2.IsEmpty()) 00720 { 00721 m_recent2 = m_recent1; 00722 m_recent1 = fpath; 00723 } 00724 else if( m_recent3.IsEmpty()) 00725 { 00726 m_recent3 = m_recent2; 00727 m_recent2 = m_recent1; 00728 m_recent1 = fpath; 00729 } 00730 else if( m_recent4.IsEmpty()) 00731 { 00732 m_recent4 = m_recent3; 00733 m_recent3 = m_recent2; 00734 m_recent2 = m_recent1; 00735 m_recent1 = fpath; 00736 } 00737 else if( m_recent5.IsEmpty()) 00738 { 00739 m_recent5 = m_recent4; 00740 m_recent4 = m_recent3; 00741 m_recent3 = m_recent2; 00742 m_recent2 = m_recent1; 00743 m_recent1 = fpath; 00744 } 00745 } 00746 } 00747 00748 void CConsoleCtrl::runScript() 00749 { 00750 RunScript(); 00751 } 00752 00753 void CConsoleCtrl::relScript() // reload 00754 { 00755 LoadScript(_bstr_t(m_edit.GetLoadedScriptFileName())); 00756 } 00757 00758 void CConsoleCtrl::rlrScript() // reload & run 00759 { 00760 LoadScript(_bstr_t(m_edit.GetLoadedScriptFileName())); 00761 RunScript(); 00762 } 00763 00764 void CConsoleCtrl::selectEngine() 00765 { 00766 try { 00767 CComPtr<IMgaLauncher> launcher; 00768 COMTHROW( launcher.CoCreateInstance(L"Mga.MgaLauncher") ); 00769 COMTHROW( launcher->GmeDlg()); 00770 } 00771 catch(...) { 00772 Message( _T("Error while trying to show GME settings dialog"), MSG_ERROR); 00773 } 00774 } 00775 00776 void CConsoleCtrl::loadRecent( UINT which) 00777 { 00778 switch( which) { 00779 case IDC_RECENT_SCRIPT1: LoadScript(_bstr_t(m_recent1));break; 00780 case IDC_RECENT_SCRIPT2: LoadScript(_bstr_t(m_recent2));break; 00781 case IDC_RECENT_SCRIPT3: LoadScript(_bstr_t(m_recent3));break; 00782 case IDC_RECENT_SCRIPT4: LoadScript(_bstr_t(m_recent4));break; 00783 case IDC_RECENT_SCRIPT5: LoadScript(_bstr_t(m_recent5));break; 00784 } 00785 } 00786 00787 void CConsoleCtrl::prevCommand() 00788 { 00789 m_edit.showPrev(); 00790 } 00791 00792 void CConsoleCtrl::nextCommand() 00793 { 00794 m_edit.showNext(); 00795 } 00796 00797 void CConsoleCtrl::retCommand() 00798 { 00799 m_edit.returnHit(); 00800 } 00801 00802 BOOL CConsoleCtrl::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult) 00803 { 00804 // need to handle both ANSI and UNICODE versions of the message 00805 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; 00806 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; 00807 UINT_PTR nID = pNMHDR->idFrom; 00808 00809 CString tip; 00810 00811 if( pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) || 00812 pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND)) 00813 { 00814 // idFrom is actually the HWND of the tool 00815 nID = ::GetDlgCtrlID((HWND)nID); 00816 } 00817 00818 if( nID != 0) // will be zero on a separator 00819 { 00820 //tip.Format("Control ID = %d", nID); 00821 switch( nID) 00822 { 00823 case IDC_RETURN_COMMAND: tip = _T("Executes the command typed into the edit field"); 00824 break;case IDC_RUNSCRIPT_COMMAND: tip = _T("Executes ") + m_edit.GetLoadedScriptFileName(); 00825 break;case IDC_MENU_COMMAND: tip = _T("Load scripts and access recent scripts"); 00826 break;case IDC_CLEARCONSOLE_COMMAND: tip = _T("Clear the console"); 00827 break;case IDC_PREV_COMMAND: tip = _T("Previous command in history"); 00828 break;case IDC_NEXT_COMMAND: tip = _T("Next command in history"); 00829 break;case IDD_EDIT: tip = _T("Enter a command here"); 00830 } 00831 } 00832 00833 CStringA aTip(tip); 00834 CStringW wTip(tip); 00835 if( pNMHDR->code == TTN_NEEDTEXTA) 00836 StringCchCopyA(pTTTA->szText, sizeof(pTTTA->szText) / sizeof(char) - 1, aTip); 00837 else 00838 StringCchCopyW(pTTTW->szText, sizeof(pTTTW->szText) / sizeof(wchar_t) - 1, wTip); 00839 00840 *pResult = 0; 00841 return TRUE; // message was handled 00842 } 00843 00844 BOOL CConsoleCtrl::PreTranslateMessage(MSG* pMsg) { 00845 HWND h = ::GetFocus(); 00846 while (h) { 00847 if (h == m_browser.GetSafeHwnd()) { 00848 return m_browser.PreTranslateMessage(pMsg); 00849 } 00850 h = ::GetParent(h); 00851 } 00852 return FALSE; 00853 } 00854 00855 HRESULT CConsoleCtrl::AddGMEToScript() 00856 { 00857 COMTRY { 00858 HRESULT hr; 00859 00860 CComPtr<IHTMLDocument2> pHtmlDoc; 00861 CComPtr<IDispatch> pDispatch = m_browser.GetHtmlDocument(); 00862 // This QI fails on Win7 if the link is to file:///folder 00863 COMTHROW(pDispatch.QueryInterface(&pHtmlDoc)); 00864 00865 CComPtr<IDispatch> script; 00866 pHtmlDoc->get_Script(&script); 00867 CComPtr<IDispatchEx> scriptex; 00868 if (script) 00869 { 00870 script->QueryInterface(IID_IDispatchEx, (void**)&scriptex); 00871 } 00872 00873 if(script == NULL) // || m_gmeptr == NULL) 00874 return E_INVALIDARG; 00875 00876 DISPID dispIdThis = 0; 00877 hr = scriptex->GetDispID(_bstr_t(L"gme"), fdexNameEnsure | fdexNameCaseSensitive, &dispIdThis); 00878 if (FAILED(hr)) 00879 return hr; 00880 if (dispIdThis == 0) 00881 return E_FAIL; 00882 00883 DISPID dispIdPut = DISPID_PROPERTYPUT; 00884 DISPPARAMS params = {0}; 00885 EXCEPINFO ei; 00886 00887 CComVariant arg = m_gmeptr; 00888 params.cArgs = 1; 00889 params.rgvarg = &arg; 00890 params.cNamedArgs = 1; 00891 params.rgdispidNamedArgs = &dispIdPut; 00892 00893 return scriptex->InvokeEx(dispIdThis, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, ¶ms, NULL, &ei, NULL); 00894 } COMCATCH(;) 00895 } 00896