⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 status.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Interface code to StatusWindow widget/control
 *
 * Copyright 1996 Bruce Milner
 * Copyright 1998, 1999 Eric Kohl
 * Copyright 2002 Dimitrie O. Paun
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 * NOTE
 * 
 * This code was audited for completeness against the documented features
 * of Comctl32.dll version 6.0 on Sep. 24, 2002, by Dimitrie O. Paun.
 * 
 * Unless otherwise noted, we believe this code to be complete, as per
 * the specification mentioned above.
 * If you discover missing features, or bugs, please note them below.
 * 
 * TODO:
 * 	-- CCS_BOTTOM (default)
 * 	-- CCS_LEFT
 * 	-- CCS_NODEVIDER
 * 	-- CCS_NOMOVEX
 * 	-- CCS_NOMOVEY
 * 	-- CCS_NOPARENTALIGN
 * 	-- CCS_RIGHT
 * 	-- CCS_TOP
 * 	-- CCS_VERT (defaults to RIGHT)
 */

#include <stdarg.h>
#include <string.h>

#include "windef.h"
#include "winbase.h"
#include "wine/unicode.h"
#include "wingdi.h"
#include "winuser.h"
#include "winnls.h"
#include "commctrl.h"
#include "comctl32.h"
#include "uxtheme.h"
#include "tmschema.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(statusbar);

typedef struct
{
    INT 	x;
    INT 	style;
    RECT	bound;
    LPWSTR	text;
    HICON       hIcon;
} STATUSWINDOWPART;

typedef struct
{
    HWND              Self;
    HWND              Notify;
    WORD              numParts;
    UINT              height;
    BOOL              simple;
    HWND              hwndToolTip;
    HFONT             hFont;
    HFONT             hDefaultFont;
    COLORREF          clrBk;		/* background color */
    BOOL              bUnicode;		/* unicode flag */
    BOOL              NtfUnicode;	/* notify format */
    STATUSWINDOWPART  part0;		/* simple window */
    STATUSWINDOWPART* parts;
    INT               horizontalBorder;
    INT               verticalBorder;
    INT               horizontalGap;
} STATUS_INFO;

/*
 * Run tests using Waite Group Windows95 API Bible Vol. 1&2
 * The second cdrom contains executables drawstat.exe, gettext.exe,
 * simple.exe, getparts.exe, setparts.exe, statwnd.exe
 */

#define HORZ_BORDER 0
#define VERT_BORDER 2
#define HORZ_GAP    2

static const WCHAR themeClass[] = { 'S','t','a','t','u','s',0 };

/* prototype */
static void
STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr);

static inline LPCSTR debugstr_t(LPCWSTR text, BOOL isW)
{
  return isW ? debugstr_w(text) : debugstr_a((LPCSTR)text);
}

static void
STATUSBAR_DrawSizeGrip (HTHEME theme, HDC hdc, LPRECT lpRect)
{
    HPEN hPenFace, hPenShadow, hPenHighlight, hOldPen;
    POINT pt;
    INT i;

    TRACE("draw size grip %d,%d - %d,%d\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
    
    if (theme)
    {
        RECT gripperRect;
        SIZE gripperSize;
        gripperRect = *lpRect;
        if (SUCCEEDED (GetThemePartSize (theme, hdc, SP_GRIPPER, 0, lpRect, 
            TS_DRAW, &gripperSize)))
        {
            gripperRect.left = gripperRect.right - gripperSize.cx;
            gripperRect.top = gripperRect.bottom - gripperSize.cy;
            if (SUCCEEDED (DrawThemeBackground(theme, hdc, SP_GRIPPER, 0, &gripperRect, NULL)))
                return;
        }
    }

    pt.x = lpRect->right - 1;
    pt.y = lpRect->bottom - 1;

    hPenFace = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DFACE ));
    hOldPen = SelectObject( hdc, hPenFace );
    MoveToEx (hdc, pt.x - 12, pt.y, NULL);
    LineTo (hdc, pt.x, pt.y);
    LineTo (hdc, pt.x, pt.y - 13);

    pt.x--;
    pt.y--;

    hPenShadow = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DSHADOW ));
    SelectObject( hdc, hPenShadow );
    for (i = 1; i < 11; i += 4) {
	MoveToEx (hdc, pt.x - i, pt.y, NULL);
	LineTo (hdc, pt.x + 1, pt.y - i - 1);

	MoveToEx (hdc, pt.x - i - 1, pt.y, NULL);
	LineTo (hdc, pt.x + 1, pt.y - i - 2);
    }

    hPenHighlight = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DHIGHLIGHT ));
    SelectObject( hdc, hPenHighlight );
    for (i = 3; i < 13; i += 4) {
	MoveToEx (hdc, pt.x - i, pt.y, NULL);
	LineTo (hdc, pt.x + 1, pt.y - i - 1);
    }

    SelectObject (hdc, hOldPen);
    DeleteObject( hPenFace );
    DeleteObject( hPenShadow );
    DeleteObject( hPenHighlight );
}


