📄 status.c
字号:
/*
* 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 + -