Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

587 lines
13 KiB

//============================================================================
// Copyright (c) 1996, Microsoft Corporation
//
// File: bubble.c
//
// History:
// Abolade Gbadegesin Mar-1-1996 Created.
//
// This file contains code for the bubble-popup control.
//============================================================================
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <debug.h>
#include <nouiutil.h>
#include <uiutil.h>
#include "bpopup.h" // public declarations
#include "bubble.h" // private declarations
//----------------------------------------------------------------------------
// Function: BubblePopup_Init
//
// This function is called to initialize the control class.
// It registers the bubble-popup window class.
//----------------------------------------------------------------------------
BOOL
BubblePopup_Init(
IN HINSTANCE hinstance
) {
//
// if the window class is registered already, return
//
WNDCLASS wc;
if (GetClassInfo(hinstance, WC_BUBBLEPOPUP, &wc)) { return TRUE; }
//
// set up the window class for registration
//
wc.lpfnWndProc = BP_WndProc;
wc.hCursor = LoadCursor(hinstance, IDC_ARROW);
wc.hIcon = NULL;
wc.lpszMenuName = NULL;
wc.hInstance = hinstance;
wc.lpszClassName = WC_BUBBLEPOPUP;
wc.hbrBackground = (HBRUSH)(COLOR_INFOBK + 1);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbWndExtra = sizeof(BPOPUP *);
wc.cbClsExtra = 0;
return RegisterClass(&wc);
}
//----------------------------------------------------------------------------
// Function: BP_WndProc
//
// This is the window procedure for all windows in the BubblePopup class.
//----------------------------------------------------------------------------
LRESULT
CALLBACK
BP_WndProc(
IN HWND hwnd,
IN UINT uiMsg,
IN WPARAM wParam,
IN LPARAM lParam
) {
BPOPUP *pbp;
//
// attempt to retrieve the private data pointer for the window
// on WM_NCCREATE, this fails, so we allocate the data.
//
if ( NULL == hwnd)
{
return (LRESULT)FALSE;
}
pbp = BP_GetPtr(hwnd);
if (pbp == NULL) {
if (uiMsg != WM_NCCREATE) {
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
//
// allocate a block of memory
//
pbp = (BPOPUP *)Malloc(sizeof(BPOPUP));
if (pbp == NULL) { return (LRESULT)FALSE; }
//
// save the pointer in the window's private bytes
//
pbp->hwnd = hwnd;
//
//Reset Error code, because BP_SetPtr won't reset the error code when
//it succeeds
//
SetLastError( 0 );
if ((0 == BP_SetPtr(hwnd, pbp)) && (0 != GetLastError()))
{
Free(pbp);
return (LRESULT)FALSE;
}
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
//
// if the window is being destroyed, free the block allocated
// and set the private bytes pointer to NULL
//
if (uiMsg == WM_NCDESTROY) {
Free(pbp);
BP_SetPtr(hwnd, 0);
return (LRESULT)0;
}
//
// handle other messages
//
switch(uiMsg) {
HANDLE_MSG(pbp, WM_CREATE, BP_OnCreate);
HANDLE_MSG(pbp, WM_DESTROY, BP_OnDestroy);
case WM_PAINT: {
return BP_OnPaint(pbp);
}
case WM_WINDOWPOSCHANGED: {
BP_ResizeClient(pbp);
return 0;
}
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN: {
//
// hide the window if it is showing
//
BP_OnDeactivate(pbp);
return 0;
}
case WM_GETFONT: {
return (LRESULT)pbp->hfont;
}
case WM_SETFONT: {
BOOL bRet = BP_OnSetFont(pbp, (HFONT)wParam, (BOOL)LOWORD(lParam));
BP_ResizeClient(pbp);
if (pbp->dwFlags & BPFLAG_Activated) {
InvalidateRect(pbp->hwnd, NULL, TRUE);
UpdateWindow(pbp->hwnd);
}
return bRet;
}
case WM_SETTEXT: {
//
// change the text we're currently using,
// and invalidate our client area
//
Free0(pbp->pszText);
pbp->pszText = StrDup((PTSTR)lParam);
BP_ResizeClient(pbp);
if (pbp->dwFlags & BPFLAG_Activated) {
InvalidateRect(pbp->hwnd, NULL, TRUE);
UpdateWindow(pbp->hwnd);
}
return (pbp->pszText) ? TRUE : FALSE;
}
case WM_GETTEXT: {
//
// return the text we're currently using
//
PTSTR dst = (LPTSTR)lParam;
PTSTR src = pbp->pszText;
return lstrlen(lstrcpyn(dst, src ? src : TEXT(""), (int)wParam));
}
case WM_TIMER: {
BP_OnDeactivate(pbp);
return 0;
}
case BPM_SETTIMEOUT: {
pbp->uiTimeout = (UINT)lParam;
if (pbp->dwFlags & BPFLAG_Activated) {
KillTimer(pbp->hwnd, pbp->ulpTimer);
pbp->ulpTimer = SetTimer(
pbp->hwnd, BP_TimerId, pbp->uiTimeout, NULL
);
}
return 0;
}
case BPM_ACTIVATE: {
return BP_OnActivate(pbp);
}
case BPM_DEACTIVATE: {
return BP_OnDeactivate(pbp);
}
}
return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}
//----------------------------------------------------------------------------
// Function: BP_OnCreate
//
// This function handles the creation of private data for a bubble-popup.
//----------------------------------------------------------------------------
BOOL
BP_OnCreate(
IN BPOPUP * pbp,
IN CREATESTRUCT * pcs
) {
//
// initialize the structure members
//
pbp->iCtrlId = PtrToUlong(pcs->hMenu);
pbp->pszText = (pcs->lpszName ? StrDup((PTSTR)pcs->lpszName) : NULL);
pbp->dwFlags = 0;
pbp->ulpTimer = 0;
pbp->uiTimeout = 5000;
//
// we force the window to have the WS_POPUP style
//
SetWindowLong(pbp->hwnd, GWL_STYLE, WS_POPUP);
//
// set the WS_EX_TOOLWINDOW style to make sure
// that this window doesn't show up in the tasklist
//
SetWindowLong(pbp->hwnd, GWL_EXSTYLE, pcs->dwExStyle | WS_EX_TOOLWINDOW);
return BP_OnSetFont(pbp, NULL, FALSE);
}
//----------------------------------------------------------------------------
// Function: BP_OnDestroy
//
// This function handles the deallocation of private data for a bubble-popup.
//----------------------------------------------------------------------------
VOID
BP_OnDestroy(
IN BPOPUP * pbp
) {
//
// if the font was created by this window, delete it
//
if (pbp->dwFlags & BPFLAG_FontCreated) { DeleteObject(pbp->hfont); }
pbp->dwFlags = 0;
pbp->hfont = NULL;
}
//----------------------------------------------------------------------------
// Function: BP_OnSetFont
//
// This function handles the changing of the font in use by a bubble-popup.
//----------------------------------------------------------------------------
BOOL
BP_OnSetFont(
IN BPOPUP * pbp,
IN HFONT hfont,
IN BOOL bRedraw
) {
if (pbp->dwFlags & BPFLAG_FontCreated) { DeleteObject(pbp->hfont); }
pbp->dwFlags &= ~BPFLAG_FontCreated;
pbp->hfont = NULL;
if (!hfont) {
//
// (re)create the default font.
//
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
if (!SystemParametersInfo(
SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0
)) {
TRACE1("error %d getting font info", GetLastError());
return FALSE;
}
hfont = CreateFontIndirect(&ncm.lfStatusFont);
if (!hfont) {
TRACE("error creating bubble-popup font");
return FALSE;
}
pbp->dwFlags |= BPFLAG_FontCreated;
}
pbp->hfont = hfont;
if (bRedraw) { InvalidateRect(pbp->hwnd, NULL, TRUE); }
return TRUE;
}
//----------------------------------------------------------------------------
// Function: BP_OnGetRect
//
// This function recomputes the rectangle required to display
// a bubble-popup's current text.
//----------------------------------------------------------------------------
VOID
BP_OnGetRect(
IN BPOPUP * pbp,
IN RECT * prc
) {
if (!pbp->pszText) { SetRectEmpty(prc); }
else {
HFONT hfontOld;
HDC hdc = GetDC(pbp->hwnd);
if (hdc)
{
//
// select the font into the DC and compute the new rectangle
//
hfontOld = SelectObject(hdc, pbp->hfont);
DrawText(hdc, pbp->pszText, -1, prc, DT_CALCRECT | DT_EXPANDTABS);
if (hfontOld) { SelectObject(hdc, hfontOld); }
ReleaseDC(pbp->hwnd, hdc);
//
// make space in the rectangle for the border
//
InflateRect(
prc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)
);
}
}
//
// convert the rectangle to screen coordinates
//
MapWindowPoints(pbp->hwnd, NULL, (POINT *)prc, 2);
}
//----------------------------------------------------------------------------
// Function: BP_ResizeClient
//
// When a change occurs (e.g. font-change, new text) this function is called
// to resize the bubble-popup's window so the text still fits.
//----------------------------------------------------------------------------
VOID
BP_ResizeClient(
IN BPOPUP * pbp
) {
RECT rc;
//
// find out what size the window needs to be to hold
// the text it is currently set to display
//
BP_OnGetRect(pbp, &rc);
//
// resize the window so its client area is large enough
// to hold DrawText's output
//
SetWindowPos(
pbp->hwnd, HWND_TOPMOST, 0, 0, rc.right - rc.left,
rc.bottom - rc.top, SWP_NOMOVE
);
}
//----------------------------------------------------------------------------
// Function: BP_OnPaint
//
// This function handles the painting of a bubble-popup window.
//----------------------------------------------------------------------------
DWORD
BP_OnPaint(
IN BPOPUP * pbp
) {
HDC hdc;
HBRUSH hbr;
HFONT hfontOld;
PAINTSTRUCT ps;
RECT rc, rcText;
if (!pbp->hfont || !pbp->pszText) { return (DWORD)-1; }
hdc = BeginPaint(pbp->hwnd, &ps);
GetClientRect(pbp->hwnd, &rc);
rcText = rc;
InflateRect(
&rcText, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE)
);
hfontOld = SelectObject(hdc, pbp->hfont);
SetTextColor(hdc, GetSysColor(COLOR_INFOTEXT));
//
// clear the window's background
//
hbr = CreateSolidBrush(GetSysColor(COLOR_INFOBK));
if (hbr)
{
FillRect(hdc, &rc, hbr);
DeleteObject(hbr);
}
//
// draw our formatted text in the window
//
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, pbp->pszText, -1, &rcText, DT_EXPANDTABS);
//
// draw a border around the window
//
DrawEdge(hdc, &rc, BDR_RAISEDOUTER, BF_RECT);
if (hfontOld) { SelectObject(hdc, hfontOld); }
EndPaint(pbp->hwnd, &ps);
return 0;
}
BOOL
BP_OnActivate(
IN BPOPUP * pbp
) {
if (pbp->dwFlags & BPFLAG_Activated) {
KillTimer(pbp->hwnd, pbp->ulpTimer);
}
ShowWindow(pbp->hwnd, SW_SHOW);
UpdateWindow(pbp->hwnd);
pbp->ulpTimer = SetTimer(pbp->hwnd, BP_TimerId, pbp->uiTimeout, NULL);
pbp->dwFlags |= BPFLAG_Activated;
return TRUE;
}
BOOL
BP_OnDeactivate(
IN BPOPUP * pbp
) {
if (pbp->ulpTimer) { KillTimer(pbp->hwnd, pbp->ulpTimer); pbp->ulpTimer = 0; }
ShowWindow(pbp->hwnd, SW_HIDE);
pbp->dwFlags &= ~BPFLAG_Activated;
return TRUE;
}