static void
STATUSBAR_DrawPart (STATUS_INFO *infoPtr, HDC hdc, STATUSWINDOWPART *part, int itemID)
{
    RECT r = part->bound;
    UINT border = BDR_SUNKENOUTER;
    HTHEME theme = GetWindowTheme (infoPtr->Self);
    int themePart = SP_PANE;

    TRACE("part bound %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom);
    if (part->style & SBT_POPOUT)
        border = BDR_RAISEDOUTER;
    else if (part->style & SBT_NOBORDERS)
        border = 0;

    if (theme)
    {
        if ((GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP)
            && (infoPtr->simple || (itemID == (infoPtr->numParts-1))))
            themePart = SP_GRIPPERPANE;
        DrawThemeBackground(theme, hdc, themePart, 0, &r, NULL);
    }
    else
        DrawEdge(hdc, &r, border, BF_RECT|BF_ADJUST);

    if (part->style & SBT_OWNERDRAW) {
	DRAWITEMSTRUCT dis;

	dis.CtlID = GetWindowLongPtrW (infoPtr->Self, GWLP_ID);
	dis.itemID = itemID;
	dis.hwndItem = infoPtr->Self;
	dis.hDC = hdc;
	dis.rcItem = r;
	dis.itemData = (ULONG_PTR)part->text;
	SendMessageW (infoPtr->Notify, WM_DRAWITEM, (WPARAM)dis.CtlID, (LPARAM)&dis);
    } else {
	if (part->hIcon) {
	   INT cy = r.bottom - r.top;

	    r.left += 2;
	    DrawIconEx (hdc, r.left, r.top, part->hIcon, cy, cy, 0, 0, DI_NORMAL);
	    r.left += cy;
	}
        DrawStatusTextW (hdc, &r, part->text, SBT_NOBORDERS);
    }
}


static void
STATUSBAR_RefreshPart (STATUS_INFO *infoPtr, HDC hdc, STATUSWINDOWPART *part, int itemID)
{
    HBRUSH hbrBk;
    HFONT  hOldFont;
    HTHEME theme;

    TRACE("item %d\n", itemID);
    if (!IsWindowVisible (infoPtr->Self))
        return;

    if (part->bound.right < part->bound.left) return;

    if ((theme = GetWindowTheme (infoPtr->Self)))
    {
        RECT cr;
        GetClientRect (infoPtr->Self, &cr);
        DrawThemeBackground(theme, hdc, 0, 0, &cr, &part->bound);
    }
    else
    {
        if (infoPtr->clrBk != CLR_DEFAULT)
                hbrBk = CreateSolidBrush (infoPtr->clrBk);
        else
                hbrBk = GetSysColorBrush (COLOR_3DFACE);
        FillRect(hdc, &part->bound, hbrBk);
        if (infoPtr->clrBk != CLR_DEFAULT)
                DeleteObject (hbrBk);
    }

    hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);

	STATUSBAR_DrawPart (infoPtr, hdc, part, itemID);

    SelectObject (hdc, hOldFont);

    if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP) {
        RECT rect;

	GetClientRect (infoPtr->Self, &rect);
	STATUSBAR_DrawSizeGrip (theme, hdc, &rect);
    }
}


static LRESULT
STATUSBAR_Refresh (STATUS_INFO *infoPtr, HDC hdc)
{
    int      i;
    RECT   rect;
    HBRUSH hbrBk;
    HFONT  hOldFont;
    HTHEME theme;

    TRACE("\n");
    if (!IsWindowVisible(infoPtr->Self))
        return 0;

    STATUSBAR_SetPartBounds(infoPtr);

    GetClientRect (infoPtr->Self, &rect);

    if ((theme = GetWindowTheme (infoPtr->Self)))
    {
        DrawThemeBackground(theme, hdc, 0, 0, &rect, NULL);
    }
    else
    {
        if (infoPtr->clrBk != CLR_DEFAULT)
            hbrBk = CreateSolidBrush (infoPtr->clrBk);
        else
            hbrBk = GetSysColorBrush (COLOR_3DFACE);
        FillRect(hdc, &rect, hbrBk);
        if (infoPtr->clrBk != CLR_DEFAULT)
            DeleteObject (hbrBk);
    }

    hOldFont = SelectObject (hdc, infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont);

    if (infoPtr->simple) {
	STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->part0, 0);
    } else {
	for (i = 0; i < infoPtr->numParts; i++) {
	    STATUSBAR_RefreshPart (infoPtr, hdc, &infoPtr->parts[i], i);
	}
    }

    SelectObject (hdc, hOldFont);

    if (GetWindowLongW (infoPtr->Self, GWL_STYLE) & SBARS_SIZEGRIP)
	    STATUSBAR_DrawSizeGrip (theme, hdc, &rect);

    return 0;
}


