1. Responding to system color changes
- Posted by Jonas Temple <jtemple at yhti.net> Mar 14, 2003
- 414 views
I know this is trivial, but if a user changes the system color scheme within Windows while your win32lib based program is running, the background colors for all your controls are the same as when the program started. Not a big deal, but it would be nice if win32lib based programs responded to these color changes like other Windows programs. To that end, I submit the following routine that I use. The beauty is you don't have to code all the controls to be changed, the routine will change all child windows/controls based on the passed parent. So if you have a main window with several child windows and they have controls and child windows and so on, this routine will work. procedure setChildColor(integer parent, atom color) sequence children children = findChildren(parent) for i = 1 to length(children) do if children[i][2] = Window then setWindowBackColor(children[i][1], color) end if if find(children[i][2],{PushButton,DefPushButton,LText,Radio,CheckBox}) then setWindowBackColor(children[i][1], color) elsif children[i][2]=Group then setWindowBackColor(children[i][1],color) setChildColor(children[i][1],color) else setChildColor(children[i][1], color) end if end for end procedure In context, here's how I use it: atom cur_color procedure Main_onPaint (integer self, integer event, sequence params)--params is ( int x1, int y1, int x2, int y2 ) object color color = getSysColor(COLOR_BTNFACE) if color != cur_color then cur_color = color setWindowBackColor(Main, color) setChildColor(Main, color) end if end procedure setHandler( Main, w32HPaint, routine_id("Main_onPaint"))
2. Re: Responding to system color changes
- Posted by Elliott Sales de Andrade <quantum_analyst at hotmail.com> Mar 14, 2003
- 412 views
According to MSDN, the message for this is WM_SYSCOLORCHANGE. Here are some of the remarks... -=- The system sends a WM_PAINT message to any window that is affected by a system color change. Applications that have brushes using the existing system colors should delete those brushes and recreate them using the new system colors. Top level windows that use common controls must forward the WM_SYSCOLORCHANGE message to the controls; otherwise, the controls will not be notified of the color change. This ensures that the colors used by your common controls are consistent with those used by other user interface objects. For example, a toolbar control uses the "3D Objects" color to draw its buttons. If the user changes the 3D Objects color but the WM_SYSCOLORCHANGE message is not forwarded to the toolbar, the toolbar buttons will remain in their original color while the color of other buttons in the system changes. -=- So, what would be needed is to recreate any system brushes that win32lib might have and SendMessage() the WM_SYSCOLORCHANGE notification to all common controls. >From: Jonas Temple <jtemple at yhti.net> >Reply-To: EUforum at topica.com >To: EUforum <EUforum at topica.com> >Subject: Responding to system color changes >Date: Fri, 14 Mar 2003 16:30:28 +0000 > > >I know this is trivial, but if a user changes the system color scheme >within Windows while your win32lib based program is running, the >background colors for all your controls are the same as when the program >started. Not a big deal, but it would be nice if win32lib based >programs responded to these color changes like other Windows programs. > >To that end, I submit the following routine that I use. The beauty is >you don't have to code all the controls to be changed, the routine will >change all child windows/controls based on the passed parent. So if you >have a main window with several child windows and they have controls and >child windows and so on, this routine will work. > > >procedure setChildColor(integer parent, atom color) > sequence children > > children = findChildren(parent) > for i = 1 to length(children) do > if children[i][2] = Window then > setWindowBackColor(children[i][1], color) > end if > if >find(children[i][2],{PushButton,DefPushButton,LText,Radio,CheckBox}) >then > setWindowBackColor(children[i][1], color) > elsif children[i][2]=Group then > setWindowBackColor(children[i][1],color) > setChildColor(children[i][1],color) > else > setChildColor(children[i][1], color) > end if > end for > >end procedure > >In context, here's how I use it: > >atom cur_color > >procedure Main_onPaint (integer self, integer event, sequence >params)--params is ( int x1, int y1, int x2, int y2 ) > object color > color = getSysColor(COLOR_BTNFACE) > if color != cur_color then > cur_color = color > setWindowBackColor(Main, color) > setChildColor(Main, color) > end if >end procedure >setHandler( Main, w32HPaint, routine_id("Main_onPaint")) > > > >TOPICA - Start your own email discussion group. FREE!
3. Re: Responding to system color changes
- Posted by Derek Parnell <ddparnell at bigpond.com> Mar 14, 2003
- 427 views
----- Original Message ----- From: "Jonas Temple" <jtemple at yhti.net> To: "EUforum" <EUforum at topica.com> Subject: Responding to system color changes > > I know this is trivial, but if a user changes the system color scheme > within Windows while your win32lib based program is running, the > background colors for all your controls are the same as when the program > started. Not a big deal, but it would be nice if win32lib based > programs responded to these color changes like other Windows programs. This is already on my todo list. ---------- Derek
4. Re: Responding to system color changes
- Posted by euman at bellsouth.net Mar 15, 2003
- 420 views
*********************************************************** Jonas Temple wrote: > > I know this is trivial, but if a user changes the system color scheme > > within Windows while your win32lib based program is running, the > > background colors for all your controls are the same as when the program > > started. Not a big deal, but it would be nice if win32lib based > > programs responded to these color changes like other Windows programs. Derek Parnell wrote: > This is already on my todo list. *********************************************************** Euman writes: I know this isnt the answer to 'controls color change' but instead for images you may have in your program. In an earlier version of my (Euphoria Setup Utility for Programmers) "Eusup" I used some interesting code snippets to allow the program to be seen the same in 256 color or higher. (assuming the same palette exist in all images used) btw, I still have that code if anyone wants it, email me... There is alot of work figuring out palette operations so I offer what I have. You'll need these: -- DCstuff xSaveDC = define_c_func(gdi32, "SaveDC",{C_LONG},C_INT) -- Palette Manipulation xCreatePalette = define_c_func(gdi32, "CreatePalette", {C_LONG},C_LONG) xSelectPalette = define_c_func(gdi32, "SelectPalette", {C_INT, C_INT, C_INT}, C_UINT) xRealizePalette = define_c_func(gdi32, "RealizePalette", {C_INT}, C_INT) xSetPaletteEntries = define_c_func(gdi32, "SetPaletteEntries",{C_LONG, C_UINT, C_UINT, C_POINTER},C_UINT) --Winstuff xInvalidateRect = define_c_func(user32, "InvalidateRect", {C_POINTER, C_POINTER, C_LONG}, C_LONG) --Memstuff xCopyMemory = define_c_func(kernel32,"RtlMoveMemory",{C_POINTER,C_POINTER,C_LONG},C_LONG) global procedure pokew(atom addr,object w) -- poke word by Jacques Deschenes if atom(w) then poke(addr,{remainder(w,256),floor(w/256)}) else for i = 1 to length(w) do poke(addr+(i-1)*2,{remainder(w[i],256),floor(w[i]/256)}) end for end if end procedure -- (highly modified!) Code from win32lib development -- "contains palette code and optimizations" -- Euman 2002 global atom newpal, palinfo newpal = 0 ---------------------------------------------------------------------------- - function packScanLine( sequence pixels ) -- convert a scanline of data into a packed scanline integer fill sequence packed packed = pixels fill = and_bits( length( packed ), 4 - 1 ) if fill then packed = packed & repeat( 0, 4-fill ) end if return packed end function constant CBM_INIT = #4 global atom hPal, ple ple = myalloc(1028) atom memBitmapInfo integer pal_exist pal_exist = 0 global sequence spal global function createDIB(atom hdc, sequence pal, sequence pixels) integer palSize, headerSize, bitsPer, h, w, at atom memBits, hDIB palSize = length(pal) bitsPer = 8 -- size of bitmap w = length( pixels[1] ) h = length( pixels ) -- calculate the size of the BITMAPINFO header headerSize = 40 + (4 * palSize ) -- Allocate memory for DIB memBitmapInfo = allocate(headerSize) -- build the bitmap info header poke4( memBitmapInfo + 0, 40 ) poke4( memBitmapInfo + 4, w ) -- Width in pixels. poke4( memBitmapInfo + 8, -h ) -- Height in pixels. poke ( memBitmapInfo + 12, {1,0} ) -- 1 color plane. poke ( memBitmapInfo + 14, {8,0} ) -- bits per pixel. poke4( memBitmapInfo + 32, 256 ) -- Colors used. poke4( memBitmapInfo + 36, 256 ) -- Colors used. for i = 1 to h do pixels[i] = packScanLine( pixels[i] ) end for -- get bytes per scanline w = length( pixels[1] ) -- Allocate storage memBits = allocate(h * w) -- copy pixels to memory at = memBits for i = 1 to h do poke( at, pixels[i] ) at = at + w end for at = memBitmapInfo + 40 if pal_exist = 0 then for i = 1 to 256 do poke(at, pal[i]) at = at + 4 end for pokew(ple + 0, #300) pokew(ple + 2, 256) junk = c_func(xCopyMemory,{ple+4, at - 1024, 1024}) newpal = c_func(xCreatePalette,{ple}) junk = c_func(xSetPaletteEntries, {newpal, 0, 255, ple+4}) hPal = c_func(xSelectPalette, {hdc, newpal, 1}) junk = c_func(xRealizePalette, {hdc}) junk = c_func(xSelectPalette, {hdc, hPal, 1}) pal_exist = 1 else junk = c_func(xCopyMemory,{at, ple+4, 1024}) end if -- Create the DIB. hDIB = c_func( xCreateDIBitmap, { hdc, memBitmapInfo, CBM_INIT, memBits, memBitmapInfo, 0} ) free(memBits) free(memBitmapInfo) return hDIB end function In my "WndProc( )" I use this method to insure that when the app looses then regains focus that the palette is automagically returned to show the images as they were ment to be seen in the first place.... Hope this crap helps! elsif iMsg = WM_ACTIVATE then if LOWORD(wParam) = 0 then hPal = c_func(xSelectPalette, {hdc, newpal, 0}) junk = c_func(xRealizePalette, {hdc}) InvalidateRect(hwnd, NULL, 0) savedDC = c_func(xSaveDC,{hdc}) elsif LOWORD(wParam) = 1 or LOWORD(wParam) = 2 then if savedDC > 0 then junk = c_func(xRestoreDC,{hdc, -1}) hPal = c_func(xSelectPalette, {hdc, newpal, 0}) junk = c_func(xRealizePalette, {hdc}) InvalidateRect(hwnd, NULL, 0) end if end if return junk There is alot more to this than meets the eye but, I give this info to help save time. Make sure to DeleteObject's & DeleteDC's or you'll have resources stuck out there. Hopefully helpfull, The Euman