Hi,
First, this is going to be a long post, sorry ;-) You might have noticed, that I have been working on the desk.cpl appearance tab, wich is working partly. Here's the first version: http://www.reactos.org/bugzilla/show_bug.cgi?id=1732
Some things still don't work. For example the desktop doesn't get repainted in the new color.
------- /Comment #5 http://www.reactos.org/bugzilla/show_bug.cgi?id=1732#c5 >From jimtabor 2006-08-05 04:46:36 CET / [reply
http://www.reactos.org/bugzilla/show_bug.cgi?id=1732#add_comment]
Hi, You can use WM_SYSCOLORCHANGE in the desktop proc if it is used, should be!, user32/misc/desktop.c;
static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { DPRINT1("Desktop Class Atom!\n"); switch(message) { case WM_NCCREATE: return TRUE;
case WM_CREATE: /* when I spy I see notify */ SendNotifyMessageW( hwnd, WM_SYSCOLORCHANGE , 0, 0 ); break; case WM_SYSCOLORCHANGE: /* update everything, well in theory anyway */ RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE |RDW_ALLCHILDREN ); break;
default: return DefWindowProcW(hwnd,message,wParam,lParam); } return 0; /* all other messages are ignored */}
Its crude, I'm not sure if it will compile, its off the top of my head ATM. 8^D Thanks, James
Thanks for helping, James. I tried it, but it doesn't work. 1.) Sending WM_SYSCOLORCHANGE on WM_CREATE will probably do nothing, because the desktop has just been created with the initial SysColors, no need to update them. 2.) RedrawWindow calls NtUserRedrawWindow wich calls co_UserRedrawWindow wich calls co_IntPaintWindows wich sends a WM_PAINT message to the desktop window. WM_PAINT is then passed to DefWindowProc and passed on to User32DefWindowProc wich does only repaint the icon as it seems. So WM_PAINT must be evaluated in DesktopWndProc.
I tried the following:
case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); PaintDesktop(hdc); EndPaint(hwnd, &ps); }
PaintDesktop calls NtUserPaintDesktop, wich then paints the desktop. I have also replaced DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE); with DesktopBrush = IntGetSysColorBrush(COLOR_BACKGROUND);
But the desktop is still painted in the original color, whereas the icon text is in the color I have set in the registry.
I played a little around with the code in NtUserPaintDesktop. I added the following code before the desktop background is painted:
if (IntGetSysColor(COLOR_BACKGROUND) == 0) // This is true after SysColors are loaded from Registry { DesktopBrush = IntGetSysColorBrush(COLOR_ACTIVECAPTION); }
And suddenly the desktop is painted in COLOR_ACTIVECAPTION. This is strange, because I also added CreateSysColorObjects(); at the beginning of NtUserPaintDesktop.
Anybody any idea?
Some additionms:
1.) IntGetSysColorBrush is a fuction I wrote to make things easier:
HBRUSH IntGetSysColorBrush(UINT nBrush) { if (nBrush < NUM_SYSCOLORS) { return SysColorBrushes[nBrush]; } else { return NULL; } }
2.) After starting ROS the desktop gets painted in original color first. After userlogon (during hw detection, shortly before explorer starts) the desktop get painted in COLOR_ACTIVECAPTION.
Saveliy Tretiakov schrieb:
Timo Kreuzer ?????:
1.) IntGetSysColorBrush is a fuction I wrote to make things easie
It is already implemented (see r23525).
Funny, my working copy was only 5 revisions behind ;-) I also implemented IntGetSysColor.
HGDIOBJ FASTCALL IntGetSysColorBrush(INT Object) { return ((Object < 0) || (NUM_SYSCOLORS <= Object)) ? NULL : SysColorBrushes[Object]; }
First question: Is there a reason you used HGDIOBJ and DWORD instead of HBRUSH and COLORREF (that's what I used).
Second question: Wouldn't an "(UINT Object)" make life easier here? There would be no need for (Object < 0) (?) IntGetSysColor also uses an INT instead of UINT. Just my 3,1415 cents ;-) Timo
Timo Kreuzer ?????:
First question: Is there a reason you used HGDIOBJ and DWORD instead of HBRUSH and COLORREF (that's what I used).
Second question: Wouldn't an "(UINT Object)" make life easier here? There would be no need for (Object < 0) (?) IntGetSysColor also uses an INT instead of UINT.
Maybe. I did it the same way it was in NtGdiGetStockObject.
Hi, Timo Kreuzer wrote:
Hi,
First, this is going to be a long post, sorry ;-) You might have noticed, that I have been working on the desk.cpl appearance tab, wich is working partly. Here's the first version: http://www.reactos.org/bugzilla/show_bug.cgi?id=1732
Some things still don't work. For example the desktop doesn't get repainted in the new color.
------- /Comment #5 http://www.reactos.org/bugzilla/show_bug.cgi?id=1732#c5 >From jimtabor 2006-08-05 04:46:36 CET / [reply
http://www.reactos.org/bugzilla/show_bug.cgi?id=1732#add_comment]
Hi, You can use WM_SYSCOLORCHANGE in the desktop proc if it is used, should be!, user32/misc/desktop.c;
static LRESULT WINAPI DesktopWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { DPRINT1("Desktop Class Atom!\n"); switch(message) { case WM_NCCREATE: return TRUE;
case WM_CREATE: /* when I spy I see notify */ SendNotifyMessageW( hwnd, WM_SYSCOLORCHANGE , 0, 0 ); break;
case WM_SYSCOLORCHANGE: /* update everything, well in theory anyway */ RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN ); break;
default: return DefWindowProcW(hwnd,message,wParam,lParam); } return 0; /* all other messages are ignored */ }
Its crude, I'm not sure if it will compile, its off the top of my head ATM. 8^D Thanks, James
Thanks for helping, James. I tried it, but it doesn't work.
Not surprised at all. We dont use the desktop class when the explorer desktop is opened.
1.) Sending WM_SYSCOLORCHANGE on WM_CREATE will probably do nothing, because the desktop has just been created with the initial SysColors, no need to update them.
To init the system colors before the desktop is displayed.
OT Q. Is our explorer desktop a plug in replacement to the windows one? One way to find out,,, look for explorer desktop replacement projects and read their source.
2.) RedrawWindow calls NtUserRedrawWindow wich calls co_UserRedrawWindow wich calls co_IntPaintWindows wich sends a WM_PAINT message to the desktop window.
Redraw should refresh all of its children including its self and not push the responsibility off to another app.
WM_PAINT is then passed to DefWindowProc and passed on to User32DefWindowProc wich does only repaint the icon as it seems. So WM_PAINT must be evaluated in DesktopWndProc.
No its not.
I tried the following:
case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); PaintDesktop(hdc); EndPaint(hwnd, &ps); }
this could be done in explorer desktop?
PaintDesktop calls NtUserPaintDesktop, wich then paints the desktop. I have also replaced DesktopBrush = (HBRUSH)UserGetClassLongPtr(WndDesktop->Class, GCL_HBRBACKGROUND, FALSE); with DesktopBrush = IntGetSysColorBrush(COLOR_BACKGROUND);
But the desktop is still painted in the original color, whereas the icon text is in the color I have set in the registry.
I played a little around with the code in NtUserPaintDesktop. I added the following code before the desktop background is painted:
if (IntGetSysColor(COLOR_BACKGROUND) == 0) // This is true after SysColors are loaded from Registry { DesktopBrush = IntGetSysColorBrush(COLOR_ACTIVECAPTION); }
And suddenly the desktop is painted in COLOR_ACTIVECAPTION. This is strange, because I also added CreateSysColorObjects(); at the beginning of NtUserPaintDesktop.
Anybody any idea?
No, sorry, not at this moment.
For the Devs, Yes, we plug in explorer by creating the desktop using the desktop class, So the class proc will get called. Was there a patch?
8^) Okay, James
Just fixed the problem in Explorer - the shell background will now be refreshed at system color changes.
Regards,
Martin
-- Martin Fuchs fuchs.martin@gmail.com
Martin Fuchs schrieb:
Just fixed the problem in Explorer - the shell background will now be refreshed at system color changes.
That's great. Thanks. I couldn't test it yet, becaue explorer won't start in current trunk. (I think userinit does not complete, because with my code syscolors are no longer loaded from the registry) But I guess it will at least let the new color be applied instantly.
Q: I added SendSysColorChangeMessage() to win32k wich sends WM_SYSCOLORCHANGE to *all* windows after setting new syscolors. Is that the way it should be? Or should the message be passed to child windows by the windows itself (in DefWindowProc)?
But it will probably not help to use the correct SysColorBrush on startup, wich was the thing I stumbled upon. It seems that NtUserPaintDesktop is called several times (15+, but not really sure about that) before userinit (Does that cause the heavy redraw of the text in the hardware detection window on startup?). And on userinit SysColors[COLOR_BACKGROUND] is loaded correctly from registry (before explorer.exe is loaded), but NtUserPaintDesktop won't use the correct SysColorBrush, although CreateSysColorObjects() is called at the beginning.
I think CreateSysColorObjects might not work correctly.But I can't figure out why.If noone has a tip for me, I'll go on trying to find out, hopefully DBG=1 boots now and explorer will start again soon.
Greetings, Timo