📄 minimule.cpp
字号:
void CMiniMule::UpdateContent(UINT uUpDatarate, UINT uDownDatarate)
{
SetElementHtml(_T("connected"), CComBSTR(theApp.IsConnected() ? GetResString(IDS_YES) : GetResString(IDS_NO)));
SetElementHtml(_T("upRate"), CComBSTR(theApp.emuledlg->GetUpDatarateString(uUpDatarate)));
SetElementHtml(_T("downRate"), CComBSTR(theApp.emuledlg->GetDownDatarateString(uDownDatarate)));
SetElementHtml(_T("completed"), CComBSTR(CastItoIShort(thePrefs.GetDownSessionCompletedFiles(), false, 0)));
SetElementHtml(_T("freeSpace"), CComBSTR(CastItoXBytes(GetFreeDiskSpaceX(thePrefs.GetTempDir()), false, false)));
}
STDMETHODIMP CMiniMule::TranslateUrl(DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut)
{
TRACE(_T("%hs: %ls\n"), __FUNCTION__, pchURLIn);
*ppchURLOut = NULL;
return S_FALSE;
}
void CMiniMule::_OnBeforeNavigate2(LPDISPATCH pDisp, VARIANT* URL, VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData, VARIANT* Headers, BOOL* Cancel)
{
CString strURL(V_BSTR(URL));
TRACE(_T("%hs: %s\n"), __FUNCTION__, strURL);
// No external links allowed!
TCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH];
URL_COMPONENTS Url = {0};
Url.dwStructSize = sizeof(Url);
Url.lpszScheme = szScheme;
Url.dwSchemeLength = ARRSIZE(szScheme);
if (InternetCrackUrl(strURL, 0, 0, &Url) && Url.dwSchemeLength)
{
if (Url.nScheme != INTERNET_SCHEME_UNKNOWN // <absolute local file path>
&& Url.nScheme != INTERNET_SCHEME_RES // res://...
&& Url.nScheme != INTERNET_SCHEME_FILE) // file://...
{
*Cancel = TRUE;
return;
}
}
OnBeforeNavigate(pDisp, strURL);
}
void CMiniMule::OnBeforeNavigate(LPDISPATCH pDisp, LPCTSTR pszUrl)
{
TRACE(_T("%hs: %s\n"), __FUNCTION__, pszUrl);
CDHtmlDialog::OnBeforeNavigate(pDisp, pszUrl);
}
void CMiniMule::OnNavigateComplete(LPDISPATCH pDisp, LPCTSTR pszUrl)
{
TRACE(_T("%hs: %s\n"), __FUNCTION__, pszUrl);
// If the HTML file contains 'OnLoad' scripts, the HTML DOM is fully accessible
// only after 'DocumentComplete', but not after 'OnNavigateComplete'
CDHtmlDialog::OnNavigateComplete(pDisp, pszUrl);
}
void CMiniMule::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR pszUrl)
{
TRACE(_T("%hs: %s\n"), __FUNCTION__, pszUrl);
// If the HTML file contains 'OnLoad' scripts, the HTML DOM is fully accessible
// only after 'DocumentComplete', but not after 'OnNavigateComplete'
CDHtmlDialog::OnDocumentComplete(pDisp, pszUrl);
if (m_bResolveImages)
{
TCHAR szModule[_MAX_PATH];
if (GetModuleFileName(AfxGetResourceHandle(), szModule, ARRSIZE(szModule)))
{
static const struct {
LPCTSTR pszImgId;
LPCTSTR pszResourceId;
} _aImg[] = {
{ _T("connectedImg"), _T("CONNECTED.GIF") },
{ _T("uploadImg"), _T("UPLOAD.GIF") },
{ _T("downloadImg"), _T("DOWNLOAD.GIF") },
{ _T("completedImg"), _T("COMPLETED.GIF") },
{ _T("freeSpaceImg"), _T("FREESPACE.GIF") },
{ _T("restoreWndImg"), _T("RESTOREWINDOW.GIF") },
{ _T("openIncomingImg"),_T("OPENINCOMING.GIF") },
{ _T("optionsImg"), _T("PREFERENCES.GIF") }
};
for (int i = 0; i < ARRSIZE(_aImg); i++)
{
CComPtr<IHTMLImgElement> elm;
GetElementInterface(_aImg[i].pszImgId, &elm);
if (elm) {
CString strResourceURL;
strResourceURL.Format(_T("res://%s/%s"), szModule, _aImg[i].pszResourceId);
elm->put_src(CComBSTR(strResourceURL));
}
}
CComPtr<IHTMLTable> elm;
GetElementInterface(_T("table"), &elm);
if (elm) {
CString strResourceURL;
strResourceURL.Format(_T("res://%s/%s"), szModule, _T("TABLEBACKGND.GIF"));
elm->put_background(CComBSTR(strResourceURL));
elm.Release();
}
}
}
if (m_spHtmlDoc)
{
CComQIPtr<IHTMLElement> body;
if (m_spHtmlDoc->get_body(&body) == S_OK && body)
{
// NOTE: The IE control will always use the size of the associated dialog resource (IDD_MINIMULE)
// as the minium window size. 'scrollWidth' and 'scrollHeight' will therefore never return values
// smaller than the size of that window. To have the auto-size working correctly even for
// very small window sizes, the size of the dialog resource should therefore be kept very small!
// TODO: Only in debug build: Check the size of the dialog resource right before 'OnInitDialog'.
CComQIPtr<IHTMLElement2> body2 = body;
long lScrollWidth = 0;
long lScrollHeight = 0;
if (body2->get_scrollWidth(&lScrollWidth) == S_OK && lScrollWidth > 0 && body2->get_scrollHeight(&lScrollHeight) == S_OK && lScrollHeight > 0)
AutoSizeAndPosition(CSize(lScrollWidth, lScrollHeight));
}
}
Localize();
UpdateContent();
if (m_bAutoClose)
CreateAutoCloseTimer();
}
void CMiniMule::AutoSizeAndPosition(CSize sizClient)
{
CSize sizDesktop(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
if (sizClient.cx > sizDesktop.cx/2)
sizClient.cx = sizDesktop.cx/2;
if (sizClient.cy > sizDesktop.cy/2)
sizClient.cy = sizDesktop.cy/2;
CRect rcWnd;
GetWindowRect(&rcWnd);
if (sizClient.cx > 0 && sizClient.cy > 0)
{
CRect rcClient(0, 0, sizClient.cx, sizClient.cy);
AdjustWindowRectEx(&rcClient, GetStyle(), FALSE, GetExStyle());
rcClient.OffsetRect(-rcClient.left, -rcClient.top);
rcWnd = rcClient;
}
CPoint ptWnd;
//TODO: Taskbar can be placed on each edge!!
HWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), 0);
CRect rcTaskbar(0, sizDesktop.cy - 34, sizDesktop.cx, sizDesktop.cy);
::GetWindowRect(hWndTaskbar, &rcTaskbar);
ptWnd.x = sizDesktop.cx - 8 - rcWnd.Width();
ptWnd.y = sizDesktop.cy - rcTaskbar.Height() - 8 - rcWnd.Height();
SetWindowPos(NULL, ptWnd.x, ptWnd.y, rcWnd.Width(), rcWnd.Height(), SWP_NOZORDER | SWP_SHOWWINDOW);
}
void CMiniMule::CreateAutoCloseTimer()
{
if (m_uAutoCloseTimer == 0)
m_uAutoCloseTimer = SetTimer(IDT_AUTO_CLOSE_TIMER, 3000, NULL);
}
void CMiniMule::KillAutoCloseTimer()
{
if (m_uAutoCloseTimer != 0)
{
VERIFY( KillTimer(m_uAutoCloseTimer) );
m_uAutoCloseTimer = 0;
}
}
void CMiniMule::OnTimer(UINT nIDEvent)
{
if (m_bAutoClose && nIDEvent == m_uAutoCloseTimer)
{
KillAutoCloseTimer();
CPoint pt;
GetCursorPos(&pt);
CRect rcWnd;
GetWindowRect(&rcWnd);
if (!rcWnd.PtInRect(pt))
PostMessage(WM_CLOSE);
else
CreateAutoCloseTimer();
}
CDHtmlDialog::OnTimer(nIDEvent);
}
HRESULT CMiniMule::OnRestoreMainWindow(IHTMLElement* pElement)
{
CCounter cc(m_iInCallback);
if (theApp.emuledlg->IsRunning() && !theApp.emuledlg->IsWindowVisible())
{
if (!theApp.emuledlg->IsPreferencesDlgOpen())
{
KillAutoCloseTimer();
m_bRestoreMainWnd = true;
PostMessage(WM_CLOSE);
}
else
MessageBeep((UINT)-1);
}
return S_OK;
}
HRESULT CMiniMule::OnOpenIncomingFolder(IHTMLElement* pElement)
{
CCounter cc(m_iInCallback);
if (theApp.emuledlg->IsRunning())
{
theApp.emuledlg->SendMessage(WM_COMMAND, MP_HM_OPENINC);
if (GetAutoClose())
PostMessage(WM_CLOSE);
}
return S_OK;
}
HRESULT CMiniMule::OnOptions(IHTMLElement* pElement)
{
CCounter cc(m_iInCallback);
if (theApp.emuledlg->IsRunning())
{
// showing the 'Pref' dialog will process the message queue -> timer messages will be dispatched -> kill auto close timer!
KillAutoCloseTimer();
if (theApp.emuledlg->ShowPreferences() == -1)
MessageBeep((UINT)-1);
if (GetAutoClose())
CreateAutoCloseTimer();
}
return S_OK;
}
STDMETHODIMP CMiniMule::ShowContextMenu(DWORD dwID, POINT* ppt, IUnknown* pcmdtReserved, IDispatch* pdispReserved)
{
CCounter cc(m_iInCallback);
// Avoid IE context menu
return S_OK; // S_OK = Host displayed its own user interface (UI). MSHTML will not attempt to display its UI.
}
STDMETHODIMP CMiniMule::TranslateAccelerator(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID)
{
CCounter cc(m_iInCallback);
// Allow only some basic keys
//
//TODO: Allow the ESC key (for closing the window); does currently not work properly because
// we don't get a callback that the window was just hidden(!) by MSHTML.
switch (lpMsg->message)
{
case WM_CHAR:
switch (lpMsg->wParam)
{
case ' ': // SPACE - Activate a link
return S_FALSE; // S_FALSE = Let the control process the key stroke.
}
break;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
switch (lpMsg->wParam)
{
case VK_TAB: // Cycling through controls which can get the focus
case VK_SPACE: // Activate a link
return S_FALSE; // S_FALSE = Let the control process the key stroke.
case VK_ESCAPE:
//TODO: Small problem here.. If the options dialog was open and was closed with ESC,
//we still get an ESC here too and the HTML window would be closed too..
//PostMessage(WM_CLOSE);
break;
}
break;
}
// Avoid any IE shortcuts (especially F5 (Refresh) which messes up the content)
return S_OK; // S_OK = Don't let the control process the key stroke.
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -