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