windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/floatbar.cpp
2020-09-26 16:20:57 +08:00

297 lines
8.1 KiB
C++

// File: floatbar.cpp
#include "precomp.h"
#include "global.h"
#include "ConfRoom.h"
#include "cmd.h"
#include "FloatBar.h"
#include "resource.h"
#include "ConfPolicies.h"
CFloatToolbar::CFloatToolbar(CConfRoom* pcr):
m_pConfRoom (pcr),
m_hwnd (NULL),
m_hwndT (NULL),
m_hBmp (NULL),
m_fInPopup (FALSE)
{
TRACE_OUT(("Constructing CFloatToolbar"));
}
CFloatToolbar::~CFloatToolbar()
{
TRACE_OUT(("Destructing CFloatToolbar"));
ASSERT(!m_fInPopup);
if (NULL != m_hBmp)
{
::DeleteObject(m_hBmp);
}
if (NULL != m_hwnd)
{
// bug 1450: don't destroy the window inside the notification,
// instead, use PostMessage() to insure that we return from the
// WM_NOTIFY message before the window is destroyed:
::PostMessage(m_hwnd, WM_CLOSE, 0L, 0L);
// DestroyWindow(m_hwnd);
}
}
/****************************************************************************
*
* CLASS: CFloatToolbar
*
* MEMBER: FloatWndProc(HWND, unsigned, WORD, LONG)
*
* PURPOSE:
*
****************************************************************************/
LRESULT CALLBACK CFloatToolbar::FloatWndProc(
HWND hWnd, /* window handle */
UINT message, /* type of message */
WPARAM wParam, /* additional information */
LPARAM lParam) /* additional information */
{
CFloatToolbar* pft;
LPCREATESTRUCT lpcs;
switch (message)
{
case WM_CREATE:
{
TRACE_OUT(("Float Window created"));
lpcs = (LPCREATESTRUCT) lParam;
pft = (CFloatToolbar*) lpcs->lpCreateParams;
ASSERT(pft);
::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pft);
const COLORMAP MyColorMap[] =
{
{TOOLBAR_MASK_COLOR, ::GetSysColor(COLOR_BTNFACE)}, // bright grey
{TOOLBAR_HIGHLIGHT_COLOR, ::GetSysColor(COLOR_BTNHIGHLIGHT)},// white
};
pft->m_hBmp = ::CreateMappedBitmap( GetInstanceHandle(),
IDB_POPUPBAR,
0,
(LPCOLORMAP) MyColorMap,
2);
CConfRoom * pcr = GetConfRoom();
BYTE bASState = (pcr && pcr->IsSharingAllowed()) ? TBSTATE_ENABLED : 0;
BYTE bChatState = (pcr && pcr->IsChatAllowed()) ? TBSTATE_ENABLED : 0;
BYTE bWBState = (pcr && pcr->IsNewWhiteboardAllowed()) ? TBSTATE_ENABLED : 0;
BYTE bFTState = (pcr && pcr->IsFileTransferAllowed()) ? TBSTATE_ENABLED : 0;
TBBUTTON tbFloatButtonAry[] =
{
{ ShareBitmapIndex , ID_TB_SHARING , bASState, TBSTYLE_BUTTON, 0, -1 },
{ ChatBitmapIndex , ID_TB_CHAT , bChatState, TBSTYLE_BUTTON, 0, -1 },
{ WhiteboardBitmapIndex, ID_TB_NEWWHITEBOARD, bWBState, TBSTYLE_BUTTON, 0, -1 },
{ FTBitmapIndex , ID_TB_FILETRANSFER , bFTState, TBSTYLE_BUTTON, 0, -1 },
} ;
ASSERT(pft->m_pConfRoom);
pft->m_hwndT = CreateToolbarEx(hWnd,
WS_CHILD | WS_VISIBLE | CCS_NODIVIDER |
TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE,
ID_FLOAT_TOOLBAR,
NUM_FLOATBAR_TOOLBAR_BITMAPS,
NULL, // no instance
(UINT_PTR) pft->m_hBmp, // bitmap handle
tbFloatButtonAry, // buttons
ARRAY_ELEMENTS(tbFloatButtonAry),
16, 16, // button sizes
16, 16, // bitmap sizes
sizeof(TBBUTTON));
ASSERT(pft->m_hwndT);
// Put buttons in the correct state:
pft->UpdateButtons();
// Make the toolbar control window active so we can insure we will get a
// WM_ACTIVATE when the user clicks somewhere off the toolbar
::SetForegroundWindow(pft->m_hwndT);
break;
}
case WM_ACTIVATE:
{
// Click outside the toolbar:
pft = (CFloatToolbar*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
//
// Kill the toolbar if we're not in the middle of handling the
// popup menu with the list of apps to share. In that case,
// activation will cancel menu mode and we'll get a chance to
// kill ourselves after we come back.
//
// We don't want to because COMCTL32 will trash our heap. It
// can't handle the toolbar window and structure going away
// while processing a TBN_DROPDOWN notification. When we return
// back it will try to use the now-freed window data.
//
// Yes, we post ourselves a WM_CLOSE on destroy, but with a
// message box up or other things, this could easily be
// processed long before menu processing returns.
//
if ((NULL != pft) &&
(!pft->m_fInPopup) &&
(NULL != pft->m_hwnd) &&
(NULL != pft->m_hwndT))
{
// NULL out the object pointer:
::SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
delete pft;
}
break;
}
case WM_NOTIFY:
{
// BUGBUG: Copied from CConfRoom : put this is a central location:
LPNMHDR pnmh = (LPNMHDR) lParam;
if (TTN_NEEDTEXT == pnmh->code)
{
LPTOOLTIPTEXT lpToolTipText = (LPTOOLTIPTEXT)lParam;
if (0 == (TTF_IDISHWND & lpToolTipText->uFlags))
{
lpToolTipText->hinst = ::GetInstanceHandle();
lpToolTipText->lpszText = (LPTSTR) lpToolTipText->hdr.idFrom;
}
}
break;
}
case WM_COMMAND:
{
TRACE_OUT(("Float Window command wp=0x%x", wParam));
pft = (CFloatToolbar*) ::GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (NULL != pft)
{
if (NULL != pft->m_pConfRoom)
{
::PostMessage(pft->m_pConfRoom->GetTopHwnd(), WM_COMMAND,
wParam, lParam);
}
//
// If we're in the middle of the popup, don't kill ourself.
// We wait until the stack unwinds back above.
//
if (!pft->m_fInPopup)
{
// Dismiss the floating toolbar window:
// NULL out the object pointer:
::SetWindowLongPtr(hWnd, GWLP_USERDATA, 0L);
delete pft;
}
}
break;
}
default:
{
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
}
return FALSE;
}
/****************************************************************************
*
* CLASS: CFloatToolbar
*
* MEMBER: Create(POINT ptClickPos)
*
* PURPOSE: Creates a floating toolbar window
*
****************************************************************************/
HWND CFloatToolbar::Create(POINT ptClickPos)
{
// BUGBUG: move these defines once the size is finalized
static const int TOOLBAR_WIDTH = 6 + 23 * NUM_FLOATBAR_STANDARD_TOOLBAR_BUTTONS;
static const int TOOLBAR_HEIGHT = 6 + 22 * 1;
HWND hwndDesktop = GetDesktopWindow();
RECT rctDesktop;
if (NULL != hwndDesktop)
{
if (GetWindowRect(hwndDesktop, &rctDesktop))
{
// First attempt will be to center the toolbar horizontally
// with respect to the mouse position and place it directly
// above vertically.
int xPos = ptClickPos.x - (TOOLBAR_WIDTH / 2);
int yPos = ptClickPos.y - (TOOLBAR_HEIGHT);
// If we are too high on the screen (the taskbar is probably
// docked on top), then use the click position as the top of
// where the toolbar will appear.
if (yPos < 0)
{
yPos = ptClickPos.y;
}
// Repeat the same logic for the horizontal position
if (xPos < 0)
{
xPos = ptClickPos.x;
}
// If the toolbar if off the screen to the right, then right-justify it
if (xPos > (rctDesktop.right - TOOLBAR_WIDTH))
{
xPos = ptClickPos.x - TOOLBAR_WIDTH;
}
m_hwnd = CreateWindowEx(WS_EX_PALETTEWINDOW,
g_szFloatWndClass,
g_szEmpty,
WS_POPUP | WS_VISIBLE | WS_DLGFRAME,
xPos, yPos,
TOOLBAR_WIDTH, TOOLBAR_HEIGHT,
NULL,
NULL,
_Module.GetModuleInstance(),
(LPVOID) this);
return m_hwnd;
}
}
// Something went wrong
return NULL;
}
/****************************************************************************
*
* CLASS: CFloatToolbar
*
* MEMBER: UpdateButtons()
*
* PURPOSE: Puts the toolbar buttons in their correct state
*
****************************************************************************/
BOOL CFloatToolbar::UpdateButtons()
{
return TRUE;
}