winamp/Src/Plugins/Library/ml_devices/statusBar.cpp

1001 lines
22 KiB
C++

#include "main.h"
#include "./statusBar.h"
#include <vector>
#include <strsafe.h>
typedef struct StatusTextBlock
{
wchar_t *text;
size_t length;
long width;
} StatusTextBlock;
typedef struct StaturRecord
{
unsigned int id;
StatusTextBlock mainBlock;
StatusTextBlock rightBlock;
} StatusRecord;
typedef std::vector<StatusRecord*> StatusRecordList;
typedef struct StatusBar
{
HFONT font;
HBRUSH backBrush;
COLORREF textColor;
COLORREF backColor;
StatusRecordList list;
int idealHeight;
long spacing;
long leftBlockMinWidth;
BackBuffer backBuffer;
} StatusBar;
#define STATUSBAR(_hwnd) ((StatusBar*)(LONGX86)GetWindowLongPtrW((_hwnd), 0))
#define STATUSBAR_RET_VOID(_self, _hwnd) {(_self) = STATUSBAR((_hwnd)); if (NULL == (_self)) return;}
#define STATUSBAR_RET_VAL(_self, _hwnd, _error) {(_self) = STATUSBAR((_hwnd)); if (NULL == (_self)) return (_error);}
static LRESULT CALLBACK
StatusBar_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam);
static ATOM
StatusBar_GetClassAtom(HINSTANCE instance)
{
WNDCLASSEXW klass;
ATOM klassAtom;
klassAtom = (ATOM)GetClassInfoExW(instance, STATUSBAR_WINDOW_CLASS, &klass);
if (0 != klassAtom)
return klassAtom;
memset(&klass, 0, sizeof(klass));
klass.cbSize = sizeof(klass);
klass.style = 0;
klass.lpfnWndProc = StatusBar_WindowProc;
klass.cbClsExtra = 0;
klass.cbWndExtra = sizeof(StatusBar*);
klass.hInstance = instance;
klass.hIcon = NULL;
klass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
klass.hbrBackground = NULL;
klass.lpszMenuName = NULL;
klass.lpszClassName = STATUSBAR_WINDOW_CLASS;
klass.hIconSm = NULL;
klassAtom = RegisterClassExW(&klass);
return klassAtom;
}
HWND
StatusBar_CreateWindow(unsigned long windowExStyle, const wchar_t *text, unsigned long windowStyle,
int x, int y, int width, int height,
HWND parentWindow, unsigned int controlId)
{
HINSTANCE instance = GetModuleHandleW(NULL);
ATOM klassAtom = StatusBar_GetClassAtom(instance);
if (0 == klassAtom)
return NULL;
return CreateWindowExW(WS_EX_NOPARENTNOTIFY | windowExStyle, (LPCWSTR)MAKEINTATOM(klassAtom), text,
WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | windowStyle,
x, y, width, height, parentWindow, (HMENU)controlId, instance, NULL);
}
static void
StatusBar_InitTextBlock(StatusTextBlock *block)
{
if (NULL != block)
{
block->text = NULL;
block->length = ((size_t)-1);
block->width = -1;
}
}
static void
StatusBar_FreeTextBlock(StatusTextBlock *block)
{
if (NULL != block)
{
ResourceString_Free(block->text);
StatusBar_InitTextBlock(block);
}
}
static const wchar_t *
StatusBar_RetriveText(StatusTextBlock *block)
{
const wchar_t *source;
if (NULL == block)
return NULL;
source = block->text;
if (FALSE != IS_INTRESOURCE(source) &&
NULL != source)
{
wchar_t buffer[256] = {0};
if (NULL == WASABI_API_LNG)
return NULL;
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)source, buffer, ARRAYSIZE(buffer));
block->text = String_Duplicate(buffer);
}
return block->text;
}
static size_t
StatusBar_GetTextBlockLength(StatusTextBlock *block)
{
const wchar_t *text;
if (NULL == block)
return NULL;
if (((size_t)-1) != block->length)
{
text = StatusBar_RetriveText(block);
block->length = (NULL != text) ? lstrlenW(text) : 0;
}
return block->length;
}
static const wchar_t *
StatusBar_GetTextBlockInfo(StatusTextBlock *block, HDC hdc)
{
const wchar_t *text;
text = StatusBar_RetriveText(block);
if (((size_t)-1) == block->length)
{
if (FALSE == IS_STRING_EMPTY(text))
block->length = lstrlenW(text);
else
block->length = 0;
}
if (-1 == block->width)
{
block->width = 0;
if (0 != block->length)
{
RECT rect;
DRAWTEXTPARAMS textParams;
textParams.cbSize = sizeof(textParams);
textParams.iTabLength = 4;
textParams.iLeftMargin = 0;
textParams.iRightMargin = 0;
SetRect(&rect, 0, 0, 0x7FFFFFFF, 0);
if (FALSE != DrawTextEx(hdc, (wchar_t*)text, -1, &rect,
DT_LEFT | DT_TOP | DT_TABSTOP | DT_SINGLELINE |
DT_NOPREFIX | DT_EXPANDTABS | DT_NOCLIP | DT_CALCRECT | DT_EDITCONTROL,
&textParams))
{
block->width = RECTWIDTH(rect);
}
}
TEXTMETRIC metrics;
if (FALSE != GetTextMetrics(hdc, &metrics))
{
block->width += metrics.tmAveCharWidth/2;
}
}
return text;
}
static unsigned int
StatusBar_GetNextFreeId(StatusBar *self)
{
unsigned int id;
size_t index, count;
StatusRecord *record;
BOOL checkId;
count = self->list.size();
id = (unsigned int)count;
do
{
if (0xFFFFFFFF == id)
return STATUS_ERROR;
checkId = FALSE;
index = count;
while(index--)
{
record = self->list[index];
if (record->id == id)
{
id++;
checkId = TRUE;
break;
}
}
} while(FALSE != checkId);
return id;
}
static StatusRecord *
StatusBar_AddRecord(StatusBar *self, const wchar_t *text)
{
StatusRecord *record;
unsigned int id;
id = StatusBar_GetNextFreeId(self);
if (STATUS_ERROR == id)
return NULL;
record = (StatusRecord*)malloc(sizeof(StatusRecord));
if(NULL == record)
return NULL;
record->id = 0;
StatusBar_InitTextBlock(&record->mainBlock);
StatusBar_InitTextBlock(&record->rightBlock);
record->mainBlock.text = ResourceString_Duplicate(text);
self->list.push_back(record);
return record;
}
static StatusRecord *
StatusBar_FindRecord(StatusBar *self, unsigned int id, size_t *indexOut)
{
StatusRecord *record;
size_t index;
index = self->list.size();
while(index--)
{
record = self->list[index];
if (record->id == id)
{
if (NULL != indexOut)
*indexOut = index;
return record;
}
}
return NULL;
}
static StatusRecord *
StatusBar_FindVisibleRecord(StatusBar *self, size_t *indexOut)
{
StatusRecord *record;
size_t index;
const wchar_t *text;
index = self->list.size();
while(index--)
{
record = self->list[index];
text = StatusBar_RetriveText(&record->mainBlock);
if (FALSE != IS_STRING_EMPTY(text))
text = StatusBar_RetriveText(&record->rightBlock);
if (FALSE == IS_STRING_EMPTY(text))
{
if (NULL != indexOut)
*indexOut = index;
return record;
}
}
return NULL;
}
static void
StatusBar_Paint(HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
{
StatusBar *self;
StatusRecord *record;
const wchar_t *text;
STATUSBAR_RET_VOID(self, hwnd);
if (FALSE != erase)
{
FillRect(hdc, paintRect, self->backBrush);
}
record = StatusBar_FindVisibleRecord(self, NULL);
if (NULL != record)
{
COLORREF prevBackColor, prevTextColor;
HFONT prevFont;
RECT clientRect, textRect;
DRAWTEXTPARAMS textParams;
long limit;
prevBackColor = SetBkColor(hdc, self->backColor);
prevTextColor = SetTextColor(hdc, self->textColor);
prevFont = SelectFont(hdc, self->font);
textParams.cbSize = sizeof(textParams);
textParams.iTabLength = 4;
textParams.iLeftMargin = 0;
textParams.iRightMargin = 0;
GetClientRect(hwnd, &clientRect);
if (-1 == self->spacing)
self->spacing = Graphics_GetAveStrWidth(hdc, 2);
if (-1 == self->leftBlockMinWidth)
self->leftBlockMinWidth = Graphics_GetAveStrWidth(hdc, 16);
text = StatusBar_GetTextBlockInfo(&record->rightBlock, hdc);
if (FALSE == IS_STRING_EMPTY(text))
{
CopyRect(&textRect, &clientRect);
textRect.left = textRect.right - record->rightBlock.width;
limit = clientRect.left + self->spacing + self->leftBlockMinWidth;
if (textRect.left < limit)
textRect.left = limit;
if (textRect.left < textRect.right)
{
DrawTextEx(hdc, (wchar_t*)text, -1, &textRect,
DT_LEFT | DT_BOTTOM | DT_TABSTOP | DT_SINGLELINE |
DT_NOPREFIX | DT_EXPANDTABS, &textParams);
}
}
text = StatusBar_GetTextBlockInfo(&record->mainBlock, hdc);
if (FALSE == IS_STRING_EMPTY(text))
{
CopyRect(&textRect, &clientRect);
textRect.right = textRect.left + record->mainBlock.width;
limit = clientRect.right - record->rightBlock.width - 8;
if (limit < self->leftBlockMinWidth)
limit = self->leftBlockMinWidth;
if (textRect.right > limit)
textRect.right = limit;
if (textRect.left < textRect.right)
{
DrawTextEx(hdc, (wchar_t*)text, -1, &textRect,
DT_LEFT | DT_BOTTOM | DT_TABSTOP | DT_SINGLELINE |
DT_NOPREFIX | DT_EXPANDTABS | DT_END_ELLIPSIS, &textParams);
}
}
SetBkColor(hdc, prevBackColor);
SetTextColor(hdc, prevTextColor);
SelectFont(hdc, prevFont);
}
return;
}
static void
StatusBar_PaintBuffered(HWND hwnd, HDC hdc, const RECT *paintRect, BOOL erase)
{
StatusBar *self;
HDC bufferDC, targetDC;
RECT clientRect;
STATUSBAR_RET_VOID(self, hwnd);
GetClientRect(hwnd, &clientRect);
if (FALSE != BackBuffer_EnsureSizeEx(&self->backBuffer,
RECTWIDTH(*paintRect), RECTHEIGHT(*paintRect),
RECTWIDTH(clientRect), RECTHEIGHT(clientRect)))
{
bufferDC = BackBuffer_GetDC(&self->backBuffer);
if (NULL != bufferDC)
{
SetViewportOrgEx(bufferDC, -paintRect->left, -paintRect->top, NULL);
targetDC = hdc;
hdc = bufferDC;
}
}
else
{
bufferDC = NULL;
targetDC = NULL;
}
StatusBar_Paint(hwnd, hdc, paintRect, erase);
if (NULL != bufferDC)
{
hdc = targetDC;
SetViewportOrgEx(bufferDC, 0, 0, NULL);
BackBuffer_Copy(&self->backBuffer, hdc,
paintRect->left, paintRect->top, RECTWIDTH(*paintRect), RECTHEIGHT(*paintRect));
}
return;
}
static BOOL
StatusBar_InvalidateByIndex(StatusBar *self, HWND hwnd, size_t recordIndex)
{
unsigned int windowStyle;
size_t visibleIndex;
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
return FALSE;
if(NULL != StatusBar_FindVisibleRecord(self, &visibleIndex))
{
if (recordIndex == visibleIndex)
return InvalidateRect(hwnd, NULL, FALSE);
}
return FALSE;
}
static BOOL
StatusBar_InvalidateByRecord(StatusBar *self, HWND hwnd, StatusRecord *record)
{
unsigned int windowStyle;
StatusRecord *visibleRecord;
windowStyle = GetWindowStyle(hwnd);
if (0 == (WS_VISIBLE & windowStyle))
return FALSE;
visibleRecord = StatusBar_FindVisibleRecord(self, NULL);
if (record == visibleRecord &&
NULL != visibleRecord)
{
return InvalidateRect(hwnd, NULL, FALSE);
}
return FALSE;
}
static LRESULT
StatusBar_OnCreate(HWND hwnd, CREATESTRUCT *createStruct)
{
StatusBar *self;
self = new StatusBar();
if (NULL == self)
return -1;
SetLastError(ERROR_SUCCESS);
if (!SetWindowLongPtr(hwnd, 0, (LONGX86)self) && ERROR_SUCCESS != GetLastError())
{
delete self;
return -1;
}
if (NULL != createStruct->lpszName)
StatusBar_AddRecord(self, createStruct->lpszName);
self->backBrush = GetSysColorBrush(COLOR_WINDOW);
self->backColor = GetSysColor(COLOR_WINDOW);
self->textColor = GetSysColor(COLOR_WINDOWTEXT);
self->idealHeight = -1;
self->spacing = -1;
self->leftBlockMinWidth = -1;
BackBuffer_Initialize(&self->backBuffer, hwnd);
return 0;
}
static void
StatusBar_OnDestroy(HWND hwnd)
{
StatusBar *self;
size_t index;
StatusRecord *record;
self = STATUSBAR(hwnd);
SetWindowLongPtr(hwnd, 0, 0);
if (NULL == self)
return;
index = self->list.size();
while(index--)
{
record = self->list[index];
StatusBar_FreeTextBlock(&record->mainBlock);
StatusBar_FreeTextBlock(&record->rightBlock);
}
BackBuffer_Uninitialize(&self->backBuffer);
delete self;
}
static void
StatusBar_OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
if (NULL != BeginPaint(hwnd, &ps))
{
StatusBar_PaintBuffered(hwnd, ps.hdc, &ps.rcPaint, ps.fErase);
EndPaint(hwnd, &ps);
}
}
static void
StatusBar_OnPrintClient(HWND hwnd, HDC hdc, UINT options)
{
RECT clientRect;
if (GetClientRect(hwnd, &clientRect))
{
StatusBar_Paint(hwnd, hdc, &clientRect, TRUE);
}
}
static void
StatusBar_OnWindowPosChanged(HWND hwnd, WINDOWPOS *windowPos)
{
if (SWP_NOSIZE != ((SWP_NOSIZE | SWP_FRAMECHANGED) & windowPos->flags) &&
0 == (SWP_NOREDRAW & windowPos->flags))
{
InvalidateRect(hwnd, NULL, FALSE);
}
}
static LRESULT
StatusBar_OnSetText(HWND hwnd, LPCWSTR text)
{
StatusBar *self;
StatusRecord *record;
size_t count;
STATUSBAR_RET_VAL(self, hwnd, FALSE);
count = self->list.size();
if (0 == count)
{
if (NULL == text)
return TRUE;
record = StatusBar_AddRecord(self, text);
if (NULL == record)
return FALSE;
}
else
{
record = self->list[count - 1];
StatusBar_FreeTextBlock(&record->mainBlock);
StatusBar_FreeTextBlock(&record->rightBlock);
record->mainBlock.text = ResourceString_Duplicate(text);
}
StatusBar_InvalidateByRecord(self, hwnd, record);
return TRUE;
}
static LRESULT
StatusBar_OnGetText(HWND hwnd, LPWSTR buffer, size_t bufferMax)
{
StatusBar *self;
StatusRecord *record;
const wchar_t *lText, *rText;
size_t count, remaining;
wchar_t *cursor;
HRESULT hr;
STATUSBAR_RET_VAL(self, hwnd, 0);
if (NULL == buffer)
return 0;
count = self->list.size();
if (0 == count)
{
lText = NULL;
rText = NULL;
}
else
{
record = self->list[count - 1];
lText = StatusBar_RetriveText(&record->mainBlock);
rText = StatusBar_RetriveText(&record->rightBlock);
}
cursor = buffer;
remaining = bufferMax;
if (NULL != lText)
hr = StringCchCopyEx(cursor, bufferMax, lText, &cursor, &remaining, 0);
else
hr = S_OK;
if (NULL != rText && SUCCEEDED(hr))
{
hr = StringCchCopyEx(cursor, bufferMax, L"\f", &cursor, &remaining, 0);
if (SUCCEEDED(hr))
hr = StringCchCopyEx(cursor, bufferMax, rText, &cursor, &remaining, 0);
}
return (bufferMax - remaining);
}
static LRESULT
StatusBar_OnGetTextLength(HWND hwnd)
{
StatusBar *self;
StatusRecord *record;
size_t length, r;
STATUSBAR_RET_VAL(self, hwnd, 0);
length = self->list.size();
if (0 == length)
return 0;
record = self->list[length - 1];
length = StatusBar_GetTextBlockLength(&record->mainBlock);
r = StatusBar_GetTextBlockLength(&record->rightBlock);
if (0 != r)
{
length += (r + 1);
}
return length;
}
static void
StatusBar_OnSetFont(HWND hwnd, HFONT font, BOOL redraw)
{
StatusBar *self;
StatusRecord *record;
size_t index;
STATUSBAR_RET_VOID(self, hwnd);
self->font = font;
self->idealHeight = -1;
self->spacing = -1;
self->leftBlockMinWidth = -1;
index = self->list.size();
while(index--)
{
record = self->list[index];
record->mainBlock.width = -1;
record->rightBlock.width = -1;
}
if (NULL != redraw)
InvalidateRect(hwnd, NULL, TRUE);
}
static LRESULT
StatusBar_OnGetFont(HWND hwnd)
{
StatusBar *self;
STATUSBAR_RET_VAL(self, hwnd, NULL);
return (LRESULT)self->font;
}
static LRESULT
StatusBar_OnSetBackBrush(HWND hwnd, HBRUSH brush, BOOL redraw)
{
StatusBar *self;
HBRUSH prevBrush;
STATUSBAR_RET_VAL(self, hwnd, (LRESULT)GetSysColorBrush(COLOR_WINDOW));
prevBrush = self->backBrush;
self->backBrush = brush;
if (NULL != redraw)
InvalidateRect(hwnd, NULL, TRUE);
return (LRESULT)prevBrush;
}
static LRESULT
StatusBar_OnGetBackBrush(HWND hwnd)
{
StatusBar *self;
STATUSBAR_RET_VAL(self, hwnd, (LRESULT)GetSysColorBrush(COLOR_WINDOW));
return (LRESULT)self->backBrush;
}
static LRESULT
StatusBar_OnSetBackColor(HWND hwnd, COLORREF color, BOOL redraw)
{
StatusBar *self;
COLORREF prevColor;
STATUSBAR_RET_VAL(self, hwnd, GetSysColor(COLOR_WINDOW));
prevColor = self->backColor;
self->backColor = color;
if (NULL != redraw)
InvalidateRect(hwnd, NULL, FALSE);
return (LRESULT)prevColor;
}
static LRESULT
StatusBar_OnGetBackColor(HWND hwnd)
{
StatusBar *self;
STATUSBAR_RET_VAL(self, hwnd, GetSysColor(COLOR_WINDOW));
return (LRESULT)self->backColor;
}
static LRESULT
StatusBar_OnSetTextColor(HWND hwnd, COLORREF color, BOOL redraw)
{
StatusBar *self;
COLORREF prevColor;
STATUSBAR_RET_VAL(self, hwnd, GetSysColor(COLOR_WINDOWTEXT));
prevColor = self->textColor;
self->textColor = color;
if (NULL != redraw)
InvalidateRect(hwnd, NULL, FALSE);
return (LRESULT)prevColor;
}
static LRESULT
StatusBar_OnGetTextColor(HWND hwnd)
{
StatusBar *self;
STATUSBAR_RET_VAL(self, hwnd, GetSysColor(COLOR_WINDOWTEXT));
return (LRESULT)self->textColor;
}
static LRESULT
StatusBar_OnGetIdealHeight(HWND hwnd)
{
StatusBar *self;
STATUSBAR_RET_VAL(self, hwnd, 0);
if (self->idealHeight < 0)
{
HDC hdc;
self->idealHeight = 0;
hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
if (NULL != hdc)
{
TEXTMETRIC metrics;
HFONT font, prevFont;
font = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
prevFont = SelectFont(hdc, font);
if (FALSE != GetTextMetrics(hdc, &metrics))
self->idealHeight = metrics.tmHeight;
SelectFont(hdc, prevFont);
ReleaseDC(hwnd, hdc);
}
}
return (LRESULT)self->idealHeight;
}
static LRESULT
StatusBar_OnAddStatus(HWND hwnd, const wchar_t *text)
{
StatusBar *self;
StatusRecord *record;
STATUSBAR_RET_VAL(self, hwnd, STATUS_ERROR);
record = StatusBar_AddRecord(self, text);
if (NULL == record)
return STATUS_ERROR;
StatusBar_InvalidateByRecord(self, hwnd, record);
return record->id;
}
static LRESULT
StatusBar_OnRemoveStatus(HWND hwnd, unsigned int statusId)
{
StatusBar *self;
StatusRecord *record;
size_t index;
STATUSBAR_RET_VAL(self, hwnd, FALSE);
record = StatusBar_FindRecord(self, statusId, &index);
if (NULL == record)
return FALSE;
StatusBar_InvalidateByRecord(self, hwnd, record);
self->list.erase(self->list.begin() + index);
StatusBar_FreeTextBlock(&record->mainBlock);
StatusBar_FreeTextBlock(&record->rightBlock);
free(record);
return (LRESULT)TRUE;
}
static LRESULT
StatusBar_OnSetStatusText(HWND hwnd, unsigned int statusId, const wchar_t *text)
{
StatusBar *self;
StatusRecord *record;
size_t index;
STATUSBAR_RET_VAL(self, hwnd, FALSE);
record = StatusBar_FindRecord(self, statusId, &index);
if (NULL == record)
return FALSE;
StatusBar_InvalidateByRecord(self, hwnd, record);
StatusBar_FreeTextBlock(&record->mainBlock);
record->mainBlock.text = ResourceString_Duplicate(text);
StatusBar_InvalidateByRecord(self, hwnd, record);
return (LRESULT)TRUE;
}
static LRESULT
StatusBar_OnSetStatusRightText(HWND hwnd, unsigned int statusId, const wchar_t *text)
{
StatusBar *self;
StatusRecord *record;
size_t index;
STATUSBAR_RET_VAL(self, hwnd, FALSE);
record = StatusBar_FindRecord(self, statusId, &index);
if (NULL == record)
return FALSE;
StatusBar_InvalidateByRecord(self, hwnd, record);
StatusBar_FreeTextBlock(&record->rightBlock);
record->rightBlock.text = ResourceString_Duplicate(text);
StatusBar_InvalidateByRecord(self, hwnd, record);
return (LRESULT)TRUE;
}
static LRESULT
StatusBar_OnMoveStatus(HWND hwnd, unsigned int statusId, unsigned int moveCommand)
{
StatusBar *self;
StatusRecord *record;
size_t index, count, newIndex;
STATUSBAR_RET_VAL(self, hwnd, FALSE);
record = StatusBar_FindRecord(self, statusId, &index);
if (NULL == record)
return FALSE;
count = self->list.size();
switch(moveCommand)
{
case STATUS_MOVE_BOTTOM:
if (0 == index)
return TRUE;
self->list.erase(self->list.begin() + index);
self->list.insert(self->list.begin(), record);
newIndex = 0;
break;
case STATUS_MOVE_TOP:
if (index == (count - 1))
return TRUE;
self->list.erase(self->list.begin() + index);
self->list.push_back(record);
newIndex = count - 1;
break;
case STATUS_MOVE_UP:
if (index == (count - 1))
return TRUE;
self->list.erase(self->list.begin() + index);
newIndex = index + 1;
self->list.insert(self->list.begin() + newIndex, record);
break;
case STATUS_MOVE_DOWN:
if (index == 0)
return TRUE;
self->list.erase(self->list.begin() + index);
newIndex = index - 1;
self->list.insert(self->list.begin() + newIndex, record);
break;
}
if (index != newIndex)
{
StatusBar_InvalidateByIndex(self, hwnd, index);
StatusBar_InvalidateByIndex(self, hwnd, newIndex);
}
return (LRESULT)TRUE;
}
static LRESULT CALLBACK
StatusBar_WindowProc(HWND hwnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE: return StatusBar_OnCreate(hwnd, (CREATESTRUCT*)lParam);
case WM_DESTROY: StatusBar_OnDestroy(hwnd); return 0;
case WM_PAINT: StatusBar_OnPaint(hwnd); return 0;
case WM_PRINTCLIENT: StatusBar_OnPrintClient(hwnd, (HDC)wParam, (UINT)lParam); return 0;
case WM_PRINT: return 0;
case WM_ERASEBKGND: return 0;
case WM_WINDOWPOSCHANGED: StatusBar_OnWindowPosChanged(hwnd, (WINDOWPOS*)lParam); return 0;
case WM_SIZE: return 0;
case WM_MOVE: return 0;
case WM_SETTEXT: return StatusBar_OnSetText(hwnd, (LPCWSTR)lParam);
case WM_GETTEXT: return StatusBar_OnGetText(hwnd, (LPWSTR)lParam, (INT)wParam);
case WM_GETTEXTLENGTH: return StatusBar_OnGetTextLength(hwnd);
case WM_SETFONT: StatusBar_OnSetFont(hwnd, (HFONT)wParam, (BOOL)LOWORD(lParam)); return 0;
case WM_GETFONT: return StatusBar_OnGetFont(hwnd);
case STATUSBAR_WM_SET_BACK_BRUSH: return StatusBar_OnSetBackBrush(hwnd, (HBRUSH)lParam, (BOOL)wParam);
case STATUSBAR_WM_GET_BACK_BRUSH: return StatusBar_OnGetBackBrush(hwnd);
case STATUSBAR_WM_SET_BACK_COLOR: return StatusBar_OnSetBackColor(hwnd, (COLORREF)lParam, (BOOL)wParam);
case STATUSBAR_WM_GET_BACK_COLOR: return StatusBar_OnGetBackColor(hwnd);
case STATUSBAR_WM_SET_TEXT_COLOR: return StatusBar_OnSetTextColor(hwnd, (COLORREF)lParam, (BOOL)wParam);
case STATUSBAR_WM_GET_TEXT_COLOR: return StatusBar_OnGetTextColor(hwnd);
case STATUSBAR_WM_GET_IDEAL_HEIGHT: return StatusBar_OnGetIdealHeight(hwnd);
case STATUSBAR_WM_ADD_STATUS: return StatusBar_OnAddStatus(hwnd, (const wchar_t*)lParam);
case STATUSBAR_WM_REMOVE_STATUS: return StatusBar_OnRemoveStatus(hwnd, (unsigned int)(wParam));
case STATUSBAR_WM_SET_STATUS_TEXT: return StatusBar_OnSetStatusText(hwnd, (unsigned int)(wParam), (const wchar_t*)lParam);
case STATUSBAR_WM_SET_STATUS_RTEXT: return StatusBar_OnSetStatusRightText(hwnd, (unsigned int)(wParam), (const wchar_t*)lParam);
case STATUSBAR_WM_MOVE_STATUS: return StatusBar_OnMoveStatus(hwnd, (unsigned int)(wParam), (unsigned int)lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}