760 lines
19 KiB
C++
760 lines
19 KiB
C++
|
#include "main.h"
|
||
|
#include "./welcomeWidget.h"
|
||
|
#include "../winamp/commandLink.h"
|
||
|
|
||
|
#include <strsafe.h>
|
||
|
|
||
|
#define WELCOMEWIDGET_OFFSET_LEFT_DLU 4
|
||
|
#define WELCOMEWIDGET_OFFSET_TOP_DLU 2
|
||
|
#define WELCOMEWIDGET_OFFSET_RIGHT_DLU 4
|
||
|
#define WELCOMEWIDGET_OFFSET_BOTTOM_DLU 2
|
||
|
|
||
|
#define WELCOMEWIDGET_IMAGE_MIN_WIDTH 280
|
||
|
#define WELCOMEWIDGET_IMAGE_MIN_HEIGHT (424 - 200)
|
||
|
|
||
|
#define WELCOMEWIDGET_TITLE_MAX_HEIGHT 168
|
||
|
#define WELCOMEWIDGET_TITLE_MIN_WIDTH WELCOMEWIDGET_IMAGE_MIN_WIDTH
|
||
|
|
||
|
#define WELCOMEWIDGET_TEXT_MAX_HEIGHT 66
|
||
|
#define WELCOMEWIDGET_TEXT_MIN_WIDTH WELCOMEWIDGET_IMAGE_MIN_WIDTH
|
||
|
|
||
|
#define WELCOMEWIDGET_HELP_LINK 1000
|
||
|
|
||
|
typedef struct WelcomeWidget
|
||
|
{
|
||
|
HDC context;
|
||
|
long contextWidth;
|
||
|
long contextHeight;
|
||
|
HBITMAP previousBitmap;
|
||
|
HFONT helpFont;
|
||
|
} WelcomeWidget;
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_GetBestTextRect(HDC hdc, const wchar_t *text, unsigned int length,
|
||
|
RECT *rect, long maxWidth, unsigned int format)
|
||
|
{
|
||
|
RECT testRect;
|
||
|
long right;
|
||
|
|
||
|
if (NULL == rect)
|
||
|
return FALSE;
|
||
|
|
||
|
format |= DT_CALCRECT;
|
||
|
|
||
|
if (length < 0)
|
||
|
length = (NULL != text) ? lstrlen(text) : 0;
|
||
|
|
||
|
if (0 == length || NULL == text)
|
||
|
{
|
||
|
rect->right = rect->left;
|
||
|
rect->bottom = rect->top;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
SetRect(&testRect, rect->left, rect->top, rect->right, rect->top);
|
||
|
maxWidth += rect->left;
|
||
|
right = rect->right;
|
||
|
|
||
|
for(;;)
|
||
|
{
|
||
|
if (FALSE == DrawText(hdc, text, length, &testRect, format))
|
||
|
return FALSE;
|
||
|
|
||
|
if (testRect.bottom <= rect->bottom || right >= maxWidth)
|
||
|
{
|
||
|
CopyRect(rect, &testRect);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
long increment = maxWidth - right;
|
||
|
if (increment > 60)
|
||
|
increment = increment / 4;
|
||
|
else if (increment > 4)
|
||
|
increment = increment / 2;
|
||
|
|
||
|
right += increment;
|
||
|
testRect.right = right;
|
||
|
testRect.bottom = rect->top;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static COLORREF
|
||
|
WelcomeWidget_GetTextColor(WidgetStyle *style, COLORREF *shadowColor, BOOL titleMode)
|
||
|
{
|
||
|
COLORREF frontColor, backColor;
|
||
|
WORD backHue, backLuma, backSat, frontHue, frontLuma, frontSat;
|
||
|
|
||
|
backColor = WIDGETSTYLE_BACK_COLOR(style);
|
||
|
frontColor = WIDGETSTYLE_TEXT_COLOR(style);
|
||
|
|
||
|
ColorRGBToHLS(backColor, &backHue, &backLuma, &backSat);
|
||
|
ColorRGBToHLS(frontColor, &frontHue, &frontLuma, &frontSat);
|
||
|
|
||
|
if(frontLuma > backLuma)
|
||
|
{
|
||
|
if (NULL != shadowColor)
|
||
|
{
|
||
|
if (FALSE != titleMode || backLuma > 180)
|
||
|
*shadowColor = Graphics_BlendColors(0x000000, backColor, 102);
|
||
|
else
|
||
|
*shadowColor = backColor;
|
||
|
}
|
||
|
|
||
|
return Graphics_BlendColors((FALSE != titleMode) ? 0xBBBBBB : 0xEEEEEE, frontColor, 230);
|
||
|
}
|
||
|
|
||
|
if (NULL != shadowColor)
|
||
|
{
|
||
|
if (FALSE != titleMode || backLuma < 60)
|
||
|
*shadowColor = Graphics_BlendColors(0xFFFFFF, backColor, 102);
|
||
|
else
|
||
|
*shadowColor = backColor;
|
||
|
}
|
||
|
|
||
|
return Graphics_BlendColors((FALSE != titleMode) ? 0x333333 : 0x111111, frontColor, 230);
|
||
|
}
|
||
|
|
||
|
static HFONT
|
||
|
WelcomeWidget_CreateTitleFont(WidgetStyle *style, HDC hdc)
|
||
|
{
|
||
|
LOGFONT lf;
|
||
|
HFONT textFont;
|
||
|
long height, pixelsY;
|
||
|
|
||
|
pixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
|
||
|
height = MulDiv(16, pixelsY, 96);
|
||
|
|
||
|
textFont = WIDGETSTYLE_TITLE_FONT(style);
|
||
|
if (NULL != textFont)
|
||
|
{
|
||
|
HFONT prevFont;
|
||
|
TEXTMETRIC tm;
|
||
|
|
||
|
prevFont = SelectFont(hdc, textFont);
|
||
|
if (FALSE != GetTextMetricsW(hdc, &tm))
|
||
|
{
|
||
|
long test = MulDiv(tm.tmHeight - tm.tmInternalLeading, 96, pixelsY);
|
||
|
test = MulDiv((test + 2), pixelsY, 72);
|
||
|
if (test > height)
|
||
|
height = test;
|
||
|
}
|
||
|
SelectFont(hdc, prevFont);
|
||
|
}
|
||
|
|
||
|
lf.lfHeight = -height;
|
||
|
lf.lfWidth = 0;
|
||
|
lf.lfEscapement = 0;
|
||
|
lf.lfOrientation = 0;
|
||
|
lf.lfWeight = FW_DONTCARE;
|
||
|
lf.lfItalic = FALSE;
|
||
|
lf.lfUnderline = FALSE;
|
||
|
lf.lfStrikeOut = FALSE;
|
||
|
lf.lfCharSet = DEFAULT_CHARSET;
|
||
|
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||
|
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||
|
lf.lfQuality = Graphics_GetSysFontQuality();
|
||
|
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||
|
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial");
|
||
|
|
||
|
return CreateFontIndirect(&lf);
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_FillContext(HDC targetDC, long width, long height, HDC sourceDC,
|
||
|
HBITMAP backBitmap, long backWidth, long backHeight, WidgetStyle *style)
|
||
|
{
|
||
|
RECT rect, partRect;
|
||
|
wchar_t buffer[4096] = {0};
|
||
|
int bufferLength;
|
||
|
COLORREF textColor, shadowColor;
|
||
|
HFONT prevFont;
|
||
|
|
||
|
if (NULL == targetDC ||
|
||
|
NULL == sourceDC ||
|
||
|
NULL == style)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
SetRect(&rect, 0, 0, width, height);
|
||
|
|
||
|
FillRect(targetDC, &rect, WIDGETSTYLE_BACK_BRUSH(style));
|
||
|
|
||
|
|
||
|
if (NULL != backBitmap)
|
||
|
{
|
||
|
Image_AlphaBlend(targetDC, &rect, sourceDC, NULL, 255, backBitmap, NULL,
|
||
|
AlphaBlend_AlignCenter | AlphaBlend_AlignVCenter, NULL);
|
||
|
}
|
||
|
|
||
|
SetBkMode(targetDC, TRANSPARENT);
|
||
|
|
||
|
|
||
|
WASABI_API_LNGSTRINGW_BUF(IDS_WELCOMEWIDGET_TITLE, buffer, ARRAYSIZE(buffer));
|
||
|
if (L'\0' != buffer[0])
|
||
|
{
|
||
|
BOOL textMode;
|
||
|
|
||
|
textMode = TRUE;
|
||
|
|
||
|
if (CSTR_EQUAL == CompareString(CSTR_INVARIANT, NORM_IGNORECASE, buffer, -1, L"WINAMP DEVICE MANAGER", -1))
|
||
|
{
|
||
|
HBITMAP titleBitmap;
|
||
|
titleBitmap = Image_LoadEx(Plugin_GetInstance(), MAKEINTRESOURCE(IDR_WELCOME_WIDGET_TITLE_IMAGE),
|
||
|
SRC_TYPE_PNG, ISF_PREMULTIPLY, 0, 0);
|
||
|
if (NULL != titleBitmap)
|
||
|
{
|
||
|
SetRect(&partRect, rect.left, rect.top, rect.right, rect.top + WELCOMEWIDGET_TITLE_MAX_HEIGHT);
|
||
|
|
||
|
if (FALSE != Image_AlphaBlend(targetDC, &partRect, sourceDC, NULL, 255, titleBitmap, NULL,
|
||
|
AlphaBlend_AlignCenter | AlphaBlend_AlignVCenter, NULL))
|
||
|
{
|
||
|
textMode = FALSE;
|
||
|
}
|
||
|
|
||
|
DeleteObject(titleBitmap);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (FALSE != textMode)
|
||
|
{
|
||
|
HFONT titleFont;
|
||
|
|
||
|
bufferLength = lstrlen(buffer);
|
||
|
|
||
|
titleFont = WelcomeWidget_CreateTitleFont(style, targetDC);
|
||
|
|
||
|
textColor = WelcomeWidget_GetTextColor(style, &shadowColor, TRUE);
|
||
|
prevFont = SelectFont(targetDC, (NULL != titleFont) ? titleFont : WIDGETSTYLE_TITLE_FONT(style));
|
||
|
|
||
|
SetRect(&partRect, 0, 0, width, 0);
|
||
|
|
||
|
if (FALSE != DrawText(targetDC, buffer, bufferLength, &partRect,
|
||
|
DT_CALCRECT | DT_LEFT | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS))
|
||
|
{
|
||
|
if (partRect.bottom > WELCOMEWIDGET_TITLE_MAX_HEIGHT)
|
||
|
{
|
||
|
TEXTMETRIC textMetrics;
|
||
|
if (FALSE != GetTextMetrics(targetDC, &textMetrics))
|
||
|
partRect.bottom = (WELCOMEWIDGET_TITLE_MAX_HEIGHT/textMetrics.tmHeight)*textMetrics.tmHeight;
|
||
|
}
|
||
|
|
||
|
OffsetRect(&partRect,
|
||
|
rect.left + (RECTWIDTH(rect) - RECTWIDTH(partRect))/2,
|
||
|
rect.top + (WELCOMEWIDGET_TITLE_MAX_HEIGHT - RECTHEIGHT(partRect))/2);
|
||
|
|
||
|
OffsetRect(&partRect, 0, 2);
|
||
|
SetTextColor(targetDC, shadowColor);
|
||
|
DrawText(targetDC, buffer, bufferLength, &partRect,
|
||
|
DT_CENTER | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS);
|
||
|
|
||
|
OffsetRect(&partRect, 0, -2);
|
||
|
|
||
|
SetTextColor(targetDC, textColor);
|
||
|
DrawText(targetDC, buffer, bufferLength, &partRect,
|
||
|
DT_CENTER | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS);
|
||
|
}
|
||
|
|
||
|
SelectFont(targetDC, prevFont);
|
||
|
if (NULL != titleFont)
|
||
|
DeleteObject(titleFont);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WASABI_API_LNGSTRINGW_BUF(IDS_WELCOMEWIDGET_TEXT, buffer, ARRAYSIZE(buffer));
|
||
|
if (L'\0' != buffer[0])
|
||
|
{
|
||
|
bufferLength = lstrlen(buffer);
|
||
|
|
||
|
textColor = WelcomeWidget_GetTextColor(style, &shadowColor, FALSE);
|
||
|
prevFont = SelectFont(targetDC, WIDGETSTYLE_TEXT_FONT(style));
|
||
|
|
||
|
SetRect(&partRect, 0, 0, WELCOMEWIDGET_TEXT_MIN_WIDTH, WELCOMEWIDGET_TEXT_MAX_HEIGHT);
|
||
|
|
||
|
if (FALSE != WelcomeWidget_GetBestTextRect(targetDC, buffer, bufferLength, &partRect, width,
|
||
|
DT_LEFT | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS))
|
||
|
{
|
||
|
if (partRect.bottom > WELCOMEWIDGET_TEXT_MAX_HEIGHT)
|
||
|
{
|
||
|
TEXTMETRIC textMetrics;
|
||
|
if (FALSE != GetTextMetrics(targetDC, &textMetrics))
|
||
|
partRect.bottom = (WELCOMEWIDGET_TEXT_MAX_HEIGHT/textMetrics.tmHeight)*textMetrics.tmHeight;
|
||
|
}
|
||
|
|
||
|
OffsetRect(&partRect,
|
||
|
rect.left + (RECTWIDTH(rect) - RECTWIDTH(partRect))/2,
|
||
|
rect.bottom - WELCOMEWIDGET_TEXT_MAX_HEIGHT);
|
||
|
|
||
|
OffsetRect(&partRect, 0, 1);
|
||
|
SetTextColor(targetDC, shadowColor);
|
||
|
DrawText(targetDC, buffer, bufferLength, &partRect,
|
||
|
DT_LEFT | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS);
|
||
|
|
||
|
OffsetRect(&partRect, 0, -1);
|
||
|
|
||
|
SetTextColor(targetDC, textColor);
|
||
|
DrawText(targetDC, buffer, bufferLength, &partRect,
|
||
|
DT_LEFT | DT_TOP | DT_WORDBREAK | DT_NOPREFIX | DT_EDITCONTROL | DT_END_ELLIPSIS);
|
||
|
}
|
||
|
|
||
|
SelectFont(targetDC, prevFont);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static HDC
|
||
|
WelcomeWidget_CreateContext(HWND hwnd, WidgetStyle *style, HBITMAP *prevBitmapOut, long *widthOut, long *heightOut)
|
||
|
{
|
||
|
|
||
|
HDC windowDC, targetDC, sourceDC;
|
||
|
HBITMAP backBitmap, targetBitmap;
|
||
|
HBITMAP prevTargetBitmap;
|
||
|
long width, height, backWidth, backHeight;
|
||
|
|
||
|
if (NULL == prevBitmapOut || NULL == style)
|
||
|
return NULL;
|
||
|
|
||
|
windowDC = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||
|
if (NULL == windowDC)
|
||
|
return NULL;
|
||
|
|
||
|
backBitmap = Image_LoadEx(Plugin_GetInstance(), MAKEINTRESOURCE(IDR_WELCOME_WIDGET_IMAGE),
|
||
|
SRC_TYPE_PNG, ISF_PREMULTIPLY, 0, 0);
|
||
|
|
||
|
width = WELCOMEWIDGET_IMAGE_MIN_WIDTH;
|
||
|
height = WELCOMEWIDGET_IMAGE_MIN_HEIGHT;
|
||
|
backWidth = 0;
|
||
|
backHeight = 0;
|
||
|
|
||
|
if (NULL != backBitmap)
|
||
|
{
|
||
|
BITMAP bi;
|
||
|
if (sizeof(bi) == GetObject(backBitmap, sizeof(bi), &bi))
|
||
|
{
|
||
|
backWidth = bi.bmWidth;
|
||
|
if (backWidth > width)
|
||
|
width = backWidth;
|
||
|
|
||
|
backHeight = ABS(bi.bmHeight);
|
||
|
if (backHeight > height)
|
||
|
height = backHeight;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
targetDC = CreateCompatibleDC(windowDC);
|
||
|
sourceDC = CreateCompatibleDC(windowDC);
|
||
|
targetBitmap = CreateCompatibleBitmap(windowDC, width, height);
|
||
|
prevTargetBitmap = NULL;
|
||
|
|
||
|
ReleaseDC(hwnd, windowDC);
|
||
|
|
||
|
if (NULL != targetDC &&
|
||
|
NULL != sourceDC &&
|
||
|
NULL != targetBitmap)
|
||
|
{
|
||
|
|
||
|
HFONT prevTargetFont;
|
||
|
prevTargetBitmap = SelectBitmap(targetDC, targetBitmap);
|
||
|
prevTargetFont = GetCurrentFont(targetDC);
|
||
|
HBITMAP prevSourceBitmap = GetCurrentBitmap(sourceDC);
|
||
|
|
||
|
if (FALSE == WelcomeWidget_FillContext(targetDC, width, height, sourceDC,
|
||
|
backBitmap, backWidth, backHeight, style))
|
||
|
{
|
||
|
SelectBitmap(targetDC, prevTargetBitmap);
|
||
|
prevTargetBitmap = NULL;
|
||
|
DeleteObject(targetBitmap);
|
||
|
targetBitmap = NULL;
|
||
|
}
|
||
|
|
||
|
SelectFont(targetDC, prevTargetFont);
|
||
|
SelectBitmap(sourceDC, prevSourceBitmap);
|
||
|
}
|
||
|
|
||
|
if (NULL != sourceDC)
|
||
|
DeleteDC(sourceDC);
|
||
|
|
||
|
if (NULL != targetDC && NULL == targetBitmap)
|
||
|
{
|
||
|
DeleteDC(targetDC);
|
||
|
targetDC = NULL;
|
||
|
prevTargetBitmap = NULL;
|
||
|
}
|
||
|
|
||
|
if (NULL != backBitmap)
|
||
|
DeleteObject(backBitmap);
|
||
|
|
||
|
*prevBitmapOut = prevTargetBitmap;
|
||
|
if (NULL != widthOut)
|
||
|
*widthOut = width;
|
||
|
if (NULL != heightOut)
|
||
|
*heightOut = height;
|
||
|
|
||
|
return targetDC;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_ResetContext(WelcomeWidget * self)
|
||
|
{
|
||
|
if (NULL == self ||
|
||
|
NULL == self->context)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (NULL != self->previousBitmap)
|
||
|
{
|
||
|
HBITMAP bitmap = SelectBitmap(self->context, self->previousBitmap);
|
||
|
if (NULL != bitmap)
|
||
|
DeleteObject(bitmap);
|
||
|
}
|
||
|
|
||
|
DeleteDC(self->context);
|
||
|
self->context = NULL;
|
||
|
self->previousBitmap = NULL;
|
||
|
self->contextWidth = 0;
|
||
|
self->contextHeight = 0;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_GetViewOrigin(HWND hwnd, POINT *pt)
|
||
|
{
|
||
|
SCROLLINFO scrollInfo;
|
||
|
|
||
|
if (NULL == pt)
|
||
|
return FALSE;
|
||
|
|
||
|
scrollInfo.cbSize = sizeof(scrollInfo);
|
||
|
scrollInfo.fMask = SIF_POS;
|
||
|
|
||
|
if (FALSE == GetScrollInfo(hwnd, SB_HORZ, &scrollInfo))
|
||
|
return FALSE;
|
||
|
pt->x = -scrollInfo.nPos;
|
||
|
|
||
|
if (FALSE == GetScrollInfo(hwnd, SB_VERT, &scrollInfo))
|
||
|
return FALSE;
|
||
|
pt->y = -scrollInfo.nPos;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_UpdateHelpPosition(WelcomeWidget *self, HWND hwnd, const RECT *clientRect, BOOL redraw)
|
||
|
{
|
||
|
HWND elementWindow;
|
||
|
RECT elementRect;
|
||
|
unsigned int positionFlags;
|
||
|
long left, top;
|
||
|
POINT origin;
|
||
|
|
||
|
if (NULL == self || NULL == hwnd || NULL == clientRect)
|
||
|
return FALSE;
|
||
|
|
||
|
elementWindow = GetDlgItem(hwnd, WELCOMEWIDGET_HELP_LINK);
|
||
|
if (NULL == elementWindow)
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
if (FALSE == WelcomeWidget_GetViewOrigin(hwnd, &origin))
|
||
|
{
|
||
|
origin.x = 0;
|
||
|
origin.y = 0;
|
||
|
}
|
||
|
|
||
|
if (FALSE == GetWindowRect(elementWindow, &elementRect))
|
||
|
return FALSE;
|
||
|
|
||
|
positionFlags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE;
|
||
|
if (FALSE == redraw)
|
||
|
positionFlags |= SWP_NOREDRAW;
|
||
|
|
||
|
left = clientRect->right;
|
||
|
left -= (RECTWIDTH(elementRect) + 2);
|
||
|
if (left < clientRect->left)
|
||
|
left = clientRect->left;
|
||
|
|
||
|
top = clientRect->top;
|
||
|
top += 2;
|
||
|
|
||
|
return SetWindowPos(elementWindow, NULL, left, origin.y + top, 0, 0, positionFlags);
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_EnsureHelpVisible(WelcomeWidget *self, HWND hwnd)
|
||
|
{
|
||
|
HWND elementWindow;
|
||
|
POINT origin;
|
||
|
|
||
|
if (NULL == self || NULL == hwnd)
|
||
|
return FALSE;
|
||
|
|
||
|
elementWindow = GetDlgItem(hwnd, WELCOMEWIDGET_HELP_LINK);
|
||
|
if (NULL == elementWindow)
|
||
|
return FALSE;
|
||
|
|
||
|
if (FALSE != WelcomeWidget_GetViewOrigin(hwnd, &origin) &&
|
||
|
0 != origin.y)
|
||
|
{
|
||
|
return WIDGET_SCROLL(hwnd, 0, origin.y, TRUE);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_GetHelpUrl(wchar_t *buffer, size_t bufferMax)
|
||
|
{
|
||
|
if (NULL == buffer)
|
||
|
return FALSE;
|
||
|
|
||
|
WASABI_API_LNGSTRINGW_BUF(IDS_WELCOMEWIDGET_HELP_URL, buffer, bufferMax);
|
||
|
return (L'\0' != buffer[0]);
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_InitCb(HWND hwnd, void **object, void *param)
|
||
|
{
|
||
|
wchar_t buffer[64] = {0};
|
||
|
WelcomeWidget *self = (WelcomeWidget*)malloc(sizeof(WelcomeWidget));
|
||
|
|
||
|
if (NULL == self)
|
||
|
return FALSE;
|
||
|
|
||
|
ZeroMemory(self, sizeof(WelcomeWidget));
|
||
|
WIDGET_ENABLE_CHILDREN_SCROLL(hwnd, FALSE);
|
||
|
|
||
|
|
||
|
WASABI_API_LNGSTRINGW_BUF(IDS_HELP_LINK, buffer, ARRAYSIZE(buffer));
|
||
|
CommandLink_CreateWindow(WS_EX_NOPARENTNOTIFY,
|
||
|
buffer,
|
||
|
WS_CHILD | WS_VISIBLE | WS_TABSTOP |
|
||
|
/*CLS_ALWAYSUNDERLINE |*/ CLS_HOTTRACK | CLS_HIGHLIGHTCOLOR,
|
||
|
0, 0, 0, 0, hwnd, WELCOMEWIDGET_HELP_LINK);
|
||
|
|
||
|
*object = self;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_DestroyCb(WelcomeWidget *self, HWND hwnd)
|
||
|
{
|
||
|
if (NULL == self)
|
||
|
return;
|
||
|
|
||
|
WelcomeWidget_ResetContext(self);
|
||
|
if (NULL != self->helpFont)
|
||
|
DeleteObject(self->helpFont);
|
||
|
|
||
|
free(self);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_LayoutCb(WelcomeWidget *self, HWND hwnd, WidgetStyle *style,
|
||
|
const RECT *clientRect, SIZE *viewSize, BOOL redraw)
|
||
|
{
|
||
|
if (NULL == self || NULL == style)
|
||
|
return;
|
||
|
|
||
|
if (NULL == self->context)
|
||
|
{
|
||
|
self->context = WelcomeWidget_CreateContext(hwnd, style, &self->previousBitmap, &self->contextWidth, &self->contextHeight);
|
||
|
if (NULL == self->context)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
viewSize->cx = self->contextWidth +
|
||
|
WIDGETSTYLE_DLU_TO_HORZ_PX(style, WELCOMEWIDGET_OFFSET_LEFT_DLU);
|
||
|
|
||
|
viewSize->cy = self->contextHeight +
|
||
|
WIDGETSTYLE_DLU_TO_VERT_PX(style, WELCOMEWIDGET_OFFSET_TOP_DLU);
|
||
|
|
||
|
|
||
|
WelcomeWidget_UpdateHelpPosition(self, hwnd, clientRect, redraw);
|
||
|
}
|
||
|
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_PaintCb(WelcomeWidget *self, HWND hwnd, WidgetStyle *style, HDC hdc, const RECT *paintRect, BOOL erase)
|
||
|
{
|
||
|
FillRegion fillRegion;
|
||
|
|
||
|
FillRegion_Init(&fillRegion, paintRect);
|
||
|
|
||
|
if (NULL != self->context)
|
||
|
{
|
||
|
RECT partRect, rect;
|
||
|
long offsetX, offsetY;
|
||
|
|
||
|
GetClientRect(hwnd, &rect);
|
||
|
|
||
|
SetRect(&partRect, 0, 0, self->contextWidth, self->contextHeight);
|
||
|
|
||
|
offsetX = rect.left + WIDGETSTYLE_DLU_TO_HORZ_PX(style, WELCOMEWIDGET_OFFSET_LEFT_DLU);
|
||
|
offsetY = WIDGETSTYLE_DLU_TO_HORZ_PX(style, WELCOMEWIDGET_OFFSET_RIGHT_DLU);
|
||
|
if ((offsetX + partRect.right + offsetY) < rect.right)
|
||
|
offsetX += (rect.right - (offsetX + partRect.right + offsetY))/2;
|
||
|
|
||
|
offsetY = rect.top + WIDGETSTYLE_DLU_TO_VERT_PX(style, WELCOMEWIDGET_OFFSET_TOP_DLU);
|
||
|
|
||
|
OffsetRect(&partRect, offsetX, offsetY);
|
||
|
|
||
|
if (FALSE != IntersectRect(&rect, &partRect, paintRect) &&
|
||
|
FALSE != BitBlt(hdc, rect.left, rect.top, RECTWIDTH(rect), RECTHEIGHT(rect),
|
||
|
self->context, rect.left - partRect.left, rect.top - partRect.top, SRCCOPY))
|
||
|
{
|
||
|
FillRegion_ExcludeRect(&fillRegion, &rect);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
if (FALSE != erase)
|
||
|
FillRegion_BrushFill(&fillRegion, hdc, WIDGETSTYLE_BACK_BRUSH(style));
|
||
|
|
||
|
FillRegion_Uninit(&fillRegion);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_StyleColorChangedCb(WelcomeWidget *self, HWND hwnd, WidgetStyle *style)
|
||
|
{
|
||
|
HWND elementWindow;
|
||
|
|
||
|
if (NULL == self)
|
||
|
return;
|
||
|
|
||
|
WelcomeWidget_ResetContext(self);
|
||
|
self->context = WelcomeWidget_CreateContext(hwnd, style, &self->previousBitmap, &self->contextWidth, &self->contextHeight);
|
||
|
|
||
|
elementWindow = GetDlgItem(hwnd, WELCOMEWIDGET_HELP_LINK);
|
||
|
if (NULL != elementWindow)
|
||
|
{
|
||
|
CommandLink_SetBackColor(elementWindow, WIDGETSTYLE_BACK_COLOR(style));
|
||
|
CommandLink_SetTextColor(elementWindow, WelcomeWidget_GetTextColor(style, NULL, TRUE));
|
||
|
CommandLink_SetHighlightColor(elementWindow, WelcomeWidget_GetTextColor(style, NULL, FALSE));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_StyleFontChangedCb(WelcomeWidget *self, HWND hwnd, WidgetStyle *style)
|
||
|
{
|
||
|
HWND elementWindow;
|
||
|
|
||
|
if (NULL == self)
|
||
|
return;
|
||
|
|
||
|
WelcomeWidget_ResetContext(self);
|
||
|
self->context = WelcomeWidget_CreateContext(hwnd, style, &self->previousBitmap, &self->contextWidth, &self->contextHeight);
|
||
|
|
||
|
elementWindow = GetDlgItem(hwnd, WELCOMEWIDGET_HELP_LINK);
|
||
|
if (NULL != elementWindow)
|
||
|
{
|
||
|
SIZE elementSize;
|
||
|
|
||
|
if (NULL != self->helpFont)
|
||
|
DeleteObject(self->helpFont);
|
||
|
|
||
|
self->helpFont = Graphics_DuplicateFont(WIDGETSTYLE_TEXT_FONT(style), 0, TRUE, TRUE);
|
||
|
|
||
|
SendMessage(elementWindow, WM_SETFONT, (WPARAM)self->helpFont, 0L);
|
||
|
if (FALSE != CommandLink_GetIdealSize(elementWindow, &elementSize))
|
||
|
{
|
||
|
SetWindowPos(elementWindow, NULL, 0, 0, elementSize.cx, elementSize.cy,
|
||
|
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_ScrollCb(WelcomeWidget *self, HWND hwnd, int *dx, int *dy)
|
||
|
{
|
||
|
RECT clientRect;
|
||
|
if (FALSE != GetClientRect(hwnd, &clientRect))
|
||
|
WelcomeWidget_UpdateHelpPosition(self, hwnd, &clientRect, TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
WelcomeWidget_HelpLinkCb(WelcomeWidget *self, HWND hwnd, NMHDR *pnmh, LRESULT *result)
|
||
|
{
|
||
|
switch(pnmh->code)
|
||
|
{
|
||
|
case NM_CLICK:
|
||
|
{
|
||
|
wchar_t buffer[4096] = {0};
|
||
|
if (FALSE != WelcomeWidget_GetHelpUrl(buffer, ARRAYSIZE(buffer)))
|
||
|
MediaLibrary_ShowHelp(Plugin_GetLibraryWindow(), buffer);
|
||
|
}
|
||
|
break;
|
||
|
case NM_SETFOCUS:
|
||
|
WelcomeWidget_EnsureHelpVisible(self, hwnd);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_NotifyCb(WelcomeWidget *self, HWND hwnd, NMHDR *pnmh, LRESULT *result)
|
||
|
{
|
||
|
switch(pnmh->idFrom)
|
||
|
{
|
||
|
case WELCOMEWIDGET_HELP_LINK:
|
||
|
WelcomeWidget_HelpLinkCb(self, hwnd, pnmh, result);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static BOOL
|
||
|
WelcomeWidget_HelpCb(WelcomeWidget *self, HWND hwnd, wchar_t *buffer, size_t bufferMax)
|
||
|
{
|
||
|
return WelcomeWidget_GetHelpUrl(buffer, bufferMax);
|
||
|
}
|
||
|
|
||
|
HWND WelcomeWidget_CreateWindow(HWND parentWindow, int x, int y, int width, int height, BOOL border, unsigned int controlId)
|
||
|
{
|
||
|
const static WidgetInterface welcomeWidgetInterface =
|
||
|
{
|
||
|
(WidgetInitCallback)WelcomeWidget_InitCb,
|
||
|
(WidgetDestroyCallback)WelcomeWidget_DestroyCb,
|
||
|
(WidgetLayoutCallback)WelcomeWidget_LayoutCb,
|
||
|
(WidgetPaintCallback)WelcomeWidget_PaintCb,
|
||
|
(WidgetStyleCallback)WelcomeWidget_StyleColorChangedCb,
|
||
|
(WidgetStyleCallback)WelcomeWidget_StyleFontChangedCb,
|
||
|
NULL /*mouseMove*/,
|
||
|
NULL /*leftButtonDown*/,
|
||
|
NULL /*leftButtonUp*/,
|
||
|
NULL /*leftButtonDblClk*/,
|
||
|
NULL /*rightButtonDown*/,
|
||
|
NULL /*rightButtonUp*/,
|
||
|
NULL /*keyDown*/,
|
||
|
NULL /*keyUp*/,
|
||
|
NULL /*character*/,
|
||
|
NULL /*inputRequest*/,
|
||
|
NULL /*focusChanged*/,
|
||
|
NULL /*contextMenu*/,
|
||
|
NULL /*zoomChanging*/,
|
||
|
NULL /*scrollBefore*/,
|
||
|
(WidgetScrollCallback)WelcomeWidget_ScrollCb,
|
||
|
(WidgetNotifyCallback)WelcomeWidget_NotifyCb,
|
||
|
(WidgetHelpCallback)WelcomeWidget_HelpCb,
|
||
|
|
||
|
};
|
||
|
|
||
|
return Widget_CreateWindow(WIDGET_TYPE_WELCOME,
|
||
|
&welcomeWidgetInterface,
|
||
|
NULL,
|
||
|
((FALSE != border) ? WS_EX_CLIENTEDGE : 0) | WS_EX_CONTROLPARENT,
|
||
|
WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
||
|
x, y, width, height,
|
||
|
parentWindow,
|
||
|
controlId, 0L);
|
||
|
}
|