static void
STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr)
{
    STATUSWINDOWPART *part;
    RECT rect, *r;
    int	i;

    /* get our window size */
    GetClientRect (infoPtr->Self, &rect);
    TRACE("client wnd size is %d,%d - %d,%d\n", rect.left, rect.top, rect.right, rect.bottom);

    rect.left += infoPtr->horizontalBorder;
    rect.top += infoPtr->verticalBorder;

    /* set bounds for simple rectangle */
    infoPtr->part0.bound = rect;

    /* set bounds for non-simple rectangles */
    for (i = 0; i < infoPtr->numParts; i++) {
	part = &infoPtr->parts[i];
	r = &infoPtr->parts[i].bound;
	r->top = rect.top;
	r->bottom = rect.bottom;
	if (i == 0)
	    r->left = 0;
	else
	    r->left = infoPtr->parts[i-1].bound.right + infoPtr->horizontalGap;
	if (part->x == -1)
	    r->right = rect.right;
	else
	    r->right = part->x;

	if (infoPtr->hwndToolTip) {
	    TTTOOLINFOW ti;

	    ti.cbSize = sizeof(TTTOOLINFOW);
	    ti.hwnd = infoPtr->Self;
	    ti.uId = i;
	    ti.rect = *r;
	    SendMessageW (infoPtr->hwndToolTip, TTM_NEWTOOLRECTW,
			    0, (LPARAM)&ti);
	}
    }
}


static LRESULT
STATUSBAR_Relay2Tip (STATUS_INFO *infoPtr, UINT uMsg,
		     WPARAM wParam, LPARAM lParam)
{
    MSG msg;

    msg.hwnd = infoPtr->Self;
    msg.message = uMsg;
    msg.wParam = wParam;
    msg.lParam = lParam;
    msg.time = GetMessageTime ();
    msg.pt.x = (short)LOWORD(GetMessagePos ());
    msg.pt.y = (short)HIWORD(GetMessagePos ());

    return SendMessageW (infoPtr->hwndToolTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
}


static BOOL
STATUSBAR_GetBorders (STATUS_INFO *infoPtr, INT out[])
{
    TRACE("\n");
    out[0] = infoPtr->horizontalBorder;
    out[1] = infoPtr->verticalBorder;
    out[2] = infoPtr->horizontalGap;

    return TRUE;
}


static BOOL
STATUSBAR_SetBorders (STATUS_INFO *infoPtr, INT in[])
{
    TRACE("\n");
    infoPtr->horizontalBorder = in[0];
    infoPtr->verticalBorder = in[1];
    infoPtr->horizontalGap = in[2];
    InvalidateRect(infoPtr->Self, NULL, FALSE);

    return TRUE;
}


static HICON
STATUSBAR_GetIcon (STATUS_INFO *infoPtr, INT nPart)
{
    TRACE("%d\n", nPart);
    /* MSDN says: "simple parts are indexed with -1" */
    if ((nPart < -1) || (nPart >= infoPtr->numParts))
	return 0;

    if (nPart == -1)
        return (infoPtr->part0.hIcon);
    else
        return (infoPtr->parts[nPart].hIcon);
}


static INT
STATUSBAR_GetParts (STATUS_INFO *infoPtr, INT num_parts, INT parts[])
{
    INT   i;

    TRACE("(%d)\n", num_parts);
    if (parts) {
	for (i = 0; i < num_parts; i++) {
	    parts[i] = infoPtr->parts[i].x;
	}
    }
    return infoPtr->numParts;
}


static BOOL
STATUSBAR_GetRect (STATUS_INFO *infoPtr, INT nPart, LPRECT rect)
{
    TRACE("part %d\n", nPart);
    if (infoPtr->simple)
	*rect = infoPtr->part0.bound;
    else
	*rect = infoPtr->parts[nPart].bound;
    return TRUE;
}


static LRESULT
STATUSBAR_GetTextA (STATUS_INFO *infoPtr, INT nPart, LPSTR buf)
{
    STATUSWINDOWPART *part;
    LRESULT result;

    TRACE("part %d\n", nPart);

    /* MSDN says: "simple parts use index of 0", so this check is ok. */
    if (nPart < 0 || nPart >= infoPtr->numParts) return 0;

    if (infoPtr->simple)
	part = &infoPtr->part0;
    else
	part = &infoPtr->parts[nPart];

    if (part->style & SBT_OWNERDRAW)
	result = (LRESULT)part->text;
    else {
        DWORD len = part->text ? WideCharToMultiByte( CP_ACP, 0, part->text, -1,
                                                      NULL, 0, NULL, NULL ) - 1 : 0;
        result = MAKELONG( len, part->style );
        if (part->text && buf)
            WideCharToMultiByte( CP_ACP, 0, part->text, -1, buf, len+1, NULL, NULL );
    }
    return result;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -