windows-nt/Source/XPSP1/NT/shell/browseui/chanbar.cpp
2020-09-26 16:20:57 +08:00

426 lines
12 KiB
C++

#include "priv.h"
#ifdef ENABLE_CHANNELS
#include "sccls.h"
#include "resource.h"
#include "mshtmhst.h"
#include "deskbar.h"
#include "bands.h"
#define WANT_CBANDSITE_CLASS
#include "bandsite.h"
#include "chanbar.h"
#ifdef UNIX
#include <mainwin.h>
#endif
#include "mluisupp.h"
#define TBHEIGHT 20 // default height of the toolbar inside channel bar
#define TBWIDTH 20 // default width of the toolbar inside channel bar
CChannelDeskBarApp::CChannelDeskBarApp() : _hwndDummy(NULL)
{
}
CChannelDeskBarApp::~CChannelDeskBarApp()
{
if (IsWindow(_hwndDummy))
{
DestroyWindow(_hwndDummy);
}
}
void CChannelDeskBarApp::_OnCreate()
{
CDeskBarApp::_OnCreate();
// remember screen resolution
_cxScreen = GetSystemMetrics(SM_CXSCREEN);
_cyScreen = GetSystemMetrics(SM_CYSCREEN);
// create the dummy for receiving and forwarding broadcast messages
if (!_hwndDummy)
{
_hwndDummy = SHCreateWorkerWindow(DummyWndProc, 0, 0, 0, 0, this);
}
if (_hwndDummy)
{
// make sure we so a select a realize of a palette in this
// window so that we will get palette change notifications..
HDC hdc = GetDC( _hwndDummy );
if (hdc)
{
HPALETTE hpal = SHCreateShellPalette( hdc );
if (hpal)
{
HPALETTE hpalOld = SelectPalette( hdc, hpal, TRUE );
RealizePalette( hdc );
// now select the old one back in
SelectPalette( hdc, hpalOld, TRUE );
DeletePalette( hpal );
}
ReleaseDC( _hwndDummy, hdc );
}
}
}
void CChannelDeskBarApp::_OnDisplayChange()
{
// do not use lParam, since it may give us (0,0).
UINT cxScreen = GetSystemMetrics(SM_CXSCREEN);
UINT cyScreen = GetSystemMetrics(SM_CYSCREEN);
UINT cxOldScreen = _cxScreen;
UINT cyOldScreen = _cyScreen;
_cxScreen = cxScreen;
_cyScreen = cyScreen;
if (_hwnd) {
RECT rc;
GetWindowRect(_hwnd, &rc);
if (cxOldScreen)
rc.left = (rc.left * _cxScreen) / cxOldScreen;
if (cyOldScreen)
rc.top = (rc.top * _cyScreen) / cyOldScreen;
SetWindowPos(_hwnd, NULL, rc.left, rc.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
// we need to change the cached pos/size.
OffsetRect(&_rcFloat, rc.left - _rcFloat.left, rc.top - _rcFloat.top);
}
}
LRESULT CChannelDeskBarApp::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = 0;
switch (uMsg) {
case WM_CONTEXTMENU: // disable context menu MENU_DESKBARAPP
case WM_NCRBUTTONUP: // disable context menu MENU_WEBBAR
break;
case WM_GETMINMAXINFO: // prevent it from getting too small
((MINMAXINFO *)lParam)->ptMinTrackSize.x = TBWIDTH + 10;
((MINMAXINFO *)lParam)->ptMinTrackSize.y = TBHEIGHT + 10;
break;
default:
lRes = CDeskBarApp::v_WndProc(hwnd, uMsg, wParam, lParam);
if (_hwnd) { // If our window is still alive
switch (uMsg) {
case WM_DISPLAYCHANGE:
_OnDisplayChange(); // reposition when window resolution changes
break;
case WM_EXITSIZEMOVE:
_PersistState(); // persist pos/size
break;
}
}
}
return lRes;
}
LRESULT CALLBACK CChannelDeskBarApp::DummyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CChannelDeskBarApp* pcba = (CChannelDeskBarApp*)GetWindowPtr0(hwnd);
switch (uMsg) {
case WM_PALETTECHANGED :
return SendMessage(pcba->_hwnd, uMsg, wParam, lParam );
case WM_DISPLAYCHANGE :
// this message must be sent to the channel bar itself
PostMessage(pcba->_hwnd, uMsg, wParam, lParam);
// fall through ;
case WM_WININICHANGE :
case WM_SYSCOLORCHANGE :
PropagateMessage(pcba->_hwnd, uMsg, wParam, lParam, InSendMessage());
// fall through ;
default:
return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
}
}
// overload CDeskBarApp::_UpdateCaptionTitle() to set title to "ChanApp"
void CChannelDeskBarApp::_UpdateCaptionTitle()
{
SetWindowText(_hwnd, TEXT("ChanApp"));
}
// create the close button
void CChannelDeskBarApp::_CreateToolbar()
{
_hwndTB = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
WS_VISIBLE |
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_CUSTOMERASE |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOMOVEY | CCS_NOPARENTALIGN |
CCS_NORESIZE,
0, 2, TBWIDTH, TBHEIGHT, _hwnd, 0, HINST_THISDLL, NULL);
if (_hwndTB) {
static const TBBUTTON tb[] =
{
{ 1, IDM_AB_CLOSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0, 0 }
};
#ifndef UNIX
HIMAGELIST himl = ImageList_LoadImage(HINST_THISDLL,
MAKEINTRESOURCE(IDB_BROWSERTOOLBAR),
13, 0, RGB(255,0,255),
IMAGE_BITMAP, LR_CREATEDIBSECTION);
#else
HIMAGELIST himl;
COLORREF crTextColor = GetSysColor( COLOR_BTNTEXT );
crTextColor = MwGetTrueRGBValue( crTextColor );
himl = ImageList_LoadImage(HINST_THISDLL,
crTextColor == RGB(255,255,255) ?
MAKEINTRESOURCE(IDB_WHITEBROWSERTOOLBAR) :
MAKEINTRESOURCE(IDB_BROWSERTOOLBAR),
13, 0, RGB(255,0,255),
IMAGE_BITMAP, LR_CREATEDIBSECTION);
#endif
ImageList_SetBkColor(himl, RGB(0,0,0));
SendMessage(_hwndTB, TB_SETIMAGELIST, 0, (LPARAM)himl);
SendMessage(_hwndTB, TB_BUTTONSTRUCTSIZE, SIZEOF(TBBUTTON), 0);
SendMessage(_hwndTB, TB_ADDBUTTONS, ARRAYSIZE(tb), (LPARAM)tb);
SendMessage(_hwndTB, TB_SETINDENT, (WPARAM)0, 0);
_SizeTB();
}
}
HRESULT CChannelDeskBarApp::ShowDW(BOOL fShow)
{
if (fShow && !_hwndTB) {
_CreateToolbar();
}
HRESULT hres = CDeskBarApp::ShowDW(fShow);
return hres;
}
void CChannelDeskBarApp::_PositionTB()
{
// position the toolbar
if (_hwndTB) {
// always put the close restore at the top right of the floater window
RECT rc;
RECT rcTB;
GetClientRect(_hwnd, &rc);
GetWindowRect(_hwndTB, &rcTB);
rc.left = rc.right - RECTWIDTH(rcTB) - 2;
SetWindowPos(_hwndTB, HWND_TOP, rc.left, 2, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
}
}
void CChannelDeskBarApp::_SizeTB()
{
RECT rc;
GetWindowRect(_hwndTB, &rc);
LRESULT lButtonSize = SendMessage(_hwndTB, TB_GETBUTTONSIZE, 0, 0L);
SetWindowPos(_hwndTB, NULL, 0, 0, LOWORD(lButtonSize),
RECTHEIGHT(rc), SWP_NOMOVE | SWP_NOACTIVATE);
_PositionTB();
}
void CChannelDeskBarApp::_OnSize()
{
RECT rc, rcTB;
if (!_hwndChild)
return;
ASSERT(IsWindow(_hwndChild));
GetClientRect(_hwnd, &rc);
if (_hwndTB) {
GetWindowRect(_hwndTB, &rcTB);
SetWindowPos(_hwndTB, HWND_TOP, rc.right - RECTWIDTH(rcTB) - 2, 2, 0, 0,
SWP_NOSIZE | SWP_NOACTIVATE);
SetWindowPos(_hwndChild, 0, rc.left, rc.top + RECTHEIGHT(rcTB) + 3,
RECTWIDTH(rc), RECTHEIGHT(rc), SWP_NOACTIVATE|SWP_NOZORDER);
}
else {
// how could there be no toolbar?
ASSERT(0);
SetWindowPos(_hwndChild, 0, rc.left, rc.top + TBHEIGHT + 3,
RECTWIDTH(rc), RECTHEIGHT(rc), SWP_NOACTIVATE|SWP_NOZORDER);
}
rc.bottom = rc.top + TBHEIGHT + 3;
InvalidateRect(_hwnd, &rc, TRUE);
}
#define ABS(i) (((i) < 0) ? -(i) : (i))
LRESULT CChannelDeskBarApp::_OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
HWND hwnd = GET_WM_COMMAND_HWND(wParam, lParam);
if (hwnd == _hwndTB) {
switch (idCmd) {
case IDM_AB_CLOSE:
Exec(&CGID_DeskBarClient, DBCID_EMPTY, 0, NULL, NULL);
break;
}
} else {
return CDeskBarApp::_OnCommand(uMsg, wParam, lParam);
}
return 0;
}
BOOL CChannelDeskBarApp::_OnCloseBar(BOOL fConfirm)
{
return CDeskBarApp::_OnCloseBar(FALSE);
}
HRESULT CChannelDeskBarApp::CloseDW(DWORD dwReserved)
{
// close the toolbar window
if (_hwndTB) {
HIMAGELIST himl = (HIMAGELIST)SendMessage(_hwndTB, TB_SETIMAGELIST, 0, 0);
ImageList_Destroy(himl);
DestroyWindow(_hwndTB);
_hwndTB = NULL;
}
if (_hwnd) {
CDeskBarApp::CloseDW(dwReserved);
// Check the active desktop is ON. If so, do not ask for the confirmation.
// we need to kill the channel bar silently.
if (WhichPlatform() == PLATFORM_INTEGRATED) // SHGetSetSettings is not supported in IE3
{
SHELLSTATE ss = { 0 };
SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); // Get the setting
if (ss.fDesktopHTML) //Active desktop is ON. Die silently.
return S_OK;
}
// set AutoLaunch reg value --
// decide whether to launch channel bar when machine is rebooted next time
int iRes = MLShellMessageBox(_hwnd,
MAKEINTRESOURCE(IDS_CHANBAR_SHORTCUT_MSG),
MAKEINTRESOURCE(IDS_CHANBAR_SHORTCUT_TITLE),
MB_YESNO | MB_SETFOREGROUND);
ChanBarSetAutoLaunchRegValue(iRes == IDYES);
}
return S_OK;
}
// store position and size to registry
void CChannelDeskBarApp::_PersistState()
{
if (_hwnd) {
CISSTRUCT cis;
cis.iVer = 1;
GetWindowRect(_hwnd, &cis.rc);
SHRegSetUSValue(SZ_REGKEY_CHANBAR, SZ_REGVALUE_CHANBAR, REG_BINARY,
(LPVOID)&cis, sizeof(CISSTRUCT), SHREGSET_HKCU | SHREGSET_FORCE_HKCU );
}
}
void ChanBarSetAutoLaunchRegValue(BOOL fAutoLaunch)
{
SHRegSetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
TEXT("Show_ChannelBand"), REG_SZ,
fAutoLaunch ? TEXT("yes") : TEXT("no"),
sizeof(fAutoLaunch ? TEXT("yes") : TEXT("no")),
SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
}
//***
// NOTES
// REARCHITECT: nuke this, fold it into CChannelDeskBarApp_CreateInstance
HRESULT ChannelDeskBarApp_Create(IUnknown** ppunk, IUnknown** ppbs)
{
HRESULT hres;
*ppunk = NULL;
if (ppbs)
*ppbs = NULL;
CChannelDeskBarApp *pdb = new CChannelDeskBarApp();
if (!pdb)
return E_OUTOFMEMORY;
CBandSite *pcbs = new CBandSite(NULL);
if (pcbs)
{
IDeskBarClient *pdbc = SAFECAST(pcbs, IDeskBarClient*);
hres = pdb->SetClient(pdbc);
if (SUCCEEDED(hres))
{
if (ppbs) {
*ppbs = pdbc;
pdbc->AddRef();
}
pdb->_pbs = pcbs;
pcbs->AddRef();
*ppunk = SAFECAST(pdb, IDeskBar*);
}
pdbc->Release();
}
else
{
hres = E_OUTOFMEMORY;
}
if (FAILED(hres))
{
pdb->Release();
}
return hres;
}
HRESULT CChannelDeskBarApp::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
{
HRESULT hres = CDeskBarApp::Load(pPropBag, pErrorLog);
BANDSITEINFO bsinfo;
bsinfo.dwMask = BSIM_STYLE;
bsinfo.dwStyle = BSIS_NOGRIPPER | BSIS_NODROPTARGET;
_pbs->SetBandSiteInfo(&bsinfo);
return hres;
}
#endif // ENABLE_CHANNELS