winamp/Src/Plugins/General/gen_ff/ff_ipc.cpp
2024-09-24 14:54:57 +02:00

536 lines
19 KiB
C++

#include "precomp__gen_ff.h"
#include "gen_ff_ipc.h"
#include "ff_ipc.h"
#include "../winamp/wa_ipc.h"
#include "wa2frontend.h"
#include <tataki/color/skinclr.h>
#include <api/wnd/wndclass/buttwnd.h>
#include <api/wndmgr/skinwnd.h>
#include <tataki/blending/blending.h>
#include <api/skin/skinparse.h>
#include <api/wnd/wndtrack.h>
#include "wa2wndembed.h"
#include "embedwndguid.h"
#include <tataki/canvas/bltcanvas.h>
#include "../nu/AutoChar.h"
#include "../nu/AutoWide.h"
ColorThemeMonitor *colorThemeMonitor = NULL;
HBITMAP CreateBitmapDIB(int w, int h, int planes, int bpp, void *data)
{
#if 0
return CreateBitmap(w, h, planes, bpp, data);
#else
void *bits=0;
BITMAPINFO bmi={0,};
bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = w;
bmi.bmiHeader.biHeight = -h;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = bpp;
bmi.bmiHeader.biSizeImage = w*h*(bpp/8);
bmi.bmiHeader.biCompression=BI_RGB;
HBITMAP bm=CreateDIBSection(0,&bmi,0,&bits,NULL,0);
if (bm && bits) memcpy(bits,data,w*h*(bpp/8));
return bm;
#endif
}
HWND ff_ipc_getContentWnd(HWND w) {
HWND ret = w;
ifc_window *wnd = windowTracker->rootWndFromHwnd(w); // TODO: API_WNDMGR->
if (wnd) {
ifc_window *dp = wnd->getDesktopParent();
if (dp) {
Layout *l = static_cast<Layout *>(dp->getInterface(layoutGuid));
if (l) {
Container *c = l->getParentContainer();
if (c) {
GUID g = c->getDefaultContent();
if (g != INVALID_GUID) {
if (g == playerWndGuid)
ret = wa2.getMainWindow();
else if (g == pleditWndGuid)
ret = wa2.getWnd(IPC_GETWND_PE);
else if (g == videoWndGuid)
ret = wa2.getWnd(IPC_GETWND_VIDEO);
else {
embedWindowState *ews = embedWndGuidMgr.getEmbedWindowState(g);
if (ews)
ret = ews->me;
}
}
}
}
}
}
return ret;
}
void ff_ipc_getSkinColor(ff_skincolor *cs)
{
if (cs == NULL) return;
cs->color = RGBTOBGR(SkinColor(AutoWide(cs->colorname)));
}
#define USE_WIN32_ALPHABLEND
static void ButtonSetup(ButtonWnd &_w)
{
_w.setVirtual(0);
_w.setStartHidden(1);
_w.setParent(WASABI_API_WND->main_getRootWnd());
_w.init(WASABI_API_WND->main_getRootWnd());
_w.setCloaked(1);
_w.setVisible(1);
}
static void DoButtonBlit(ButtonWnd &_w, int w, int h, int state, const wchar_t *overlayelement, int xpos, int ypos, BltCanvas *c)
{
if (state == BUTTONSTATE_PUSHED) _w.setPushed(1);
else _w.setPushed(0);
_w.resize(0, 0, w, h);
_w.deferedInvalidate();
_w.paint(NULL, NULL);
Canvas *cv = NULL;
cv = _w.getFrameBuffer();
if (cv != NULL) {
BltCanvas *bltcanvas = static_cast<BltCanvas *>(cv); // hackish
#ifdef USE_WIN32_ALPHABLEND
bltcanvas->/*getSkinBitmap()->*/blitAlpha(c, xpos, ypos);
#else
bltcanvas->getSkinBitmap()->blitAlpha(c, xpos, ypos);
#endif
}
if (overlayelement && *overlayelement) {
AutoSkinBitmap b(overlayelement);
SkinBitmap *sb = b.getBitmap();
int shift = (state == BUTTONSTATE_PUSHED) ? 1 : 0;
sb->blitAlpha(c, xpos+(w-sb->getWidth())/2+shift, ypos+(h-sb->getHeight())/2+shift);
}
}
void blitButtonToCanvas(int w, int h, int state, const wchar_t *overlayelement, int xpos, int ypos, BltCanvas *c)
{
ButtonWnd _w;
ButtonSetup(_w);
DoButtonBlit(_w, w, h, state, overlayelement, xpos, ypos, c);
}
static HBITMAP generateButtonBitmap(int w, int h, int state, const wchar_t *overlayelement=NULL) {
BltCanvas c(w, h);
blitButtonToCanvas(w,h,state,overlayelement,0,0,&c);
SysCanvas cc;
c.blit(0, 0, &cc, 0, 0, w, h);
return CreateBitmapDIB(w, h, 1, 32, c.getBits());
}
COLORREF getWindowBackground(COLORREF *wb)
{
static String last_skin, last_theme;
static COLORREF last_windowbackground = 0x00000000;
COLORREF windowbackground = 0x00000000;
// window background (used to set the bg color for the dialog)
if (!WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.window.background"))
{
String curskin = AutoChar(WASABI_API_SKIN->getSkinName());
String curtheme = AutoChar(WASABI_API_SKIN->colortheme_getColorSet());
if (!last_skin.iscaseequal(curskin) || !last_theme.iscaseequal(curtheme)) {
last_skin = curskin;
last_theme = curtheme;
// extract the window color from an active piece of skin
SkinWnd w(L"$$$.some.purposedly.undefined.group.$$$", NULL, 0, NULL, 1, 1);
ifc_window *wnd = w.getWindow();
if (wnd != NULL) {
ifc_window *wh = wnd->findWindowByInterface(windowHolderGuid);
if (wh != NULL) {
wnd = wnd->getDesktopParent();
if (w.isNewContainer()) {
wnd->setCloaked(1);
wnd->setVisible(1);
wnd->resize(0, 0, 320, 200);
wnd->paint();
}
BltCanvas *canvas = static_cast<BltCanvas *>(wnd->getFrameBuffer());
if (!canvas) goto basetexture; // eek :-D
int x=0, y=0;
RECT r;
wh->getClientRect(&r);
x = r.left + (r.right-r.left)/2; y = r.top + (r.bottom-r.top)/2;
COLORREF *bits = (COLORREF *)canvas->getBits();
int w, h;
canvas->getDim(&w, &h, NULL);
if (w == 0 || h == 0)
windowbackground = 0; // black by default
else
windowbackground = bits[y*w+x];
}
}
w.destroy();
if (windowbackground == 0x00000000) {
basetexture:
// try for wasabi.basetexture ...
int _w, _h, _x, _y;
ARGB32 *b = WASABI_API_SKIN->imgldr_requestSkinBitmap(L"wasabi.basetexture", NULL, &_x, &_y, NULL, NULL, &_w, &_h, 1);
if (b != NULL) {
windowbackground = b[_w*_y+_x];
WASABI_API_SKIN->imgldr_releaseSkinBitmap(b);
} else {
// no idea... we'll just set the default windows color
windowbackground = GetSysColor(COLOR_WINDOWFRAME);
}
}
last_windowbackground = windowbackground;
} else {
windowbackground = last_windowbackground;
}
if (wb) *wb=windowbackground;
return windowbackground;
} else {
COLORREF c = RGBTOBGR(SkinColor(L"wasabi.window.background"));
if (wb) *wb = c;
return c;
}
}
inline int lumidiff(int a, int b) {
int r1 = (a & 0xFF0000) >> 16;
int r2 = (b & 0xFF0000) >> 16;
int g1 = (a & 0xFF00) >> 8;
int g2 = (b & 0xFF00) >> 8;
int b1 = a & 0xFF;
int b2 = b & 0xFF;
return MIN((ABS(r1-r2), ABS(g1-g2)), ABS(b1-b2));
}
HBITMAP ff_genwa2skinbitmap()
{
int interpolate = 0;
if (SkinParser::getSkinVersion()*10 < 10) interpolate = 1;
BltCanvas c(132, 75);
COLORREF windowbackground = 0;
COLORREF wbg=getWindowBackground(&windowbackground);
COLORREF *ptr=(COLORREF *)c.getBits();
c.fillBits(wbg);
// set up bg color for the picky pixel parser heh
int x;
for (x = 47; x < 132; x ++) ptr[x]=ptr[x+132]=RGB(0,198,255);
ButtonWnd _w;
ButtonSetup(_w);
DoButtonBlit(_w, 47,15,0,NULL,0,0,&c);
DoButtonBlit(_w, 47,15,1,NULL,0,15,&c);
DoButtonBlit(_w, 14,14,0,L"wasabi.button.label.arrow.up",0,31,&c);
DoButtonBlit(_w, 14,14,0,L"wasabi.button.label.arrow.down",14,31,&c);
DoButtonBlit(_w, 14,14,1,L"wasabi.button.label.arrow.up",28,31,&c);
DoButtonBlit(_w, 14,14,1,L"wasabi.button.label.arrow.down",42,31,&c);
DoButtonBlit(_w, 14,14,0,L"wasabi.button.label.arrow.left",0,45,&c);
DoButtonBlit(_w, 14,14,0,L"wasabi.button.label.arrow.right",14,45,&c);
DoButtonBlit(_w, 14,14,1,L"wasabi.button.label.arrow.left",28,45,&c);
DoButtonBlit(_w, 14,14,1,L"wasabi.button.label.arrow.right",42,45,&c);
DoButtonBlit(_w, 14,28,0,L"wasabi.scrollbar.vertical.grip",56,31,&c);
DoButtonBlit(_w, 14,28,1,L"wasabi.scrollbar.vertical.grip",70,31,&c);
DoButtonBlit(_w, 28,14,0,L"wasabi.scrollbar.horizontal.grip",84,31,&c);
DoButtonBlit(_w, 28,14,1,L"wasabi.scrollbar.horizontal.grip",84,45,&c);
// item background (background to edits, listviews etc)
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.background"))
ptr[48] = RGBTOBGR(SkinColor(L"wasabi.list.background"));
else
ptr[48] = WASABI_API_SKIN->skin_getBitmapColor(L"wasabi.list.background"); // RGBTOBGR(SkinColor(L"wasabi.edit.background"));
COLORREF listbkg = ptr[48];
// item foreground (text color of edit/listview, etc)
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text"))
ptr[50] = RGBTOBGR(SkinColor(L"wasabi.list.text"));
else {
int c = RGBTOBGR(SkinColor(L"wasabi.edit.text"));
ptr[50] = c;
}
if (interpolate) {
int c = ptr[50];
c = lumidiff(c, listbkg) < 0x1F ? Blenders::BLEND_AVG(ptr[50], 0xFF7F7F7F) : c;
c = lumidiff(c, listbkg) < 0x1F ? Blenders::BLEND_AVG(ptr[50], 0xFF101010) : c;
ptr[50] = c | 0xFF000000;
}
ptr[52] = wbg;
ptr[54] = RGBTOBGR(SkinColor(SKINCOLOR_BUTTON_TEXT));
// window text color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.window.text"))
ptr[56] = RGBTOBGR(SkinColor(L"wasabi.window.text"));
else {
ptr[56] = RGBTOBGR(SkinColor(SKINCOLOR_LIST_ITEMTEXT)); //"wasabi.textbar.text");//
}
// color of dividers and sunken borders
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.border.sunken"))
ptr[58] = RGBTOBGR(SkinColor(L"wasabi.border.sunken"));
else {
int a = MAX((windowbackground & 0xFF0000) >> 16, MAX((windowbackground & 0xFF00) >> 8, windowbackground & 0xFF));
ptr[58] = Blenders::BLEND_AVG(windowbackground, a > 0xE0 ? 0xFF000000: 0xFFFFFFFF);
}
// listview header background color
COLORREF col = RGBTOBGR(SkinColor(SKINCOLOR_LIST_COLUMNBKG));
if (interpolate) {
int a = MAX((col & 0xFF0000) >> 16, MAX((col & 0xFF00) >> 8, col & 0xFF));
col = a < 0x1F ? Blenders::BLEND_AVG(windowbackground, 0xFF000000) : col;
}
ptr[62] = col;
// listview header text color
ptr[64] = RGBTOBGR(SkinColor(SKINCOLOR_LIST_COLUMNTEXT));
// listview header frame top color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.column.frame.top"))
ptr[66] = RGBTOBGR(SkinColor(L"wasabi.list.column.frame.top"));
else
ptr[66] = Blenders::BLEND_AVG(col, 0xFFFFFFFF);//listview header frame top color
// listview header frame middle color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.column.frame.middle"))
ptr[68] = RGBTOBGR(SkinColor(L"wasabi.list.column.frame.middle"));
else
ptr[68] = Blenders::BLEND_AVG(col, 0xFF2F2F2F);
// listview header frame bottom color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.column.frame.bottom"))
ptr[70] = RGBTOBGR(SkinColor(L"wasabi.list.column.frame.bottom"));
else
ptr[70] = Blenders::BLEND_AVG(col, 0xFF000000);
// listview header empty color
COLORREF empty;
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.column.empty"))
empty = RGBTOBGR(SkinColor(L"wasabi.list.column.empty"));
else
empty = Blenders::BLEND_AVG(col, 0xFF000000);
ptr[72] = empty;
// scrollbar foreground color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.scrollbar.foreground"))
ptr[74] = RGBTOBGR(SkinColor(L"wasabi.scrollbar.foreground"));
else
ptr[74] = empty;
// scrollbar background color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.scrollbar.background"))
ptr[76] = RGBTOBGR(SkinColor(L"wasabi.scrollbar.background"));
else
ptr[76] = empty;
// inverse scrollbar foreground color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.scrollbar.foreground.inverted"))
ptr[78] = RGBTOBGR(SkinColor(L"wasabi.scrollbar.foreground.inverted"));
else
ptr[78] = col;
// inverse scrollbar background color
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.scrollbar.background.inverted"))
ptr[80] = RGBTOBGR(SkinColor(L"wasabi.scrollbar.background.inverted"));
else
ptr[80] = empty;
// scrollbar dead area color
ptr[82] = windowbackground;
// listview/treeview selection bar text color
COLORREF selfg;
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.selected"))
selfg = RGBTOBGR(SkinColor(L"wasabi.list.text.selected"));
else
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text"))
selfg = RGBTOBGR(SkinColor(L"wasabi.list.text"));
else
selfg = SkinColor(L"wasabi.edit.text");
ptr[84] = selfg;
// listview/treeview selection bar back color
COLORREF selbg;
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.selected.background"))
selbg = RGBTOBGR(SkinColor(L"wasabi.list.text.selected.background"));
else {
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.item.selected"))
selbg = RGBTOBGR(SkinColor(L"wasabi.list.item.selected"));
else
selbg = RGBTOBGR(SkinColor(SKINCOLOR_TREE_SELITEMBKG));
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(windowbackground, 0xFF7F7F7F) : selbg;
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(listbkg, 0xFF7F7F7F) : selbg;
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(windowbackground, 0xFFF0F0F0) : selbg;
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(listbkg, 0xFFF0F0F0) : selbg;
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(col, 0xFFF0F0F0) : selbg;
selbg = lumidiff(selbg, listbkg) < 0x2F ? Blenders::BLEND_AVG(col, 0xFF101010) : selbg;
selbg = lumidiff(selbg, selfg) < 0x1F ? Blenders::BLEND_AVG(selbg, 0xFF101010) : selbg;
selbg = lumidiff(selbg, selfg) < 0x1F ? Blenders::BLEND_AVG(selbg, 0xFFF0F0F0) : selbg;
}
ptr[86] = ptr[60] = (selbg | 0xFF000000);
// listview/treeview selection bar text color (inactive)
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.selected.inactive"))
ptr[88] = RGBTOBGR(SkinColor(L"wasabi.list.text.selected.inactive"));
else
ptr[88] = selfg;
// listview/treeview selection bar back color (inactive)
if (!interpolate && WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.selected.background.inactive"))
ptr[90] = RGBTOBGR(SkinColor(L"wasabi.list.text.selected.background.inactive"));
else
ptr[90] = Blenders::BLEND_ADJ1(selbg, 0xFF000000, 210);
// alternate item background
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.background.alternate"))
ptr[92] = RGBTOBGR(SkinColor(L"wasabi.list.background.alternate"));
else
ptr[92] = ptr[48];
// alternate item foreground
if (WASABI_API_SKIN->skin_getColorElementRef(L"wasabi.list.text.alternate"))
{
ptr[50] = RGBTOBGR(SkinColor(L"wasabi.list.text.alternate"));
if (interpolate) {
int c = ptr[94];
c = lumidiff(c, listbkg) < 0x1F ? Blenders::BLEND_AVG(ptr[94], 0xFF7F7F7F) : c;
c = lumidiff(c, listbkg) < 0x1F ? Blenders::BLEND_AVG(ptr[94], 0xFF101010) : c;
ptr[94] = c | 0xFF000000;
}
}
else {
ptr[94] = ptr[50];
}
return CreateBitmapDIB(132, 75, 1, 32, c.getBits());
}
void ff_ipc_genSkinBitmap(ff_skinbitmap *sb) {
if (sb == NULL) return;
switch (sb->id) {
case SKINBITMAP_BUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state);
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBARVBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state, L"wasabi.scrollbar.vertical.grip");
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBARHBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state, L"wasabi.scrollbar.horizontal.grip");
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBARUPBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state, L"wasabi.button.label.arrow.up");
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBARDOWNBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state, L"wasabi.button.label.arrow.down");
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBARLEFTBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, sb->state, L"wasabi.button.label.arrow.left");
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_UPBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.vertical.left.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.vertical.left.hover":
L"wasabi.scrollbar.vertical.left")));
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_DOWNBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.vertical.right.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.vertical.right.hover":
L"wasabi.scrollbar.vertical.right")));
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_LEFTBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.horizontal.left.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.horizontal.left.hover":
L"wasabi.scrollbar.horizontal.left")));
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_RIGHTBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.horizontal.right.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.horizontal.right.hover":
L"wasabi.scrollbar.horizontal.right")));
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_BARHBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.horizontal.button.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.horizontal.button.hover":
L"wasabi.scrollbar.horizontal.button")));
sb->bitmap = bmp;
break;
}
case SKINBITMAP_SCROLLBAR_FF_BARVBUTTON: {
HBITMAP bmp = generateButtonBitmap(sb->w, sb->h, SCROLLBARSTATE_NORMAL,
((sb->state==SCROLLBARSTATE_PRESSED)?L"wasabi.scrollbar.vertical.button.pressed":
((sb->state==SCROLLBARSTATE_HOVER)?L"wasabi.scrollbar.vertical.button.hover":
L"wasabi.scrollbar.vertical.button.pressed")));
sb->bitmap = bmp;
break;
}
}
#if 0 // debug
HDC ddc = GetDC(NULL);
HDC sdc = CreateCompatibleDC(ddc);
SelectObject(sdc, sb->bitmap);
BitBlt(ddc, 100, 100, sb->w, sb->h, sdc, 0, 0, SRCCOPY);
DeleteObject(sdc);
ReleaseDC(NULL, ddc);
#endif
}
ColorThemeMonitor::ColorThemeMonitor() {
WASABI_API_SYSCB->syscb_registerCallback(this);
}
ColorThemeMonitor::~ColorThemeMonitor() {
WASABI_API_SYSCB->syscb_deregisterCallback(this);
}
int ColorThemeMonitor::skincb_onColorThemeChanged( const wchar_t *colortheme )
{
SendMessageW( wa2.getMainWindow(), WM_WA_IPC, (WPARAM) colortheme, IPC_FF_ONCOLORTHEMECHANGED );
return 1;
}